/*
 * Created on Dec 21, 2003
 *
 */
package LumiSoft.UI.Controls;

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;

import javax.swing.event.EventListenerList;

/**
 * Simple push button.
 */
public class WButton extends WControl
{
	private EventListenerList m_pListners      = null;
	private String            m_Text           = ""; 
	private String            m_TextID         = "";
	private Point             m_MousePos       = new Point(-1,-1);
	private int               m_MouseModifiers = 0;
	
	/**
	 * Default constructor.
	 *
	 */
	public WButton()
	{
		super();
		
		m_pListners = new EventListenerList();
			
		this.setFocusable(true);
		this.setFont(new Font("SansSerif",Font.PLAIN,12));
		
		this.addMouseListener(new MouseAdapter(){
			public void mousePressed(MouseEvent e){
				OnMousePressed(e);
			}
			
			public void mouseReleased(MouseEvent e){
				OnMouseReleased(e);
			}
			
			public void mouseEntered(MouseEvent e){
				OnMouseEntered(e);
			}
			
			public void mouseExited(MouseEvent e){
				OnMouseExited(e);
			}
		});
		this.addMouseMotionListener(new MouseMotionAdapter(){
			public void mouseMoved(MouseEvent e){
				OnMouseMoved(e);
			}
		});
		this.addKeyListener(new KeyAdapter(){
			public void keyPressed(KeyEvent e){
				OnKeyPressed(e);
			}
			
			public void keyReleased(KeyEvent e){
				OnKeyReleased(e);
			}
		});
		this.addFocusListener(new FocusAdapter(){
			public void focusGained(FocusEvent e){
				OnFocusGained(e);
			}
			
			public void focusLost(FocusEvent e){
				OnFocusLost(e);
			}
		});
	}
	
	/**
	 * Clean up any resources being used.
	 */
	public void Dispose()
	{
		super.Dispose();
	}
	
	/**
	 * Is called by system when control need to repaint.
	 */
	public void paintComponent(Graphics g)
	{
		super.paintComponent(g);
		
		// Create offscreen graphics
		BufferedImage paintBuffer = (BufferedImage)this.createImage(this.getBounds().width,this.getBounds().height);
		Graphics2D g2 = paintBuffer.createGraphics();
		
		// Draw offscreen
		Rectangle clientRect = new Rectangle(0,0,this.getSize().width,this.getSize().height);
		boolean hot = (this.hasFocus() || (clientRect.contains(m_MousePos))) && this.isEnabled();
		
		DrawButton((Graphics2D)g2,hot,m_MouseModifiers == MouseEvent.BUTTON1_DOWN_MASK && this.isEnabled());		
		g2.dispose();
		
		// Draw offscreen image
		g.drawImage(paintBuffer,0,0,this);	
	}
	
	/**
	 * Draws button.
	 * @param g Graphics where to draw.
	 * @param hot Specifies if button is hot.
	 * @param pressed Specifies if button is pressed.
	 */
	private void DrawButton(Graphics2D g,boolean hot,boolean pressed)
	{
		Rectangle clientRect = new Rectangle(0,0,this.getSize().width - 1,this.getSize().height - 1);
		
		// Fill backround
		g.setColor(getViewStyle().GetButtonColor(hot,pressed));		
		g.fill(clientRect);
		
		//--- Draw text -----------------------------------------------------------------------------
		Rectangle txtRect = new Rectangle(1,1,this.getSize().width - 1,this.getSize().height - 1);
		if(pressed){
			txtRect = new Rectangle(txtRect.x + 1,txtRect.y + 2,txtRect.width - 1,txtRect.height - 2);
		}
		if(this.isEnabled()){
			g.setColor(Color.black);
		}
		else{
			g.setColor(Color.GRAY);			
		}
		Paint.DrawText(g,this.getFont(),this.getText(),txtRect,HorizontalAlignment.Center);
		//-------------------------------------------------------------------------------------------
		
		// Draw border
		g.setColor(getViewStyle().GetBorderColor(hot));		
		g.draw(clientRect);
	}
	
	
	/**
	 * Is called when mouse has pressed down.
	 * @param e
	 */
	private void OnMousePressed(MouseEvent e)
	{
		m_MouseModifiers = e.getModifiersEx();
		
		this.repaint();
	}
	
