/*
 * Java-Gnome Bindings Library
 *
 * Copyright 1998-2004 the Java-Gnome Team, all rights reserved.
 *
 * The Java-Gnome bindings library is free software distributed under
 * the terms of the GNU Library General Public License version 2.
 */
package org.gnu.gtk;

import java.util.Vector;

import org.gnu.glib.EventMap;
import org.gnu.glib.GObject;
import org.gnu.gtk.event.ComboBoxEvent;
import org.gnu.gtk.event.ComboBoxListener;
import org.gnu.gtk.event.GtkEventType;

/**
 */
public class ComboBox extends Bin {
	
	// for glade
	public ComboBox(int hndl) {
		super(hndl);
		initializeEventHandlers();
	}
	
	/**
	 * Construct a new ComboBox that will contain only Strings.
	 * If you need to include objects other than strings you must
	 * use the constructor that takes a TreeModel.  When you use
	 * this constructor you should use the appendText, insertText,
	 * prependText, and removeText methods to add or remove text
	 * from the comboBox.
	 */
	public ComboBox() {
		super(gtk_combo_box_new_text());
		initializeEventHandlers();
	}
	
	/**
	 * Create a new ComboBox with the provided model.  If you
	 * use this constructor you should not use the appendText,
	 * insertText, prependText, or removeText methods.  You should
	 * update the model when you need to change the values in the
	 * ComboBox. 
	 * @param model
	 */
	public ComboBox(TreeModel model) {
		super(gtk_combo_box_new_with_model(model.getHandle()));
		initializeEventHandlers();
	}
	
	/**
	 * Sets the wrap width of the ComboBox.  The wrap widgth is the
	 * preferred number of columns when you want the popup to be layed
	 * out in a table.
	 * @param width
	 */
	public void setWrapWidth(int width) {
		gtk_combo_box_set_wrap_width(getHandle(), width);
	}
	
	/**
	 * Sets the row span for the ComboBox.  The row span is the 
	 * number of rows an item should span.
	 * @param rowSpan
	 */
	public void setRowSpanColumn(int rowSpan) {
		gtk_combo_box_set_row_span_column(getHandle(), rowSpan);
	}
	
	/**
	 * Sets the column span for the ComboBox.  The column span
	 * is the number of columns an item should span.
	 * @param columnSpan
	 */	
	public void setColumnSpanColumn(int columnSpan) {
		gtk_combo_box_set_column_span_column(getHandle(), columnSpan);
	}
	
	/**
	 * Returns the index of the currently active item or -1 if there's
	 * no active item.
	 * @return
	 */
	public int getActive() {
		return gtk_combo_box_get_active(getHandle());
	}
	
	/**
	 * Sets the active item of the ComboBox to be index.
	 * @param index
	 */
	public void setActive(int index) {
		gtk_combo_box_set_active(getHandle(), index);
	}
	
	/**
	 * Returns a TreeIter that is pointing to the currently active
	 * item in the ComboBox.
	 * @return
	 */
	public TreeIter getActiveIter() {
		int [] iter = new int[1];
		boolean ret = gtk_combo_box_get_active_iter(getHandle(), iter);
		if (ret) {
			int hndl = gtk_combo_box_get_model(getHandle());
			GObject obj = retrieveGObject(hndl);
			TreeModel tm;
			if (null != obj)
				tm = (TreeModel)obj;
			else
				tm = new TreeModel(hndl);
			return new TreeIter(iter[0], tm);
		}
		return null;
	}
	
	/**
	 * Sets the current active item to the one referenced by iter.
	 * @param iter
	 */
	public void setActiveIter(TreeIter iter) {
		gtk_combo_box_set_active_iter(getHandle(), iter.getHandle());
	}
	
	/**
	 * Returns the TreeModel for the ComboBox.
	 * @return
	 */
	public TreeModel getModel() {
		int hndl = gtk_combo_box_get_model(getHandle());
		GObject obj = retrieveGObject(hndl);
		if (null != obj)
			return (TreeModel)obj;
		return new TreeModel(hndl);
	}
	
	/**
	 * Sets the model for the ComboBox.  
	 * @param model
	 */
	public void setModel(TreeModel model) {
		gtk_combo_box_set_model(getHandle(), model.getHandle());
	}
	
	/**
	 * Appends a string to the list of strings in the ComboBox.  This
	 * method can only be called if you created the ComboBox with the
	 * no-op constructor.
	 * @param text
	 */
	public void appendText(String text) {
		gtk_combo_box_append_text(getHandle(), text);
	}
	
	/**
	 * Inserts a string into the list of strings in the ComboBox at
	 * the provided position.  This method can only be called if you
	 * created the ComboBox with the no-op constructor.
	 * @param position
	 * @param text
	 */
	public void insertText(int position, String text) {
		gtk_combo_box_insert_text(getHandle(), position, text);
	}
	
