/* SwingComponentPeer.java -- An abstract base class for Swing based peers
   Copyright (C)  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.swing;

import java.awt.AWTEvent;
import java.awt.AWTException;
import java.awt.BufferCapabilities;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.BufferCapabilities.FlipContents;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.PaintEvent;
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;

/**
 * The base class for Swing based component peers. This provides the basic
 * functionality needed for Swing based component peers. Many methods are
 * implemented to forward to the Swing component. Others however forward
 * to the component's parent and expect the toplevel component peer to provide
 * a real implementation of it. These are for example the key methods
 * {@link #getGraphics()} and {@link #createImage(int, int)}, as well as
 * {@link #getLocationOnScreen()}.
 *
 * This class also provides the necesary hooks into the Swing painting and
 * event handling system. In order to achieve this, it traps paint, mouse and
 * key events in {@link #handleEvent(AWTEvent)} and calls some special methods
 * ({@link #peerPaint(Graphics)}, {@link #handleKeyEvent(KeyEvent)},
 * {@link #handleMouseEvent(MouseEvent)} and
 * {@link #handleMouseMotionEvent(MouseEvent)}) that call the corresponding
 * Swing methods.
 *
 * @author Roman Kennke (kennke@aicas.com)
 */
public class SwingComponentPeer
  implements ComponentPeer
{

  /**
   * The AWT component for this peer.
   */
  protected Component awtComponent;

  /**
   * The Swing component for this peer.
   */
  protected SwingComponent swingComponent;

  /**
   * Creates a SwingComponentPeer instance. Subclasses are expected to call
   * this constructor and thereafter call
   * {@link #init(Component,SwingComponent)}
   * in order to setup the AWT and Swing components properly.
   */
  protected SwingComponentPeer()
  {
    // Nothing to do here.
  }

  /**
   * Initializes the AWT and Swing component for this peer. It is expected that
   * subclasses call this from within their constructor.
   *
   * @param awtComp the AWT component for this peer
   * @param swingComp the Swing component for this peer
   */
  protected void init(Component awtComp, SwingComponent swingComp)
  {
    awtComponent = awtComp;
    swingComponent = swingComp;
  }

  /**
   * Returns the construction status of the specified image. This is called
   * by {@link Component#checkImage(Image, int, int, ImageObserver)}.
   *
   * @param img the image
   * @param width the width of the image
   * @param height the height of the image
   * @param ob the image observer to be notified of updates of the status
   *
   * @return a bitwise ORed set of ImageObserver flags
   */
  public int checkImage(Image img, int width, int height, ImageObserver ob)
  {
    return Toolkit.getDefaultToolkit().checkImage(img, width, height, ob);
  }

  /**
   * Creates an image by starting the specified image producer. This is called
   * by {@link Component#createImage(ImageProducer)}.
   *
   * @param prod the image producer to be used to create the image
   *
   * @return the created image
   */
  public Image createImage(ImageProducer prod)
  {
    Image image = Toolkit.getDefaultToolkit().createImage(prod);
	return image;
  }

  /**
   * Creates an empty image with the specified <code>width</code> and
   * <code>height</code>.
   *
   * This is implemented to let the parent component create the image. This
   * eventually goes up to the top-level component peer, which is then expected
   * to deliver the image.
   *
   * @param width the width of the image to be created
   * @param height the height of the image to be created
   *
   * @return the created image
   */
  public Image createImage(int width, int height)
  {
    Component parent = awtComponent.getParent();
    ComponentPeer parentPeer = parent.getPeer();
    return parentPeer.createImage(width, height);
  }

  /**
   * Disables the component. This is called by {@link Component#disable()}.
   */
  public void disable()
  {
    if (swingComponent != null)
      swingComponent.getJComponent().setEnabled(false);
  }

  /**
   * Disposes the component peer. This should release all resources held by the
   * peer. This is called when the component is no longer in use.
   */
  public void dispose()
  {
    awtComponent = null;
    swingComponent = null;
  }

  /**
   * Enables the component. This is called by {@link Component#enable()}.
   */
  public void enable()
  {
    if (swingComponent != null)
      swingComponent.getJComponent().setEnabled(true);
  }

  /**
   * Returns the color model of the component. This is currently not used.
   *
   * @return the color model of the component
   */
  public ColorModel getColorModel()
  {
    // FIXME: When this peer method will be used, we need to provide an
    // implementation of this, probably forwarding to the toplevel peer, like
    // in the other methods.
    return null;
  }

  /**
   * Returns the font metrics for the specified font. This is called by
   * {@link Component#getFontMetrics(Font)}.
   *
   * This is implemented to query the font metrics from the parent component.
   * This will eventually call the top-level component peer, which is then
   * expected to deliver a font metrics object.
   *
   * @param f the font for which to query the font metrics
   *
   * @return the font metrics for the specified font
   */
  public FontMetrics getFontMetrics(Font f)
  {
    Component parent = awtComponent.getParent();
    ComponentPeer parentPeer = parent.getPeer();
    return parentPeer.getFontMetrics(f);
  }

  /**
   * Returns a {@link Graphics} object suitable for drawing on this component.
   * This is called by {@link Component#getGraphics()}.
   *
   * This is implemented to query the graphics from the parent component and
   * adjust the clip and translation to match this component.
   * This will eventually call the top-level component peer, which is then
   * expected to deliver a graphics object.
   *
   * @return a graphics object suitable for drawing on this component
   */
  public Graphics getGraphics()
  {
    Component parent = awtComponent.getParent();
    ComponentPeer parentPeer = parent.getPeer();
    Graphics g = parentPeer.getGraphics();
    g.translate(awtComponent.getX(), awtComponent.getY());
    g.setClip(0, 0, awtComponent.getWidth(), awtComponent.getHeight());
    return g;
  }

  /**
   * Returns the location of this component in screen coordinates. This is
   * called by {@link Component#getLocationOnScreen()}.
   *
   * This is implemented to query the parent component peer for its screen
   * location and adds the offset of this component to it. This will eventually
   * call the top-level component's peer, which is then expected to provide
   * it's screen location.
   *
   * @return the location of this component in screen coordinates
   */
  public Point getLocationOnScreen()
  {
    Component parent = awtComponent.getParent();
    ComponentPeer parentPeer = parent.getPeer();
    Point location = parentPeer.getLocationOnScreen();
    location.x += awtComponent.getX();
    location.y += awtComponent.getY();
    return location;
  }

  /**
   * Returns the minimum size for the component. This is called by
   * {@link Component#getMinimumSize()}.
   *
   * This is implemented to return the Swing component's minimum size.
   *
   * @return the minimum size for the component
   */
  public Dimension getMinimumSize()
  {
    Dimension retVal;
    if (swingComponent != null)
      retVal = swingComponent.getJComponent().getMinimumSize();
    else
      retVal = new Dimension(0, 0);
    return retVal;
  }

  /**
   * Returns the preferred size for the component. This is called by
   * {@link Component#getPreferredSize()}.
   *
   * This is implemented to return the Swing component's preferred size.
   *
   * @return the preferred size for the component
   */
  public Dimension getPreferredSize()
  {
    Dimension retVal;
    if (swingComponent != null)
      retVal = swingComponent.getJComponent().getPreferredSize();
    else
      retVal = new Dimension(0, 0);
    return retVal;
  }

  /**
   * Returns the toolkit that created this peer.
   *
   * @return the toolkit that created this peer
   */
  public Toolkit getToolkit()
  {
    return Toolkit.getDefaultToolkit();
  }

  /**
   * Handles the given event. This is called from
   * {@link Component#dispatchEvent(AWTEvent)} to give the peer a chance to 
   * react to events for the component.
   *
   * @param e the event
   */
  public void handleEvent(AWTEvent e)
  {
    switch (e.getID())
    {
      case PaintEvent.UPDATE:
      case PaintEvent.PAINT:
        // This only will work when the component is showing.
        if (awtComponent.isShowing())
          {
            Graphics g = getGraphics();
            Rectangle clip = ((PaintEvent)e).getUpdateRect();
            g.clipRect(clip.x, clip.y, clip.width, clip.height);
            //if (this instanceof LightweightPeer)
            //  {
            if (e.getID() == PaintEvent.UPDATE)
              awtComponent.update(g);
            else
              awtComponent.paint(g);
            //  }
            // We paint the 'heavyweights' at last, so that they appear on top of
            // everything else.
            peerPaint(g);
            g.dispose();
          }
        break;
      case MouseEvent.MOUSE_PRESSED:
      case MouseEvent.MOUSE_RELEASED:
      case MouseEvent.MOUSE_CLICKED:
      case MouseEvent.MOUSE_ENTERED:
      case MouseEvent.MOUSE_EXITED:
        handleMouseEvent((MouseEvent) e);
        break;
      case MouseEvent.MOUSE_MOVED:
      case MouseEvent.MOUSE_DRAGGED:
        handleMouseMotionEvent((MouseEvent) e);
        break;
      case KeyEvent.KEY_PRESSED:
      case KeyEvent.KEY_RELEASED:
      case KeyEvent.KEY_TYPED:
        handleKeyEvent((KeyEvent) e);
        break;
      default:
        // Other event types are not handled here.
        break;
    }
  }

  /**
   * Makes the component invisible. This is called from
   * {@link Component#hide()}.
   *
   * This is implemented to call setVisible(false) on the Swing component.
   */
  public void hide()
  {
    if (swingComponent != null)
      swingComponent.getJComponent().setVisible(false);

    Component parent = awtComponent.getParent();
    if (parent != null)
      parent.repaint(awtComponent.getX(), awtComponent.getY(),
                     awtComponent.getWidth(), awtComponent.getHeight());
  }

  /**
   * Returns <code>true</code> if the component can receive keyboard input
   * focus. This is called from {@link Component#isFocusTraversable()}.
   * 
   * This is implemented to return isFocusable() from the Swing component.
   *
   * @specnote Part of the earlier 1.1 API, replaced by isFocusable().
   */
  public boolean isFocusTraversable()
  {
    return swingComponent != null ?
             swingComponent.getJComponent().isFocusable() : false;
  }

  /**
   * Returns <code>true</code> if the component can receive keyboard input
   * focus. This is called from {@link Component#isFocusable()}.
   *
   * This is implemented to return isFocusable() from the Swing component.
   */
  public boolean isFocusable()
  {
    return swingComponent != null ?
             swingComponent.getJComponent().isFocusable() : false;
  }

  /**
   * Returns the minimum size for the component. This is called by
   * {@link Component#minimumSize()}.
   *
   * This is implemented to return the Swing component's minimum size.
   *
   * @return the minimum size for the component
   */
  public Dimension minimumSize()
  {
    Dimension retVal;
    if (swingComponent != null)
      retVal = swingComponent.getJComponent().getMinimumSize();
    else
      retVal = new Dimension(0, 0);
    return retVal;
  }

  /**
   * Returns the preferred size for the component. This is called by
   * {@link Component#getPreferredSize()}.
   *
   * This is implemented to return the Swing component's preferred size.
   *
   * @return the preferred size for the component
   */
  public Dimension preferredSize()
  {
    Dimension retVal;
    if (swingComponent != null)
      retVal = swingComponent.getJComponent().getPreferredSize();
    else
      retVal = new Dimension(0, 0);
    return retVal;
  }

  public void paint(Graphics graphics)
  {
    // FIXME: I don't know what this method is supposed to do.
  }

  /**
   * Prepares an image for rendering on this component. This is called by
   * {@link Component#prepareImage(Image, int, int, ImageObserver)}.
   *
   * @param img the image to prepare
   * @param width the desired width of the rendered image
   * @param height the desired height of the rendered image
   * @param ob the image observer to be notified of updates in the preparation
   *        process
   *
   * @return <code>true</code> if the image has been fully prepared,
   *         <code>false</code> otherwise (in which case the image observer
   *         receives updates)
   */
  public boolean prepareImage(Image img, int width, int height, ImageObserver ob)
  {
    Component parent = awtComponent.getParent();
    if(parent != null)
    {
      ComponentPeer parentPeer = parent.getPeer();
      return parentPeer.prepareImage(img, width, height, ob);
    }
    else
    {
      return Toolkit.getDefaultToolkit().prepareImage(img, width, height, ob);
    }
  }

  public void print(Graphics graphics)
  {
    // FIXME: I don't know what this method is supposed to do.
  }

  /**
   * Repaints the specified rectangle of this component. This is called from
   * {@link Component#repaint(long, int, int, int, int)}.
   *
   * This is implemented to call repaint() on the Swing component.
   *
   * @param tm number of milliseconds to wait with repainting
   * @param x the X coordinate of the upper left corner of the damaged rectangle
   * @param y the Y coordinate of the upper left corner of the damaged rectangle
   * @param width the width of the damaged rectangle
   * @param height the height of the damaged rectangle
   */
  public void repaint(long tm, int x, int y, int width, int height)
  {
    if (swingComponent != null)
      swingComponent.getJComponent().repaint(tm, x, y, width, height);
    else
      {
        PaintEvent ev = new PaintEvent(awtComponent, PaintEvent.UPDATE,
                                       new Rectangle(x, y, width, height));
        Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(ev);
      }
  }

  /**
   * Requests that this component receives the focus. This is called from
   * {@link Component#requestFocus()}.
   * 
   * This calls requestFocus() on the Swing component.
   *
   * @specnote Part of the earlier 1.1 API, apparently replaced by argument 
   *           form of the same method.
   */
  public void requestFocus()
  {
    if (swingComponent != null)
      swingComponent.getJComponent().requestFocus();
  }

  /**
   * Requests that this component receives the focus. This is called from
   * {@link Component#requestFocus()}.
   *
   * This calls requestFocus() on the Swing component.
   *
   * @param source TODO
   * @param bool1 TODO
   * @param bool2 TODO
   * @param x TODO
   *
   * @return TODO
   */
  public boolean requestFocus(Component source, boolean bool1, boolean bool2, long x)
  {
    if (swingComponent != null)
      swingComponent.getJComponent().requestFocus();
    return swingComponent != null;
  }

  /**
   * Notifies the peer that the bounds of this component have changed. This
   * is called by {@link Component#reshape(int, int, int, int)}.
   *
   * This is implemented to call setBounds() on the Swing component.
   *
   * @param x the X coordinate of the upper left corner of the component
   * @param y the Y coordinate of the upper left corner of the component
   * @param width the width of the component
   * @param height the height of the component
   */
  public void reshape(int x, int y, int width, int height)
  {
    if (swingComponent != null)
      swingComponent.getJComponent().setBounds(x, y, width, height);
  }

  /**
   * Sets the background color of the component. This is called by
   * {@link Component#setBackground(Color)}.
   *
   * This is implemented to call setBackground() on the Swing component.
   *
   * @param color the background color to set
   */
  public void setBackground(Color color)
  {
    if (swingComponent != null)
      swingComponent.getJComponent().setBackground(color);
  }

  /**
   * Notifies the peer that the bounds of this component have changed. This
   * is called by {@link Component#setBounds(int, int, int, int)}.
   *
   * This is implemented to call setBounds() on the Swing component.
   *
   * @param x the X coordinate of the upper left corner of the component
   * @param y the Y coordinate of the upper left corner of the component
   * @param width the width of the component
   * @param height the height of the component
   */
  public void setBounds(int x, int y, int width, int height)
  {
    reshape(x, y, width, height);
  }

  /**
   * Sets the cursor of the component. This is called by
   * {@link Component#setCursor(Cursor)}.
   *
   * This is implemented to call setCursor() on the Swing component.
   *
   * @specnote Part of the earlier 1.1 API, apparently no longer needed.
   */
  public void setCursor(Cursor cursor)
  {
    if (swingComponent != null)
      swingComponent.getJComponent().setCursor(cursor);
  }

  /**
   * Sets the enabled/disabled state of this component. This is called by
   * {@link Component#setEnabled(boolean)}.
   *
   * This is implemented to call setEnabled() on the Swing component.
   *
   * @param enabled <code>true</code> to enable the component,
   *        <code>false</code> to disable it
   */
  public void setEnabled(boolean enabled)
  {
    if (swingComponent != null)
      swingComponent.getJComponent().setEnabled(enabled);
  }

  /**
   * Sets the font of the component. This is called by
   * {@link Component#setFont(Font)}.
   *
   * This is implemented to call setFont() on the Swing component.
   *
   * @param font the font to set
   */
  public void setFont(Font font)
  {
    if (swingComponent != null)
      swingComponent.getJComponent().setFont(font);
  }

  /**
   * Sets the foreground color of the component. This is called by
   * {@link Component#setForeground(Color)}.
   *
   * This is implemented to call setForeground() on the Swing component.
   *
   * @param color the foreground color to set
   */
  public void setForeground(Color color)
  {
    if (swingComponent != null)
      swingComponent.getJComponent().setForeground(color);
  }

  /**
   * Sets the visibility state of the component. This is called by
   * {@link Component#setVisible(boolean)}.
   *
   * This is implemented to call setVisible() on the Swing component.
   *
   * @param visible <code>true</code> to make the component visible,
   *        <code>false</code> to make it invisible
   */
  public void setVisible(boolean visible)
  {
    if (visible)
      show();
    else
      hide();
  }

  /**
   * Makes the component visible. This is called by {@link Component#show()}.
   *
   * This is implemented to call setVisible(true) on the Swing component.
   */
  public void show()
  {
    if (swingComponent != null)
      swingComponent.getJComponent().setVisible(true);
  }

  /** 
   * Get the graphics configuration of the component. The color model
   * of the component can be derived from the configuration.
   *
   * This is implemented to return the GraphicsConfiguration of the parent
   * component. This will eventually call the toplevel component peer, which
   * is expected to provide a real implementation.
   *
   * @return the graphics configuration of the component
   */
  public GraphicsConfiguration getGraphicsConfiguration()
  {
    Component parent = awtComponent.getParent();
    ComponentPeer parentPeer = parent.getPeer();
    return parentPeer.getGraphicsConfiguration();
  }

  /**
   * Part of an older API, no longer needed.
   */
  public void setEventMask(long mask)
  {
    // Nothing to do here.
  }

  /**
   * Returns <code>true</code> if this component has been obscured,
   * <code>false</code> otherwise. This will only work if
   * {@link #canDetermineObscurity()} also returns <code>true</code>.
   *
   * This is not yet implemented.
   *
   * @return <code>true</code> if this component has been obscured,
   *         <code>false</code> otherwise.
   */
  public boolean isObscured()
  {
    return false;
  }

  /**
   * Returns <code>true</code> if this component peer can determine if the
   * component has been obscured, <code>false</code> otherwise.
   *
   * This is not yet implemented.
   *
   * @return <code>true</code> if this component peer can determine if the
   *         component has been obscured, <code>false</code> otherwise
   */
  public boolean canDetermineObscurity()
  {
    return false;
  }

  /**
   * Coalesces the specified paint event.
   *
   * @param e the paint event
   */
  public void coalescePaintEvent(PaintEvent e)
  {
    // Nothing to do here yet.
  }

  /**
   * Updates the cursor. This is not yet implemented.
   */
  public void updateCursorImmediately()
  {
    // Nothing to do here yet.
  }

  /**
   * Returns true, if this component can handle wheel scrolling,
   * <code>false</code> otherwise.
   *
   * This is not yet implemented and returns <code>false</code>. 
   *
   * @return true, if this component can handle wheel scrolling,
   *         <code>false</code> otherwise
   */
  public boolean handlesWheelScrolling()
  {
    return false;
  }

  /**
   * A convenience method that creates a volatile image.  The volatile
   * image is created on the screen device on which this component is
   * displayed, in the device's current graphics configuration.
   *
   * This is implemented to let the parent component peer create an image.
   * This eventually ends up in the toplevel component peer, which is then
   * responsible for creating the real image.
   *
   * @param width width of the image
   * @param height height of the image
   *
   * @see VolatileImage
   *
   * @since 1.2
   */
  public VolatileImage createVolatileImage(int width, int height)
  {
    Component parent = awtComponent.getParent();
    VolatileImage im = null;
    if (parent != null)
      {
        ComponentPeer parentPeer = parent.getPeer();
        im = parentPeer.createVolatileImage(width, height);
      }
    return im;
  }

  /**
   * Create a number of image buffers that implement a buffering
   * strategy according to the given capabilities.
   *
   * This is implemented to forward to the parent component peer. Eventually
   * this ends up in the top level component peer, which is then responsible
   * for doing the real work.
   *
   * @param numBuffers the number of buffers
   * @param caps the buffering capabilities
   *
   * @throws AWTException if the specified buffering strategy is not
   * implemented
   *
   * @since 1.2
   */
  public void createBuffers(int numBuffers, BufferCapabilities caps) throws AWTException
  {
    Component parent = awtComponent.getParent();
    ComponentPeer parentPeer = parent.getPeer();
    parentPeer.createBuffers(numBuffers, caps);
  }

  /**
   * Return the back buffer of this component.
   *
   * This is implemented to forward to the parent. Eventually this ends
   * up in the toplevel component, which is then responsible for providing
   * a back buffer.
   *
   * @return the back buffer of this component.
   *
   * @since 1.2
   */
  public Image getBackBuffer()
  {
    Component parent = awtComponent.getParent();
    ComponentPeer parentPeer = parent.getPeer();
    return parentPeer.getBackBuffer();
  }

  /**
   * Perform a page flip, leaving the contents of the back buffer in
   * the specified state.
   *
   * This is implemented to forward to the parent. Eventually this ends
   * up in the toplevel component, which is then responsible for doing the real
   * work.
   *
   * @param contents the state in which to leave the back buffer
   *
   * @since 1.2
   */
  public void flip(FlipContents contents)
  {
    Component parent = awtComponent.getParent();
    ComponentPeer parentPeer = parent.getPeer();
    parentPeer.flip(contents);
  }

  /**
   * Destroy the resources created by createBuffers.
   *
   * This is implemented to forward to the parent component peer. Eventually
   * this ends up in the top level component peer, which is then responsible
   * for doing the real work.
   *
   * @since 1.2
   */
  public void destroyBuffers()
  {
    Component parent = awtComponent.getParent();
    ComponentPeer parentPeer = parent.getPeer();
    parentPeer.destroyBuffers();
  }

  /**
   * Get the bounds of this component peer.
   *
   * This is implemented to forward to the Swing component.
   *
   * @return component peer bounds
   * @since 1.5
   */
  public Rectangle getBounds()
  {
    Rectangle retVal;
    if (swingComponent != null)
      retVal = swingComponent.getJComponent().getBounds();
    else
      retVal = new Rectangle();
    return retVal;
  }

  /**
   * Reparent this component under another container.
   * 
   * @param parent
   * @since 1.5
   */
  public void reparent(ContainerPeer parent)
  {
    // Nothing to do here.
  }

  /**
   * Set the bounds of this component peer.
   *
   * This is implemented to forward to the swing component.
   *
   * @param x the new x co-ordinate
   * @param y the new y co-ordinate
   * @param width the new width
   * @param height the new height
   * @param z the new stacking level
   * @since 1.5
   */
  public void setBounds(int x, int y, int width, int height, int z)
  {
    if (swingComponent != null)
      swingComponent.getJComponent().setBounds(x, y, width, height);
    // FIXME: Somehow handle the Z order.
  }

  /**
   * Check if this component supports being reparented.
   * 
   * @return true if this component can be reparented,
   * false otherwise.
   * @since 1.5
   */
  public boolean isReparentSupported()
  {
    return true;
  }


  /**
   * Layout this component peer.
   *
   * @since 1.5
   */
  public void layout()
  {
    if (swingComponent != null)
      swingComponent.getJComponent().doLayout();
  }

  /**
   * Triggers 'heavyweight' painting of the components. This usually calls
   * paint() on the Swing component.
   *
   * @param g the graphics context to use for painting
   */
  protected void peerPaint(Graphics g)
  {
    if (swingComponent != null)
      swingComponent.getJComponent().paint(g);
  }

  /**
   * Handles mouse events on the component. This is usually forwarded to the
   * SwingComponent's processMouseEvent() method.
   *
   * @param e the mouse event
   */
  protected void handleMouseEvent(MouseEvent e)
  {
    if (swingComponent != null)
      swingComponent.handleMouseEvent(e);
  }

  /**
   * Handles mouse motion events on the component. This is usually forwarded
   * to the SwingComponent's processMouseMotionEvent() method.
   *
   * @param e the mouse motion event
   */
  protected void handleMouseMotionEvent(MouseEvent e)
  {
    if (swingComponent != null)
      swingComponent.handleMouseMotionEvent(e);
  }

  /**
   * Handles key events on the component. This is usually forwarded to the
   * SwingComponent's processKeyEvent() method.
   *
   * @param e the key event
   */
  protected void handleKeyEvent(KeyEvent e)
  {
    if (swingComponent != null)
      swingComponent.handleKeyEvent(e);
  }

  /**
   * Returns the AWT component for this peer.
   *
   * @return the AWT component for this peer
   */
  public Component getComponent()
  {
    return awtComponent;
  }
}
