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

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.EventListenerList;

/**
 * 
 */
public class WComboBox extends WButtonEdit_base implements FocusListener,KeyListener
{
	private EventListenerList m_pListners = null;
	private JTextField  m_pTextbox        = null;
	private int         m_MaxVisibleItems = 10;
	private WComboItems m_pItems          = null;
	private boolean     m_AcceptsAddKey   = true;
	private WComboItem  m_pSelectedItem   = null;
//	private WComboPopUp m_pPopup          = null;
	
	/**
	 * Default constructor.
	 */
	public WComboBox()
	{	
		m_pListners = new EventListenerList();		
		m_pItems = new WComboItems();
		
		m_pTextbox = new JTextField();
		m_pTextbox.setBorder(null);
		m_pTextbox.setDisabledTextColor(getViewStyle().getEditDisabledTextColor());
		m_pTextbox.addFocusListener(this);
		m_pTextbox.addMouseListener(this);
		m_pTextbox.addMouseMotionListener(this);
		m_pTextbox.addKeyListener(this);
		
		this.addFocusListener(this);
		this.add(m_pTextbox);
	}
	
	/**
	 * Is called when ViewStyle has changed.
	 *
	 */
	protected void OnViewStyleChaned()
	{
		super.OnViewStyleChaned();
		
		m_pTextbox.setBackground(getViewStyle().GetEditColor(!this.getEditable(),this.isEnabled(),m_pTextbox.hasFocus()));
		m_pTextbox.setDisabledTextColor(getViewStyle().getEditDisabledTextColor());
	}
	
	public void focusGained(FocusEvent e)
	{
		if(!m_pTextbox.hasFocus()){
			m_pTextbox.grabFocus();
		}
		m_pTextbox.selectAll();
		m_pTextbox.setBackground(getViewStyle().GetEditColor(!this.getEditable(),this.isEnabled(),hasFocus()));
		
		this.repaint();
	}
	
	public void focusLost(FocusEvent e)
	{
		m_pTextbox.setBackground(getViewStyle().GetEditColor(!this.getEditable(),this.isEnabled(),hasFocus()));
		
		this.repaint();
	}
	
	//--- Forward nested editbox keyevents to this -------------------//
	public void keyTyped(KeyEvent e)
	{	
		// If read only, allow only arrows to be used
		if(!this.getEditable()){
			if(!ReadOnlyAllowedKey(e)){
				e.consume();				
			}
		}
		
		if(m_AcceptsAddKey && e.getKeyChar() == '+'){
			RaiseButtonClicked();
			e.consume();
		}
		
		KeyListener[] listeners = this.getKeyListeners();
		for(int i=0;i < listeners.length;i++){
			// pass the event to the listeners event dispatch method
			listeners[i].keyTyped(e);			            
		}
	}	
	public void keyPressed(KeyEvent e)
	{		
		// If read only, allow only arrows to be used
		if(!this.getEditable()){
			if(!ReadOnlyAllowedKey(e)){
				e.consume();				
			}
		}
		
		KeyListener[] listeners = this.getKeyListeners();
		for(int i=0;i < listeners.length;i++){
			// pass the event to the listeners event dispatch method
			listeners[i].keyPressed(e);			            
		}	
	}	
	public void keyReleased(KeyEvent e)
	{
		// If read only, allow only arrows to be used
		if(!this.getEditable()){
			if(!ReadOnlyAllowedKey(e)){
				e.consume();				
			}
		}
		
		KeyListener[] listeners = this.getKeyListeners();
		for(int i=0;i < listeners.length;i++){
			// pass the event to the listeners event dispatch method
			listeners[i].keyReleased(e);			            
		}	
	}
	//-----------------------------------------------------------------//
	
	
	/**
	 * Checks if specified key is allowed when this is readonly.
	 * @param e
	 * @return Returns true if specified key is allowed.
	 */
	private boolean ReadOnlyAllowedKey(KeyEvent e)
	{
		if(e.getKeyCode() == KeyEvent.VK_LEFT){
			return true;
		}
		else if(e.getKeyCode() == KeyEvent.VK_RIGHT){
			return true;
		}
		else if(e.getKeyCode() == KeyEvent.VK_UP){
			return true;
		}
		else if(e.getKeyCode() == KeyEvent.VK_DOWN){
			return true;
		}
		
		return false;
	}
	
	protected void OnPopupItemSelected(WComboItem item)
	{
		if(item != null){
			m_pTextbox.setText(item.toString());
			
			m_pSelectedItem = item;
			
			// Raise SelectionChanged event
			OnSelectionChanged();
		}
	}
	
	protected void OnPopupClosed()
	{
//		m_pPopup = null;
	}
	
	
	protected void SizeChanged()
	{	
		m_pTextbox.setLocation(this.getEditRect().getLocation());		
		m_pTextbox.setSize(this.getEditRect().getSize());
	}
	
	protected void RaiseButtonClicked()
	{
		super.RaiseButtonClicked();
		
		if(!m_pTextbox.hasFocus()){
			m_pTextbox.grabFocus();
		}
		
//		if(m_pPopup == null){
			WComboPopUp m_pPopup = new WComboPopUp(this);
			m_pPopup.show(this,0,this.getHeight());
//		}
//		else{
	//		m_pPopup.hide();
//		}		
	}
	
