/*
 * 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.atk.AtkObject;
import org.gnu.gdk.Bitmap;
import org.gnu.gdk.Color;
import org.gnu.gdk.Colormap;
import org.gnu.gdk.Display;
import org.gnu.gdk.DragAction;
import org.gnu.gdk.DragContext;
import org.gnu.gdk.EventButton;
import org.gnu.gdk.EventCrossing;
import org.gnu.gdk.EventExpose;
import org.gnu.gdk.EventKey;
import org.gnu.gdk.EventMotion;
import org.gnu.gdk.EventNoExpose;
import org.gnu.gdk.EventScroll;
import org.gnu.gdk.ModifierType;
import org.gnu.gdk.Pixbuf;
import org.gnu.gdk.Pixmap;
import org.gnu.gdk.Point;
import org.gnu.gdk.Rectangle;
import org.gnu.gdk.Screen;
import org.gnu.gdk.Window;
import org.gnu.glib.EventMap;
import org.gnu.glib.EventType;
import org.gnu.glib.GObject;
import org.gnu.glib.Handle;
import org.gnu.glib.Type;
import org.gnu.gtk.event.DragDestinationListener;
import org.gnu.gtk.event.DragSourceListener;
import org.gnu.gtk.event.ExposeEvent;
import org.gnu.gtk.event.ExposeListener;
import org.gnu.gtk.event.FocusEvent;
import org.gnu.gtk.event.FocusListener;
import org.gnu.gtk.event.KeyEvent;
import org.gnu.gtk.event.KeyListener;
import org.gnu.gtk.event.LifeCycleEvent;
import org.gnu.gtk.event.LifeCycleListener;
import org.gnu.gtk.event.MouseEvent;
import org.gnu.gtk.event.MouseListener;
import org.gnu.gtk.event.MouseMotionEvent;
import org.gnu.gtk.event.MouseMotionListener;
import org.gnu.pango.Context;
import org.gnu.pango.FontDescription;

/**
 * GtkWidget is the base class of all widgets.
 */
public class Widget extends GtkObject {

    // Cached class array used in makeWidget.
    private static Class[] handleClass = new Class[] { Handle.class };

	/**
	 * The list of objects interested in focus events.
	 */
	private Vector focusListeners = null;

	/**
	 * Ths list of objects interested in key events.
	 */
	private Vector keyListeners = null;

	/**
	 * The list of objects interested in life cycle events.
	 */
	private Vector lifeCycleListeners = null;

	/**
	 * The list of objects interested in mouse events.
	 */
	private Vector mouseListeners = null;

	/**
	 * The list of objects interested in drag destination events.
	 */
	private Vector dragDestinationListeners = null;

	/**
	 * The list of objects interested in drag source events.
	 */
	private Vector dragSourceListeners = null;

	/**
	 * The list of objects interested in expose events.
	 */
	private Vector exposeListeners = null;

	/**
	 * The list of objects interested in expose events.
	 */
	private Vector mouseMotionListeners = null;

	/**
	 * Create a new Widget 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 Widget(Handle handle) {
		super(handle);
	}

	/**
	 * Cause this Widget to be visible.
	 */
	public void show() {
		Widget.gtk_widget_show(getHandle());
	}

	/**
	 * Cause this Widget and all of its' children to be visible.
	 */
	public void showAll() {
		Widget.gtk_widget_show_all(getHandle());
	}

	/**
	 * Cause this Widget to not be visible.
	 */
	public void hide() {
		Widget.gtk_widget_hide(getHandle());
	}

	/**
	 * Cause this Widget and all of its' children to not be visible.
	 */
	public void hideAll() {
		Widget.gtk_widget_hide_all(getHandle());
	}

	/**
	 * Destroy this widget.  If this widget is inside a container the widget will be
	 * removed from the container.  All of this widget's children are also destroyed.
	 */
	public void destroy() {
		Widget.gtk_widget_destroy(getHandle());
	}

	/**
	 * Creates a native window resource associated with this widget.  Normally a widget
	 * realization happens implicitly; if you show a widget and all of its' parent containers
	 * then the widget will be realized automatically.
	 */
	public void realize() {
		Widget.gtk_widget_realize(getHandle());
	}

	/**
	 *  Causes the entire widget to be redrawn.
	 */
	public void draw() {
		Widget.gtk_widget_queue_draw(getHandle());
	}

	/**
	 * Causes the specified area to be redrawn.
	 * 
	 * @param area The area to be redrawn.
	 */
	public void drawArea(Rectangle area) {
		drawArea(area.getX(), area.getY(), area.getWidth(), area.getHeight());
	}

	/**
	 * Causes the specified area to be redrawn
	 * 
	 * @param x The x coordinate for the area to be redrawn.
	 * @param y The y coordinate for the area to be redrawn.
	 * @param width The width of the area to be redrawn.
	 * @param height The height of the area to be redrawn.
	 */
	public void drawArea(int x, int y, int width, int height) {
		Widget.gtk_widget_queue_draw_area(getHandle(), x, y, width, height);
	}

	/**
	 * For widgets that can be activeated (buttons, menu items, etc.) this
	 * method activiates them.  Activation is what happens when you press
	 * Enter on a widget during keyboard navigation.
	 *
	 * @return False if this widget is not activatable.
	 */
	public boolean activate() {
		return Widget.gtk_widget_activate(getHandle());
	}

	/**
	 * Moves a widget from one Container to another.
	 * 
	 * @param newParent The widget that will be the new parent.
	 */
	public void reparent(Widget newParent) {
		Widget.gtk_widget_reparent(getHandle(), newParent.getHandle());
	}

	/**
	 * Returns the parent container for this widget
	 * 
	 * @return The parent container for this widget.
	 */
	public Widget getParent() {
	    Handle hndl = gtk_widget_get_parent(getHandle());
		if (null == hndl)
			return null;
		GObject obj = getGObjectFromHandle(hndl);
		if (null != obj)
			return (Widget)obj;
		return new Widget(hndl);
	}

	/**
	 * Returns the widget's parent window.
	 * 
	 * @return Returns the widget's parent window.
	 */
	public Window getParentWindow() {
	    Handle hndl = gtk_widget_get_parent_window(getHandle());
		GObject obj = getGObjectFromHandle(hndl);
		if (null != obj)
			return (Window)obj;
		return new Window(hndl);
	}

	/**
	 * Return the widget's gdk window. This is the window to draw
	 * upon when writing custom widgets. It's available after the
	 * widget has been mapped. Thus if you listen to
	 * LifeCycleEvents, you can fetch the Window instance using
	 * this method after an LifeCycleEvent of type MAP has
	 * occured.
	 *
	 * @return the widget's gdk window, or null if a) it hasn't
	 * been mapped yet or b) it is of a type that doesn't have a
	 * gdk window.
	 */
	public Window getWindow() {
	    Handle hndl = Widget.gtk_widget_get_window(getHandle());
		if(hndl == null)
			return null;
		GObject obj = getGObjectFromHandle(hndl);
		return obj != null ? (Window)obj : new Window(hndl);
	}

