/*
 * 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.glib.Type;
import org.gnu.gtk.event.OptionMenuEvent;
import org.gnu.gtk.event.OptionMenuListener;
import org.gnu.gtk.event.GtkEventType;

/**
 * deprecated menu widget replaced by {@link ComboBox} in gtk 2.3.
 * 
 * An OptionMenu is a widget that allows the user to choose from a list
 * of valid choices.  When activated the OptionMenu displays a popup
 * Menu which allows the user to make a new choice.
 *
 * @deprecated Replaced by {@link ComboBox} in gtk 2.3
 */
public class OptionMenu extends Button {
	
	/**
	 * Create a new OptionMenu.
	 */
	public OptionMenu() {
		super(gtk_option_menu_new());
		initializeEventHandlers();
	}
	
	/**
	 * Construct an OptionMenu using a handle to a native resource.
	 */
	public OptionMenu(int handle) {
	    super(handle);
	    initializeEventHandlers();
	}

	/**
	 * Provides the Menu that is popped up to allow the user to choose
	 * a new value.  You should provide a simple menu avoiding the use
	 * of tearoff menu items, submenus, and accelerators.
	 * 
	 * @param menu The Menu to add to the OptionMenu.
	 */
	public void setMenu(Menu menu) {
		OptionMenu.gtk_option_menu_set_menu(getHandle(), menu.getHandle());
	}
	
	/**
	 * Returns the Menu associated with this OptionMenu.
	 * 
	 * @return The Menu assoicated with this OptionMenu.
	 */
	public Menu getMenu() {
		int hndl = OptionMenu.gtk_option_menu_get_menu(getHandle());
		GObject obj = retrieveGObject(hndl);
		if (null != obj)
			return (Menu)obj;
		return new Menu(hndl);
	}
	
	/**
	 * Removes the Menu from the OptionMenu
	 */
	public void removeMenu() {
		OptionMenu.gtk_option_menu_remove_menu(getHandle());
	}
	
	/**
	 * Retrieve the runtime type used by the GLib library.
	 */
	public static Type getType() {
		return new Type(gtk_option_menu_get_type());
	}

	/**
	 * Retrieves the index of the currently selected menu item. The menu items
	 * are numbered from top to bottom, starting with 0.  
	 * @return 	 index of the selected menu item, or -1 if there are no menu
	 * items 
	 */
	public int getHistory(){
		return gtk_option_menu_get_history(getHandle());
	}

	/**
	 * Selects the menu item specified by <code>index</code> making it the newly
	 * selected value for the option menu.  
	 * @param index 	the index of the menu item to select. Index values are
	 * from 0 to n-1.
	 */
	public void setHistory( int index ){
		gtk_option_menu_set_history( getHandle(), index );
	}

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

	/**
	 * Listeners for handling button events
	 */
	private Vector optionMenuListeners = null;
	
	/**
	 * Register an object to handle optionMenu events.
	 * @see org.gnu.gtk.event.OptionMenuListener
	 */
	public void addListener(OptionMenuListener listener) {
		// Don't add the listener a second time if it is in the Vector.
		int i = findListener(optionMenuListeners, listener);
		if (i == -1) {
			if (null == optionMenuListeners) {
				optionMenuListeners = new Vector();
			}
			optionMenuListeners.addElement(listener);
		}
	}
	/**
	 * Removes a listener
	 * @see #addListener(OptionMenuListener)
	 */
	public void removeListener(OptionMenuListener listener) {
		int i = findListener(optionMenuListeners, listener);
		if (i > -1) {
			optionMenuListeners.remove(i);
		}
		if (0 == optionMenuListeners.size()) {
			optionMenuListeners = null;
		}
	}

	protected void fireOptionMenuEvent(OptionMenuEvent event) {
		if (null == optionMenuListeners) {
			return;
		}
		int size = optionMenuListeners.size();
		int i = 0;
		while (i < size) {
			OptionMenuListener bl = (OptionMenuListener)optionMenuListeners.elementAt(i);
			bl.optionMenuEvent(event);
			i++;
		}
	}

	private void handleChange() {
		fireOptionMenuEvent(new OptionMenuEvent(this, OptionMenuEvent.Type.CHANGE));
	}

	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.
	 */
	protected static void addEvents(EventMap evtMap) {
	    evtMap.addEvent("changed", "handleChange",
			    OptionMenuEvent.Type.CHANGE, 
			    OptionMenuListener.class);
	}

	/****************************************
	 * BEGINNING OF GENERATED CODE
	 ****************************************/
	native static final protected int gtk_option_menu_get_type();
	native static final protected int gtk_option_menu_new();
	native static final protected int gtk_option_menu_get_menu(int option_menu);
	native static final protected void gtk_option_menu_set_menu(int option_menu, int menu);
	native static final protected void gtk_option_menu_remove_menu(int option_menu);
	native static final protected int gtk_option_menu_get_history(int option_menu);
	native static final protected void gtk_option_menu_set_history(int option_menu, int index);
	/****************************************
	 * END OF GENERATED CODE
	 ****************************************/
}
