/* GtkComponentPeer.java -- Implements ComponentPeer with GTK
   Copyright (C) 1998, 1999, 2002, 2004, 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.AWTEvent;
import java.awt.AWTException;
import java.awt.BufferCapabilities;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Insets;
import java.awt.ItemSelectable;
import java.awt.KeyboardFocusManager;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.FocusEvent;
import java.awt.event.ItemEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.PaintEvent;
import java.awt.event.TextEvent;
import java.awt.image.ColorModel;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.awt.image.VolatileImage;
import java.awt.peer.ComponentPeer;
import java.awt.peer.ContainerPeer;
import java.awt.peer.LightweightPeer;
import java.awt.peer.WindowPeer;
import java.util.Timer;
import java.util.TimerTask;

public class GtkComponentPeer extends GtkGenericPeer
  implements ComponentPeer
{
  VolatileImage backBuffer;
  BufferCapabilities caps;

  Component awtComponent;

  Insets insets;

  /* this isEnabled differs from Component.isEnabled, in that it
     knows if a parent is disabled.  In that case Component.isEnabled 
     may return true, but our isEnabled will always return false */
  native boolean isEnabled ();
  static native boolean modalHasGrab();

  native int[] gtkWidgetGetForeground ();
  native int[] gtkWidgetGetBackground ();
  native void gtkWidgetGetDimensions (int[] dim);
  native void gtkWidgetGetPreferredDimensions (int[] dim);
  native void gtkWindowGetLocationOnScreen (int[] point);
  native void gtkWidgetGetLocationOnScreen (int[] point);
  native void gtkWidgetSetCursor (int type, GtkImage image, int x, int y);
  native void gtkWidgetSetCursorUnlocked (int type, GtkImage image,
					  int x, int y);
  native void gtkWidgetSetBackground (int red, int green, int blue);
  native void gtkWidgetSetForeground (int red, int green, int blue);
  native void gtkWidgetSetSensitive (boolean sensitive);
  native void gtkWidgetSetParent (ComponentPeer parent);
  native void gtkWidgetRequestFocus ();
  native void gtkWidgetDispatchKeyEvent (int id, long when, int mods,
                                         int keyCode, int keyLocation);
  native boolean gtkWidgetHasFocus();
  native boolean gtkWidgetCanFocus();

  native void realize();
  native void setNativeEventMask ();

  void create ()
  {
    throw new RuntimeException ();
  }

  native void connectSignals ();

  protected GtkComponentPeer (Component awtComponent)
  {
    super (awtComponent);
    this.awtComponent = awtComponent;
    insets = new Insets (0, 0, 0, 0);

    create ();

    connectSignals ();

    if (awtComponent.getForeground () != null)
      setForeground (awtComponent.getForeground ());
    if (awtComponent.getBackground () != null)
      setBackground (awtComponent.getBackground ());
    if (awtComponent.getFont() != null)
      setFont(awtComponent.getFont());

    Component parent = awtComponent.getParent ();

    setParentAndBounds ();

    setNativeEventMask ();

    // This peer is guaranteed to have an X window upon construction.
    // That is, native methods such as those in GdkGraphics can rely
    // on this component's widget->window field being non-null.
    realize ();

    if (awtComponent.isCursorSet())
      setCursor ();
  }

  void setParentAndBounds ()
  {
    setParent ();

    setComponentBounds ();

    setVisibleAndEnabled ();
  }

  void setParent ()
  {
    ComponentPeer p;
    Component component = awtComponent;
    do
      {
        component = component.getParent ();
        p = component.getPeer ();
      }
    while (p instanceof java.awt.peer.LightweightPeer);

    if (p != null)
      gtkWidgetSetParent (p);
  }

  /*
   * Set the bounds of this peer's AWT Component based on dimensions
   * returned by the native windowing system.  Most Components impose
   * their dimensions on the peers which is what the default
   * implementation does.  However some peers, like GtkFileDialogPeer,
   * need to pass their size back to the AWT Component.
   */
  void setComponentBounds ()
  {
    Rectangle bounds = awtComponent.getBounds ();
    setBounds (bounds.x, bounds.y, bounds.width, bounds.height);
  }

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

  public int checkImage (Image image, int width, int height, 
			 ImageObserver observer) 
  {
    return getToolkit().checkImage(image, width, height, observer);
  }

  public Image createImage (ImageProducer producer) 
  {
    return new GtkImage (producer);
  }

  public Image createImage (int width, int height)
  {
    return CairoSurface.getBufferedImage(width, height);
  }

  public void disable () 
  {
    setEnabled (false);
  }

  public void enable () 
  {
    setEnabled (true);
  }

  public ColorModel getColorModel () 
  {
    return ColorModel.getRGBdefault ();
  }

  public FontMetrics getFontMetrics (Font font)
  {
    return getToolkit().getFontMetrics(font);
  }

  // getGraphics may be overridden by derived classes but it should
  // never return null.
  public Graphics getGraphics ()
  {
    return ComponentGraphics.getComponentGraphics(this);
  }

  public Point getLocationOnScreen () 
  { 
    int point[] = new int[2];
    if( this instanceof WindowPeer )
      gtkWindowGetLocationOnScreen (point);
    else
      gtkWidgetGetLocationOnScreen (point);
    return new Point (point[0], point[1]);
  }

  public Dimension getMinimumSize () 
  {
    return minimumSize ();
  }

  public Dimension getPreferredSize ()
  {
    return preferredSize ();
  }

  public Toolkit getToolkit ()
  {
    return Toolkit.getDefaultToolkit();
  }
  
  public void handleEvent (AWTEvent event)
  {
    int id = event.getID();
    KeyEvent ke = null;

    switch (id)
      {
      case PaintEvent.PAINT:
        paintComponent((PaintEvent) event);
        break;
      case PaintEvent.UPDATE:
        updateComponent((PaintEvent) event);
        break;
      case KeyEvent.KEY_PRESSED:
        ke = (KeyEvent) event;
        gtkWidgetDispatchKeyEvent (ke.getID (), ke.getWhen (), ke.getModifiersEx (),
                                   ke.getKeyCode (), ke.getKeyLocation ());
        break;
      case KeyEvent.KEY_RELEASED:
        ke = (KeyEvent) event;
        gtkWidgetDispatchKeyEvent (ke.getID (), ke.getWhen (), ke.getModifiersEx (),
                                   ke.getKeyCode (), ke.getKeyLocation ());
        break;
      }
  }

  // This method and its overrides are the only methods in the peers
  // that should call awtComponent.paint.
  protected void paintComponent (PaintEvent event)
  {
    // Do not call Component.paint if the component is not showing or
    // if its bounds form a degenerate rectangle.
    if (!awtComponent.isShowing()
        || (awtComponent.getWidth() < 1 || awtComponent.getHeight() < 1))
      return;

    // Creating and disposing a GdkGraphics every time paint is called
    // seems expensive.  However, the graphics state does not carry
    // over between calls to paint, and resetting the graphics object
    // may even be more costly than simply creating a new one.
    Graphics g = getGraphics();

    g.setClip(event.getUpdateRect());

    awtComponent.paint(g);

    g.dispose();
  }

  // This method and its overrides are the only methods in the peers
  // that should call awtComponent.update.
  protected void updateComponent (PaintEvent event)
  {
    // Do not call Component.update if the component is not showing or
    // if its bounds form a degenerate rectangle.
    if (!awtComponent.isShowing()
        || (awtComponent.getWidth() < 1 || awtComponent.getHeight() < 1))
      return;

    Graphics g = getGraphics();

    g.setClip(event.getUpdateRect());

    awtComponent.update(g);

    g.dispose();
  }

  public boolean isFocusTraversable () 
  {
    return true;
  }

  public Dimension minimumSize () 
  {
    int dim[] = new int[2];

    gtkWidgetGetPreferredDimensions (dim);

    return new Dimension (dim[0], dim[1]);
  }

  public void paint (Graphics g)
  {
  }

  public Dimension preferredSize ()
  {
    int dim[] = new int[2];

    gtkWidgetGetPreferredDimensions (dim);

    return new Dimension (dim[0], dim[1]);
  }

  public boolean prepareImage (Image image, int width, int height,
			       ImageObserver observer) 
  {
    return getToolkit().prepareImage(image, width, height, observer);
  }

  public void print (Graphics g) 
  {
    g.drawImage( ComponentGraphics.grab( this ), 0, 0, null );
  }

  public void repaint (long tm, int x, int y, int width, int height)
  {
    if (width < 1 || height < 1)
      return;

    if (tm <= 0)
      q().postEvent(new PaintEvent(awtComponent, PaintEvent.UPDATE,
				   new Rectangle(x, y, width, height)));
    else
      RepaintTimerTask.schedule(tm, x, y, width, height, awtComponent);
  }

  /**
   * Used for scheduling delayed paint updates on the event queue.
   */
  private static class RepaintTimerTask extends TimerTask
  {
    private static final Timer repaintTimer = new Timer(true);

    private int x, y, width, height;
    private Component awtComponent;

    RepaintTimerTask(Component c, int x, int y, int width, int height)
    {
      this.x = x;
      this.y = y;
      this.width = width;
      this.height = height;
      this.awtComponent = c;
    }

    public void run()
    {
      q().postEvent (new PaintEvent (awtComponent, PaintEvent.UPDATE,
                                     new Rectangle (x, y, width, height)));
    }

    static void schedule(long tm, int x, int y, int width, int height,
			 Component c)
    {
      repaintTimer.schedule(new RepaintTimerTask(c, x, y, width, height), tm);
    }
  }

  public void requestFocus ()
  {
    assert false: "Call new requestFocus() method instead";
  }

  public void reshape (int x, int y, int width, int height) 
  {
    setBounds (x, y, width, height);
  }

  public void setBackground (Color c) 
  {
    gtkWidgetSetBackground (c.getRed(), c.getGreen(), c.getBlue());
  }

  native void setNativeBounds (int x, int y, int width, int height);

  public void setBounds (int x, int y, int width, int height)
  {
    int new_x = x;
    int new_y = y;

    Component parent = awtComponent.getParent ();
    
    // Heavyweight components that are children of one or more
    // lightweight containers have to be handled specially.  Because
    // calls to GLightweightPeer.setBounds do nothing, GTK has no
    // knowledge of the lightweight containers' positions.  So we have
    // to add the offsets manually when placing a heavyweight
    // component within a lightweight container.  The lightweight
    // container may itself be in a lightweight container and so on,
    // so we need to continue adding offsets until we reach a
    // container whose position GTK knows -- that is, the first
    // non-lightweight.
    Insets i;    
    while (parent.isLightweight())
      {
        i = ((Container) parent).getInsets();
        
        new_x += parent.getX() + i.left;
        new_y += parent.getY() + i.top;
        
        parent = parent.getParent();
      }
    // We only need to convert from Java to GTK coordinates if we're
    // placing a heavyweight component in a Window.
    if (parent instanceof Window)
      {
        GtkWindowPeer peer = (GtkWindowPeer) parent.getPeer ();
        // important: we want the window peer's insets here, not the
        // window's, since user sub-classes of Window can override
        // getInset and we only want to correct for the frame borders,
        // not for any user-defined inset values
        Insets insets = peer.getInsets ();

        int menuBarHeight = 0;
        if (peer instanceof GtkFramePeer)
          menuBarHeight = ((GtkFramePeer) peer).getMenuBarHeight ();
        
        new_x -= insets.left;
        new_y -= insets.top;
        new_y += menuBarHeight;
      }

    setNativeBounds (new_x, new_y, width, height);

    // If the height or width were (or are now) smaller than zero
    // then we want to adjust the visibility.
    setVisible(awtComponent.isVisible());
  }

  void setCursor ()
  {
    setCursor (awtComponent.getCursor ());
  }

  public void setCursor (Cursor cursor) 
  {
    int x, y;
    GtkImage image;
    int type = cursor.getType();
    if (cursor instanceof GtkCursor)
      {
	GtkCursor gtkCursor = (GtkCursor) cursor;
	image = gtkCursor.getGtkImage();
	Point hotspot = gtkCursor.getHotspot();
	x = hotspot.x;
	y = hotspot.y;
      }
    else
      {
	image = null;
	x = 0;
	y = 0;
      }

    if (Thread.currentThread() == GtkToolkit.mainThread)
      gtkWidgetSetCursorUnlocked(cursor.getType(), image, x, y);
    else
      gtkWidgetSetCursor(cursor.getType(), image, x, y);
  }

  public void setEnabled (boolean b)
  {
    gtkWidgetSetSensitive (b);
  }

  public void setFont (Font f)
  {
    // FIXME: This should really affect the widget tree below me.
    // Currently this is only handled if the call is made directly on
    // a text widget, which implements setFont() itself.
    gtkWidgetModifyFont(f.getName(), f.getStyle(), f.getSize());
  }

  public void setForeground (Color c) 
  {
    gtkWidgetSetForeground (c.getRed(), c.getGreen(), c.getBlue());
  }

  public Color getForeground ()
  {
    int rgb[] = gtkWidgetGetForeground ();
    return new Color (rgb[0], rgb[1], rgb[2]);
  }

  public Color getBackground ()
  {
    int rgb[] = gtkWidgetGetBackground ();
    return new Color (rgb[0], rgb[1], rgb[2]);
  }

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

  public void setVisible (boolean b)
  {
    // Only really set visible when component is bigger than zero pixels.
    if (b && ! (awtComponent instanceof Window))
      {
        Rectangle bounds = awtComponent.getBounds();
	b = (bounds.width > 0) && (bounds.height > 0);
      }

    if (Thread.currentThread() == GtkToolkit.mainThread)
      setVisibleNativeUnlocked (b);
    else
      setVisibleNative (b);
  }

  public void hide ()
  {
    setVisible (false);
  }

  public void show ()
  {
    setVisible (true);
  }

  protected void postMouseEvent(int id, long when, int mods, int x, int y, 
				int clickCount, boolean popupTrigger) 
  {
    q().postEvent(new MouseEvent(awtComponent, id, when, mods, x, y, 
			       clickCount, popupTrigger));
  }

  /**
   * Callback for component_scroll_cb.
   */
  protected void postMouseWheelEvent(int id, long when, int mods,
				     int x, int y, int clickCount,
				     boolean popupTrigger,
				     int type, int amount, int rotation) 
  {
    q().postEvent(new MouseWheelEvent(awtComponent, id, when, mods,
				      x, y, clickCount, popupTrigger,
				      type, amount, rotation));
  }

  protected void postExposeEvent (int x, int y, int width, int height)
  {
    q().postEvent (new PaintEvent (awtComponent, PaintEvent.PAINT,
                                   new Rectangle (x, y, width, height)));
  }

  protected void postKeyEvent (int id, long when, int mods,
                               int keyCode, char keyChar, int keyLocation)
  {
    KeyEvent keyEvent = new KeyEvent (awtComponent, id, when, mods,
                                      keyCode, keyChar, keyLocation);

    EventQueue q = q();

    // Also post a KEY_TYPED event if keyEvent is a key press that
    // doesn't represent an action or modifier key.
    if (keyEvent.getID () == KeyEvent.KEY_PRESSED
        && (!keyEvent.isActionKey ()
            && keyCode != KeyEvent.VK_SHIFT
            && keyCode != KeyEvent.VK_CONTROL
            && keyCode != KeyEvent.VK_ALT))
      {
        synchronized(q)
	  {
	    q.postEvent(keyEvent);
	    keyEvent = new KeyEvent(awtComponent, KeyEvent.KEY_TYPED, when,
				    mods, KeyEvent.VK_UNDEFINED, keyChar,
				    keyLocation);
	    q.postEvent(keyEvent);
          }
      }
    else
      q.postEvent(keyEvent);
  }

  /**
   * Referenced from native code.
   *
   * @param id
   * @param temporary
   */
  protected void postFocusEvent (int id, boolean temporary)
  {
    q().postEvent (new FocusEvent (awtComponent, id, temporary));
  }

  protected void postItemEvent (Object item, int stateChange)
  {
    q().postEvent (new ItemEvent ((ItemSelectable)awtComponent, 
				ItemEvent.ITEM_STATE_CHANGED,
				item, stateChange));
  }

  protected void postTextEvent ()
  {
    q().postEvent (new TextEvent (awtComponent, TextEvent.TEXT_VALUE_CHANGED));
  }

  public GraphicsConfiguration getGraphicsConfiguration ()
  {
    // FIXME: The component might be showing on a non-default screen.
    GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
    GraphicsDevice dev = env.getDefaultScreenDevice();
    return dev.getDefaultConfiguration();
  }

  public void setEventMask (long mask)
  {
    // FIXME: just a stub for now.
  }

  public boolean isFocusable ()
  {
    return false;
  }

  public boolean requestFocus (Component request, boolean temporary, 
                               boolean allowWindowFocus, long time)
  {
    assert request == awtComponent || isLightweightDescendant(request);
    boolean retval = false;
    if (gtkWidgetHasFocus())
      {
        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 (gtkWidgetCanFocus())
          {
            if (allowWindowFocus)
              {
                Window window = getWindowFor(request);
                GtkWindowPeer wPeer = (GtkWindowPeer) window.getPeer();
                if (! wPeer.gtkWindowHasFocus())
                  wPeer.requestWindowFocus();
              }
            // Store requested focus component so that the corresponding
            // event is dispatched correctly.
            gtkWidgetRequestFocus();
            retval = true;
          }
      }
    return retval;
  }

  private Window getWindowFor(Component c)
  {
    Component comp = c;
    while (! (comp instanceof Window))
      comp = comp.getParent();
    return (Window) comp;
  }

  /**
   * Returns <code>true</code> if the component is a direct (== no intermediate
   * heavyweights) lightweight descendant of this peer's component.
   *
   * @param c the component to check
   *
   * @return <code>true</code> if the component is a direct (== no intermediate
   *         heavyweights) lightweight descendant of this peer's component
   */
  protected boolean isLightweightDescendant(Component c)
  {
    Component comp = c;
    while (comp.getPeer() instanceof LightweightPeer)
      comp = comp.getParent();
    return comp == awtComponent;
  }

  public boolean isObscured ()
  {
    return false;
  }

  public boolean canDetermineObscurity ()
  {
    return false;
  }

  public void coalescePaintEvent (PaintEvent e)
  {
    
  }

  public void updateCursorImmediately ()
  {
    if (awtComponent.getCursor() != null)
      setCursor(awtComponent.getCursor());
  }

  public boolean handlesWheelScrolling ()
  {
    return false;
  }

  // Convenience method to create a new volatile image on the screen
  // on which this component is displayed.
  public VolatileImage createVolatileImage (int width, int height)
  {
    return new GtkVolatileImage (this, width, height, null);
  }

  // Creates buffers used in a buffering strategy.
  public void createBuffers (int numBuffers, BufferCapabilities caps)
    throws AWTException
  {
    // numBuffers == 2 implies double-buffering, meaning one back
    // buffer and one front buffer.
    if (numBuffers == 2)
      backBuffer = new GtkVolatileImage(this, awtComponent.getWidth(),
					awtComponent.getHeight(),
					caps.getBackBufferCapabilities());
    else
      throw new AWTException("GtkComponentPeer.createBuffers:"
			     + " multi-buffering not supported");
    this.caps = caps;
  }

  // Return the back buffer.
  public Image getBackBuffer ()
  {
    return backBuffer;
  }

  // FIXME: flip should be implemented as a fast native operation
  public void flip (BufferCapabilities.FlipContents contents)
  {
    getGraphics().drawImage(backBuffer,
			    awtComponent.getWidth(),
			    awtComponent.getHeight(),
			    null);

    // create new back buffer and clear it to the background color.
    if (contents == BufferCapabilities.FlipContents.BACKGROUND)
	{
	  backBuffer = createVolatileImage(awtComponent.getWidth(),
					   awtComponent.getHeight());
	  backBuffer.getGraphics().clearRect(0, 0,
					     awtComponent.getWidth(),
					     awtComponent.getHeight());
	}
    // FIXME: support BufferCapabilities.FlipContents.PRIOR
  }

  // Release the resources allocated to back buffers.
  public void destroyBuffers ()
  {
    backBuffer.flush();
  }
  
  public String toString ()
  {
    return "peer of " + awtComponent.toString();
  }
  public Rectangle getBounds()
  {
      // FIXME: implement
    return null;
  }
  public void reparent(ContainerPeer parent)
  {
    // FIXME: implement
  
  }
  public void setBounds(int x, int y, int width, int height, int z)
  {
    // FIXME: implement
      setBounds (x, y, width, height);
   
  }
  public boolean isReparentSupported()
  {
    // FIXME: implement

    return false;
  }
  public void layout()
  {
    // FIXME: implement
 
  }
}
