/*
 * 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.MenuItemEvent;
import org.gnu.gtk.event.MenuItemListener;

/**
 * The MenuItem widget and derived widgets are the only valid children
 * for Menus.  Their function is to correctly handle highlighting, alignment,
 * events, and submenus.
 */
public class MenuItem extends Item {

	/**
	 * Container to hold all listeners that are to receive events.
	 */
	private Vector listeners = null;

	/**
	 * Construct a new menu item.
	 */
	public MenuItem() {
		super(gtk_menu_item_new());
	}

	/**
	 * Create a new MenuItem with a handle to a native resource
	 * returned from a call to the native libraries.
	 * 
	 * @param handle The handle that represents a pointer to a native resource.
	 */
	public MenuItem(Handle handle) {
		super(handle);
	}

	/**
	 * Construct a new menu item with the provided label.
	 * 
	 * @param label The label to display in the menu item.
	 * @param hasMnemonic Indicates if the provided string contains mnemonics
	 */
	public MenuItem(String label, boolean hasMnemonic) {
		super(init(label, hasMnemonic));
	}

	private static Handle init(String label, boolean hasMnemonic) {
		if (hasMnemonic)
			return gtk_menu_item_new_with_mnemonic(label);
		else
			return gtk_menu_item_new_with_label(label);
	}
	
	/**
	 * Sets whether the menu item appears to the right side of the menu bar.
	 * This was traditionally done for the Help menu, but is now considered a 
	 * bad idea.  (If the widget layout is reversed for a right to left language
	 * like Hebrew or Arabic, right-justified menu items appear at the left).
	 */
	public void setRightJustified() {
		MenuItem.gtk_menu_item_set_right_justified(getHandle(), true);
	}

	/**
	 * MenuItem's are left justified by default.  Use this method to change
	 * a MenuItem from right justified back to left justified.
	 */
	public void setLeftJustified() {
		MenuItem.gtk_menu_item_set_right_justified(getHandle(), false);
	}

	/**
	 * Sets the submenu, or changes it.
	 * 
	 * @param submenu The submenu.
	 */
	public void setSubmenu(Menu submenu) {
		MenuItem.gtk_menu_item_set_submenu(getHandle(), submenu.getHandle());
	}

	/**
	 * Removes the widget's submenu.
	 */
	public void removeSubmenu() {
		MenuItem.gtk_menu_item_remove_submenu(getHandle());
	}

	/**
	 * Emits the "deselect" signal on this MenuItem.
	 */
	public void emitDeselect() {
		MenuItem.gtk_menu_item_deselect(getHandle());
	}

	/**
	 * Emits the "activate" signal on this MenuItem.
	 */
	public void emitActivate() {
		MenuItem.gtk_menu_item_activate(getHandle());
	}

	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("activate", "handleActivate", MenuItemEvent.Type.ACTIVATE, MenuItemListener.class);
	}

	/**
	 * Register an object to receive event notification.
	 * 
	 * @param listener The object that has implemented the 
	 * MenuItemListener interface that is to receive the menu
	 * item events.
	 */
	public void addListener(MenuItemListener 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, MenuItemEvent.Type.ACTIVATE);
				listeners = new Vector();
			}
			listeners.addElement(listener);
		}
	}

	/**
	 * Unregister an object that was receiving menuitem event 
	 * notification.
	 * 
	 * @param listener The object that is to no longer receive
	 * menuitem events.
	 */
	public void removeListener(MenuItemListener listener) {
		int i = findListener(listeners, listener);
		if (i > -1) {
			listeners.remove(i);
		}
		if (0 == listeners.size()) {
			evtMap.uninitialize(this, MenuItemEvent.Type.ACTIVATE);
			listeners = null;
		}
	}

	protected void fireMenuItemEvent(MenuItemEvent event) {
		if (null == listeners) {
			return;
		}
		int size = listeners.size();
		int i = 0;
		while (i < size) {
			MenuItemListener mil = (MenuItemListener)listeners.elementAt(i);
			mil.menuItemEvent(event);
			i++;
		}
	}

	private void handleActivate() {
		fireMenuItemEvent(new MenuItemEvent(this));
	}

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


	native static final protected int gtk_menu_item_get_type();
	native static final protected Handle gtk_menu_item_new();
	native static final protected Handle gtk_menu_item_new_with_label(String label);
	native static final protected Handle gtk_menu_item_new_with_mnemonic(String label);
	native static final protected void gtk_menu_item_set_submenu(Handle menu_item, Handle submenu);
	native static final protected Handle gtk_menu_item_get_submenu(Handle menu_item);
	native static final protected void gtk_menu_item_remove_submenu(Handle menu_item);
	native static final protected void gtk_menu_item_select(Handle menu_item);
	native static final protected void gtk_menu_item_deselect(Handle menu_item);
	native static final protected void gtk_menu_item_activate(Handle menu_item);
	native static final protected void gtk_menu_item_toggle_size_request(Handle menu_item, int[] requisition);
	native static final protected void gtk_menu_item_toggle_size_allocate(Handle menu_item, int allocation);
	native static final protected void gtk_menu_item_set_right_justified(Handle menu_item, boolean rightJustified);
	native static final protected boolean gtk_menu_item_get_right_justified(Handle menu_item);
	native static final protected void gtk_menu_item_set_accel_path(Handle menu_item, String accelPath);

}