	/**
	 * Computes the intersection of the widget's area and <code>area</code>.
	 * 
	 * @param area The area to use to compute the intersection.
	 * @return The intersection.  If the areas don't intersect this method returns null.
	 */
	public Rectangle intersect(Rectangle area) {
	    Handle rect = GObject.getNullHandle();
		boolean val = Widget.gtk_widget_intersect(getHandle(), area.getHandle(), rect);
		if (false == val)
			return null;
		return new Rectangle(rect);
	}

	/**
	 * Determines if the widget has focus within its' TOPLEVEL.
	 * 
	 * @return true if the widget has focus.
	 */
	public boolean hasFocus() {
		return Widget.gtk_widget_is_focus(getHandle());
	}

	/**
	 * Causes the widget to gain focus within its' TOPLEVEL.
	 */
	public void grabFocus() {
		Widget.gtk_widget_grab_focus(getHandle());
	}

	/**
	 * Causes the widget to become the default widget.  The default widget
	 * is activated when the user presses Enter in the window.  Default widgets
	 * must be activatable.
	 */
	public void grabDefault() {
		// make sure CAN_DEFAULT has been set.
		//Moving flag setting to the c layer.
		//GtkObject.setFlags(handle, WidgetFlags.CAN_DEFAULT.getValue());
		Widget.gtk_widget_grab_default(getHandle());
	}

	/**
	 * Sets the name for this widget.  Widgets can be named which allows you
	 * to refer to them from a gtkrc file.  You can apply a style to widgets with a
	 * particular name in the gtkrc file.
	 * 
	 * @param name The name for the widget.
	 */
	public void setName(String name) {
		Widget.gtk_widget_set_name(getHandle(), name);
	}

	/**
	 * Returns the name for the widget.
	 * 
	 * @return The name for the widget.
	 */
	public String getName() {
		return Widget.gtk_widget_get_name(getHandle());
	}

	/**
	 * Sets the sensitivity of the widget.
	 * 
	 * @param sensitive Indicates if the widget should be sensitive.
	 */
	public void setSensitive(boolean sensitive) {
		Widget.gtk_widget_set_sensitive(getHandle(), sensitive);
	}

	/**
	 * Gets the sensitivity of the widget.
	 *
	 * @return true if the widget is sensitive, false otherwise.
	 */
    public boolean getSensitive() {
		return gtk_widget_get_sensitive(getHandle());
	}

	/**
	 * Returns the topmost widget in the container hierarchy.
	 * 
	 * @return The topmost widget.
	 */
	public Widget getToplevel() {
	    Handle hndl = gtk_widget_get_toplevel(getHandle());
		if (null == hndl)
			return null;
		GObject obj = getGObjectFromHandle(hndl);
		if (null != obj)
			return (Widget)obj;
		return new Widget(hndl);
	}

	/**
	 * Returns the Colormap that will be used to render this widget.
	 * 
	 * @return The colormap used for this widget.
	 */
	public Colormap getColormap() {
	    Handle colorHandle = Widget.gtk_widget_get_colormap(getHandle());
		GObject obj = getGObjectFromHandle(colorHandle);
		if (null != obj)
			return (Colormap)obj;
		return new Colormap(colorHandle);
	}

	/**
	 * Set the Colormap that will be used to render this widget.
	 * 
	 * @param colormap The colormap to be used.
	 */
	public void setColormap(Colormap colormap) {
		Widget.gtk_widget_set_colormap(getHandle(), colormap.getHandle());
	}

	/**
	 * Returns the location of the mouse pointer in widget coordinates.  This
	 * method will return null if the mouse is not currently in the widget.
	 * 
	 * @return The location of the mouse or null
	 */
	public Point getPointer() {
		int[] x = new int[1];
		int[] y = new int[1];
		Widget.gtk_widget_get_pointer(getHandle(), x, y);
		if (null == x)
			return null;
		if (null == y)
			return null;
		return new Point(x[0], y[0]);
	}

	/**
	 * Determines whether this widget is somewhere inside of ancestor.
	 * 
	 * @param ancestor The possible parent widget
	 */
	public boolean isAncestor(Widget ancestor) {
		return Widget.gtk_widget_is_ancestor(getHandle(), ancestor.getHandle());
	}

	/**
	 * Pushes a Colormap onto the stack of colormaps.  The topmost Colormap
	 * on the stack will be used to create all Widgets.
	 * 
	 * @param colormap The Colormap to push onto the stack.
	 */
	public void pushColormap(Colormap colormap) {
		Widget.gtk_widget_push_colormap(colormap.getHandle());
	}

	/**
	 * Pops the top colormap off of the stack of colormaps.  The topmost Colormap
	 * on the stack will be used to create all Widgets.
	 */
	public void popColormap() {
		Widget.gtk_widget_pop_colormap();
	}

	/**
	 * Sets the shape of this widgets OS window.  This allows for transparent windows.
	 * 
	 * @param shapeMask Shape to be added or null to remove an existing shape.
	 * @param x X Position of the shape mask with respect to the window.
	 * @param y Y Position of the shape mask with respect to the window.
	 */
	public void shapeCombineMask(Bitmap shapeMask, int x, int y) {
		Widget.gtk_widget_shape_combine_mask(getHandle(), shapeMask.getHandle(), x, y);
	}

	/**
	 * Sets the foreground color for a widget in a particular state.  All other
	 * style values are left untouched.
	 * 
	 * @param state The widget state to modify.
	 * @param color The color to set the foreground.
	 */
	public void setForegroundColor(StateType state, Color color) {
		Widget.gtk_widget_modify_fg(getHandle(), state.getValue(), color.getHandle());
	}

	/**
	 * Sets the background color for a widget in a particular state.  All other
	 * style values are left untouched.
	 * 
	 * @param state The widget state to modify.
	 * @param color The color to set the background.
	 */
	public void setBackgroundColor(StateType state, Color color) {
		Widget.gtk_widget_modify_bg(getHandle(), state.getValue(), color.getHandle());
	}

	/**
	 * Sets the text color for a widget in a particilar state.  All other style values
	 * are left untouched.  The text color is the foreground color along with the
	 * base color for widgets such as Entry, TextView, etc.
	 * 
	 * @param state The widget state to modify.
	 * @param color The color to set the text.
	 */
	public void setTextColor(StateType state, Color color) {
		Widget.gtk_widget_modify_text(getHandle(), state.getValue(), color.getHandle());
	}

	/**
	 * Sets the base color used for a widget in a particular state.  The base color
	 * is the backgound color used along with the text color for widgets such as
	 * Entry, TextView, etc.
	 * 
	 * @param state The widget state to modify.
	 * @param color The color to set.
	 */
	public void setBaseColor(StateType state, Color color) {
		Widget.gtk_widget_modify_base(getHandle(), state.getValue(), color.getHandle());
	}

	/**
	 * Sets the font to use for the widget.
	 * 
	 * @param fontDesc The font description to use.
	 */
	public void setFont(FontDescription fontDesc) {
		Widget.gtk_widget_modify_font(getHandle(), fontDesc.getHandle());
	}

	/**
	 * Modifies style values on the Widget.  Modifications made using this
	 * technique take precedence over style values set via an RC file.
	 * 
	 * @param style The style to apply to the Widget
	 */
	public void modifyStyle(RcStyle style) {
		Widget.gtk_widget_modify_style(getHandle(), style.getHandle());
	}

