/* GtkWindowPeer.java -- Implements WindowPeer with GTK
   Copyright (C) 1998, 1999, 2002, 2005, 2006  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package gnu.java.awt.peer.gtk;

import java.awt.Component;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.KeyboardFocusManager;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.ComponentEvent;
import java.awt.event.FocusEvent;
import java.awt.event.PaintEvent;
import java.awt.event.WindowEvent;
import java.awt.peer.WindowPeer;

public class GtkWindowPeer extends GtkContainerPeer
  implements WindowPeer
{
  protected static final int GDK_WINDOW_TYPE_HINT_NORMAL = 0;
  protected static final int GDK_WINDOW_TYPE_HINT_DIALOG = 1;
  protected static final int GDK_WINDOW_TYPE_HINT_MENU = 2;
  protected static final int GDK_WINDOW_TYPE_HINT_TOOLBAR = 3;
  protected static final int GDK_WINDOW_TYPE_HINT_SPLASHSCREEN = 4;
  protected static final int GDK_WINDOW_TYPE_HINT_UTILITY = 5;
  protected static final int GDK_WINDOW_TYPE_HINT_DOCK = 6;
  protected static final int GDK_WINDOW_TYPE_HINT_DESKTOP = 7;

  private boolean hasBeenShown = false;
  private int oldState = Frame.NORMAL;

  // Cached awt window component location, width and height.
  private int x, y, width, height;

  native void gtkWindowSetTitle (String title);
  native void gtkWindowSetResizable (boolean resizable);
  native void gtkWindowSetModal (boolean modal);
  native void gtkWindowSetAlwaysOnTop ( boolean alwaysOnTop );
  native boolean gtkWindowHasFocus();
  native void realize ();

  /** Returns the cached width of the AWT window component. */
  int getX ()
  {
    return x;
  }

  /** Returns the cached width of the AWT window component. */
  int getY ()
  {
    return y;
  }

  /** Returns the cached width of the AWT window component. */
  int getWidth ()
  {
    return width;
  }

  /** Returns the cached height of the AWT window component. */
  int getHeight ()
  {
    return height;
  }

  native void create (int type, boolean decorated, GtkWindowPeer parent);

  void create (int type, boolean decorated)
  {
    Window window = (Window) awtComponent;
    GtkWindowPeer parent_peer = null;
    Component parent = awtComponent.getParent();
    x = awtComponent.getX();
    y = awtComponent.getY();
    height = awtComponent.getHeight();
    width = awtComponent.getWidth();
    
    if (!window.isFocusableWindow())
      type = GDK_WINDOW_TYPE_HINT_MENU;
    
    if (parent != null)
      parent_peer = (GtkWindowPeer) awtComponent.getParent().getPeer();
    
    create (type, decorated, parent_peer);
  }

  void create ()
  {
    // Create a normal undecorated window.
    create (GDK_WINDOW_TYPE_HINT_NORMAL, false);
  }

  void setParent ()
  {
    setVisible (awtComponent.isVisible ());
    setEnabled (awtComponent.isEnabled ());
  }

  void setVisibleAndEnabled ()
  {
  }

  public native void setVisibleNative (boolean b);
  public native void setVisibleNativeUnlocked (boolean b);

  native void connectSignals ();

  public GtkWindowPeer (Window window)
  {
    super (window);
  }

  public native void toBack();
  public native void toFront();

  native void nativeSetBounds (int x, int y, int width, int height);
  native void nativeSetBoundsUnlocked (int x, int y, int width, int height);
  native void nativeSetLocation (int x, int y);
  native void nativeSetLocationUnlocked (int x, int y);

  // Called from show.
  protected void setLocation (int x, int y)
  {
    nativeSetLocation (x, y);
  }

  public void setBounds (int x, int y, int width, int height)
  {
    if (x != getX()
	|| y != getY()
	|| width != getWidth()
	|| height != getHeight())
      {
	this.x = x;
	this.y = y;
	this.width = width;
	this.height = height;
	
	nativeSetBounds (x, y,
			 width - insets.left - insets.right,
			 height - insets.top - insets.bottom);
      }
  }

  public void setTitle (String title)
  {
    gtkWindowSetTitle (title);
  }

  // Called from setResizable
  protected native void setSize (int width, int height);
  
  /**
   * Needed by both GtkFramePeer and GtkDialogPeer subclasses, so
   * implemented here. But never actually called on a GtkWindowPeer
   * itself.
   */
  public void setResizable (boolean resizable)
  {
    // Call setSize; otherwise when resizable is changed from true to
    // false the window will shrink to the dimensions it had before it
    // was resizable.
    x = awtComponent.getX();
    y = awtComponent.getY();
    width = awtComponent.getWidth();
    height = awtComponent.getHeight();
    setSize (width - insets.left - insets.right,
	     height - insets.top - insets.bottom);
    gtkWindowSetResizable (resizable);
  }

  protected void postInsetsChangedEvent (int top, int left,
					 int bottom, int right)
  {
    insets.top = top;
    insets.left = left;
    insets.bottom = bottom;
    insets.right = right;
  }

  // called back by native side: window_configure_cb
  // only called from GTK thread
  protected void postConfigureEvent (int x, int y, int width, int height)
  {
    int frame_width = width + insets.left + insets.right;
    int frame_height = height + insets.top + insets.bottom;

    if (frame_width != getWidth()
	|| frame_height != getHeight())
      {
	this.width = frame_width;
	this.height = frame_height;
	q().postEvent(new ComponentEvent(awtComponent,
					 ComponentEvent.COMPONENT_RESIZED));
      }

    int frame_x = x - insets.left;
    int frame_y = y - insets.top;

    if (frame_x != getX()
	|| frame_y != getY())
      {
	this.x = frame_x;
	this.y = frame_y;
	q().postEvent(new ComponentEvent(awtComponent,
					 ComponentEvent.COMPONENT_MOVED));
      }
  }

  public void show ()
  {
    x = awtComponent.getX();
    y = awtComponent.getY();
    width = awtComponent.getWidth();
    height = awtComponent.getHeight();
    setLocation(x, y);
    setVisible (true);
  }

  void postWindowEvent (int id, Window opposite, int newState)
  {
    if (id == WindowEvent.WINDOW_OPENED)
      {
	// Post a WINDOW_OPENED event the first time this window is shown.
	if (!hasBeenShown)
	  {
	    q().postEvent (new WindowEvent ((Window) awtComponent, id,
					  opposite));
	    hasBeenShown = true;
	  }
      }
    else if (id == WindowEvent.WINDOW_STATE_CHANGED)
      {
	if (oldState != newState)
	  {
	    q().postEvent (new WindowEvent ((Window) awtComponent, id, opposite,
					  oldState, newState));
	    oldState = newState;
	  }
      }
    else
      q().postEvent (new WindowEvent ((Window) awtComponent, id, opposite));
  }

  /**
   * Update the always-on-top status of the native window.
   */
  public void updateAlwaysOnTop()
  {
    gtkWindowSetAlwaysOnTop( ((Window)awtComponent).isAlwaysOnTop() );
  }

  protected void postExposeEvent (int x, int y, int width, int height)
  {
    // Translate GTK co-ordinates, which do not include a window
    // frame's insets, to AWT co-ordinates, which do include a window
    // frame's insets.  GtkWindowPeer should always have all-zero
    // insets but GtkFramePeer and GtkDialogPeer insets will be
    // non-zero.
    q().postEvent (new PaintEvent (awtComponent, PaintEvent.PAINT,
                                   new Rectangle (x + insets.left, 
                                                  y + insets.top, 
                                                  width, height)));
  }

  public boolean requestWindowFocus()
  {
    // TODO Auto-generated method stub
    return false;
  }

  public boolean requestFocus (Component request, boolean temporary, 
                               boolean allowWindowFocus, long time)
  {
    assert request == awtComponent || isLightweightDescendant(request);
    boolean retval = false;
    if (gtkWindowHasFocus())
      {
        KeyboardFocusManager kfm =
          KeyboardFocusManager.getCurrentKeyboardFocusManager();
        Component currentFocus = kfm.getFocusOwner();
        if (currentFocus == request)
          // Nothing to do in this trivial case.
          retval = true;
        else
          {
            // Requested component is a lightweight descendant of this one
            // or the actual heavyweight.
            // Since this (native) component is already focused, we simply
            // change the actual focus and be done.
            postFocusEvent(FocusEvent.FOCUS_GAINED, temporary);
            retval = true;
          }
      }
    else
      {
        if (allowWindowFocus)
          {
            retval = requestWindowFocus();
          }
      }
    return retval;
  }

  public Graphics getGraphics ()
  {
    Graphics g = super.getGraphics ();
    // Translate AWT co-ordinates, which include a window frame's
    // insets, to GTK co-ordinates, which do not include a window
    // frame's insets.  GtkWindowPeer should always have all-zero
    // insets but GtkFramePeer and GtkDialogPeer insets will be
    // non-zero.
    g.translate (-insets.left, -insets.top);
    return g;
  }

  protected void updateComponent (PaintEvent event)
  {
    // Do not clear anything before painting.  Sun never calls
    // Window.update, only Window.paint.
    paintComponent(event);
  }

  protected void postMouseEvent(int id, long when, int mods, int x, int y, 
				int clickCount, boolean popupTrigger)
  {
    // Translate AWT co-ordinates, which include a window frame's
    // insets, to GTK co-ordinates, which do not include a window
    // frame's insets.  GtkWindowPeer should always have all-zero
    // insets but GtkFramePeer and GtkDialogPeer insets will be
    // non-zero.
    super.postMouseEvent (id, when, mods, 
			  x + insets.left, y + insets.top, 
			  clickCount, popupTrigger);
  }

  // We override this to keep it in sync with our internal
  // representation.
  public Rectangle getBounds()
  {
    return new Rectangle(x, y, width, height);
  }
}
