/*
 * 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 org.gnu.gdk.Geometry;
import org.gnu.gdk.Gravity;
import org.gnu.gdk.Pixbuf;
import org.gnu.gdk.Point;
import org.gnu.gdk.Screen;
import org.gnu.gdk.WindowHints;
import org.gnu.glib.GObject;
import org.gnu.glib.Type;

/**
 * A Window is a window that can be displayed on the screen. It also
 * is a container that can hold a single child widget. It is common to
 * have the window in Window supply the margin around the window of
 * the contained widget.
 */
public class Window extends Bin {

	/**
	 * Construct a new Window object.
	 * 
	 * @param type The type of window to create
	 */
	public Window(WindowType windowType) {
		super(Window.gtk_window_new(windowType.getValue()));
	}

	/**
	 * Create a new Window 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 Window(int handle) {
	    super(handle);
	}
	
	/**
	 * Set the title for this Window object
	 * 
	 * @param title A string containing the title for this Window
	 */
	public void setTitle(String title) {
		Window.gtk_window_set_title(getHandle(), title);
	}

	/**
	 * Returns the title for the Window object
	 * 
	 * @return A string containing the title.
	 */
	public String getTitle() {
		return Window.gtk_window_get_title(getHandle());
	}

	/**
	 * Sets whether the user can resize the window.  Windows are user
	 * resizable by default.
	 * 
	 * @param resizable Determines if the window can be resized.
	 */
	public void setResizable(boolean resizable) {
		Window.gtk_window_set_resizable(getHandle(), resizable);
	}
	
	/**
	 * Associate <code>accesGroup</code> with the window.
	 * 
	 * @param accelGroup	The AccelGroup to associate with this window.
	 */
	public void addAccelGroup(AccelGroup accelGroup) {
		Window.gtk_window_add_accel_group(getHandle(), accelGroup.getHandle());
	}
	
	/**
	 * Reverses the effect of <code>addAccelGroup</code>.
	 * 
	 * @param accelGroup The AccelGroup to disassociate with this window.
	 */
	public void removeAccelGroup(AccelGroup accelGroup) {
		Window.gtk_window_remove_accel_group(getHandle(), accelGroup.getHandle());
	}
	
	/**
	 * Sets a window modal or non-modal. 
	 * 
	 * @param modal Indicates whether the window should be modal or not.
	 */
	public void setModal(boolean modal) {
		Window.gtk_window_set_modal(getHandle(), modal);
	}

	/**
	 * Sets the default size for a Window.  If a Window's natural size is larger
	 * than the default, the default will be ignored.  
	 * 
	 * @param width The width to set for the default size.
	 * @param height the height to set for the default size.
	 */
	public void setDefaultSize(int width, int height) {
		Window.gtk_window_set_default_size(getHandle(), width, height);
	}
	
	/**
	 * This method sets up hints about how a Window can be resized
	 * by the user.  You can set a minimum and maximum size, allowable
	 * resize increments, aspect ratios and more.
	 * 
	 * @param geometryWidget The Widget the geometry hints will be applied to.
	 * @param geometry The geometry information.
	 * @param geomMask Mask indicating which fields should be paid attention to.
	 */
	public void setGeometryHints(Widget geometryWidget, Geometry geometry, WindowHints geomMask) {
		Window.gtk_window_set_geometry_hints(getHandle(), geometryWidget.getHandle(), geometry.getHandle(), geomMask.getValue());
	}
	
	/**
	 * Window gravity defines the meaning of coordinates passed to <code>move()</code>.
	 * 
	 * @param gravity The window gravity.
	 */
	public void setGravity(	Gravity gravity) {
		Window.gtk_window_set_gravity(getHandle(), gravity.getValue());
	}	
	
	/**
	 * Gets the value set by <code>setGravity()</code>.
	 * 
	 * @return The Gravity for the Window.
	 */
	public Gravity getGravity() {
		int val = Window.gtk_window_get_gravity(getHandle());
		return Gravity.intern(val);
	}	
	
	/**
	 * Sets a position constraint for this window. If the old or new constraint
	 * is {@link WindowPosition#CENTER_ALWAYS}, this will also cause the window
	 * to be repositioned to satisfy the new constraint.
	 * 
	 * @param position A position constraint.
	 */
	public void setPosition(WindowPosition position) {
		Window.gtk_window_set_position(getHandle(), position.getValue());
	}
	
	/**
	 * Retrieves the current focused Widget within the window.
	 * 
	 * @return The Widget that has focus.
	 */
	public Widget getFocusWidget() {
		int hndl = gtk_window_get_focus(getHandle());
		if (0 == hndl)
			return null;
		GObject obj = retrieveGObject(hndl);
		if (null != obj)
			return (Widget)obj;
		return new Widget(hndl);
	}
	