	/**
	 * Is called when mouse has released.
	 * @param e
	 */
	private void OnMouseReleased(MouseEvent e)
	{
		// Reset, we don't need them anymore
		m_MouseModifiers = 0;
		
		if(this.isEnabled() && m_MousePos.x > -1){
			RaiseButtonClicked();
		}
		
		this.repaint();
	}
	
	/**
	 * Is called when mouse cursor has entered to this control.
	 * @param e
	 */
	private void OnMouseEntered(MouseEvent e)
	{
		this.repaint();
	}
	
	/**
	 * Is called when mouse cursor has exited this control.
	 * @param e
	 */
	private void OnMouseExited(MouseEvent e)
	{
		m_MousePos = new Point(-1,-1);
		
		this.repaint();
	}
	
	/**
	 * Is called when mouse has moved.
	 * @param e
	 */
	private void OnMouseMoved(MouseEvent e)
	{
		m_MousePos = e.getPoint();
	}
	
	/**
	 * Is called when key has pressed down.
	 * @param e
	 */
	private void OnKeyPressed(KeyEvent e)
	{		
		if(e.getKeyCode() == KeyEvent.VK_SPACE || e.getKeyCode() == KeyEvent.VK_ENTER){
			// Draw button pressed
			DrawButton((Graphics2D)this.getGraphics(),true,true);
			
			// Space key gives click whent it's released
			if(e.getKeyCode() == KeyEvent.VK_SPACE){				
			}
			// Enter key gives immediate click
			else if(e.getKeyCode() == KeyEvent.VK_ENTER){
				RaiseButtonClicked();
			}
		}
	}
	
	/**
	 * Is called when key has released.
	 * @param e
	 */
	private void OnKeyReleased(KeyEvent e)
	{
		if(e.getKeyCode() == KeyEvent.VK_SPACE || e.getKeyCode() == KeyEvent.VK_ENTER){
			// Draw button hot
			DrawButton((Graphics2D)this.getGraphics(),true,false);
			
			// Space key gives click whent it's released
			if(e.getKeyCode() == KeyEvent.VK_SPACE){
				RaiseButtonClicked();
			}
		}
	}
	
	/**
	 * Is called when focus has gained.
	 * @param e
	 */	
	private void OnFocusGained(FocusEvent e)
	{
		this.repaint();
	}
	
	/**
	 * Is called when focus has lost.
	 * @param e
	 */
	private void OnFocusLost(FocusEvent e)
	{
		this.repaint();
	}
	
	/**
	 * Is called when UI language has changed.
	 */
	protected void OnLanguageChanged()
	{
		this.repaint();
	}
	
		
	
	/**
	 * Sets text info and language controller.
	 * @param text
	 * @param textID
	 * @param wText
	 */
	public void SetTextInfo(String text,String textID,WText wText)
	{
		this.setText(text);
		this.setTextID(textID);
		this.setWText(wText);
	}
	
	
		
	/** 
	 * Gets button text.
	 */
	public String getText()
	{
		if(getWText() != null && getTextID().length() > 0){
			return getWText().get(getTextID());
		}
		else{
			return m_Text;
		}
	}
	/** 
	 * Sets button text.
	 * @param value Value to set.
	 */
	public void setText(String value)
	{
		if(value != m_Text){
			m_Text = value;
			
			this.repaint();
		}
	}
	
	/**
	 * Gets textID.
	 * @return
	 */
	public String getTextID()
	{
		return m_TextID;
	}
	/**
	 * Sets textID.
	 * @param value
	 */
	public void setTextID(String value)
	{
		m_TextID = value;
	}
	
	
	/**
	 * Adds the specified action listener to receive action events
	 * from this button.
	 * @param l the action listener
	 */ 
	public void addClickedListener(ActionListener l) 
	{
		m_pListners.add(ActionListener.class,l);
	}

	/**
	 * Removes the specified action listener so it no longer receives
	 * action events from this button.
	 * @param l the action listener
	 */ 
	public void removeClickedListener(ActionListener l) 
	{
		m_pListners.remove(ActionListener.class,l);
	}
	
	/**
	 * Raises clicked event.
	 *
	 */
	private void RaiseButtonClicked()
	{
		Object[] listeners = m_pListners.getListenerList();
		// loop through each listener and pass on the event if needed		
		for(int i=0;i<listeners.length;i++){
			if(listeners[i] == ActionListener.class){
				// pass the event to the listeners event dispatch method
				((ActionListener)listeners[i+1]).actionPerformed(new ActionEvent(this,ActionEvent.ACTION_PERFORMED,""));
			}            
		}
	}
}