	/**
	 * Retruns the Widget's {@link RcStyle}.
	 * 
	 * @return The current RcStyle for the Widget.
	 */
	public RcStyle getModifierStyle() {
	    Handle hndl = Widget.gtk_widget_get_modifier_style(getHandle());
		return new RcStyle(hndl);
	}

	/**
	 * Returns the Widgets {@link Style}.
	 * 
	 * @return The current Style for the Widget.
	 */
	public Style getStyle() {
	    Handle hndl = Widget.gtk_widget_get_style(getHandle());
		GObject obj = getGObjectFromHandle(hndl);
		if (null != obj)
			return (Style)obj;
		return new Style(hndl);
	}

	/**
	 * Creates a new Context with the appropriate Colormap, FontDescription,
	 * and base direction for drawing text for this widget.
	 * 
	 * @return A context that can be used for drawig text.
	 */
	public Context createContext() {
	    Handle pc = Widget.gtk_widget_create_pango_context(getHandle());
		return new Context(pc);
	}

	/**
	 * Gets a Context with the appropriate Colormap, FontDescription and base
	 * direction for this widget.  Unlike the createContext method, this context
	 * is owned by the widget and can be as long as the widget exists.  This
	 * context will be updated to match any changes to the widget's attributes.
	 *
	 * @return A context that can be used for drawing text.
	 */
	public Context getContext() {
	    Handle pc = Widget.gtk_widget_get_pango_context(getHandle());
		GObject obj = getGObjectFromHandle(pc);
		if (null != obj)
			return (Context)obj;
		return new Context(pc);
	}

	/**
	 * Creates a new Layout with the appropriate Colormap, FontDescription and
	 * base direction for drawing text for this widget.
	 *
	 * @param text The text used for the layout.
	 * @return The layout that can be used for drawing text.
	 */
	public org.gnu.pango.Layout createLayout(String text) {
	    Handle layout = Widget.gtk_widget_create_pango_layout(getHandle(), text);
		return new org.gnu.pango.Layout(layout);
	}

	/**
	 * Enables/Disables double buffering for this widget.  Widgets are double buffered
	 * by default.
	 * 
	 * @param doubleBuffered Set if the widget should be double buffered.
	 */
	public void setDoubleBuffered(boolean doubleBuffered) {
		Widget.gtk_widget_set_double_buffered(getHandle(), doubleBuffered);
	}

	/**
	 * Returns the accessible object associated with this widget.
	 * 
	 * @return The AtkObject.
	 */
	public AtkObject getAccessible() {
	    Handle ao = Widget.gtk_widget_get_accessible(getHandle());
		GObject obj = getGObjectFromHandle(ao);
		if (null != obj)
			return (AtkObject)obj;
		return new AtkObject(ao);
	}

	public boolean canActivateAccel(int signalId) {
		return gtk_widget_can_activate_accel(getHandle(), signalId);
	}

	public Screen getScreen() {
	    Handle hndl = gtk_widget_get_screen(getHandle());
		GObject obj = getGObjectFromHandle(hndl);
		if (null != obj)
			return (Screen)obj;
		return new Screen(hndl);
	}

	public boolean hasScreen() {
		return gtk_widget_has_screen(getHandle());
	}

	public Display getDisplay() {
	    Handle hndl = gtk_widget_get_display(getHandle());
		GObject obj = getGObjectFromHandle(hndl);
		if (null != obj)
			return (Display)obj;
		return new Display(hndl);
	}

	public Window getRootWindow() {
	    Handle hndl = gtk_widget_get_root_window(getHandle());
		GObject obj = getGObjectFromHandle(hndl);
		if (null != obj)
			return (Window)obj;
		return new Window(hndl);
	}