	/**
	 * If <code>focus</code> is not the current focus widget and is focusable, set it as the
	 * focus widget for the window.
	 * 
	 * @param focus The widget to receive focus for the Window.
	 */
	public void setFocusWidget(Widget focus) {
		Window.gtk_window_set_focus(getHandle(), focus.getHandle());
	}
	
	/**
	 * The default widget is the widget that is activated when the user presses the
	 * Enter key.  This method will set defaultWidget to the default widget for the
	 * Window.
	 * 
	 * @param defaultWidget The widget that should become the default widget.
	 */
	public void setDefaultWidget(Widget defaultWidget) {
		Window.gtk_window_set_default(getHandle(), defaultWidget.getHandle());
	}	

	/**
	 * Presents a window to the user.  This may mean raising the window in the
	 * stack order, deiconifying it, moving it to the current desktop, and/or giving
	 * it the keyboard focus, possibly dependent on the user's platform, window
	 * manager, and preferences.  If the Window is hidden it will also call <code>
	 * show</code> as well.
	 */
	public void present() {
		Window.gtk_window_present(getHandle());
	}
	
	/**
	 * Asks to iconify the Window.  Note that you shouldn't assume the Window is
	 * iconified afterward because other entities could deiconify it again or there may
	 * not be a window manager in which case iconification is not possible. 
	 */
	public void iconify() {
		Window.gtk_window_iconify(getHandle());
	}
	
	/**
	 * Asks to deiconify the specified Window. 
	 */
	public void deiconify() {
		Window.gtk_window_deiconify(getHandle());
	}
	
	/**
	 * Asks to stick the window.  This means that the window appear on all
	 * user desktops.  Note that you shouldn't assume that the Window is 
	 * definately stuck after calling this method.  Other entities could unstick
	 * the Window or the window manager may not support this feature.
	 */
	public void stick() {
		Window.gtk_window_stick(getHandle());
	}
	
	/**
	 * Asks to unstick the window.
	 */
	public void unstick() {
		Window.gtk_window_unstick(getHandle());
	}
	
	/**
	 * Asks to maximize the Window so it becomes full-screen.
	 */
	public void maximize() {
		Window.gtk_window_maximize(getHandle());
	}
	
	/**
	 * Asks to unmaximize the Window so it becomes it normal size.
	 */
	public void unmaximize() {
		Window.gtk_window_unmaximize(getHandle());
	}
	
	/**
	 * By default Windows are decorated by a titlebar, resize controls, etc.  Some
	 * window managers allow you to disable these decorations, creating a borderless
	 * Window.  This method allows you to change teh decorated setting for the Window.
	 * 
	 * @param setting Determines if the Window should be decorated.
	 */
	public void setDecorated(boolean setting) {
		Window.gtk_window_set_decorated(getHandle(), setting);
	}
	
	/**
	 * Returns the current size of a Window.  If the window is not onscreen, it
	 * returns the size that will be suggested to the window manager for the
	 * initial window size.
	 * 
	 * @return The size of the Window.
	 */
	public Requisition getSize() {
		int [] width = new int[1];
		int [] height = new int[1];
		Window.gtk_window_get_size(getHandle(), width, height);
		return new Requisition(width[0], height[0]);
	}
	
	/**
	 * Retuns the current position of the window.
	 * 
	 * @return The position of the window.
	 */
	public Point getPosition() {
		int [] x = new int[1];
		int [] y = new int[1];
		Window.gtk_window_get_position(getHandle(), x, y);
		return new Point(x[0], y[0]);
	}
	
	/**
	 * Ask the window manager to move the Window to a given location.  Window
	 * managers are free to ignore this request.  Most window managers ignore the
	 * request for the initial window position but honor the request after the window
	 * has been shown.
	 * 
	 * @param x The x coordinate for the move.
	 * @param y The y coordinate for the move.
	 */
	public void move(int x, int y) {
		Window.gtk_window_move(getHandle(), x, y);
	}
	
	/**
	 * Resizes the Window as if the user had done so, obeying the geometry
	 * constraints. 
	 * 
	 * @param width The width for the resized Window.
	 * @param height The height for the resized Window.
	 */
	public void resize(int width, int height) {
		Window.gtk_window_resize(getHandle(), width, height);
	}
	
	/**
	 * Sets up the icon representing a Window.  The icon is used when
	 * the Window is minimized.
	 * 
	 * @param icon The Icon to use for this Window.
	 */
	public void setIcon(Pixbuf icon) {
		Window.gtk_window_set_icon(getHandle(), icon.getHandle());
	}

	/**
	 * Set to true to keep this window from appearing in the task bar.
	 * @param skipHint
	 */
	public void setSkipTaskbarHint(boolean skipHint) {
		gtk_window_set_skip_taskbar_hint(getHandle(), skipHint);
	}
	