	/**
	 * Prepends a string to the list of strings in the ComboBox.  This
	 * method can only be called if you created the ComboBox with the
	 * no-op constructor.
	 * @param text
	 */
	public void prependText(String text) {
		gtk_combo_box_prepend_text(getHandle(), text);
	}
	
	/**
	 * Removes the string at the provided position from the list of
	 * strings in the ComboBox.  This method can only be called if 
	 * you created the ComboBox with the no-op constructor.
	 * @param position
	 */
	public void removeText(int position) {
		gtk_combo_box_remove_text(getHandle(), position);
	}
	
	/**
	 * Pops up the menu or dropdown list of the ComboBox.
	 */
	public void popup() {
		gtk_combo_box_popup(getHandle());
	}
	
	/**
	 * Hides the menu or dropdown list of the ComboBox.
	 */
	public void popdown() {
		gtk_combo_box_popdown(getHandle());
	}

	/* **************************************
	 * EVENT LISTENERS
	 ****************************************/

	/**
	 * Listeners for handling ComboBox events
	 */
	private Vector cbListeners = null;

	/**
	 * Register an object to handle ComboBox events.
	 * @see ComboBoxListener
	 */
	public void addListener(ComboBoxListener listener) {
		// Don't add the listener a second time if it is in the Vector.
		int i = findListener(cbListeners, listener);
		if (i == -1) {
			if (null == cbListeners) {
				cbListeners = new Vector();
			}
			cbListeners.addElement(listener);
		}
	}
	
	/**
	 * Removes a listener
	 * @see #addListener(ComboBoxListener)
	 */
	public void removeListener(ComboBoxListener listener) {
		int i = findListener(cbListeners, listener);
		if (i > -1) {
			cbListeners.remove(i);
		}
		if (0 == cbListeners.size()) {
			cbListeners = null;
		}
	}

	protected void fireComboBoxEvent(ComboBoxEvent event) {
		if (null == cbListeners) {
			return;
		}
		int size = cbListeners.size();
		int i = 0;
		while (i < size) {
			ComboBoxListener cbl = (ComboBoxListener)cbListeners.elementAt(i);
			cbl.comboBoxEvent(event);
			i++;
		}
	}

	private void handleChanged() {
		fireComboBoxEvent(new ComboBoxEvent(this, ComboBoxEvent.Type.CHANGED));
	}

	protected void initializeEventHandlers() {
		if (!eventsInitialized) {
			super.initializeEventHandlers();
			evtMap.initialize(this);
			eventsInitialized = true;
		}
	}

	public Class getEventListenerClass(String signal) {
		Class cls = evtMap.getEventListenerClass(signal);
		if (cls == null) cls = super.getEventListenerClass(signal);
		return cls;
	}

	public GtkEventType getEventType(String signal) {
		GtkEventType et = evtMap.getEventType(signal);
		if (et == null) et = super.getEventType(signal);
		return et;
	}

	private static EventMap evtMap = new EventMap();
	static {
		addEvents(evtMap);
	}

	/**
	 * Implementation method to build an EventMap for this widget class.
	 * Not useful (or supported) for application use.
	 */
	private static void addEvents(EventMap anEvtMap) {
		anEvtMap.addEvent("changed", "handleChanged", ComboBoxEvent.Type.CHANGED, ComboBoxListener.class);
	}

	/****************************************
	 * BEGINNING OF JNI CODE
	 ****************************************/
	native static final protected int gtk_combo_box_get_type ();
	native static final protected int gtk_combo_box_new();
	native static final protected int gtk_combo_box_new_with_model(int model);
	native static final protected void gtk_combo_box_set_wrap_width(int combo, int width);
	native static final protected void gtk_combo_box_set_row_span_column(int box, int rowSpan);
	native static final protected void gtk_combo_box_set_column_span_column(int box, int columnSpan);
	native static final protected int gtk_combo_box_get_active(int combo);
	native static final protected void gtk_combo_box_set_active(int combo, int index);
	native static final protected boolean gtk_combo_box_get_active_iter(int combo, int[] iter);
	native static final protected void gtk_combo_box_set_active_iter(int combo, int iter);
	native static final protected void gtk_combo_box_set_model(int combo, int model);
	native static final protected int gtk_combo_box_get_model(int combo);
	native static final protected int gtk_combo_box_new_text();
	native static final protected void gtk_combo_box_append_text(int combo, String text);
	native static final protected void gtk_combo_box_insert_text(int combo, int position, String text);
	native static final protected void gtk_combo_box_prepend_text(int combo, String text);
	native static final protected void gtk_combo_box_remove_text(int combo, int position);
	native static final protected void gtk_combo_box_popup(int combo);
	native static final protected void gtk_combo_box_popdown(int combo);
	/****************************************
	 * END OF JNI CODE
	 ****************************************/
}