	/**
	 * Selects item by specified item tag.
	 * @param tag
	 */
	public void SelectItemByTag(Object itemTag)
	{
		for(int i=0;i<this.getItems().getCount();i++){
			WComboItem item = this.getItems().get(i);

			if(itemTag.equals(item.getTag())){
				m_pSelectedItem = item;
				m_pTextbox.setText(item.getText());
				
				// Raise SelectionChanged event
				OnSelectionChanged();
				return;
			}
		}
	}
	
	/**
	 * Selects first item which has specified text. If item with specified text doesn't exist, nothing is done.
	 * @param text
	 */
	public void SelectItemByText(String text)
	{
		for(int i=0;i<this.getItems().getCount();i++){
			WComboItem item = this.getItems().get(i);

			if(item.getText().equals(text)){
				m_pSelectedItem = item;
				m_pTextbox.setText(item.getText());
				
				// Raise SelectionChanged event
				OnSelectionChanged();				
				return;
			}
		}
	}
	
	
	/**
	 * Gets font.
	 */
	public Font getFont()
	{
		if(m_pTextbox != null){
			return m_pTextbox.getFont();
		}
		else{
			return super.getFont();
		}
	}
	/**
	 * Sets font.
	 */
	public void setFont(Font value)
	{
		if(m_pTextbox != null){
			m_pTextbox.setFont(value);
		}
	}
	
	/**
	 * Gets currently selected item or null if item isn't selected.
	 * 
	 * @return
	 */
	public WComboItem getSelectedItem()
	{
		return m_pSelectedItem;
	}
	
	/**
	 * Gets currently selected item index or -1 if ite, isn't selected.
	 * 
	 * @return
	 */
	public int getSelectedIndex()
	{
		if(m_pSelectedItem != null && this.getItems().Contains(m_pSelectedItem)){
			return this.getItems().IndexOf(m_pSelectedItem);
		}
		else{
			return -1;
		}
	}
	/**
	 * Selects item with specified index. If item with specified index doesn't exist, nothing is done.
	 * 
	 * @param value
	 */
	public void setSelectedIndex(int value)
	{
		if(value > -1 && value < this.getItems().getCount()){
			m_pSelectedItem = (WComboItem)this.getItems().get(value);
			m_pTextbox.setText(m_pSelectedItem.getText());
			
			// Raise SelectionChanged event
			OnSelectionChanged();
		}
	}
	
	/**
	 * Gets text selection start position.
	 * 
	 * @return
	 */
	public int getSelectionStart()
	{
		return m_pTextbox.getSelectionStart();
	}
	/**
	 * Sets text selection start position.
	 * 
	 * @param value
	 */
	public void setSelectionStart(int value)
	{
		m_pTextbox.setSelectionStart(value);
	}
	
	/**
	 * Gets text selection end position.
	 * @return
	 */
	public int getSelectionEnd()
	{
		return m_pTextbox.getSelectionEnd();
	}
	/**
	 * Sets text selection end position.
	 * 
	 * @param value
	 */
	public void setSelectionEnd(int value)
	{
		m_pTextbox.setSelectionEnd(value);
	}	
	
	/**
	 * Gets maximum allowed visible items in combo popup before it starts to scroll.
	 * 
	 * @return
	 */
	public int getMaxVisibleItems()
	{
		return m_MaxVisibleItems;
	}
	/**
	 * Sets maximum allowed visible items in combo popup before it starts to scroll.
	 * 
	 * @param value
	 */
	public void setMaxVisibleItems(int value)
	{
		if(m_MaxVisibleItems != value){
			m_MaxVisibleItems = value;			
		}
	}
			
	/**
	 * Gets if + key simulates button click.
	 * 
	 * @return
	 */
	public boolean getAcceptsAddKey()
	{
		return m_AcceptsAddKey;
	}
	/**
	 * Sets if + key simulates button click.
	 * 
	 * @param value
	 */
	public void setAcceptsAddKey(boolean value)
	{
		if(m_AcceptsAddKey != value){
			m_AcceptsAddKey = value;			
		}
	}
	
	/**
	 * Gets combobox items collection.
	 * 
	 * @return
	 */
	public WComboItems getItems()
	{
		return m_pItems;
	}
	
	/**
	 * Gets currently visible text in combobox.
	 * 
	 * @return
	 */
	public String getText()
	{
		return m_pTextbox.getText();
	}
	/**
	 * Sets currently visible text in combobox.
	 * 
	 * @param text
	 */
	public void setText(String text)
	{
		m_pTextbox.setText(text);
	}
	
	
	/**
	 * Sets if enabled.
	 */
	public void setEnabled(boolean value)
	{
		super.setEnabled(value);
		
		m_pTextbox.setEnabled(value);
		m_pTextbox.setBackground(getViewStyle().GetEditColor(!getEditable(),value));
		
		this.repaint();
	}
	
	/**
	 * Sets if control is editable.
	 */
	public void setEditable(boolean value)
	{
		m_pTextbox.setBackground(getViewStyle().GetEditColor(!value,isEnabled(),hasFocus()));
		super.setEditable(value);
	}
	
	
	/**
	 * Adds the specified action listener to receive action events
	 * from this button.
	 * @param l the action listener
	 */ 
	public void addSelectionChangedListener(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 removeSelectionChangedListener(ActionListener l) 
	{
		m_pListners.remove(ActionListener.class,l);
	}
	
	/**
	 * Raises ButtonClicked event.
	 *
	 */
	protected void OnSelectionChanged()
	{
		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,1,""));
			}            
		}
	}
}