	/**
	 * Sets the minimum size of a widget.  You can use this method to force a widget
	 * to be either larger or smaller that it normally be.  
	 * <p>
	 * In most cases <code>Window.setDefaultSize()</code> is a better choice for toplevel
	 * windows than this method.  Setting the default size will still allow users to shrink
	 * the window.  Setting the minimum size will force them to leave the window at
	 * least as large as the request.  
	 * <p>
	 * Note the inherent danger of setting any fixed size - themes, translations into
	 * other languages, different fonts, and user action can change the appropriate
	 * size for a given widget.  So, it's basically impossible to hardcode a size that 
	 * will always be correct.
	 * <p>
	 * If the minimum size in a given direction is -1 then the "natural" size for the
	 * widget will be used instead.
	 * 
	 * @param width The minimum width size to use.
	 * @param height The minimum height size to use.
	 */
	public void setMinimumSize(int width, int height) {
		Widget.gtk_widget_set_size_request(getHandle(), width, height);
	}

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

	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("hide", "handleHide", LifeCycleEvent.Type.HIDE, LifeCycleListener.class);
		anEvtMap.addEvent("show", "handleShow", LifeCycleEvent.Type.SHOW, LifeCycleListener.class);
		anEvtMap.addEvent("realize", "handleRealize", LifeCycleEvent.Type.REALIZE, LifeCycleListener.class);
		anEvtMap.addEvent("unrealize", "handleUnrealize", LifeCycleEvent.Type.UNREALIZE, LifeCycleListener.class);
		anEvtMap.addEvent("destroy_event", "handleDestroy", LifeCycleEvent.Type.DESTROY, LifeCycleListener.class);
		anEvtMap.addEvent("delete_event", "handleDelete", LifeCycleEvent.Type.DELETE, LifeCycleListener.class);
		anEvtMap.addEvent("map", "handleMap", LifeCycleEvent.Type.MAP, LifeCycleListener.class);
		anEvtMap.addEvent("unmap", "handleUnmap", LifeCycleEvent.Type.UNMAP, LifeCycleListener.class);
		anEvtMap.addEvent("focus_in_event", "handleFocusIn", FocusEvent.Type.FOCUS_IN, FocusListener.class);
		anEvtMap.addEvent("focus_out_event", "handleFocusOut", FocusEvent.Type.FOCUS_OUT, FocusListener.class);
		anEvtMap.addEvent("key_press_event", "handleKeyPressed", KeyEvent.Type.KEY_PRESSED, KeyListener.class);
		anEvtMap.addEvent("key_release_event", "handleKeyReleased", KeyEvent.Type.KEY_RELEASED, KeyListener.class);
		anEvtMap.addEvent("button_press_event", "handleButtonPressed", MouseEvent.Type.BUTTON_PRESS, MouseListener.class);
		anEvtMap.addEvent("button_release_event", "handleButtonReleased", MouseEvent.Type.BUTTON_RELEASE, MouseListener.class);
		anEvtMap.addEvent("scroll_event", "handleScroll", MouseEvent.Type.WHEEL_SCROLL, MouseListener.class);
		anEvtMap.addEvent("enter_notify_event", "handleMouseEnter", MouseEvent.Type.ENTER, MouseListener.class);
		anEvtMap.addEvent("leave_notify_event", "handleMouseLeave", MouseEvent.Type.LEAVE, MouseListener.class);
		anEvtMap.addEvent("expose_event", "handleExpose", ExposeEvent.Type.EXPOSE, ExposeListener.class); 
		anEvtMap.addEvent("no_expose_event", "handleNoExpose", ExposeEvent.Type.NO_EXPOSE, ExposeListener.class);
		anEvtMap.addEvent("motion-notify-event", "handleMouseMotion", MouseMotionEvent.Type.MOTION, MouseMotionListener.class);
		//anEvtMap.addEvent("drag_data_received", "handleDragDestination", null, DragDestinationListener.class);
		//anEvtMap.addEvent("drag_data_get", "handleDragDataGet", null, DragSourceListener.class);
 	}

	/****************************************
	 * Life Cycle event handling.
	 ****************************************/
	/**
	 * Register an object to receive life cycle event notification.
	 * 
	 * @param listener The object that has implemented the 
	 * LifeCycleListener interface that is to receive the life cycle events.
	 */
	public void addListener(LifeCycleListener listener) {
		// Don't add the listener a second time if it is in the Vector.
		int i = findListener(lifeCycleListeners, listener);
		if (i == -1) {
			if (null == lifeCycleListeners) {
				evtMap.initialize(this, LifeCycleEvent.Type.HIDE);
				evtMap.initialize(this, LifeCycleEvent.Type.SHOW);
				evtMap.initialize(this, LifeCycleEvent.Type.REALIZE);
				evtMap.initialize(this, LifeCycleEvent.Type.UNREALIZE);
				evtMap.initialize(this, LifeCycleEvent.Type.DESTROY);
				evtMap.initialize(this, LifeCycleEvent.Type.DELETE);
				lifeCycleListeners = new Vector();
			}
			lifeCycleListeners.addElement(listener);
		}
	}

	/**
	 * Unregister an object that was receiving life cycle event notification.
	 * 
	 * @param listener The object that is to no longer receive
	 * life cycle events.
	 */
	public void removeListener(LifeCycleListener listener) {
		int i = findListener(lifeCycleListeners, listener);
		if (i > -1)
			lifeCycleListeners.remove(i);
		if (0 == lifeCycleListeners.size()) {
			evtMap.uninitialize(this, LifeCycleEvent.Type.HIDE);
			evtMap.uninitialize(this, LifeCycleEvent.Type.SHOW);
			evtMap.uninitialize(this, LifeCycleEvent.Type.REALIZE);
			evtMap.uninitialize(this, LifeCycleEvent.Type.UNREALIZE);
			evtMap.uninitialize(this, LifeCycleEvent.Type.DESTROY);
			evtMap.uninitialize(this, LifeCycleEvent.Type.DELETE);
			lifeCycleListeners = null;
		}
	}

	protected void fireLifeCycleEvent(LifeCycleEvent event) {
		if (null == lifeCycleListeners)
			return;
		int size = lifeCycleListeners.size();
		int i = 0;
		while (i < size) {
			LifeCycleListener lc = (LifeCycleListener)lifeCycleListeners.elementAt(i);
			lc.lifeCycleEvent(event);
			i++;
		}
	}

	protected boolean fireBooleanLifeCycleEvent(LifeCycleEvent event, boolean defaultValue) {
		boolean returnValue = defaultValue;
		if (null == lifeCycleListeners)
			return defaultValue;
		int size = lifeCycleListeners.size();
		int i = 0;
		while (i < size) {
			LifeCycleListener lc = (LifeCycleListener)lifeCycleListeners.elementAt(i);
			if (lc.lifeCycleQuery(event) != defaultValue)
				returnValue = !defaultValue;
			i++;
		}
		return returnValue;
	}

	protected void handleShow() {
		fireLifeCycleEvent(new LifeCycleEvent(this, LifeCycleEvent.Type.SHOW));
	}

	protected void handleHide() {
		fireLifeCycleEvent(new LifeCycleEvent(this, LifeCycleEvent.Type.HIDE));
	}

	protected void handleRealize() {
		fireLifeCycleEvent(new LifeCycleEvent(this, LifeCycleEvent.Type.REALIZE));
	}

	private void handleUnrealize() {
		fireLifeCycleEvent(new LifeCycleEvent(this, LifeCycleEvent.Type.UNREALIZE));
	}

	private boolean handleDestroy(Handle event) {
		return fireBooleanLifeCycleEvent(new LifeCycleEvent(this, LifeCycleEvent.Type.DESTROY), true );
	}

	protected boolean handleDelete(Handle event) {
		return fireBooleanLifeCycleEvent(new LifeCycleEvent(this, LifeCycleEvent.Type.DELETE), false);
	}

	protected void handleMap() {
		fireLifeCycleEvent(new LifeCycleEvent(this, LifeCycleEvent.Type.MAP));
	}
	
	protected void handleUnmap() {
		fireLifeCycleEvent(new LifeCycleEvent(this, LifeCycleEvent.Type.UNMAP));
	}

	/****************************************
	 * Focus event handling.
	 ****************************************/
	/**
	 * Register an object to receive focus event notification.
	 * 
	 * @param listener The object that has implemented the 
	 * FocusListener interface that is to receive the focus events.
	 */
	public void addListener(FocusListener listener) {
		// Don't add the listener a second time if it is in the Vector.
		int i = findListener(focusListeners, listener);
		if (i == -1) {
			if (null == focusListeners) {
				evtMap.initialize(this, FocusEvent.Type.FOCUS_IN);
				evtMap.initialize(this, FocusEvent.Type.FOCUS_OUT);
				focusListeners = new Vector();
			}
			focusListeners.addElement(listener);
		}
	}

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

	protected boolean fireFocusEvent(FocusEvent event) {
		if (null == focusListeners)
			return false;
		boolean retval = false;
		int size = focusListeners.size();
		int i = 0;
		while (i < size) {
			FocusListener fl = (FocusListener)focusListeners.elementAt(i);
			if (fl.focusEvent(event))
				retval = true;
			i++;
		}
		return retval;
	}

	protected boolean handleFocusIn(Handle event) {
		return fireFocusEvent(new FocusEvent(this, FocusEvent.Type.FOCUS_IN));
	}

	protected boolean handleFocusOut(Handle event) {
		return fireFocusEvent(new FocusEvent(this, FocusEvent.Type.FOCUS_OUT));
	}

	/****************************************
	 * Key event handling.
	 ****************************************/
	/**
	 * Register an object to receive key event notification.
	 * <p>
	 * An important thing to notice is that some widgets don't 
	 * receive <i>low-level</i> events (such as a key-press event) by default. 
	 * So if you want to capture events from them, you should add them to an 
	 * <code>EventBox</code>, and capture events on the <code>EventBox</code>. 
	 * <p>
	 * The reason why this happens is that some widgets, for efficiency, don't
	 * have their own X window, which is necessary to receive events. These are
	 * the widgets that don't have their own X window:
	 * <p>
	 * <code>Alignment</code> <br>
	 * <code>Arrow</code> <br>
	 * <code>Bin</code> <br>
	 * <code>Box</code> <br>
	 * <code>Image</code> <br>
	 * <code>Item</code> <br>
	 * <code>Label</code> <br>
	 * <code>Pixmap</code> <br>
	 * <code>ScrolledWindow</code> <br>
	 * <code>Separator</code> <br>
	 * <code>Table</code> <br>
	 * <code>AspectFrame</code> <br>
	 * <code>Frame</code> <br>
	 * <code>VBox</code> <br>
	 * <code>HBox</code> <br>
	 * <code>VSeparator</code> <br>
	 * <code>HSeparator</code> <br>
	 * 
	 * @param listener The object that has implemented the 
	 * KeyListener interface that is to receive the key events.
	 */
	public void addListener(KeyListener listener) {
		// Don't add the listener a second time if it is in the Vector.
		int i = findListener(keyListeners, listener);
		if (i == -1) {
			if (null == keyListeners) {
				evtMap.initialize(this, KeyEvent.Type.KEY_PRESSED);
				evtMap.initialize(this, KeyEvent.Type.KEY_RELEASED);
				keyListeners = new Vector();
			}
			keyListeners.addElement(listener);
		}
	}

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

	protected boolean fireKeyEvent(KeyEvent event) {
		if (null == keyListeners)
			return false;
		boolean retval = false;
		int size = keyListeners.size();
		int i = 0;
		while (i < size) {
			KeyListener kl = (KeyListener)keyListeners.elementAt(i);
			if (kl.keyEvent(event))
				retval = true;
			i++;
		}
		return retval;
	}

	protected boolean handleKeyPressed(Handle event) {
		return fireKeyEvent(new KeyEvent(this, KeyEvent.Type.KEY_PRESSED, new EventKey(event)));
	}

	protected boolean handleKeyReleased(Handle event) {
		return fireKeyEvent(new KeyEvent(this, KeyEvent.Type.KEY_RELEASED, new EventKey(event)));
	}

	/****************************************
	 * Mouse event handling.
	 ****************************************/
	/**
	 * Register an object to receive mouse event notification.
	 * <p>
	 * An important thing to notice is that some widgets don't 
	 * receive <i>low-level</i> events (such as a mouse-click event) by default. 
	 * So if you want to capture events from them, you should add them to an 
	 * <code>EventBox</code>, and capture events on the <code>EventBox</code>. 
	 * <p>
	 * The reason why this happens is that some widgets, for efficiency, don't
	 * have their own X window, which is necessary to receive events. These are
	 * the widgets that don't have their own X window:
	 * <p>
	 * <code>Alignment</code> <br>
	 * <code>Arrow</code> <br>
	 * <code>Bin</code> <br>
	 * <code>Box</code> <br>
	 * <code>Image</code> <br>
	 * <code>Item</code> <br>
	 * <code>Label</code> <br>
	 * <code>Pixmap</code> <br>
	 * <code>ScrolledWindow</code> <br>
	 * <code>Separator</code> <br>
	 * <code>Table</code> <br>
	 * <code>AspectFrame</code> <br>
	 * <code>Frame</code> <br>
	 * <code>VBox</code> <br>
	 * <code>HBox</code> <br>
	 * <code>VSeparator</code> <br>
	 * <code>HSeparator</code> <br>
	 * 
	 * @param listener The object that has implemented the 
	 * MouseListener interface that is to receive the mouse events.
	 */
	public void addListener(MouseListener listener) {
		// Don't add the listener a second time if it is in the Vector.
		int i = findListener(mouseListeners, listener);
		if (i == -1) {
			if (null == mouseListeners) {
				evtMap.initialize(this, MouseEvent.Type.BUTTON_PRESS);
				evtMap.initialize(this, MouseEvent.Type.BUTTON_RELEASE);
				evtMap.initialize(this, MouseEvent.Type.WHEEL_SCROLL);
				evtMap.initialize(this, MouseEvent.Type.ENTER);
				evtMap.initialize(this, MouseEvent.Type.LEAVE);
				mouseListeners = new Vector();
			}
			mouseListeners.addElement(listener);
		}
	}

	/**
	 * Unregister an object that was receiving mouse event notification.
	 * 
	 * @param listener The object that is to no longer receive
	 * mouse events.
	 */
	public void removeListener(MouseListener listener) {
		int i = findListener(mouseListeners, listener);
		if (i > -1)
			mouseListeners.remove(i);
		if (0 == mouseListeners.size()) {
			evtMap.uninitialize(this, MouseEvent.Type.BUTTON_PRESS);
			evtMap.uninitialize(this, MouseEvent.Type.BUTTON_RELEASE);
			evtMap.uninitialize(this, MouseEvent.Type.WHEEL_SCROLL);
			evtMap.uninitialize(this, MouseEvent.Type.ENTER);
			evtMap.uninitialize(this, MouseEvent.Type.LEAVE);
			mouseListeners = null;
		}
	}

	protected boolean fireMouseEvent(MouseEvent event) {
		if (null == mouseListeners)
			return false;
		boolean retval = false;
		int size = mouseListeners.size();
		int i = 0;
		while (i < size) {
			MouseListener ml = (MouseListener)mouseListeners.elementAt(i);
			if (ml.mouseEvent(event))
				retval = true;
			i++;
		}
		return retval;
	}

	protected boolean handleButtonPressed(Handle event) {
		return fireMouseEvent(new MouseEvent(this, MouseEvent.Type.BUTTON_PRESS, new EventButton(event)));
	}

	protected boolean handleButtonReleased(Handle event) {
		return fireMouseEvent(new MouseEvent(this, MouseEvent.Type.BUTTON_RELEASE, new EventButton(event)));
	}

	protected boolean handleScroll(Handle event) {
		return fireMouseEvent(new MouseEvent(this, MouseEvent.Type.WHEEL_SCROLL, new EventScroll(event)));
	}

	protected boolean handleMouseEnter(Handle event) {
		return fireMouseEvent(new MouseEvent(this, MouseEvent.Type.ENTER, new EventCrossing(event)));
	}

	protected boolean handleMouseLeave(Handle event) {
		return fireMouseEvent(new MouseEvent(this, MouseEvent.Type.LEAVE, new EventCrossing(event)));
	}

	/**
	 * Give us a way to locate a specific listener in a Vector.
	* @param list The Vector of listeners to search.
	* @param listener The object that is to be located in the Vector.
	* @return Returns the index of the listener in the Vector, or -1 if
	*                 the listener is not contained in the Vector.
	 */
	protected static int findListener(Vector list, Object listener) {
		if (null == list || null == listener)
			return -1;
		return list.indexOf(listener);
	}

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

	/**
	* Create a Java-GNOME Widget subclass from an existing native
	* GTK+ handle.  
	*
	* @param handle The handle that represents a pointer to a 
	*               native resource.
	* @throws ClassNotFoundException if a Java-GNOME class cannot
	*         be found for the specified handle.
	*/
	public static Widget makeWidget(Handle handle) throws ClassNotFoundException {
		String widgetClass = getTypeClass(handle);
		if (widgetClass == null)
			throw new ClassNotFoundException("No GTK class name: invalid handle?");
		try {
			Class cls = Class.forName(widgetClass);
			java.lang.reflect.Constructor constr = 
                            cls.getConstructor(handleClass);
			Widget cons =  (Widget)constr.newInstance(new Object[] { handle});
			return cons;
		} catch (ClassNotFoundException e) {
			throw e;
		} catch (NoSuchMethodException e) {
			throw new ClassNotFoundException("could not find constructor: " + widgetClass + "(Handle)");
		} catch (Exception e) {
			throw new ClassNotFoundException(e.toString());
		}
	}

	private static String getTypeClass(Handle handle) {
		String widgetType = Gtk.getTypeName(handle);
		if (widgetType.startsWith("Gtk")) {
                    String wname = widgetType.substring(3);
                    // Check for naming exceptions.
                    if ( wname.equals( "Statusbar" ) ) {
                        wname = "StatusBar";
                    } else if ( wname.equals( "Toolbar" ) ) {
                        wname = "ToolBar";
                    }
                    return "org.gnu.gtk." + wname;
                }
		else if (widgetType.startsWith("Gnome"))
			return "org.gnu.gnome." + widgetType.substring(5);

		// Custom class?  See if it exists as specified.
		return widgetType;
	}

	/****************************************
	 * Drag and Drop Support
	 ****************************************/
	/**
	 * Sets up the widget so that it can be the source of drag and drop
	 * operations.
	 * @param buttons Buttons which can start the drag
	 * @param targets An array of names of drag and drop operations accepted
	 * (these are made up by the application designers. Widgets must set as drag
	 * sources and destinations with one of these the same)
	 * @param actions Drag action - determines which events will be called.
	 */
	public void setDragSource(
		ModifierType buttons,
		TargetEntry[] targets,
		DragAction actions) {
	    Handle[] targets_g = new Handle[targets.length];
		for (int i = 0; i < targets.length; i++)
			targets_g[i] = targets[i].getHandle();
		gtk_drag_source_set(getHandle(), buttons.getValue(), targets_g, actions.getValue());
	}

	/**
	 * Removes support for this widget being a drag and drop source.
	 */
	public void setNoDragSource() {
		gtk_drag_source_unset(getHandle());
	}

	public void setDragIcon(Widget widget, Colormap cmap, Pixmap pixmap, Bitmap mask) {
		gtk_drag_source_set_icon(widget.getHandle(), cmap.getHandle(), pixmap.getHandle(), mask.getHandle());
	}
	
	public void setDragIconPixbuf(Widget widget, Pixbuf pixbuf) {
		gtk_drag_source_set_icon_pixbuf(widget.getHandle(), pixbuf.getHandle());
	}
	
	public void setDragIconStock(Widget widget, String stockId) {
		gtk_drag_source_set_icon_stock(widget.getHandle(), stockId);
	}

	/**
	 * Sets up the widget so that is can receive drops as part of drag drop
	 * events and specifies what sort of drops it will accept
	 * @param flags 
	 */
	public void setDragDestination(DestDefaults flags, TargetEntry[] targets, org.gnu.gdk.DragAction actions) {
	    Handle[] targets_g = new Handle[targets.length];
		for (int i = 0; i < targets.length; i++)
			targets_g[i] = targets[i].getHandle();
		gtk_drag_dest_set(getHandle(), flags.getValue(), targets_g, actions.getValue());
	}

	/**
	 * Removes support for this widget being a drag and drop target
	 */
	public void setNoDragDestination() {
		gtk_drag_dest_unset(getHandle());
	}
	public static void getData(Widget widget, DragContext context, int target) {
		gtk_drag_get_data(widget.getHandle(), context.getHandle(), target);
	}
	
	public static void finish(DragContext context, boolean success, boolean delete) {
		gtk_drag_finish(context.getHandle(), success, delete);
	}
	
	public static void highlight(Widget widget) {
		gtk_drag_highlight(widget.getHandle());
	}
	
	public static void unHighlight(Widget widget) {
		gtk_drag_unhighlight(widget.getHandle());
	}
	
	
	/**
	 * Register an object to receive drag drop (destination) events.
	 * 
	 * @param listener The object that has implemented the
	 * DragDestinationListener interface
	 */
	public void addListener(DragDestinationListener listener) {
		// Don't add the listener a second time if it is in the Vector.
		int i = findListener(dragDestinationListeners, listener);
		if (i == -1) {
			if (null == dragDestinationListeners)
				dragDestinationListeners = new Vector();
			dragDestinationListeners.addElement(listener);
		}
	}

	/**
	 * Unregister an object that was receiving dragDestination event notification.
	 * 
	 * @param listener The object that is to no longer receive
	 * dragDestination events
	 */
	public void removeListener(DragDestinationListener listener) {
		int i = findListener(dragDestinationListeners, listener);
		if (i > -1)
			dragDestinationListeners.remove(i);
		if (0 == dragDestinationListeners.size())
			dragDestinationListeners = null;
	}

	protected void fireDragDestinationEvent(
		Widget widget,
		org.gnu.gdk.DragContext dragContext,
		int x,
		int y,
		SelectionData data,
		int id,
		int time) {
		if (null == dragDestinationListeners)
			return;
		int size = dragDestinationListeners.size();
		int i = 0;
		while (i < size) {
			DragDestinationListener lc = (DragDestinationListener)dragDestinationListeners.elementAt(i);
			lc.dataReceived(widget, dragContext, data, id);
			i++;
		}
	}

	protected void handleDragDestination(Handle context, int x, int y, Handle data, int id, int time) {
		SelectionData sd;
		GObject obj = getGObjectFromHandle(data);
		if (null != obj)
			sd = (SelectionData)obj;
		else
			sd = new SelectionData(data);
		DragContext dc;
		GObject obj2 = getGObjectFromHandle(context);
		if (null != obj2)
			dc = (DragContext)obj2;
		else
			dc = new DragContext(context);
		fireDragDestinationEvent(this, dc, x, y, sd, id, time);
	}

	/**
	 * Register an object to receive drag source events.
	 * 
	 * @param listener The object that has implemented the
	 * DragSourceListener interface
	 */
	public void addListener(DragSourceListener listener) {
		// Don't add the listener a second time if it is in the Vector.
		int i = findListener(dragSourceListeners, listener);
		if (i == -1) {
			if (null == dragSourceListeners)
				dragSourceListeners = new Vector();
			dragSourceListeners.addElement(listener);
		}
	}

	/**
	 * Unregister an object that was receiving drag source event notification.
	 * 
	 * @param listener The object that is to no longer receive
	 * drag source events
	 */
	public void removeListener(DragSourceListener listener) {
		int i = findListener(dragSourceListeners, listener);
		if (i > -1)
			dragSourceListeners.remove(i);
		if (0 == dragSourceListeners.size())
			dragSourceListeners = null;
	}

	protected void fireDragSourceEvent(
		Widget widget,
		org.gnu.gdk.DragContext dragContext,
		SelectionData data,
		int id,
		int time) {
		if (null == dragSourceListeners)
			return;
		int size = dragSourceListeners.size();
		int i = 0;
		while (i < size) {
			DragSourceListener lc = (DragSourceListener)dragSourceListeners.elementAt(i);
			lc.getDragData(widget, dragContext, data, id);
			i++;
		}
	}

	protected void handleDragDataGet(Handle context, Handle data, int id, int time) {
		SelectionData sd;
		GObject obj = getGObjectFromHandle(data);
		if (null != obj)
			sd = (SelectionData)obj;
		else
			sd = new SelectionData(data);
		DragContext dc;
		GObject obj2 = getGObjectFromHandle(context);
		if (null != obj2)
			dc = (DragContext)obj2;
		else
			dc = new DragContext(context);
		fireDragSourceEvent(this, dc, sd, id, time);
	}

	/****************************************
	 * Expose event handling.
	 ****************************************/
	/**
	 * Register an object to receive expose event
	 * notification.
	 *
	 * @param listener The object that has implemented the
	 * ExposeListener interface that is to receive the
	 * expose events.
	 */
	public void addListener(ExposeListener listener) {
		// Don't add the listener a second time if it is in the Vector.
		int i = findListener(exposeListeners, listener);
		if (i == -1) {
			if (null == exposeListeners) {
				evtMap.initialize(this, ExposeEvent.Type.EXPOSE);
				evtMap.initialize(this, ExposeEvent.Type.NO_EXPOSE);
				exposeListeners = new Vector();
			}
			exposeListeners.addElement(listener);
		}
	}

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

	protected boolean fireExposeEvent(ExposeEvent event) {
		if (null == exposeListeners)
			return false;
		boolean retval = false;
		int size = exposeListeners.size();
		int i = 0;
		while (i < size) {
			ExposeListener kl =
				(ExposeListener)exposeListeners.elementAt(i);
			if (kl.exposeEvent(event))
				retval = true;
			i++;
		}
		return retval;
	}

	protected boolean handleExpose(Handle event) {
		return fireExposeEvent(new ExposeEvent(this, new EventExpose(event)));
	}

	protected boolean handleNoExpose(Handle event) {
		return fireExposeEvent(new ExposeEvent(this, new EventNoExpose(event)));
	}

	/****************************************
	 * MouseMotion event handling.
	 ****************************************/
	/**
	 * Register an object to receive mouse motion event
	 * notification.
	 * <p>
	 * An important thing to notice is that some widgets don't 
	 * receive <i>low-level</i> events (such as a mouse-enter event) by default. 
	 * So if you want to capture events from them, you should add them to an 
	 * <code>EventBox</code>, and capture events on the <code>EventBox</code>. 
	 * <p>
	 * The reason why this happens is that some widgets, for efficiency, don't
	 * have their own X window, which is necessary to receive events. These are
	 * the widgets that don't have their own X window:
	 * <p>
	 * <code>Alignment</code> <br>
	 * <code>Arrow</code> <br>
	 * <code>Bin</code> <br>
	 * <code>Box</code> <br>
	 * <code>Image</code> <br>
	 * <code>Item</code> <br>
	 * <code>Label</code> <br>
	 * <code>Pixmap</code> <br>
	 * <code>ScrolledWindow</code> <br>
	 * <code>Separator</code> <br>
	 * <code>Table</code> <br>
	 * <code>AspectFrame</code> <br>
	 * <code>Frame</code> <br>
	 * <code>VBox</code> <br>
	 * <code>HBox</code> <br>
	 * <code>VSeparator</code> <br>
	 * <code>HSeparator</code> <br>
	 *
	 * @param listener The object that has implemented the
	 * MouseMotionListener interface that is to receive the
	 * mouse motion events.
	 */
	public void addListener(MouseMotionListener listener) {
		// Don't add the listener a second time if it is in the Vector.
		int i = findListener(mouseMotionListeners, listener);
		if (i == -1) {
			if (null == mouseMotionListeners) {
				evtMap.initialize(this, MouseMotionEvent.Type.MOTION);
				mouseMotionListeners = new Vector();
			}
			mouseMotionListeners.addElement(listener);
		}
	}

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

	protected boolean fireMouseMotionEvent(MouseMotionEvent event) {
		if (null == mouseMotionListeners)
			return false;
		boolean retval = false;
		int size = mouseMotionListeners.size();
		int i = 0;
		while (i < size) {
			MouseMotionListener kl =
				(MouseMotionListener)mouseMotionListeners.elementAt(i);
			if (kl.mouseMotionEvent(event))
				retval = true;
			i++;
		}
		return retval;
	}

	protected boolean handleMouseMotion(Handle event) {
		return fireMouseMotionEvent(new MouseMotionEvent(this, new EventMotion(event)));
	}

	native static final protected int gtk_widget_get_type();
	native static final protected Handle gtk_widget_ref(Handle widget);
	native static final protected void gtk_widget_unref(Handle widget);
	native static final protected void gtk_widget_destroy(Handle widget);
	native static final protected void gtk_widget_destroyed(Handle widget, Handle[] widgetPointer);
	native static final protected void gtk_widget_unparent(Handle widget);
	native static final protected void gtk_widget_show(Handle widget);
	native static final protected void gtk_widget_show_now(Handle widget);
	native static final protected void gtk_widget_hide(Handle widget);
	native static final protected void gtk_widget_show_all(Handle widget);
	native static final protected void gtk_widget_hide_all(Handle widget);
	native static final protected void gtk_widget_map(Handle widget);
	native static final protected void gtk_widget_unmap(Handle widget);
	native static final protected void gtk_widget_realize(Handle widget);
	native static final protected void gtk_widget_unrealize(Handle widget);
	native static final protected void gtk_widget_queue_draw(Handle widget);
	native static final protected void gtk_widget_queue_draw_area(Handle widget, int x, int y, int width, int height);
	native static final protected void gtk_widget_queue_resize(Handle widget);
	native static final protected void gtk_widget_size_request(Handle widget, Handle requisition);
	native static final protected void gtk_widget_get_child_requisition(Handle widget, Handle[] requisition);
	native static final protected void gtk_widget_size_allocate(Handle widget, Handle allocation);
	native static final protected void gtk_widget_add_accelerator(Handle widget, String accelSignal, Handle accelGroup, int accelKey, int accelMods, int accelFlags);
	native static final protected boolean gtk_widget_remove_accelerator(Handle widget, Handle accelGroup, int accelKey, int accelMods);
	native static final protected void gtk_widget_set_accel_path(Handle widget, String accelPath, Handle accelGroup);
	// TODO: this signature is wrong - needs to be fixed prior to using
	native static final protected int gtk_widget_list_accel_closures(Handle widget);
	native static final protected boolean gtk_widget_can_activate_accel(Handle widget, int signalId);
	native static final protected boolean gtk_widget_mnemonic_activate(Handle widget, boolean groupCycling);
	native static final protected boolean gtk_widget_event(Handle widget, Handle event);
	native static final protected int gtk_widget_send_expose(Handle widget, Handle event);
	native static final protected boolean gtk_widget_activate(Handle widget);
	native static final protected void gtk_widget_set_scroll_adjustments(Handle widget, Handle hadj, Handle vadj);
	native static final protected void gtk_widget_reparent(Handle widget, Handle newParent);
	native static final protected boolean gtk_widget_intersect(Handle widget, Handle area, Handle intersection);
	native static final protected int gtk_widget_region_intersect(Handle widget, Handle region);
	native static final protected void gtk_widget_freeze_child_notify(Handle widget);
	native static final protected void gtk_widget_child_notify(Handle widget, String childProperty);
	native static final protected void gtk_widget_thaw_child_notify(Handle widget);
	native static final protected boolean gtk_widget_is_focus(Handle widget);
	native static final protected void gtk_widget_grab_focus(Handle widget);
	native static final protected void gtk_widget_grab_default(Handle widget);
	native static final protected void gtk_widget_set_name(Handle widget, String name);
	native static final protected String gtk_widget_get_name(Handle widget);
	native static final protected void gtk_widget_set_state(Handle widget, int state);
	native static final protected void gtk_widget_set_sensitive(Handle widget, boolean sensitive);
	native static final protected void gtk_widget_set_app_paintable(Handle widget, boolean appPaintable);
	native static final protected void gtk_widget_set_double_buffered(Handle widget, boolean doubleBuffered);
	native static final protected void gtk_widget_set_redraw_on_allocate(Handle widget, boolean redrawOnAllocate);
	native static final protected void gtk_widget_set_parent(Handle widget, Handle parent);
	native static final protected void gtk_widget_set_parent_window(Handle widget, Handle parent);
	native static final protected void gtk_widget_set_child_visible(Handle widget, boolean isVisible);
	native static final protected boolean gtk_widget_get_child_visible(Handle widget);
	native static final protected Handle gtk_widget_get_parent(Handle widget);
	native static final protected Handle gtk_widget_get_parent_window(Handle widget);
	native static final protected Handle gtk_widget_get_window(Handle widget);
	native static final protected boolean gtk_widget_child_focus(Handle widget, int direction);
	native static final protected void gtk_widget_set_size_request(Handle widget, int width, int height);
	native static final protected void gtk_widget_get_size_request(Handle widget, int[] width, int[] height);
	native static final protected void gtk_widget_set_events(Handle widget, int events);
	native static final protected void gtk_widget_add_events(Handle widget, int events);
	native static final protected void gtk_widget_set_extension_events(Handle widget, int mode);
	native static final protected int gtk_widget_get_extension_events(Handle widget);
	native static final protected Handle gtk_widget_get_toplevel(Handle widget);
	native static final protected Handle gtk_widget_get_ancestor(Handle widget, int widgetType);
	native static final protected Handle gtk_widget_get_colormap(Handle widget);
	native static final protected Handle gtk_widget_get_visual(Handle widget);
	native static final protected Handle gtk_widget_get_screen(Handle widget);
	native static final protected boolean gtk_widget_has_screen(Handle widget); 
	native static final protected Handle gtk_widget_get_display(Handle widget);
	native static final protected Handle gtk_widget_get_root_window(Handle widget);
	native static final protected boolean gtk_widget_get_sensitive(Handle widget);
	native static final protected Handle gtk_widget_get_settings(Handle widget);
	native static final protected Handle gtk_widget_get_accessible(Handle widget);
	native static final protected void gtk_widget_set_colormap(Handle widget, Handle cmap);
	native static final protected int gtk_widget_get_events(Handle widget);
	native static final protected void gtk_widget_get_pointer(Handle widget, int[] x, int[] y);
	native static final protected boolean gtk_widget_is_ancestor(Handle widget, Handle ancestor);
	native static final protected boolean gtk_widget_translate_coordinates(Handle srcWidget, Handle destWidget, int srcX, int srcY, int[] destX, int[] destY);
	native static final protected boolean gtk_widget_hide_on_delete(Handle widget);
	native static final protected void gtk_widget_set_style(Handle widget, Handle style);
	native static final protected void gtk_widget_ensure_style(Handle widget);
	native static final protected Handle gtk_widget_get_style(Handle widget);
	native static final protected void gtk_widget_modify_style(Handle widget, Handle style);
	native static final protected Handle gtk_widget_get_modifier_style(Handle widget);
	native static final protected void gtk_widget_modify_fg(Handle widget, int state, Handle color);
	native static final protected void gtk_widget_modify_bg(Handle widget, int state, Handle color);
	native static final protected void gtk_widget_modify_text(Handle widget, int state, Handle color);
	native static final protected void gtk_widget_modify_base(Handle widget, int state, Handle color);
	native static final protected void gtk_widget_modify_font(Handle widget, Handle fontDesc);
	native static final protected Handle gtk_widget_create_pango_context(Handle widget);
	native static final protected Handle gtk_widget_get_pango_context(Handle widget);
	native static final protected Handle gtk_widget_create_pango_layout(Handle widget, String text);
	native static final protected Handle gtk_widget_render_icon(Handle widget, String stockID, int size, String detail);
	native static final protected void gtk_widget_set_composite_name(Handle widget, String name);
	native static final protected String gtk_widget_get_composite_name(Handle widget);
	native static final protected void gtk_widget_reset_rc_styles(Handle widget);
	native static final protected void gtk_widget_push_colormap(Handle cmap);
	native static final protected void gtk_widget_pop_colormap();
	native static final protected void gtk_widget_push_composite_child();
	native static final protected void gtk_widget_pop_composite_child();
	native static final protected void gtk_widget_style_get_property(Handle widget, String propertyName, Handle value);
	native static final protected void gtk_widget_set_default_colormap(Handle cmap);
	native static final protected Handle gtk_widget_get_default_colormap();
	native static final protected Handle gtk_widget_get_default_visual();
	native static final protected Handle gtk_widget_get_default_style();
	native static final protected void gtk_widget_set_direction(Handle widget, int dir);
	native static final protected int gtk_widget_get_direction(Handle widget);
	native static final protected void gtk_widget_set_default_direction(int dir);
	native static final protected int gtk_widget_get_default_direction();
	native static final protected void gtk_widget_shape_combine_mask(Handle widget, Handle shapeMask, int offsetX, int offsetY); 
	native static final protected void gtk_widget_path(Handle widget, int[] pathLength, String[] path, String[] pathReversed); 
	native static final protected void gtk_widget_class_path(Handle widget, int[] pathLength, String[] path, String[] pathReversed);
	native static final protected Handle[] gtk_widget_list_mnemonic_labels(Handle widget);
	native static final protected void gtk_widget_add_mnemonic_label(Handle widget, Handle label);
	native static final protected void gtk_widget_remove_mnemonic_label(Handle widget, Handle label);
	// Drag and Drop support
	native static final protected void gtk_drag_source_set(Handle widget, int start_button_mask, Handle[] targets, int actions);
	native static final protected void gtk_drag_source_unset(Handle widget);
	native static final protected void gtk_drag_source_set_icon(Handle widget, Handle colormap, Handle pixmap, Handle mask);
	native static final protected void gtk_drag_source_set_icon_pixbuf(Handle widget, Handle pixbuf);
	native static final protected void gtk_drag_source_set_icon_stock(Handle widget, String stockId);
	native static final protected void gtk_drag_get_data(Handle widget, Handle context, int target);
	native static final protected void gtk_drag_finish(Handle context, boolean success, boolean delete);
	native static final protected void gtk_drag_highlight(Handle widget);
	native static final protected void gtk_drag_unhighlight(Handle widget);
	native static final protected void gtk_drag_dest_set(Handle widget, int flags, Handle[] targets, int actions);
	native static final protected void gtk_drag_dest_unset(Handle widget);
}
