/*
 * 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.EventType;
import org.gnu.glib.Handle;
import org.gnu.glib.Type;
import org.gnu.gtk.event.ItemEvent;
import org.gnu.gtk.event.ItemListener;

/**
 * This widget is designed to be a base class for widgets that can be
 * selected and deselected. The widgets that inherit from Item are
 * CheckMenuItem, ListItem, MenuItem, and RadioMenuItem.
 */
public class Item extends Bin 
{
	protected Item(Handle handle) {
	    super(handle);
	}

	/**
	 * Emits the "select" event.
	 */
	public void select() {
		gtk_item_select(getHandle());
	}
	
	/**
	 * Emits the "deselect" event.
	 */
	public void deselect() {
		gtk_item_deselect(getHandle());
	}
	
	/**
	 * Emits the "toggle" event.
	 */
	public void toggle() {
		gtk_item_toggle(getHandle());
	}
	
	/* **************************************
	 * EVENT LISTENERS
	 ****************************************/

	/**
	 * Listeners for handling button events
	 */
	private Vector listeners = null;

	/**
	 * Register an object to handle item events.
	 * @see org.gnu.gtk.event.ItemListener
	 */
	public void addListener(ItemListener listener) {
		// Don't add the listener a second time if it is in the Vector.
		int i = findListener(listeners, listener);
		if (i == -1) {
			if (null == listeners) {
				evtMap.initialize(this, ItemEvent.Type.DESELECT);
				evtMap.initialize(this, ItemEvent.Type.SELECT);
				evtMap.initialize(this, ItemEvent.Type.TOGGLE);
				listeners = new Vector();
			}
			listeners.addElement(listener);
		}
	}
	/**
	 * Removes a listener
	 * @see #addListener(ItemListener)
	 */
	public void removeListener(ItemListener listener) {
		int i = findListener(listeners, listener);
		if (i > -1) {
			listeners.remove(i);
		}
		if (0 == listeners.size()) {
			evtMap.uninitialize(this, ItemEvent.Type.DESELECT);
			evtMap.uninitialize(this, ItemEvent.Type.SELECT);
			evtMap.uninitialize(this, ItemEvent.Type.TOGGLE);
			listeners = null;
		}
	}

	protected void fireItemEvent(ItemEvent event) {
		if (null == listeners) {
			return;
		}
		int size = listeners.size();
		int i = 0;
		while (i < size) {
			ItemListener lis = (ItemListener)listeners.elementAt(i);
			lis.itemEvent(event);
			i++;
		}
	}

	private void handleSelect() {
		fireItemEvent(new ItemEvent(this, ItemEvent.Type.SELECT));
	}

	private void handleDeselect() {
		fireItemEvent(new ItemEvent(this, ItemEvent.Type.DESELECT));
	}

	private void handleToggle() {
		fireItemEvent(new ItemEvent(this, ItemEvent.Type.TOGGLE));
	}

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

	public EventType getEventType(String signal) {
		EventType 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("select", "handleSelect", ItemEvent.Type.SELECT, ItemListener.class);
		anEvtMap.addEvent("deselect", "handleDeselect", ItemEvent.Type.DESELECT, ItemListener.class);
		anEvtMap.addEvent("toggle", "handleToggle", ItemEvent.Type.TOGGLE, ItemListener.class);
	}

	/**
	 * Retrieve the runtime type used by the GLib library.
	 */
	public static Type getType() {
		return new Type(gtk_item_get_type());
	}


    native static final protected int gtk_item_get_type ();
    native static final protected void gtk_item_select (Handle item);
    native static final protected void gtk_item_deselect (Handle item);
    native static final protected void gtk_item_toggle (Handle item);

}