	/**
	 * Returns whether this window should appear in the task bar.
	 * @return
	 */
	public boolean getSkipTaskbarHint() {
		return gtk_window_get_skip_taskbar_hint(getHandle());
	}
	
	/**
	 * Set to true to keep the window from appearing in the pager.
	 * @param skipHint
	 */
	public void setSkipPagerHint(boolean skipHint) {
		gtk_window_set_skip_pager_hint(getHandle(), skipHint);
	}

	/**
	 * Returns whether the window should appear in the pager.
	 * @return
	 */
	public boolean getSkipPagerHint() {
		return gtk_window_get_skip_pager_hint(getHandle());
	}
	
	public void setAcceptFocus(boolean acceptFocus) {
		gtk_window_set_accept_focus(getHandle(), acceptFocus);
	}
	
	public boolean getAcceptFocus() {
		return gtk_window_get_accept_focus(getHandle());
	}

	public void setScreen(Screen screen) {
		gtk_window_set_screen(getHandle(), screen.getHandle());
	}

	public Screen getScreen() {
		int hndl = gtk_window_get_screen(getHandle());
		GObject obj = retrieveGObject(hndl);
		if (null != obj)
			return (Screen)obj;
		return new Screen(hndl);
	}

	public boolean isActive() {
		return gtk_window_is_active(getHandle());
	}
	
	public boolean hasToplevelFocus() {
		return gtk_window_has_toplevel_focus(getHandle());
	}

	public boolean setIconFromFile(String filename) {
		return gtk_window_set_icon_from_file(getHandle(), filename, new int[] {});
	}
	
	public static boolean setDefaultIconFromFile(String filename) {
		return gtk_window_set_default_icon_from_file(filename, new int[] {});
	}
	
	public static void setDefaultIcon(Pixbuf icon) {
		gtk_window_set_default_icon(icon.getHandle());
	}
	
	public static void setAutoStartupNotification(boolean setting) {
		gtk_window_set_auto_startup_notification(setting);
	}
	
	public void fullscreen() {
		gtk_window_fullscreen(getHandle());
	}
	
	public void unfullscreen() {
		gtk_window_unfullscreen(getHandle());
	}
	
	public void setKeepAbove(boolean setting) {
		gtk_window_set_keep_above(getHandle(), setting);
	}
	
	public void setKeepBelow(boolean setting) {
		gtk_window_set_keep_below(getHandle(), setting);
	}
	
	public static void setDefaultIconList(Pixbuf[] icons) {
		if (null == icons)
			return;
		int[] hndls = new int[icons.length];
		for (int i = 0; i < icons.length; i++) {
			hndls[i] = icons[i].getHandle();
		}
		gtk_window_set_default_icon_list(hndls);
	}
	
	public static Pixbuf[] getDefaultIconList() {
		int[] hndls = gtk_window_get_default_icon_list();
		Pixbuf[] pbs = new Pixbuf[hndls.length];
		for (int i = 0; i < hndls.length; i++) {
			pbs[i] = new Pixbuf(hndls[i]);
		}
		return pbs;
	}
	
	public static Window[] listToplevelWindows() {
		int[] hndls = gtk_window_list_toplevels();
		Window[] wins = new Window[hndls.length];
		for (int i = 0; i < hndls.length; i++) {
			wins[i] = new Window(hndls[i]);
		}
		return wins;
	}
	
	/**
	 * Retrieve the runtime type used by the GLib library.
	 */
	public static Type getType() {
		return new Type(gtk_window_get_type());
	}

	/****************************************
	 * BEGINNING OF JNI CODE
	 ****************************************/
	native static final protected int gtk_window_get_type();
	native static final protected int gtk_window_new(int type);
	native static final protected void gtk_window_set_title(int window, String title);
	native static final protected String gtk_window_get_title(int window);
	native static final protected void gtk_window_set_wmclass(int window, String  wmclassName, String wmclassClass);
	native static final protected void gtk_window_set_role(int window, String role);
	native static final protected String gtk_window_get_role(int window);
	native static final protected void gtk_window_add_accel_group(int window, int accelGroup);
	native static final protected void gtk_window_remove_accel_group(int window, int accelGroup);
	native static final protected void gtk_window_set_position(int window, int position);
	native static final protected int gtk_window_activate_focus(int window);
	native static final protected void gtk_window_set_focus(int window, int focus);
	native static final protected int gtk_window_get_focus(int window);
	native static final protected void gtk_window_set_default(int window, int defaultWidget);
	native static final protected boolean gtk_window_activate_default(int window);
	native static final protected void gtk_window_set_transient_for(int window, int parent);
	native static final protected int gtk_window_get_transient_for(int window);
	native static final protected void gtk_window_set_type_hint(int window, int hint);
	native static final protected int gtk_window_get_type_hint(int window);
	native static final protected void gtk_window_set_skip_taskbar_hint(int window, boolean skip);
	native static final protected boolean gtk_window_get_skip_taskbar_hint(int window);
	native static final protected void gtk_window_set_skip_pager_hint(int window, boolean skip);
	native static final protected boolean gtk_window_get_skip_pager_hint(int window);
	native static final protected void gtk_window_set_accept_focus(int window, boolean setting);
	native static final protected boolean gtk_window_get_accept_focus(int window);
	native static final protected void gtk_window_set_destroy_with_parent(int window, boolean setting);
	native static final protected boolean gtk_window_get_destroy_with_parent(int window);
	native static final protected void gtk_window_set_resizable(int window, boolean resizable);
	native static final protected boolean gtk_window_get_resizable(int window);
	native static final protected void gtk_window_set_gravity(int window, int gravity);
	native static final protected int gtk_window_get_gravity(int window);
	native static final protected void gtk_window_set_geometry_hints(int window, int geometryWidget, int geometry, int geomMask);
	native static final protected void gtk_window_set_screen(int window, int screen);
	native static final protected int gtk_window_get_screen(int window);
	native static final protected boolean gtk_window_is_active(int window);
	native static final protected boolean gtk_window_has_toplevel_focus(int window);
	native static final protected void gtk_window_set_has_frame(int window, boolean setting);
	native static final protected boolean gtk_window_get_has_frame(int window);
	native static final protected void gtk_window_set_frame_dimensions(int window, int left, int top, int right, int bottom);
	native static final protected void gtk_window_get_frame_dimensions(int window, int[] left, int[] top, int[] right, int[] bottom);
	native static final protected void gtk_window_set_decorated(int window, boolean setting);
	native static final protected boolean gtk_window_get_decorated(int window);
	native static final protected void gtk_window_set_icon_list(int window, int list);
	native static final protected int gtk_window_get_icon_list(int window);
	native static final protected void gtk_window_set_icon(int window, int icon);
	native static final protected int gtk_window_get_icon(int window);
	native static final protected boolean gtk_window_set_icon_from_file(int window, String filename, int[] error);
	native static final protected void gtk_window_set_default_icon_list(int[] list);
	native static final protected int[] gtk_window_get_default_icon_list();
	native static final protected boolean gtk_window_set_default_icon_from_file(String filename, int[] error);
	native static final protected void gtk_window_set_default_icon(int icon);
	native static final protected void gtk_window_set_auto_startup_notification(boolean setting);
	native static final protected void gtk_window_set_modal(int window, boolean modal);
	native static final protected boolean gtk_window_get_modal(int window);
	native static final protected int[] gtk_window_list_toplevels();
	native static final protected void gtk_window_add_mnemonic(int window, int keyval, int target);
	native static final protected void gtk_window_remove_mnemonic(int window, int keyval, int target);
	native static final protected boolean gtk_window_mnemonic_activate(int window, int keyval, int modifier);
	native static final protected void gtk_window_set_mnemonic_modifier(int window, int modifier);
	native static final protected int gtk_window_get_mnemonic_modifier(int window);
	native static final protected void gtk_window_present(int window);
	native static final protected void gtk_window_iconify(int window);
	native static final protected void gtk_window_deiconify(int window);
	native static final protected void gtk_window_stick(int window);
	native static final protected void gtk_window_unstick(int window);
	native static final protected void gtk_window_maximize(int window);
	native static final protected void gtk_window_unmaximize(int window);
	native static final protected void gtk_window_fullscreen(int window);
	native static final protected void gtk_window_unfullscreen(int window);
	native static final protected void gtk_window_set_keep_above(int window, boolean setting);
	native static final protected void gtk_window_set_keep_below(int window, boolean setting);
	native static final protected void gtk_window_begin_resize_drag(int window, int edge, int button, int rootX, int rootY, int timestamp);
	native static final protected void gtk_window_begin_move_drag(int window, int button, int rootX, int rootY, int timestamp);
	native static final protected void gtk_window_set_default_size(int window, int width, int height);
	native static final protected void gtk_window_get_default_size(int window, int[] width, int[] height);
	native static final protected void gtk_window_resize(int window, int width, int height);
	native static final protected void gtk_window_get_size(int window, int[] width, int[] height);
	native static final protected void gtk_window_move(int window, int x, int y);
	native static final protected void gtk_window_get_position(int window, int[] rootX, int[] rootY);
	native static final protected boolean gtk_window_parse_geometry(int window, String geometry);
	/****************************************
	 * END OF JNI CODE
	 ****************************************/
}
