summaryrefslogtreecommitdiff
path: root/libjava/classpath/java/awt/Component.java
diff options
context:
space:
mode:
authorupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
committerupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
commit554fd8c5195424bdbcabf5de30fdc183aba391bd (patch)
tree976dc5ab7fddf506dadce60ae936f43f58787092 /libjava/classpath/java/awt/Component.java
downloadcbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.bz2
cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.xz
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository.
Diffstat (limited to 'libjava/classpath/java/awt/Component.java')
-rw-r--r--libjava/classpath/java/awt/Component.java7099
1 files changed, 7099 insertions, 0 deletions
diff --git a/libjava/classpath/java/awt/Component.java b/libjava/classpath/java/awt/Component.java
new file mode 100644
index 000000000..d2878a9fd
--- /dev/null
+++ b/libjava/classpath/java/awt/Component.java
@@ -0,0 +1,7099 @@
+/* Component.java -- a graphics component
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2006
+ Free Software Foundation
+
+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 java.awt;
+
+//import gnu.java.awt.dnd.peer.gtk.GtkDropTargetContextPeer;
+
+import gnu.java.awt.ComponentReshapeEvent;
+
+import gnu.java.lang.CPStringBuilder;
+
+import java.awt.dnd.DropTarget;
+import java.awt.event.ActionEvent;
+import java.awt.event.AdjustmentEvent;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.awt.event.HierarchyBoundsListener;
+import java.awt.event.HierarchyEvent;
+import java.awt.event.HierarchyListener;
+import java.awt.event.InputEvent;
+import java.awt.event.InputMethodEvent;
+import java.awt.event.InputMethodListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.awt.event.MouseWheelEvent;
+import java.awt.event.MouseWheelListener;
+import java.awt.event.PaintEvent;
+import java.awt.event.WindowEvent;
+import java.awt.im.InputContext;
+import java.awt.im.InputMethodRequests;
+import java.awt.image.BufferStrategy;
+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.LightweightPeer;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.Serializable;
+import java.lang.reflect.Array;
+import java.util.Collections;
+import java.util.EventListener;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Set;
+import java.util.Vector;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleComponent;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleState;
+import javax.accessibility.AccessibleStateSet;
+
+/**
+ * The root of all evil. All graphical representations are subclasses of this
+ * giant class, which is designed for screen display and user interaction.
+ * This class can be extended directly to build a lightweight component (one
+ * not associated with a native window); lightweight components must reside
+ * inside a heavyweight window.
+ *
+ * <p>This class is Serializable, which has some big implications. A user can
+ * save the state of all graphical components in one VM, and reload them in
+ * another. Note that this class will only save Serializable listeners, and
+ * ignore the rest, without causing any serialization exceptions. However, by
+ * making a listener serializable, and adding it to another element, you link
+ * in that entire element to the state of this component. To get around this,
+ * use the idiom shown in the example below - make listeners non-serializable
+ * in inner classes, rather than using this object itself as the listener, if
+ * external objects do not need to save the state of this object.
+ *
+ * <pre>
+ * import java.awt.*;
+ * import java.awt.event.*;
+ * import java.io.Serializable;
+ * class MyApp implements Serializable
+ * {
+ * BigObjectThatShouldNotBeSerializedWithAButton bigOne;
+ * // Serializing aButton will not suck in an instance of MyApp, with its
+ * // accompanying field bigOne.
+ * Button aButton = new Button();
+ * class MyActionListener implements ActionListener
+ * {
+ * public void actionPerformed(ActionEvent e)
+ * {
+ * System.out.println("Hello There");
+ * }
+ * }
+ * MyApp()
+ * {
+ * aButton.addActionListener(new MyActionListener());
+ * }
+ * }
+ * </pre>
+ *
+ * <p>Status: Incomplete. The event dispatch mechanism is implemented. All
+ * other methods defined in the J2SE 1.3 API javadoc exist, but are mostly
+ * incomplete or only stubs; except for methods relating to the Drag and
+ * Drop, Input Method, and Accessibility frameworks: These methods are
+ * present but commented out.
+ *
+ * @author original author unknown
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.0
+ * @status still missing 1.4 support
+ */
+public abstract class Component
+ implements ImageObserver, MenuContainer, Serializable
+{
+ // Word to the wise - this file is huge. Search for '\f' (^L) for logical
+ // sectioning by fields, public API, private API, and nested classes.
+
+
+ /**
+ * Compatible with JDK 1.0+.
+ */
+ private static final long serialVersionUID = -7644114512714619750L;
+
+ /**
+ * Constant returned by the <code>getAlignmentY</code> method to indicate
+ * that the component wishes to be aligned to the top relative to
+ * other components.
+ *
+ * @see #getAlignmentY()
+ */
+ public static final float TOP_ALIGNMENT = 0;
+
+ /**
+ * Constant returned by the <code>getAlignmentY</code> and
+ * <code>getAlignmentX</code> methods to indicate
+ * that the component wishes to be aligned to the centdisper relative to
+ * other components.
+ *
+ * @see #getAlignmentX()
+ * @see #getAlignmentY()
+ */
+ public static final float CENTER_ALIGNMENT = 0.5f;
+
+ /**
+ * Constant returned by the <code>getAlignmentY</code> method to indicate
+ * that the component wishes to be aligned to the bottom relative to
+ * other components.
+ *
+ * @see #getAlignmentY()
+ */
+ public static final float BOTTOM_ALIGNMENT = 1;
+
+ /**
+ * Constant returned by the <code>getAlignmentX</code> method to indicate
+ * that the component wishes to be aligned to the right relative to
+ * other components.
+ *
+ * @see #getAlignmentX()
+ */
+ public static final float RIGHT_ALIGNMENT = 1;
+
+ /**
+ * Constant returned by the <code>getAlignmentX</code> method to indicate
+ * that the component wishes to be aligned to the left relative to
+ * other components.
+ *
+ * @see #getAlignmentX()
+ */
+ public static final float LEFT_ALIGNMENT = 0;
+
+ /**
+ * Make the treelock a String so that it can easily be identified
+ * in debug dumps. We clone the String in order to avoid a conflict in
+ * the unlikely event that some other package uses exactly the same string
+ * as a lock object.
+ */
+ static final Object treeLock = new String("AWT_TREE_LOCK");
+
+ /**
+ * The default maximum size.
+ */
+ private static final Dimension DEFAULT_MAX_SIZE
+ = new Dimension(Short.MAX_VALUE, Short.MAX_VALUE);
+
+ // Serialized fields from the serialization spec.
+
+ /**
+ * The x position of the component in the parent's coordinate system.
+ *
+ * @see #getLocation()
+ * @serial the x position
+ */
+ int x;
+
+ /**
+ * The y position of the component in the parent's coordinate system.
+ *
+ * @see #getLocation()
+ * @serial the y position
+ */
+ int y;
+
+ /**
+ * The component width.
+ *
+ * @see #getSize()
+ * @serial the width
+ */
+ int width;
+
+ /**
+ * The component height.
+ *
+ * @see #getSize()
+ * @serial the height
+ */
+ int height;
+
+ /**
+ * The foreground color for the component. This may be null.
+ *
+ * @see #getForeground()
+ * @see #setForeground(Color)
+ * @serial the foreground color
+ */
+ Color foreground;
+
+ /**
+ * The background color for the component. This may be null.
+ *
+ * @see #getBackground()
+ * @see #setBackground(Color)
+ * @serial the background color
+ */
+ Color background;
+
+ /**
+ * The default font used in the component. This may be null.
+ *
+ * @see #getFont()
+ * @see #setFont(Font)
+ * @serial the font
+ */
+ Font font;
+
+ /**
+ * The font in use by the peer, or null if there is no peer.
+ *
+ * @serial the peer's font
+ */
+ Font peerFont;
+
+ /**
+ * The cursor displayed when the pointer is over this component. This may
+ * be null.
+ *
+ * @see #getCursor()
+ * @see #setCursor(Cursor)
+ */
+ Cursor cursor;
+
+ /**
+ * The locale for the component.
+ *
+ * @see #getLocale()
+ * @see #setLocale(Locale)
+ */
+ Locale locale = Locale.getDefault ();
+
+ /**
+ * True if the object should ignore repaint events (usually because it is
+ * not showing).
+ *
+ * @see #getIgnoreRepaint()
+ * @see #setIgnoreRepaint(boolean)
+ * @serial true to ignore repaints
+ * @since 1.4
+ */
+ boolean ignoreRepaint;
+
+ /**
+ * True when the object is visible (although it is only showing if all
+ * ancestors are likewise visible). For component, this defaults to true.
+ *
+ * @see #isVisible()
+ * @see #setVisible(boolean)
+ * @serial true if visible
+ */
+ boolean visible = true;
+
+ /**
+ * True if the object is enabled, meaning it can interact with the user.
+ * For component, this defaults to true.
+ *
+ * @see #isEnabled()
+ * @see #setEnabled(boolean)
+ * @serial true if enabled
+ */
+ boolean enabled = true;
+
+ /**
+ * True if the object is valid. This is set to false any time a size
+ * adjustment means the component need to be layed out again.
+ *
+ * @see #isValid()
+ * @see #validate()
+ * @see #invalidate()
+ * @serial true if layout is valid
+ */
+ boolean valid;
+
+ /**
+ * The DropTarget for drag-and-drop operations.
+ *
+ * @see #getDropTarget()
+ * @see #setDropTarget(DropTarget)
+ * @serial the drop target, or null
+ * @since 1.2
+ */
+ DropTarget dropTarget;
+
+ /**
+ * The list of popup menus for this component.
+ *
+ * @see #add(PopupMenu)
+ * @serial the list of popups
+ */
+ Vector popups;
+
+ /**
+ * The component's name. May be null, in which case a default name is
+ * generated on the first use.
+ *
+ * @see #getName()
+ * @see #setName(String)
+ * @serial the name
+ */
+ String name;
+
+ /**
+ * True once the user has set the name. Note that the user may set the name
+ * to null.
+ *
+ * @see #name
+ * @see #getName()
+ * @see #setName(String)
+ * @serial true if the name has been explicitly set
+ */
+ boolean nameExplicitlySet;
+
+ /**
+ * Indicates if the object can be focused. Defaults to true for components.
+ *
+ * @see #isFocusable()
+ * @see #setFocusable(boolean)
+ * @since 1.4
+ */
+ boolean focusable = true;
+
+ /**
+ * Tracks whether this component's {@link #isFocusTraversable}
+ * method has been overridden.
+ *
+ * @since 1.4
+ */
+ int isFocusTraversableOverridden;
+
+ /**
+ * The focus traversal keys, if not inherited from the parent or
+ * default keyboard focus manager. These sets will contain only
+ * AWTKeyStrokes that represent press and release events to use as
+ * focus control.
+ *
+ * @see #getFocusTraversalKeys(int)
+ * @see #setFocusTraversalKeys(int, Set)
+ * @since 1.4
+ */
+ Set[] focusTraversalKeys;
+
+ /**
+ * True if focus traversal keys are enabled. This defaults to true for
+ * Component. If this is true, keystrokes in focusTraversalKeys are trapped
+ * and processed automatically rather than being passed on to the component.
+ *
+ * @see #getFocusTraversalKeysEnabled()
+ * @see #setFocusTraversalKeysEnabled(boolean)
+ * @since 1.4
+ */
+ boolean focusTraversalKeysEnabled = true;
+
+ /**
+ * Cached information on the minimum size. Should have been transient.
+ *
+ * @serial ignore
+ */
+ Dimension minSize;
+
+ /**
+ * Flag indicating whether the minimum size for the component has been set
+ * by a call to {@link #setMinimumSize(Dimension)} with a non-null value.
+ */
+ boolean minSizeSet;
+
+ /**
+ * The maximum size for the component.
+ * @see #setMaximumSize(Dimension)
+ */
+ Dimension maxSize;
+
+ /**
+ * A flag indicating whether the maximum size for the component has been set
+ * by a call to {@link #setMaximumSize(Dimension)} with a non-null value.
+ */
+ boolean maxSizeSet;
+
+ /**
+ * Cached information on the preferred size. Should have been transient.
+ *
+ * @serial ignore
+ */
+ Dimension prefSize;
+
+ /**
+ * Flag indicating whether the preferred size for the component has been set
+ * by a call to {@link #setPreferredSize(Dimension)} with a non-null value.
+ */
+ boolean prefSizeSet;
+
+ /**
+ * Set to true if an event is to be handled by this component, false if
+ * it is to be passed up the hierarcy.
+ *
+ * @see #dispatchEvent(AWTEvent)
+ * @serial true to process event locally
+ */
+ boolean newEventsOnly;
+
+ /**
+ * Set by subclasses to enable event handling of particular events, and
+ * left alone when modifying listeners. For component, this defaults to
+ * enabling only input methods.
+ *
+ * @see #enableInputMethods(boolean)
+ * @see AWTEvent
+ * @serial the mask of events to process
+ */
+ long eventMask = AWTEvent.INPUT_ENABLED_EVENT_MASK;
+
+ /**
+ * Describes all registered PropertyChangeListeners.
+ *
+ * @see #addPropertyChangeListener(PropertyChangeListener)
+ * @see #removePropertyChangeListener(PropertyChangeListener)
+ * @see #firePropertyChange(String, Object, Object)
+ * @serial the property change listeners
+ * @since 1.2
+ */
+ PropertyChangeSupport changeSupport;
+
+ /**
+ * True if the component has been packed (layed out).
+ *
+ * @serial true if this is packed
+ */
+ boolean isPacked;
+
+ /**
+ * The serialization version for this class. Currently at version 4.
+ *
+ * XXX How do we handle prior versions?
+ *
+ * @serial the serialization version
+ */
+ int componentSerializedDataVersion = 4;
+
+ /**
+ * The accessible context associated with this component. This is only set
+ * by subclasses.
+ *
+ * @see #getAccessibleContext()
+ * @serial the accessibility context
+ * @since 1.2
+ */
+ AccessibleContext accessibleContext;
+
+
+ // Guess what - listeners are special cased in serialization. See
+ // readObject and writeObject.
+
+ /** Component listener chain. */
+ transient ComponentListener componentListener;
+
+ /** Focus listener chain. */
+ transient FocusListener focusListener;
+
+ /** Key listener chain. */
+ transient KeyListener keyListener;
+
+ /** Mouse listener chain. */
+ transient MouseListener mouseListener;
+
+ /** Mouse motion listener chain. */
+ transient MouseMotionListener mouseMotionListener;
+
+ /**
+ * Mouse wheel listener chain.
+ *
+ * @since 1.4
+ */
+ transient MouseWheelListener mouseWheelListener;
+
+ /**
+ * Input method listener chain.
+ *
+ * @since 1.2
+ */
+ transient InputMethodListener inputMethodListener;
+
+ /**
+ * Hierarcy listener chain.
+ *
+ * @since 1.3
+ */
+ transient HierarchyListener hierarchyListener;
+
+ /**
+ * Hierarcy bounds listener chain.
+ *
+ * @since 1.3
+ */
+ transient HierarchyBoundsListener hierarchyBoundsListener;
+
+ // Anything else is non-serializable, and should be declared "transient".
+
+ /** The parent. */
+ transient Container parent;
+
+ /** The associated native peer. */
+ transient ComponentPeer peer;
+
+ /** The preferred component orientation. */
+ transient ComponentOrientation componentOrientation = ComponentOrientation.UNKNOWN;
+
+ /**
+ * The associated graphics configuration.
+ *
+ * @since 1.4
+ */
+ transient GraphicsConfiguration graphicsConfig;
+
+ /**
+ * The buffer strategy for repainting.
+ *
+ * @since 1.4
+ */
+ transient BufferStrategy bufferStrategy;
+
+ /**
+ * The number of hierarchy listeners of this container plus all of its
+ * children. This is needed for efficient handling of HierarchyEvents.
+ * These must be propagated to all child components with HierarchyListeners
+ * attached. To avoid traversal of the whole subtree, we keep track of
+ * the number of HierarchyListeners here and only walk the paths that
+ * actually have listeners.
+ */
+ int numHierarchyListeners;
+ int numHierarchyBoundsListeners;
+
+ /**
+ * true if requestFocus was called on this component when its
+ * top-level ancestor was not focusable.
+ */
+ private transient FocusEvent pendingFocusRequest = null;
+
+ /**
+ * The system properties that affect image updating.
+ */
+ private static transient boolean incrementalDraw;
+ private static transient Long redrawRate;
+
+ static
+ {
+ incrementalDraw = Boolean.getBoolean ("awt.image.incrementalDraw");
+ redrawRate = Long.getLong ("awt.image.redrawrate");
+ }
+
+ // Public and protected API.
+
+ /**
+ * Default constructor for subclasses. When Component is extended directly,
+ * it forms a lightweight component that must be hosted in an opaque native
+ * container higher in the tree.
+ */
+ protected Component()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the name of this component.
+ *
+ * @return the name of this component
+ * @see #setName(String)
+ * @since 1.1
+ */
+ public String getName()
+ {
+ if (name == null && ! nameExplicitlySet)
+ name = generateName();
+ return name;
+ }
+
+ /**
+ * Sets the name of this component to the specified name (this is a bound
+ * property with the name 'name').
+ *
+ * @param name the new name (<code>null</code> permitted).
+ * @see #getName()
+ * @since 1.1
+ */
+ public void setName(String name)
+ {
+ nameExplicitlySet = true;
+ String old = this.name;
+ this.name = name;
+ firePropertyChange("name", old, name);
+ }
+
+ /**
+ * Returns the parent of this component.
+ *
+ * @return the parent of this component
+ */
+ public Container getParent()
+ {
+ return parent;
+ }
+
+ /**
+ * Returns the native windowing system peer for this component. Only the
+ * platform specific implementation code should call this method.
+ *
+ * @return the peer for this component
+ * @deprecated user programs should not directly manipulate peers; use
+ * {@link #isDisplayable()} instead
+ */
+ // Classpath's Gtk peers rely on this.
+ public ComponentPeer getPeer()
+ {
+ return peer;
+ }
+
+ /**
+ * Set the associated drag-and-drop target, which receives events when this
+ * is enabled.
+ *
+ * @param dt the new drop target
+ * @see #isEnabled()
+ */
+ public void setDropTarget(DropTarget dt)
+ {
+ this.dropTarget = dt;
+
+ if (peer != null)
+ dropTarget.addNotify(peer);
+ }
+
+ /**
+ * Gets the associated drag-and-drop target, if there is one.
+ *
+ * @return the drop target
+ */
+ public DropTarget getDropTarget()
+ {
+ return dropTarget;
+ }
+
+ /**
+ * Returns the graphics configuration of this component, if there is one.
+ * If it has not been set, it is inherited from the parent.
+ *
+ * @return the graphics configuration, or null
+ * @since 1.3
+ */
+ public GraphicsConfiguration getGraphicsConfiguration()
+ {
+ GraphicsConfiguration conf = null;
+ synchronized (getTreeLock())
+ {
+ if (graphicsConfig != null)
+ {
+ conf = graphicsConfig;
+ }
+ else
+ {
+ Component par = getParent();
+ if (par != null)
+ {
+ conf = parent.getGraphicsConfiguration();
+ }
+ }
+ }
+ return conf;
+ }
+
+ /**
+ * Returns the object used for synchronization locks on this component
+ * when performing tree and layout functions.
+ *
+ * @return the synchronization lock for this component
+ */
+ public final Object getTreeLock()
+ {
+ return treeLock;
+ }
+
+ /**
+ * Returns the toolkit in use for this component. The toolkit is associated
+ * with the frame this component belongs to.
+ *
+ * @return the toolkit for this component
+ */
+ public Toolkit getToolkit()
+ {
+ // Only heavyweight peers can handle this.
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ Toolkit tk = null;
+ if (p != null)
+ {
+ tk = peer.getToolkit();
+ }
+ if (tk == null)
+ tk = Toolkit.getDefaultToolkit();
+ return tk;
+ }
+
+ /**
+ * Tests whether or not this component is valid. A invalid component needs
+ * to have its layout redone.
+ *
+ * @return true if this component is valid
+ * @see #validate()
+ * @see #invalidate()
+ */
+ public boolean isValid()
+ {
+ // Tests show that components are invalid as long as they are not showing, even after validate()
+ // has been called on them.
+ return peer != null && valid;
+ }
+
+ /**
+ * Tests if the component is displayable. It must be connected to a native
+ * screen resource. This reduces to checking that peer is not null. A
+ * containment hierarchy is made displayable when a window is packed or
+ * made visible.
+ *
+ * @return true if the component is displayable
+ * @see Container#add(Component)
+ * @see Container#remove(Component)
+ * @see Window#pack()
+ * @see Window#show()
+ * @see Window#dispose()
+ * @since 1.2
+ */
+ public boolean isDisplayable()
+ {
+ return peer != null;
+ }
+
+ /**
+ * Tests whether or not this component is visible. Except for top-level
+ * frames, components are initially visible.
+ *
+ * @return true if the component is visible
+ * @see #setVisible(boolean)
+ */
+ public boolean isVisible()
+ {
+ return visible;
+ }
+
+ /**
+ * Tests whether or not this component is actually being shown on
+ * the screen. This will be true if and only if it this component is
+ * visible and its parent components are all visible.
+ *
+ * @return true if the component is showing on the screen
+ * @see #setVisible(boolean)
+ */
+ public boolean isShowing()
+ {
+ Component par = parent;
+ return visible && peer != null && (par == null || par.isShowing());
+ }
+
+ /**
+ * Tests whether or not this component is enabled. Components are enabled
+ * by default, and must be enabled to receive user input or generate events.
+ *
+ * @return true if the component is enabled
+ * @see #setEnabled(boolean)
+ */
+ public boolean isEnabled()
+ {
+ return enabled;
+ }
+
+ /**
+ * Enables or disables this component. The component must be enabled to
+ * receive events (except that lightweight components always receive mouse
+ * events).
+ *
+ * @param enabled true to enable this component
+ *
+ * @see #isEnabled()
+ * @see #isLightweight()
+ *
+ * @since 1.1
+ */
+ public void setEnabled(boolean enabled)
+ {
+ enable(enabled);
+ }
+
+ /**
+ * Enables this component.
+ *
+ * @deprecated use {@link #setEnabled(boolean)} instead
+ */
+ public void enable()
+ {
+ if (! enabled)
+ {
+ // Need to lock the tree here, because the peers are involved.
+ synchronized (getTreeLock())
+ {
+ enabled = true;
+ ComponentPeer p = peer;
+ if (p != null)
+ p.enable();
+ }
+ }
+ }
+
+ /**
+ * Enables or disables this component.
+ *
+ * @param enabled true to enable this component
+ *
+ * @deprecated use {@link #setEnabled(boolean)} instead
+ */
+ public void enable(boolean enabled)
+ {
+ if (enabled)
+ enable();
+ else
+ disable();
+ }
+
+ /**
+ * Disables this component.
+ *
+ * @deprecated use {@link #setEnabled(boolean)} instead
+ */
+ public void disable()
+ {
+ if (enabled)
+ {
+ // Need to lock the tree here, because the peers are involved.
+ synchronized (getTreeLock())
+ {
+ enabled = false;
+ ComponentPeer p = peer;
+ if (p != null)
+ p.disable();
+ }
+ }
+ }
+
+ /**
+ * Checks if this image is painted to an offscreen image buffer that is
+ * later copied to screen (double buffering reduces flicker). This version
+ * returns false, so subclasses must override it if they provide double
+ * buffering.
+ *
+ * @return true if this is double buffered; defaults to false
+ */
+ public boolean isDoubleBuffered()
+ {
+ return false;
+ }
+
+ /**
+ * Enables or disables input method support for this component. By default,
+ * components have this enabled. Input methods are given the opportunity
+ * to process key events before this component and its listeners.
+ *
+ * @param enable true to enable input method processing
+ * @see #processKeyEvent(KeyEvent)
+ * @since 1.2
+ */
+ public void enableInputMethods(boolean enable)
+ {
+ if (enable)
+ eventMask |= AWTEvent.INPUT_ENABLED_EVENT_MASK;
+ else
+ eventMask &= ~AWTEvent.INPUT_ENABLED_EVENT_MASK;
+ }
+
+ /**
+ * Makes this component visible or invisible. Note that it wtill might
+ * not show the component, if a parent is invisible.
+ *
+ * @param visible true to make this component visible
+ *
+ * @see #isVisible()
+ *
+ * @since 1.1
+ */
+ public void setVisible(boolean visible)
+ {
+ // Inspection by subclassing shows that Sun's implementation calls
+ // show(boolean) which then calls show() or hide(). It is the show()
+ // method that is overriden in subclasses like Window.
+ show(visible);
+ }
+
+ /**
+ * Makes this component visible on the screen.
+ *
+ * @deprecated use {@link #setVisible(boolean)} instead
+ */
+ public void show()
+ {
+ // We must set visible before showing the peer. Otherwise the
+ // peer could post paint events before visible is true, in which
+ // case lightweight components are not initially painted --
+ // Container.paint first calls isShowing () before painting itself
+ // and its children.
+ if(! visible)
+ {
+ // Need to lock the tree here to avoid races and inconsistencies.
+ synchronized (getTreeLock())
+ {
+ visible = true;
+ // Avoid NullPointerExceptions by creating a local reference.
+ ComponentPeer currentPeer = peer;
+ if (currentPeer != null)
+ {
+ currentPeer.show();
+
+ // Fire HierarchyEvent.
+ fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED,
+ this, parent,
+ HierarchyEvent.SHOWING_CHANGED);
+
+ // The JDK repaints the component before invalidating the parent.
+ // So do we.
+ if (peer instanceof LightweightPeer)
+ repaint();
+ }
+
+ // Only post an event if this component actually has a listener
+ // or has this event explicitly enabled.
+ if (componentListener != null
+ || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0)
+ {
+ ComponentEvent ce =
+ new ComponentEvent(this,ComponentEvent.COMPONENT_SHOWN);
+ getToolkit().getSystemEventQueue().postEvent(ce);
+ }
+ }
+
+ // Invalidate the parent if we have one. The component itself must
+ // not be invalidated. We also avoid NullPointerException with
+ // a local reference here.
+ Container currentParent = parent;
+ if (currentParent != null)
+ currentParent.invalidate();
+
+ }
+ }
+
+ /**
+ * Makes this component visible or invisible.
+ *
+ * @param visible true to make this component visible
+ *
+ * @deprecated use {@link #setVisible(boolean)} instead
+ */
+ public void show(boolean visible)
+ {
+ if (visible)
+ show();
+ else
+ hide();
+ }
+
+ /**
+ * Hides this component so that it is no longer shown on the screen.
+ *
+ * @deprecated use {@link #setVisible(boolean)} instead
+ */
+ public void hide()
+ {
+ if (visible)
+ {
+ // Need to lock the tree here to avoid races and inconsistencies.
+ synchronized (getTreeLock())
+ {
+ visible = false;
+
+ // Avoid NullPointerExceptions by creating a local reference.
+ ComponentPeer currentPeer = peer;
+ if (currentPeer != null)
+ {
+ currentPeer.hide();
+
+ // Fire hierarchy event.
+ fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED,
+ this, parent,
+ HierarchyEvent.SHOWING_CHANGED);
+ // The JDK repaints the component before invalidating the
+ // parent. So do we. This only applies for lightweights.
+ if (peer instanceof LightweightPeer)
+ repaint();
+ }
+
+ // Only post an event if this component actually has a listener
+ // or has this event explicitly enabled.
+ if (componentListener != null
+ || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0)
+ {
+ ComponentEvent ce =
+ new ComponentEvent(this,ComponentEvent.COMPONENT_HIDDEN);
+ getToolkit().getSystemEventQueue().postEvent(ce);
+ }
+ }
+
+ // Invalidate the parent if we have one. The component itself need
+ // not be invalidated. We also avoid NullPointerException with
+ // a local reference here.
+ Container currentParent = parent;
+ if (currentParent != null)
+ currentParent.invalidate();
+
+ }
+ }
+
+ /**
+ * Returns this component's foreground color. If not set, this is inherited
+ * from the parent.
+ *
+ * @return this component's foreground color, or null
+ * @see #setForeground(Color)
+ */
+ public Color getForeground()
+ {
+ if (foreground != null)
+ return foreground;
+ return parent == null ? null : parent.getForeground();
+ }
+
+ /**
+ * Sets this component's foreground color to the specified color. This is a
+ * bound property.
+ *
+ * @param c the new foreground color
+ * @see #getForeground()
+ */
+ public void setForeground(Color c)
+ {
+ if (peer != null)
+ peer.setForeground(c);
+
+ Color previous = foreground;
+ foreground = c;
+ firePropertyChange("foreground", previous, c);
+ }
+
+ /**
+ * Tests if the foreground was explicitly set, or just inherited from the
+ * parent.
+ *
+ * @return true if the foreground has been set
+ * @since 1.4
+ */
+ public boolean isForegroundSet()
+ {
+ return foreground != null;
+ }
+
+ /**
+ * Returns this component's background color. If not set, this is inherited
+ * from the parent.
+ *
+ * @return the background color of the component, or null
+ * @see #setBackground(Color)
+ */
+ public Color getBackground()
+ {
+ if (background != null)
+ return background;
+ return parent == null ? null : parent.getBackground();
+ }
+
+ /**
+ * Sets this component's background color to the specified color. The parts
+ * of the component affected by the background color may by system dependent.
+ * This is a bound property.
+ *
+ * @param c the new background color
+ * @see #getBackground()
+ */
+ public void setBackground(Color c)
+ {
+ // return if the background is already set to that color.
+ if ((c != null) && c.equals(background))
+ return;
+
+ Color previous = background;
+ background = c;
+ if (peer != null && c != null)
+ peer.setBackground(c);
+ firePropertyChange("background", previous, c);
+ }
+
+ /**
+ * Tests if the background was explicitly set, or just inherited from the
+ * parent.
+ *
+ * @return true if the background has been set
+ * @since 1.4
+ */
+ public boolean isBackgroundSet()
+ {
+ return background != null;
+ }
+
+ /**
+ * Returns the font in use for this component. If not set, this is inherited
+ * from the parent.
+ *
+ * @return the font for this component
+ * @see #setFont(Font)
+ */
+ public Font getFont()
+ {
+ return getFontImpl();
+ }
+
+ /**
+ * Implementation of getFont(). This is pulled out of getFont() to prevent
+ * client programs from overriding this.
+ *
+ * @return the font of this component
+ */
+ private final Font getFontImpl()
+ {
+ Font f = font;
+ if (f == null)
+ {
+ Component p = parent;
+ if (p != null)
+ f = p.getFontImpl();
+ else
+ {
+ // It is important to return null here and not some kind of default
+ // font, otherwise the Swing UI would not install its fonts because
+ // it keeps non-UIResource fonts.
+ f = null;
+ }
+ }
+ return f;
+ }
+
+ /**
+ * Sets the font for this component to the specified font. This is a bound
+ * property.
+ *
+ * @param f the new font for this component
+ *
+ * @see #getFont()
+ */
+ public void setFont(Font f)
+ {
+ Font oldFont;
+ Font newFont;
+ // Synchronize on the tree because getFontImpl() relies on the hierarchy
+ // not beeing changed.
+ synchronized (getTreeLock())
+ {
+ // Synchronize on this here to guarantee thread safety wrt to the
+ // property values.
+ synchronized (this)
+ {
+ oldFont = font;
+ font = f;
+ newFont = f;
+ }
+ // Create local variable here for thread safety.
+ ComponentPeer p = peer;
+ if (p != null)
+ {
+ // The peer receives the real font setting, which can depend on
+ // the parent font when this component's font has been set to null.
+ f = getFont();
+ if (f != null)
+ {
+ p.setFont(f);
+ peerFont = f;
+ }
+ }
+ }
+
+ // Fire property change event.
+ firePropertyChange("font", oldFont, newFont);
+
+ // Invalidate when necessary as font changes can change the size of the
+ // component.
+ if (valid)
+ invalidate();
+ }
+
+ /**
+ * Tests if the font was explicitly set, or just inherited from the parent.
+ *
+ * @return true if the font has been set
+ * @since 1.4
+ */
+ public boolean isFontSet()
+ {
+ return font != null;
+ }
+
+ /**
+ * Returns the locale for this component. If this component does not
+ * have a locale, the locale of the parent component is returned.
+ *
+ * @return the locale for this component
+ * @throws IllegalComponentStateException if it has no locale or parent
+ * @see #setLocale(Locale)
+ * @since 1.1
+ */
+ public Locale getLocale()
+ {
+ if (locale != null)
+ return locale;
+ if (parent == null)
+ throw new IllegalComponentStateException
+ ("Component has no parent: can't determine Locale");
+ return parent.getLocale();
+ }
+
+ /**
+ * Sets the locale for this component to the specified locale. This is a
+ * bound property.
+ *
+ * @param newLocale the new locale for this component
+ */
+ public void setLocale(Locale newLocale)
+ {
+ if (locale == newLocale)
+ return;
+
+ Locale oldLocale = locale;
+ locale = newLocale;
+ firePropertyChange("locale", oldLocale, newLocale);
+ // New writing/layout direction or more/less room for localized labels.
+ invalidate();
+ }
+
+ /**
+ * Returns the color model of the device this componet is displayed on.
+ *
+ * @return this object's color model
+ * @see Toolkit#getColorModel()
+ */
+ public ColorModel getColorModel()
+ {
+ GraphicsConfiguration config = getGraphicsConfiguration();
+ return config != null ? config.getColorModel()
+ : getToolkit().getColorModel();
+ }
+
+ /**
+ * Returns the location of this component's top left corner relative to
+ * its parent component. This may be outdated, so for synchronous behavior,
+ * you should use a component listner.
+ *
+ * @return the location of this component
+ * @see #setLocation(int, int)
+ * @see #getLocationOnScreen()
+ * @since 1.1
+ */
+ public Point getLocation()
+ {
+ return location ();
+ }
+
+ /**
+ * Returns the location of this component's top left corner in screen
+ * coordinates.
+ *
+ * @return the location of this component in screen coordinates
+ * @throws IllegalComponentStateException if the component is not showing
+ */
+ public Point getLocationOnScreen()
+ {
+ if (! isShowing())
+ throw new IllegalComponentStateException("component "
+ + getClass().getName()
+ + " not showing");
+
+ // Need to lock the tree here. We get crazy races and explosions when
+ // the tree changes while we are trying to find the location of this
+ // component.
+ synchronized (getTreeLock())
+ {
+ // Only a heavyweight peer can answer the question for the screen
+ // location. So we are going through the hierarchy until we find
+ // one and add up the offsets while doing so.
+ int offsX = 0;
+ int offsY = 0;
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ offsX += comp.x;
+ offsY += comp.y;
+ comp = comp.parent;
+ p = comp == null ? null: comp.peer;
+ }
+ // Now we have a heavyweight component.
+ assert ! (p instanceof LightweightPeer);
+ Point loc = p.getLocationOnScreen();
+ loc.x += offsX;
+ loc.y += offsY;
+ return loc;
+ }
+ }
+
+ /**
+ * Returns the location of this component's top left corner relative to
+ * its parent component.
+ *
+ * @return the location of this component
+ * @deprecated use {@link #getLocation()} instead
+ */
+ public Point location()
+ {
+ return new Point (x, y);
+ }
+
+ /**
+ * Moves this component to the specified location, relative to the parent's
+ * coordinates. The coordinates are the new upper left corner of this
+ * component.
+ *
+ * @param x the new X coordinate of this component
+ * @param y the new Y coordinate of this component
+ * @see #getLocation()
+ * @see #setBounds(int, int, int, int)
+ */
+ public void setLocation(int x, int y)
+ {
+ move (x, y);
+ }
+
+ /**
+ * Moves this component to the specified location, relative to the parent's
+ * coordinates. The coordinates are the new upper left corner of this
+ * component.
+ *
+ * @param x the new X coordinate of this component
+ * @param y the new Y coordinate of this component
+ * @deprecated use {@link #setLocation(int, int)} instead
+ */
+ public void move(int x, int y)
+ {
+ setBounds(x, y, this.width, this.height);
+ }
+
+ /**
+ * Moves this component to the specified location, relative to the parent's
+ * coordinates. The coordinates are the new upper left corner of this
+ * component.
+ *
+ * @param p new coordinates for this component
+ * @throws NullPointerException if p is null
+ * @see #getLocation()
+ * @see #setBounds(int, int, int, int)
+ * @since 1.1
+ */
+ public void setLocation(Point p)
+ {
+ setLocation(p.x, p.y);
+ }
+
+ /**
+ * Returns the size of this object.
+ *
+ * @return the size of this object
+ * @see #setSize(int, int)
+ * @since 1.1
+ */
+ public Dimension getSize()
+ {
+ return size ();
+ }
+
+ /**
+ * Returns the size of this object.
+ *
+ * @return the size of this object
+ * @deprecated use {@link #getSize()} instead
+ */
+ public Dimension size()
+ {
+ return new Dimension (width, height);
+ }
+
+ /**
+ * Sets the size of this component to the specified width and height.
+ *
+ * @param width the new width of this component
+ * @param height the new height of this component
+ * @see #getSize()
+ * @see #setBounds(int, int, int, int)
+ */
+ public void setSize(int width, int height)
+ {
+ resize (width, height);
+ }
+
+ /**
+ * Sets the size of this component to the specified value.
+ *
+ * @param width the new width of the component
+ * @param height the new height of the component
+ * @deprecated use {@link #setSize(int, int)} instead
+ */
+ public void resize(int width, int height)
+ {
+ setBounds(this.x, this.y, width, height);
+ }
+
+ /**
+ * Sets the size of this component to the specified value.
+ *
+ * @param d the new size of this component
+ * @throws NullPointerException if d is null
+ * @see #setSize(int, int)
+ * @see #setBounds(int, int, int, int)
+ * @since 1.1
+ */
+ public void setSize(Dimension d)
+ {
+ resize (d);
+ }
+
+ /**
+ * Sets the size of this component to the specified value.
+ *
+ * @param d the new size of this component
+ * @throws NullPointerException if d is null
+ * @deprecated use {@link #setSize(Dimension)} instead
+ */
+ public void resize(Dimension d)
+ {
+ resize (d.width, d.height);
+ }
+
+ /**
+ * Returns a bounding rectangle for this component. Note that the
+ * returned rectange is relative to this component's parent, not to
+ * the screen.
+ *
+ * @return the bounding rectangle for this component
+ * @see #setBounds(int, int, int, int)
+ * @see #getLocation()
+ * @see #getSize()
+ */
+ public Rectangle getBounds()
+ {
+ return bounds ();
+ }
+
+ /**
+ * Returns a bounding rectangle for this component. Note that the
+ * returned rectange is relative to this component's parent, not to
+ * the screen.
+ *
+ * @return the bounding rectangle for this component
+ * @deprecated use {@link #getBounds()} instead
+ */
+ public Rectangle bounds()
+ {
+ return new Rectangle (x, y, width, height);
+ }
+
+ /**
+ * Sets the bounding rectangle for this component to the specified values.
+ * Note that these coordinates are relative to the parent, not to the screen.
+ *
+ * @param x the X coordinate of the upper left corner of the rectangle
+ * @param y the Y coordinate of the upper left corner of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @see #getBounds()
+ * @see #setLocation(int, int)
+ * @see #setLocation(Point)
+ * @see #setSize(int, int)
+ * @see #setSize(Dimension)
+ * @since 1.1
+ */
+ public void setBounds(int x, int y, int w, int h)
+ {
+ reshape (x, y, w, h);
+ }
+
+ /**
+ * Sets the bounding rectangle for this component to the specified values.
+ * Note that these coordinates are relative to the parent, not to the screen.
+ *
+ * @param x the X coordinate of the upper left corner of the rectangle
+ * @param y the Y coordinate of the upper left corner of the rectangle
+ * @param width the width of the rectangle
+ * @param height the height of the rectangle
+ * @deprecated use {@link #setBounds(int, int, int, int)} instead
+ */
+ public void reshape(int x, int y, int width, int height)
+ {
+ // We need to lock the tree here, otherwise we risk races and
+ // inconsistencies.
+ synchronized (getTreeLock())
+ {
+ int oldx = this.x;
+ int oldy = this.y;
+ int oldwidth = this.width;
+ int oldheight = this.height;
+
+ boolean resized = oldwidth != width || oldheight != height;
+ boolean moved = oldx != x || oldy != y;
+
+ if (resized || moved)
+ {
+ // Update the fields.
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+
+ if (peer != null)
+ {
+ peer.setBounds (x, y, width, height);
+ if (resized)
+ invalidate();
+ if (parent != null && parent.valid)
+ parent.invalidate();
+ }
+
+ // Send some events to interested listeners.
+ notifyReshape(resized, moved);
+
+ // Repaint this component and the parent if appropriate.
+ if (parent != null && peer instanceof LightweightPeer
+ && isShowing())
+ {
+ // The parent repaints the area that we occupied before.
+ parent.repaint(oldx, oldy, oldwidth, oldheight);
+ // This component repaints the area that we occupy now.
+ repaint();
+ }
+ }
+ }
+ }
+
+ /**
+ * Sends notification to interested listeners about resizing and/or moving
+ * the component. If this component has interested
+ * component listeners or the corresponding event mask enabled, then
+ * COMPONENT_MOVED and/or COMPONENT_RESIZED events are posted to the event
+ * queue.
+ *
+ * @param resized true if the component has been resized, false otherwise
+ * @param moved true if the component has been moved, false otherwise
+ */
+ void notifyReshape(boolean resized, boolean moved)
+ {
+ // Only post an event if this component actually has a listener
+ // or has this event explicitly enabled.
+ if (componentListener != null
+ || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0)
+ {
+ // Fire component event on this component.
+ if (moved)
+ {
+ ComponentEvent ce = new ComponentEvent(this,
+ ComponentEvent.COMPONENT_MOVED);
+ getToolkit().getSystemEventQueue().postEvent(ce);
+ }
+ if (resized)
+ {
+ ComponentEvent ce = new ComponentEvent(this,
+ ComponentEvent.COMPONENT_RESIZED);
+ getToolkit().getSystemEventQueue().postEvent(ce);
+ }
+ }
+ }
+
+ /**
+ * Sets the bounding rectangle for this component to the specified
+ * rectangle. Note that these coordinates are relative to the parent, not
+ * to the screen.
+ *
+ * @param r the new bounding rectangle
+ * @throws NullPointerException if r is null
+ * @see #getBounds()
+ * @see #setLocation(Point)
+ * @see #setSize(Dimension)
+ * @since 1.1
+ */
+ public void setBounds(Rectangle r)
+ {
+ setBounds (r.x, r.y, r.width, r.height);
+ }
+
+ /**
+ * Gets the x coordinate of the upper left corner. This is more efficient
+ * than getBounds().x or getLocation().x.
+ *
+ * @return the current x coordinate
+ * @since 1.2
+ */
+ public int getX()
+ {
+ return x;
+ }
+
+ /**
+ * Gets the y coordinate of the upper left corner. This is more efficient
+ * than getBounds().y or getLocation().y.
+ *
+ * @return the current y coordinate
+ * @since 1.2
+ */
+ public int getY()
+ {
+ return y;
+ }
+
+ /**
+ * Gets the width of the component. This is more efficient than
+ * getBounds().width or getSize().width.
+ *
+ * @return the current width
+ * @since 1.2
+ */
+ public int getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * Gets the height of the component. This is more efficient than
+ * getBounds().height or getSize().height.
+ *
+ * @return the current width
+ * @since 1.2
+ */
+ public int getHeight()
+ {
+ return height;
+ }
+
+ /**
+ * Returns the bounds of this component. This allows reuse of an existing
+ * rectangle, if r is non-null.
+ *
+ * @param r the rectangle to use, or null
+ * @return the bounds
+ */
+ public Rectangle getBounds(Rectangle r)
+ {
+ if (r == null)
+ r = new Rectangle();
+ r.x = x;
+ r.y = y;
+ r.width = width;
+ r.height = height;
+ return r;
+ }
+
+ /**
+ * Returns the size of this component. This allows reuse of an existing
+ * dimension, if d is non-null.
+ *
+ * @param d the dimension to use, or null
+ * @return the size
+ */
+ public Dimension getSize(Dimension d)
+ {
+ if (d == null)
+ d = new Dimension();
+ d.width = width;
+ d.height = height;
+ return d;
+ }
+
+ /**
+ * Returns the location of this component. This allows reuse of an existing
+ * point, if p is non-null.
+ *
+ * @param p the point to use, or null
+ * @return the location
+ */
+ public Point getLocation(Point p)
+ {
+ if (p == null)
+ p = new Point();
+ p.x = x;
+ p.y = y;
+ return p;
+ }
+
+ /**
+ * Tests if this component is opaque. All "heavyweight" (natively-drawn)
+ * components are opaque. A component is opaque if it draws all pixels in
+ * the bounds; a lightweight component is partially transparent if it lets
+ * pixels underneath show through. Subclasses that guarantee that all pixels
+ * will be drawn should override this.
+ *
+ * @return true if this is opaque
+ * @see #isLightweight()
+ * @since 1.2
+ */
+ public boolean isOpaque()
+ {
+ return ! isLightweight();
+ }
+
+ /**
+ * Return whether the component is lightweight. That means the component has
+ * no native peer, but is displayable. This applies to subclasses of
+ * Component not in this package, such as javax.swing.
+ *
+ * @return true if the component has a lightweight peer
+ * @see #isDisplayable()
+ * @since 1.2
+ */
+ public boolean isLightweight()
+ {
+ return peer instanceof LightweightPeer;
+ }
+
+ /**
+ * Returns the component's preferred size.
+ *
+ * @return the component's preferred size
+ * @see #getMinimumSize()
+ * @see #setPreferredSize(Dimension)
+ * @see LayoutManager
+ */
+ public Dimension getPreferredSize()
+ {
+ return preferredSize();
+ }
+
+ /**
+ * Sets the preferred size that will be returned by
+ * {@link #getPreferredSize()} always, and sends a
+ * {@link PropertyChangeEvent} (with the property name 'preferredSize') to
+ * all registered listeners.
+ *
+ * @param size the preferred size (<code>null</code> permitted).
+ *
+ * @since 1.5
+ *
+ * @see #getPreferredSize()
+ */
+ public void setPreferredSize(Dimension size)
+ {
+ Dimension old = prefSizeSet ? prefSize : null;
+ prefSize = size;
+ prefSizeSet = (size != null);
+ firePropertyChange("preferredSize", old, size);
+ }
+
+ /**
+ * Returns <code>true</code> if the current preferred size is not
+ * <code>null</code> and was set by a call to
+ * {@link #setPreferredSize(Dimension)}, otherwise returns <code>false</code>.
+ *
+ * @return A boolean.
+ *
+ * @since 1.5
+ */
+ public boolean isPreferredSizeSet()
+ {
+ return prefSizeSet;
+ }
+
+ /**
+ * Returns the component's preferred size.
+ *
+ * @return the component's preferred size
+ * @deprecated use {@link #getPreferredSize()} instead
+ */
+ public Dimension preferredSize()
+ {
+ // Create a new Dimension object, so that the application doesn't mess
+ // with the actual values.
+ return new Dimension(preferredSizeImpl());
+ }
+
+ /**
+ * The actual calculation is pulled out of preferredSize() so that
+ * we can call it from Container.preferredSize() and avoid creating a
+ * new intermediate Dimension object.
+ *
+ * @return the preferredSize of the component
+ */
+ Dimension preferredSizeImpl()
+ {
+ Dimension size = prefSize;
+ // Try to use a cached value.
+ if (size == null || !(valid || prefSizeSet))
+ {
+ // We need to lock here, because the calculation depends on the
+ // component structure not changing.
+ synchronized (getTreeLock())
+ {
+ ComponentPeer p = peer;
+ if (p != null)
+ size = peer.preferredSize();
+ else
+ size = minimumSizeImpl();
+ }
+ }
+ return size;
+ }
+
+ /**
+ * Returns the component's minimum size.
+ *
+ * @return the component's minimum size
+ * @see #getPreferredSize()
+ * @see #setMinimumSize(Dimension)
+ * @see LayoutManager
+ */
+ public Dimension getMinimumSize()
+ {
+ return minimumSize();
+ }
+
+ /**
+ * Sets the minimum size that will be returned by {@link #getMinimumSize()}
+ * always, and sends a {@link PropertyChangeEvent} (with the property name
+ * 'minimumSize') to all registered listeners.
+ *
+ * @param size the minimum size (<code>null</code> permitted).
+ *
+ * @since 1.5
+ *
+ * @see #getMinimumSize()
+ */
+ public void setMinimumSize(Dimension size)
+ {
+ Dimension old = minSizeSet ? minSize : null;
+ minSize = size;
+ minSizeSet = (size != null);
+ firePropertyChange("minimumSize", old, size);
+ }
+
+ /**
+ * Returns <code>true</code> if the current minimum size is not
+ * <code>null</code> and was set by a call to
+ * {@link #setMinimumSize(Dimension)}, otherwise returns <code>false</code>.
+ *
+ * @return A boolean.
+ *
+ * @since 1.5
+ */
+ public boolean isMinimumSizeSet()
+ {
+ return minSizeSet;
+ }
+
+ /**
+ * Returns the component's minimum size.
+ *
+ * @return the component's minimum size
+ * @deprecated use {@link #getMinimumSize()} instead
+ */
+ public Dimension minimumSize()
+ {
+ // Create a new Dimension object, so that the application doesn't mess
+ // with the actual values.
+ return new Dimension(minimumSizeImpl());
+ }
+
+ /**
+ * The actual calculation is pulled out of minimumSize() so that
+ * we can call it from Container.preferredSize() and
+ * Component.preferredSizeImpl and avoid creating a
+ * new intermediate Dimension object.
+ *
+ * @return the minimum size of the component
+ */
+ Dimension minimumSizeImpl()
+ {
+ Dimension size = minSize;
+ if (size == null || !(valid || minSizeSet))
+ {
+ // We need to lock here, because the calculation depends on the
+ // component structure not changing.
+ synchronized (getTreeLock())
+ {
+ ComponentPeer p = peer;
+ if (p != null)
+ size = peer.minimumSize();
+ else
+ size = size();
+ }
+ }
+ return size;
+ }
+
+ /**
+ * Returns the component's maximum size.
+ *
+ * @return the component's maximum size
+ * @see #getMinimumSize()
+ * @see #setMaximumSize(Dimension)
+ * @see #getPreferredSize()
+ * @see LayoutManager
+ */
+ public Dimension getMaximumSize()
+ {
+ return new Dimension(maximumSizeImpl());
+ }
+
+ /**
+ * This is pulled out from getMaximumSize(), so that we can access it
+ * from Container.getMaximumSize() without creating an additional
+ * intermediate Dimension object.
+ *
+ * @return the maximum size of the component
+ */
+ Dimension maximumSizeImpl()
+ {
+ Dimension size;
+ if (maxSizeSet)
+ size = maxSize;
+ else
+ size = DEFAULT_MAX_SIZE;
+ return size;
+ }
+
+ /**
+ * Sets the maximum size that will be returned by {@link #getMaximumSize()}
+ * always, and sends a {@link PropertyChangeEvent} (with the property name
+ * 'maximumSize') to all registered listeners.
+ *
+ * @param size the maximum size (<code>null</code> permitted).
+ *
+ * @since 1.5
+ *
+ * @see #getMaximumSize()
+ */
+ public void setMaximumSize(Dimension size)
+ {
+ Dimension old = maxSizeSet ? maxSize : null;
+ maxSize = size;
+ maxSizeSet = (size != null);
+ firePropertyChange("maximumSize", old, size);
+ }
+
+ /**
+ * Returns <code>true</code> if the current maximum size is not
+ * <code>null</code> and was set by a call to
+ * {@link #setMaximumSize(Dimension)}, otherwise returns <code>false</code>.
+ *
+ * @return A boolean.
+ *
+ * @since 1.5
+ */
+ public boolean isMaximumSizeSet()
+ {
+ return maxSizeSet;
+ }
+
+ /**
+ * Returns the preferred horizontal alignment of this component. The value
+ * returned will be between {@link #LEFT_ALIGNMENT} and
+ * {@link #RIGHT_ALIGNMENT}, inclusive.
+ *
+ * @return the preferred horizontal alignment of this component
+ */
+ public float getAlignmentX()
+ {
+ return CENTER_ALIGNMENT;
+ }
+
+ /**
+ * Returns the preferred vertical alignment of this component. The value
+ * returned will be between {@link #TOP_ALIGNMENT} and
+ * {@link #BOTTOM_ALIGNMENT}, inclusive.
+ *
+ * @return the preferred vertical alignment of this component
+ */
+ public float getAlignmentY()
+ {
+ return CENTER_ALIGNMENT;
+ }
+
+ /**
+ * Calls the layout manager to re-layout the component. This is called
+ * during validation of a container in most cases.
+ *
+ * @see #validate()
+ * @see LayoutManager
+ */
+ public void doLayout()
+ {
+ layout ();
+ }
+
+ /**
+ * Calls the layout manager to re-layout the component. This is called
+ * during validation of a container in most cases.
+ *
+ * @deprecated use {@link #doLayout()} instead
+ */
+ public void layout()
+ {
+ // Nothing to do unless we're a container.
+ }
+
+ /**
+ * Called to ensure that the layout for this component is valid. This is
+ * usually called on containers.
+ *
+ * @see #invalidate()
+ * @see #doLayout()
+ * @see LayoutManager
+ * @see Container#validate()
+ */
+ public void validate()
+ {
+ if (! valid)
+ {
+ // Synchronize on the tree here as this might change the layout
+ // of the hierarchy.
+ synchronized (getTreeLock())
+ {
+ // Create local variables for thread safety.
+ ComponentPeer p = peer;
+ if (p != null)
+ {
+ // Possibly update the peer's font.
+ Font newFont = getFont();
+ Font oldFont = peerFont;
+ // Only update when the font really changed.
+ if (newFont != oldFont
+ && (oldFont == null || ! oldFont.equals(newFont)))
+ {
+ p.setFont(newFont);
+ peerFont = newFont;
+ }
+ // Let the peer perform any layout.
+ p.layout();
+ }
+ }
+ valid = true;
+ }
+ }
+
+ /**
+ * Invalidates this component and all of its parent components. This will
+ * cause them to have their layout redone. This is called frequently, so
+ * make it fast.
+ */
+ public void invalidate()
+ {
+ // Need to lock here, to avoid races and other ugly stuff when doing
+ // layout or structure changes in other threads.
+ synchronized (getTreeLock())
+ {
+ // Invalidate.
+ valid = false;
+
+ // Throw away cached layout information.
+ if (! minSizeSet)
+ minSize = null;
+ if (! prefSizeSet)
+ prefSize = null;
+ if (! maxSizeSet)
+ maxSize = null;
+
+ // Also invalidate the parent, if it hasn't already been invalidated.
+ if (parent != null && parent.isValid())
+ parent.invalidate();
+ }
+ }
+
+ /**
+ * Returns a graphics object for this component. Returns <code>null</code>
+ * if this component is not currently displayed on the screen.
+ *
+ * @return a graphics object for this component
+ * @see #paint(Graphics)
+ */
+ public Graphics getGraphics()
+ {
+ // Only heavyweight peers can handle this.
+ ComponentPeer p = peer;
+ Graphics g = null;
+ if (p instanceof LightweightPeer)
+ {
+ if (parent != null)
+ {
+ g = parent.getGraphics();
+ if (g != null)
+ {
+ g.translate(x, y);
+ g.setClip(0, 0, width, height);
+ g.setFont(getFont());
+ }
+ }
+ }
+ else
+ {
+ if (p != null)
+ g = p.getGraphics();
+ }
+ return g;
+ }
+
+ /**
+ * Returns the font metrics for the specified font in this component.
+ *
+ * @param font the font to retrieve metrics for
+ * @return the font metrics for the specified font
+ * @throws NullPointerException if font is null
+ * @see #getFont()
+ * @see Toolkit#getFontMetrics(Font)
+ */
+ public FontMetrics getFontMetrics(Font font)
+ {
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ return p == null ? getToolkit().getFontMetrics(font)
+ : p.getFontMetrics(font);
+ }
+
+ /**
+ * Sets the cursor for this component to the specified cursor. The cursor
+ * is displayed when the point is contained by the component, and the
+ * component is visible, displayable, and enabled. This is inherited by
+ * subcomponents unless they set their own cursor.
+ *
+ * @param cursor the new cursor for this component
+ * @see #isEnabled()
+ * @see #isShowing()
+ * @see #getCursor()
+ * @see #contains(int, int)
+ * @see Toolkit#createCustomCursor(Image, Point, String)
+ */
+ public void setCursor(Cursor cursor)
+ {
+ this.cursor = cursor;
+
+ // Only heavyweight peers handle this.
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ if (p != null)
+ p.setCursor(cursor);
+ }
+
+ /**
+ * Returns the cursor for this component. If not set, this is inherited
+ * from the parent, or from Cursor.getDefaultCursor().
+ *
+ * @return the cursor for this component
+ */
+ public Cursor getCursor()
+ {
+ if (cursor != null)
+ return cursor;
+ return parent != null ? parent.getCursor() : Cursor.getDefaultCursor();
+ }
+
+ /**
+ * Tests if the cursor was explicitly set, or just inherited from the parent.
+ *
+ * @return true if the cursor has been set
+ * @since 1.4
+ */
+ public boolean isCursorSet()
+ {
+ return cursor != null;
+ }
+
+ /**
+ * Paints this component on the screen. The clipping region in the graphics
+ * context will indicate the region that requires painting. This is called
+ * whenever the component first shows, or needs to be repaired because
+ * something was temporarily drawn on top. It is not necessary for
+ * subclasses to call <code>super.paint(g)</code>. Components with no area
+ * are not painted.
+ *
+ * @param g the graphics context for this paint job
+ * @see #update(Graphics)
+ */
+ public void paint(Graphics g)
+ {
+ // This is a callback method and is meant to be overridden by subclasses
+ // that want to perform custom painting.
+ }
+
+ /**
+ * Updates this component. This is called for heavyweight components in
+ * response to {@link #repaint()}. The default implementation simply forwards
+ * to {@link #paint(Graphics)}. The coordinates of the graphics are
+ * relative to this component. Subclasses should call either
+ * <code>super.update(g)</code> or <code>paint(g)</code>.
+ *
+ * @param g the graphics context for this update
+ *
+ * @see #paint(Graphics)
+ * @see #repaint()
+ */
+ public void update(Graphics g)
+ {
+ // Note 1: We used to clear the background here for lightweights and
+ // toplevel components. Tests show that this is not what the JDK does
+ // here. Note that there is some special handling and background
+ // clearing code in Container.update(Graphics).
+
+ // Note 2 (for peer implementors): The JDK doesn't seem call update() for
+ // toplevel components, even when an UPDATE event is sent (as a result
+ // of repaint).
+ paint(g);
+ }
+
+ /**
+ * Paints this entire component, including any sub-components.
+ *
+ * @param g the graphics context for this paint job
+ *
+ * @see #paint(Graphics)
+ */
+ public void paintAll(Graphics g)
+ {
+ if (isShowing())
+ {
+ validate();
+ if (peer instanceof LightweightPeer)
+ paint(g);
+ else
+ peer.paint(g);
+ }
+ }
+
+ /**
+ * Repaint this entire component. The <code>update()</code> method
+ * on this component will be called as soon as possible.
+ *
+ * @see #update(Graphics)
+ * @see #repaint(long, int, int, int, int)
+ */
+ public void repaint()
+ {
+ repaint(0, 0, 0, width, height);
+ }
+
+ /**
+ * Repaint this entire component. The <code>update()</code> method on this
+ * component will be called in approximate the specified number of
+ * milliseconds.
+ *
+ * @param tm milliseconds before this component should be repainted
+ * @see #paint(Graphics)
+ * @see #repaint(long, int, int, int, int)
+ */
+ public void repaint(long tm)
+ {
+ repaint(tm, 0, 0, width, height);
+ }
+
+ /**
+ * Repaints the specified rectangular region within this component. The
+ * <code>update</code> method on this component will be called as soon as
+ * possible. The coordinates are relative to this component.
+ *
+ * @param x the X coordinate of the upper left of the region to repaint
+ * @param y the Y coordinate of the upper left of the region to repaint
+ * @param w the width of the region to repaint
+ * @param h the height of the region to repaint
+ * @see #update(Graphics)
+ * @see #repaint(long, int, int, int, int)
+ */
+ public void repaint(int x, int y, int w, int h)
+ {
+ repaint(0, x, y, w, h);
+ }
+
+ /**
+ * Repaints the specified rectangular region within this component. The
+ * <code>update</code> method on this component will be called in
+ * approximately the specified number of milliseconds. The coordinates
+ * are relative to this component.
+ *
+ * @param tm milliseconds before this component should be repainted
+ * @param x the X coordinate of the upper left of the region to repaint
+ * @param y the Y coordinate of the upper left of the region to repaint
+ * @param width the width of the region to repaint
+ * @param height the height of the region to repaint
+ * @see #update(Graphics)
+ */
+ public void repaint(long tm, int x, int y, int width, int height)
+ {
+ // The repaint() call has previously been delegated to
+ // {@link ComponentPeer.repaint()}. Testing on the JDK using some
+ // dummy peers show that this methods is never called. I think it makes
+ // sense to actually perform the tasks below here, since it's pretty
+ // much peer independent anyway, and makes sure only heavyweights are
+ // bothered by this.
+ ComponentPeer p = peer;
+
+ // Let the nearest heavyweight parent handle repainting for lightweight
+ // components.
+ // We need to recursivly call repaint() on the parent here, since
+ // a (lightweight) parent component might have overridden repaint()
+ // to perform additional custom tasks.
+
+ if (p instanceof LightweightPeer)
+ {
+ // We perform some boundary checking to restrict the paint
+ // region to this component.
+ if (parent != null)
+ {
+ int px = this.x + Math.max(0, x);
+ int py = this.y + Math.max(0, y);
+ int pw = Math.min(this.width, width);
+ int ph = Math.min(this.height, height);
+ parent.repaint(tm, px, py, pw, ph);
+ }
+ }
+ else
+ {
+ // Now send an UPDATE event to the heavyweight component that we've found.
+ if (isVisible() && p != null && width > 0 && height > 0)
+ {
+ PaintEvent pe = new PaintEvent(this, PaintEvent.UPDATE,
+ new Rectangle(x, y, width, height));
+ getToolkit().getSystemEventQueue().postEvent(pe);
+ }
+ }
+ }
+
+ /**
+ * Prints this component. This method is provided so that printing can be
+ * done in a different manner from painting. However, the implementation
+ * in this class simply calls the <code>paint()</code> method.
+ *
+ * @param g the graphics context of the print device
+ *
+ * @see #paint(Graphics)
+ */
+ public void print(Graphics g)
+ {
+ paint(g);
+ }
+
+ /**
+ * Prints this component, including all sub-components.
+ *
+ * @param g the graphics context of the print device
+ *
+ * @see #paintAll(Graphics)
+ */
+ public void printAll(Graphics g)
+ {
+ if( peer != null )
+ peer.print( g );
+ paintAll( g );
+ }
+
+ /**
+ * Called when an image has changed so that this component is repainted.
+ * This incrementally draws an image as more bits are available, when
+ * possible. Incremental drawing is enabled if the system property
+ * <code>awt.image.incrementalDraw</code> is not present or is true, in which
+ * case the redraw rate is set to 100ms or the value of the system property
+ * <code>awt.image.redrawrate</code>.
+ *
+ * <p>The coordinate system used depends on the particular flags.
+ *
+ * @param img the image that has been updated
+ * @param flags tlags as specified in <code>ImageObserver</code>
+ * @param x the X coordinate
+ * @param y the Y coordinate
+ * @param w the width
+ * @param h the height
+ * @return false if the image is completely loaded, loading has been
+ * aborted, or an error has occurred. true if more updates are
+ * required.
+ * @see ImageObserver
+ * @see Graphics#drawImage(Image, int, int, Color, ImageObserver)
+ * @see Graphics#drawImage(Image, int, int, ImageObserver)
+ * @see Graphics#drawImage(Image, int, int, int, int, Color, ImageObserver)
+ * @see Graphics#drawImage(Image, int, int, int, int, ImageObserver)
+ * @see ImageObserver#imageUpdate(Image, int, int, int, int, int)
+ */
+ public boolean imageUpdate(Image img, int flags, int x, int y, int w, int h)
+ {
+ if ((flags & (FRAMEBITS | ALLBITS)) != 0)
+ repaint();
+ else if ((flags & SOMEBITS) != 0)
+ {
+ if (incrementalDraw)
+ {
+ if (redrawRate != null)
+ {
+ long tm = redrawRate.longValue();
+ if (tm < 0)
+ tm = 0;
+ repaint(tm);
+ }
+ else
+ repaint(100);
+ }
+ }
+ return (flags & (ALLBITS | ABORT | ERROR)) == 0;
+ }
+
+ /**
+ * Creates an image from the specified producer.
+ *
+ * @param producer the image procedure to create the image from
+ * @return the resulting image
+ */
+ public Image createImage(ImageProducer producer)
+ {
+ // Only heavyweight peers can handle this.
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ // Sun allows producer to be null.
+ Image im;
+ if (p != null)
+ im = p.createImage(producer);
+ else
+ im = getToolkit().createImage(producer);
+ return im;
+ }
+
+ /**
+ * Creates an image with the specified width and height for use in
+ * double buffering. Headless environments do not support images.
+ *
+ * @param width the width of the image
+ * @param height the height of the image
+ * @return the requested image, or null if it is not supported
+ */
+ public Image createImage (int width, int height)
+ {
+ Image returnValue = null;
+ if (!GraphicsEnvironment.isHeadless ())
+ {
+ // Only heavyweight peers can handle this.
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ if (p != null)
+ returnValue = p.createImage(width, height);
+ }
+ return returnValue;
+ }
+
+ /**
+ * Creates an image with the specified width and height for use in
+ * double buffering. Headless environments do not support images.
+ *
+ * @param width the width of the image
+ * @param height the height of the image
+ * @return the requested image, or null if it is not supported
+ * @since 1.4
+ */
+ public VolatileImage createVolatileImage(int width, int height)
+ {
+ // Only heavyweight peers can handle this.
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ VolatileImage im = null;
+ if (p != null)
+ im = p.createVolatileImage(width, height);
+ return im;
+ }
+
+ /**
+ * Creates an image with the specified width and height for use in
+ * double buffering. Headless environments do not support images. The image
+ * will support the specified capabilities.
+ *
+ * @param width the width of the image
+ * @param height the height of the image
+ * @param caps the requested capabilities
+ * @return the requested image, or null if it is not supported
+ * @throws AWTException if a buffer with the capabilities cannot be created
+ * @since 1.4
+ */
+ public VolatileImage createVolatileImage(int width, int height,
+ ImageCapabilities caps)
+ throws AWTException
+ {
+ // Only heavyweight peers can handle this.
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ VolatileImage im = null;
+ if (p != null)
+ im = peer.createVolatileImage(width, height);
+ return im;
+ }
+
+ /**
+ * Prepares the specified image for rendering on this component.
+ *
+ * @param image the image to prepare for rendering
+ * @param observer the observer to notify of image preparation status
+ * @return true if the image is already fully prepared
+ * @throws NullPointerException if image is null
+ */
+ public boolean prepareImage(Image image, ImageObserver observer)
+ {
+ return prepareImage(image, image.getWidth(observer),
+ image.getHeight(observer), observer);
+ }
+
+ /**
+ * Prepares the specified image for rendering on this component at the
+ * specified scaled width and height
+ *
+ * @param image the image to prepare for rendering
+ * @param width the scaled width of the image
+ * @param height the scaled height of the image
+ * @param observer the observer to notify of image preparation status
+ * @return true if the image is already fully prepared
+ */
+ public boolean prepareImage(Image image, int width, int height,
+ ImageObserver observer)
+ {
+ // Only heavyweight peers handle this.
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ boolean retval;
+ if (p != null)
+ retval = p.prepareImage(image, width, height, observer);
+ else
+ retval = getToolkit().prepareImage(image, width, height, observer);
+ return retval;
+ }
+
+ /**
+ * Returns the status of the loading of the specified image. The value
+ * returned will be those flags defined in <code>ImageObserver</code>.
+ *
+ * @param image the image to check on
+ * @param observer the observer to notify of image loading progress
+ * @return the image observer flags indicating the status of the load
+ * @see #prepareImage(Image, int, int, ImageObserver)
+ * @see Toolkit#checkImage(Image, int, int, ImageObserver)
+ * @throws NullPointerException if image is null
+ */
+ public int checkImage(Image image, ImageObserver observer)
+ {
+ return checkImage(image, -1, -1, observer);
+ }
+
+ /**
+ * Returns the status of the loading of the specified image. The value
+ * returned will be those flags defined in <code>ImageObserver</code>.
+ *
+ * @param image the image to check on
+ * @param width the scaled image width
+ * @param height the scaled image height
+ * @param observer the observer to notify of image loading progress
+ * @return the image observer flags indicating the status of the load
+ * @see #prepareImage(Image, int, int, ImageObserver)
+ * @see Toolkit#checkImage(Image, int, int, ImageObserver)
+ */
+ public int checkImage(Image image, int width, int height,
+ ImageObserver observer)
+ {
+ // Only heavyweight peers handle this.
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ int retval;
+ if (p != null)
+ retval = p.checkImage(image, width, height, observer);
+ else
+ retval = getToolkit().checkImage(image, width, height, observer);
+ return retval;
+ }
+
+ /**
+ * Sets whether paint messages delivered by the operating system should be
+ * ignored. This does not affect messages from AWT, except for those
+ * triggered by OS messages. Setting this to true can allow faster
+ * performance in full-screen mode or page-flipping.
+ *
+ * @param ignoreRepaint the new setting for ignoring repaint events
+ * @see #getIgnoreRepaint()
+ * @see BufferStrategy
+ * @see GraphicsDevice#setFullScreenWindow(Window)
+ * @since 1.4
+ */
+ public void setIgnoreRepaint(boolean ignoreRepaint)
+ {
+ this.ignoreRepaint = ignoreRepaint;
+ }
+
+ /**
+ * Test whether paint events from the operating system are ignored.
+ *
+ * @return the status of ignoring paint events
+ * @see #setIgnoreRepaint(boolean)
+ * @since 1.4
+ */
+ public boolean getIgnoreRepaint()
+ {
+ return ignoreRepaint;
+ }
+
+ /**
+ * Tests whether or not the specified point is contained within this
+ * component. Coordinates are relative to this component.
+ *
+ * @param x the X coordinate of the point to test
+ * @param y the Y coordinate of the point to test
+ * @return true if the point is within this component
+ * @see #getComponentAt(int, int)
+ */
+ public boolean contains(int x, int y)
+ {
+ return inside (x, y);
+ }
+
+ /**
+ * Tests whether or not the specified point is contained within this
+ * component. Coordinates are relative to this component.
+ *
+ * @param x the X coordinate of the point to test
+ * @param y the Y coordinate of the point to test
+ * @return true if the point is within this component
+ * @deprecated use {@link #contains(int, int)} instead
+ */
+ public boolean inside(int x, int y)
+ {
+ return x >= 0 && y >= 0 && x < width && y < height;
+ }
+
+ /**
+ * Tests whether or not the specified point is contained within this
+ * component. Coordinates are relative to this component.
+ *
+ * @param p the point to test
+ * @return true if the point is within this component
+ * @throws NullPointerException if p is null
+ * @see #getComponentAt(Point)
+ * @since 1.1
+ */
+ public boolean contains(Point p)
+ {
+ return contains (p.x, p.y);
+ }
+
+ /**
+ * Returns the component occupying the position (x,y). This will either
+ * be this component, an immediate child component, or <code>null</code>
+ * if neither of the first two occupies the specified location.
+ *
+ * @param x the X coordinate to search for components at
+ * @param y the Y coordinate to search for components at
+ * @return the component at the specified location, or null
+ * @see #contains(int, int)
+ */
+ public Component getComponentAt(int x, int y)
+ {
+ return locate (x, y);
+ }
+
+ /**
+ * Returns the component occupying the position (x,y). This will either
+ * be this component, an immediate child component, or <code>null</code>
+ * if neither of the first two occupies the specified location.
+ *
+ * @param x the X coordinate to search for components at
+ * @param y the Y coordinate to search for components at
+ * @return the component at the specified location, or null
+ * @deprecated use {@link #getComponentAt(int, int)} instead
+ */
+ public Component locate(int x, int y)
+ {
+ return contains (x, y) ? this : null;
+ }
+
+ /**
+ * Returns the component occupying the position (x,y). This will either
+ * be this component, an immediate child component, or <code>null</code>
+ * if neither of the first two occupies the specified location.
+ *
+ * @param p the point to search for components at
+ * @return the component at the specified location, or null
+ * @throws NullPointerException if p is null
+ * @see #contains(Point)
+ * @since 1.1
+ */
+ public Component getComponentAt(Point p)
+ {
+ return getComponentAt (p.x, p.y);
+ }
+
+ /**
+ * AWT 1.0 event delivery.
+ *
+ * Deliver an AWT 1.0 event to this Component. This method simply
+ * calls {@link #postEvent}.
+ *
+ * @param e the event to deliver
+ * @deprecated use {@link #dispatchEvent (AWTEvent)} instead
+ */
+ public void deliverEvent (Event e)
+ {
+ postEvent (e);
+ }
+
+ /**
+ * Forwards AWT events to processEvent() if:<ul>
+ * <li>Events have been enabled for this type of event via
+ * <code>enableEvents()</code></li>,
+ * <li>There is at least one registered listener for this type of event</li>
+ * </ul>
+ *
+ * @param e the event to dispatch
+ */
+ public final void dispatchEvent(AWTEvent e)
+ {
+ // Some subclasses in the AWT package need to override this behavior,
+ // hence the use of dispatchEventImpl().
+ dispatchEventImpl(e);
+ }
+
+ /**
+ * By default, no old mouse events should be ignored.
+ * This can be overridden by subclasses.
+ *
+ * @return false, no mouse events are ignored.
+ */
+ static boolean ignoreOldMouseEvents()
+ {
+ return false;
+ }
+
+ /**
+ * AWT 1.0 event handler.
+ *
+ * This method simply calls handleEvent and returns the result.
+ *
+ * @param e the event to handle
+ * @return true if the event was handled, false otherwise
+ * @deprecated use {@link #dispatchEvent(AWTEvent)} instead
+ */
+ public boolean postEvent (Event e)
+ {
+ boolean handled = handleEvent (e);
+
+ if (!handled && getParent() != null)
+ // FIXME: need to translate event coordinates to parent's
+ // coordinate space.
+ handled = getParent ().postEvent (e);
+
+ return handled;
+ }
+
+ /**
+ * Adds the specified listener to this component. This is harmless if the
+ * listener is null, but if the listener has already been registered, it
+ * will now be registered twice.
+ *
+ * @param listener the new listener to add
+ * @see ComponentEvent
+ * @see #removeComponentListener(ComponentListener)
+ * @see #getComponentListeners()
+ * @since 1.1
+ */
+ public synchronized void addComponentListener(ComponentListener listener)
+ {
+ if (listener != null)
+ {
+ componentListener = AWTEventMulticaster.add(componentListener,
+ listener);
+ newEventsOnly = true;
+ }
+ }
+
+ /**
+ * Removes the specified listener from the component. This is harmless if
+ * the listener was not previously registered.
+ *
+ * @param listener the listener to remove
+ * @see ComponentEvent
+ * @see #addComponentListener(ComponentListener)
+ * @see #getComponentListeners()
+ * @since 1.1
+ */
+ public synchronized void removeComponentListener(ComponentListener listener)
+ {
+ componentListener = AWTEventMulticaster.remove(componentListener, listener);
+ }
+
+ /**
+ * Returns an array of all specified listeners registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addComponentListener(ComponentListener)
+ * @see #removeComponentListener(ComponentListener)
+ * @since 1.4
+ */
+ public synchronized ComponentListener[] getComponentListeners()
+ {
+ return (ComponentListener[])
+ AWTEventMulticaster.getListeners(componentListener,
+ ComponentListener.class);
+ }
+
+ /**
+ * Adds the specified listener to this component. This is harmless if the
+ * listener is null, but if the listener has already been registered, it
+ * will now be registered twice.
+ *
+ * @param listener the new listener to add
+ * @see FocusEvent
+ * @see #removeFocusListener(FocusListener)
+ * @see #getFocusListeners()
+ * @since 1.1
+ */
+ public synchronized void addFocusListener(FocusListener listener)
+ {
+ if (listener != null)
+ {
+ focusListener = AWTEventMulticaster.add(focusListener, listener);
+ newEventsOnly = true;
+ }
+ }
+
+ /**
+ * Removes the specified listener from the component. This is harmless if
+ * the listener was not previously registered.
+ *
+ * @param listener the listener to remove
+ * @see FocusEvent
+ * @see #addFocusListener(FocusListener)
+ * @see #getFocusListeners()
+ * @since 1.1
+ */
+ public synchronized void removeFocusListener(FocusListener listener)
+ {
+ focusListener = AWTEventMulticaster.remove(focusListener, listener);
+ }
+
+ /**
+ * Returns an array of all specified listeners registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addFocusListener(FocusListener)
+ * @see #removeFocusListener(FocusListener)
+ * @since 1.4
+ */
+ public synchronized FocusListener[] getFocusListeners()
+ {
+ return (FocusListener[])
+ AWTEventMulticaster.getListeners(focusListener, FocusListener.class);
+ }
+
+ /**
+ * Adds the specified listener to this component. This is harmless if the
+ * listener is null, but if the listener has already been registered, it
+ * will now be registered twice.
+ *
+ * @param listener the new listener to add
+ * @see HierarchyEvent
+ * @see #removeHierarchyListener(HierarchyListener)
+ * @see #getHierarchyListeners()
+ * @since 1.3
+ */
+ public synchronized void addHierarchyListener(HierarchyListener listener)
+ {
+ if (listener != null)
+ {
+ hierarchyListener = AWTEventMulticaster.add(hierarchyListener,
+ listener);
+ newEventsOnly = true;
+ // Need to lock the tree, otherwise we might end up inconsistent.
+ synchronized (getTreeLock())
+ {
+ numHierarchyListeners++;
+ if (parent != null)
+ parent.updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK,
+ 1);
+ }
+ }
+ }
+
+ /**
+ * Removes the specified listener from the component. This is harmless if
+ * the listener was not previously registered.
+ *
+ * @param listener the listener to remove
+ * @see HierarchyEvent
+ * @see #addHierarchyListener(HierarchyListener)
+ * @see #getHierarchyListeners()
+ * @since 1.3
+ */
+ public synchronized void removeHierarchyListener(HierarchyListener listener)
+ {
+ hierarchyListener = AWTEventMulticaster.remove(hierarchyListener, listener);
+
+ // Need to lock the tree, otherwise we might end up inconsistent.
+ synchronized (getTreeLock())
+ {
+ numHierarchyListeners--;
+ if (parent != null)
+ parent.updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK,
+ -1);
+ }
+ }
+
+ /**
+ * Returns an array of all specified listeners registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addHierarchyListener(HierarchyListener)
+ * @see #removeHierarchyListener(HierarchyListener)
+ * @since 1.4
+ */
+ public synchronized HierarchyListener[] getHierarchyListeners()
+ {
+ return (HierarchyListener[])
+ AWTEventMulticaster.getListeners(hierarchyListener,
+ HierarchyListener.class);
+ }
+
+ /**
+ * Adds the specified listener to this component. This is harmless if the
+ * listener is null, but if the listener has already been registered, it
+ * will now be registered twice.
+ *
+ * @param listener the new listener to add
+ * @see HierarchyEvent
+ * @see #removeHierarchyBoundsListener(HierarchyBoundsListener)
+ * @see #getHierarchyBoundsListeners()
+ * @since 1.3
+ */
+ public synchronized void
+ addHierarchyBoundsListener(HierarchyBoundsListener listener)
+ {
+ if (listener != null)
+ {
+ hierarchyBoundsListener =
+ AWTEventMulticaster.add(hierarchyBoundsListener, listener);
+ newEventsOnly = true;
+
+ // Need to lock the tree, otherwise we might end up inconsistent.
+ synchronized (getTreeLock())
+ {
+ numHierarchyBoundsListeners++;
+ if (parent != null)
+ parent.updateHierarchyListenerCount
+ (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, 1);
+ }
+ }
+ }
+
+ /**
+ * Removes the specified listener from the component. This is harmless if
+ * the listener was not previously registered.
+ *
+ * @param listener the listener to remove
+ * @see HierarchyEvent
+ * @see #addHierarchyBoundsListener(HierarchyBoundsListener)
+ * @see #getHierarchyBoundsListeners()
+ * @since 1.3
+ */
+ public synchronized void
+ removeHierarchyBoundsListener(HierarchyBoundsListener listener)
+ {
+ hierarchyBoundsListener =
+ AWTEventMulticaster.remove(hierarchyBoundsListener, listener);
+
+ // Need to lock the tree, otherwise we might end up inconsistent.
+ synchronized (getTreeLock())
+ {
+ numHierarchyBoundsListeners--;
+ if (parent != null)
+ parent.updateHierarchyListenerCount
+ (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
+ -1);
+ }
+ }
+
+ /**
+ * Returns an array of all specified listeners registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addHierarchyBoundsListener(HierarchyBoundsListener)
+ * @see #removeHierarchyBoundsListener(HierarchyBoundsListener)
+ * @since 1.4
+ */
+ public synchronized HierarchyBoundsListener[] getHierarchyBoundsListeners()
+ {
+ return (HierarchyBoundsListener[])
+ AWTEventMulticaster.getListeners(hierarchyBoundsListener,
+ HierarchyBoundsListener.class);
+ }
+
+ /**
+ * Fires a HierarchyEvent or HierarchyChangeEvent on this component.
+ *
+ * @param id the event id
+ * @param changed the changed component
+ * @param parent the parent
+ * @param flags the event flags
+ */
+ void fireHierarchyEvent(int id, Component changed, Container parent,
+ long flags)
+ {
+ boolean enabled = false;
+ switch (id)
+ {
+ case HierarchyEvent.HIERARCHY_CHANGED:
+ enabled = hierarchyListener != null
+ || (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0;
+ break;
+ case HierarchyEvent.ANCESTOR_MOVED:
+ case HierarchyEvent.ANCESTOR_RESIZED:
+ enabled = hierarchyBoundsListener != null
+ || (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0;
+ break;
+ default:
+ assert false : "Should not reach here";
+ }
+ if (enabled)
+ {
+ HierarchyEvent ev = new HierarchyEvent(this, id, changed, parent,
+ flags);
+ dispatchEvent(ev);
+ }
+ }
+
+ /**
+ * Adds the specified listener to this component. This is harmless if the
+ * listener is null, but if the listener has already been registered, it
+ * will now be registered twice.
+ *
+ * @param listener the new listener to add
+ * @see KeyEvent
+ * @see #removeKeyListener(KeyListener)
+ * @see #getKeyListeners()
+ * @since 1.1
+ */
+ public synchronized void addKeyListener(KeyListener listener)
+ {
+ if (listener != null)
+ {
+ keyListener = AWTEventMulticaster.add(keyListener, listener);
+ newEventsOnly = true;
+ }
+ }
+
+ /**
+ * Removes the specified listener from the component. This is harmless if
+ * the listener was not previously registered.
+ *
+ * @param listener the listener to remove
+ * @see KeyEvent
+ * @see #addKeyListener(KeyListener)
+ * @see #getKeyListeners()
+ * @since 1.1
+ */
+ public synchronized void removeKeyListener(KeyListener listener)
+ {
+ keyListener = AWTEventMulticaster.remove(keyListener, listener);
+ }
+
+ /**
+ * Returns an array of all specified listeners registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addKeyListener(KeyListener)
+ * @see #removeKeyListener(KeyListener)
+ * @since 1.4
+ */
+ public synchronized KeyListener[] getKeyListeners()
+ {
+ return (KeyListener[])
+ AWTEventMulticaster.getListeners(keyListener, KeyListener.class);
+ }
+
+ /**
+ * Adds the specified listener to this component. This is harmless if the
+ * listener is null, but if the listener has already been registered, it
+ * will now be registered twice.
+ *
+ * @param listener the new listener to add
+ * @see MouseEvent
+ * @see #removeMouseListener(MouseListener)
+ * @see #getMouseListeners()
+ * @since 1.1
+ */
+ public synchronized void addMouseListener(MouseListener listener)
+ {
+ if (listener != null)
+ {
+ mouseListener = AWTEventMulticaster.add(mouseListener, listener);
+ newEventsOnly = true;
+ }
+ }
+
+ /**
+ * Removes the specified listener from the component. This is harmless if
+ * the listener was not previously registered.
+ *
+ * @param listener the listener to remove
+ * @see MouseEvent
+ * @see #addMouseListener(MouseListener)
+ * @see #getMouseListeners()
+ * @since 1.1
+ */
+ public synchronized void removeMouseListener(MouseListener listener)
+ {
+ mouseListener = AWTEventMulticaster.remove(mouseListener, listener);
+ }
+
+ /**
+ * Returns an array of all specified listeners registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addMouseListener(MouseListener)
+ * @see #removeMouseListener(MouseListener)
+ * @since 1.4
+ */
+ public synchronized MouseListener[] getMouseListeners()
+ {
+ return (MouseListener[])
+ AWTEventMulticaster.getListeners(mouseListener, MouseListener.class);
+ }
+
+ /**
+ * Adds the specified listener to this component. This is harmless if the
+ * listener is null, but if the listener has already been registered, it
+ * will now be registered twice.
+ *
+ * @param listener the new listener to add
+ * @see MouseEvent
+ * @see #removeMouseMotionListener(MouseMotionListener)
+ * @see #getMouseMotionListeners()
+ * @since 1.1
+ */
+ public synchronized void addMouseMotionListener(MouseMotionListener listener)
+ {
+ if (listener != null)
+ {
+ mouseMotionListener = AWTEventMulticaster.add(mouseMotionListener,
+ listener);
+ newEventsOnly = true;
+ }
+ }
+
+ /**
+ * Removes the specified listener from the component. This is harmless if
+ * the listener was not previously registered.
+ *
+ * @param listener the listener to remove
+ * @see MouseEvent
+ * @see #addMouseMotionListener(MouseMotionListener)
+ * @see #getMouseMotionListeners()
+ * @since 1.1
+ */
+ public synchronized void removeMouseMotionListener(MouseMotionListener listener)
+ {
+ mouseMotionListener = AWTEventMulticaster.remove(mouseMotionListener, listener);
+ }
+
+ /**
+ * Returns an array of all specified listeners registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addMouseMotionListener(MouseMotionListener)
+ * @see #removeMouseMotionListener(MouseMotionListener)
+ * @since 1.4
+ */
+ public synchronized MouseMotionListener[] getMouseMotionListeners()
+ {
+ return (MouseMotionListener[])
+ AWTEventMulticaster.getListeners(mouseMotionListener,
+ MouseMotionListener.class);
+ }
+
+ /**
+ * Adds the specified listener to this component. This is harmless if the
+ * listener is null, but if the listener has already been registered, it
+ * will now be registered twice.
+ *
+ * @param listener the new listener to add
+ * @see MouseEvent
+ * @see MouseWheelEvent
+ * @see #removeMouseWheelListener(MouseWheelListener)
+ * @see #getMouseWheelListeners()
+ * @since 1.4
+ */
+ public synchronized void addMouseWheelListener(MouseWheelListener listener)
+ {
+ if (listener != null)
+ {
+ mouseWheelListener = AWTEventMulticaster.add(mouseWheelListener,
+ listener);
+ newEventsOnly = true;
+ }
+ }
+
+ /**
+ * Removes the specified listener from the component. This is harmless if
+ * the listener was not previously registered.
+ *
+ * @param listener the listener to remove
+ * @see MouseEvent
+ * @see MouseWheelEvent
+ * @see #addMouseWheelListener(MouseWheelListener)
+ * @see #getMouseWheelListeners()
+ * @since 1.4
+ */
+ public synchronized void removeMouseWheelListener(MouseWheelListener listener)
+ {
+ mouseWheelListener = AWTEventMulticaster.remove(mouseWheelListener, listener);
+ }
+
+ /**
+ * Returns an array of all specified listeners registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addMouseWheelListener(MouseWheelListener)
+ * @see #removeMouseWheelListener(MouseWheelListener)
+ * @since 1.4
+ */
+ public synchronized MouseWheelListener[] getMouseWheelListeners()
+ {
+ return (MouseWheelListener[])
+ AWTEventMulticaster.getListeners(mouseWheelListener,
+ MouseWheelListener.class);
+ }
+
+ /**
+ * Adds the specified listener to this component. This is harmless if the
+ * listener is null, but if the listener has already been registered, it
+ * will now be registered twice.
+ *
+ * @param listener the new listener to add
+ * @see InputMethodEvent
+ * @see #removeInputMethodListener(InputMethodListener)
+ * @see #getInputMethodListeners()
+ * @see #getInputMethodRequests()
+ * @since 1.2
+ */
+ public synchronized void addInputMethodListener(InputMethodListener listener)
+ {
+ if (listener != null)
+ {
+ inputMethodListener = AWTEventMulticaster.add(inputMethodListener,
+ listener);
+ newEventsOnly = true;
+ }
+ }
+
+ /**
+ * Removes the specified listener from the component. This is harmless if
+ * the listener was not previously registered.
+ *
+ * @param listener the listener to remove
+ * @see InputMethodEvent
+ * @see #addInputMethodListener(InputMethodListener)
+ * @see #getInputMethodRequests()
+ * @since 1.2
+ */
+ public synchronized void removeInputMethodListener(InputMethodListener listener)
+ {
+ inputMethodListener = AWTEventMulticaster.remove(inputMethodListener, listener);
+ }
+
+ /**
+ * Returns an array of all specified listeners registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addInputMethodListener(InputMethodListener)
+ * @see #removeInputMethodListener(InputMethodListener)
+ * @since 1.4
+ */
+ public synchronized InputMethodListener[] getInputMethodListeners()
+ {
+ return (InputMethodListener[])
+ AWTEventMulticaster.getListeners(inputMethodListener,
+ InputMethodListener.class);
+ }
+
+ /**
+ * Returns all registered {@link EventListener}s of the given
+ * <code>listenerType</code>.
+ *
+ * @param listenerType the class of listeners to filter (<code>null</code>
+ * not permitted).
+ *
+ * @return An array of registered listeners.
+ *
+ * @throws ClassCastException if <code>listenerType</code> does not implement
+ * the {@link EventListener} interface.
+ * @throws NullPointerException if <code>listenerType</code> is
+ * <code>null</code>.
+ *
+ * @see #getComponentListeners()
+ * @see #getFocusListeners()
+ * @see #getHierarchyListeners()
+ * @see #getHierarchyBoundsListeners()
+ * @see #getKeyListeners()
+ * @see #getMouseListeners()
+ * @see #getMouseMotionListeners()
+ * @see #getMouseWheelListeners()
+ * @see #getInputMethodListeners()
+ * @see #getPropertyChangeListeners()
+ * @since 1.3
+ */
+ public <T extends EventListener> T[] getListeners(Class<T> listenerType)
+ {
+ if (listenerType == ComponentListener.class)
+ return (T[]) getComponentListeners();
+ if (listenerType == FocusListener.class)
+ return (T[]) getFocusListeners();
+ if (listenerType == HierarchyListener.class)
+ return (T[]) getHierarchyListeners();
+ if (listenerType == HierarchyBoundsListener.class)
+ return (T[]) getHierarchyBoundsListeners();
+ if (listenerType == KeyListener.class)
+ return (T[]) getKeyListeners();
+ if (listenerType == MouseListener.class)
+ return (T[]) getMouseListeners();
+ if (listenerType == MouseMotionListener.class)
+ return (T[]) getMouseMotionListeners();
+ if (listenerType == MouseWheelListener.class)
+ return (T[]) getMouseWheelListeners();
+ if (listenerType == InputMethodListener.class)
+ return (T[]) getInputMethodListeners();
+ if (listenerType == PropertyChangeListener.class)
+ return (T[]) getPropertyChangeListeners();
+ return (T[]) Array.newInstance(listenerType, 0);
+ }
+
+ /**
+ * Returns the input method request handler, for subclasses which support
+ * on-the-spot text input. By default, input methods are handled by AWT,
+ * and this returns null.
+ *
+ * @return the input method handler, null by default
+ * @since 1.2
+ */
+ public InputMethodRequests getInputMethodRequests()
+ {
+ return null;
+ }
+
+ /**
+ * Gets the input context of this component, which is inherited from the
+ * parent unless this is overridden.
+ *
+ * @return the text input context
+ * @since 1.2
+ */
+ public InputContext getInputContext()
+ {
+ return parent == null ? null : parent.getInputContext();
+ }
+
+ /**
+ * Enables the specified events. The events to enable are specified
+ * by OR-ing together the desired masks from <code>AWTEvent</code>.
+ *
+ * <p>Events are enabled by default when a listener is attached to the
+ * component for that event type. This method can be used by subclasses
+ * to ensure the delivery of a specified event regardless of whether
+ * or not a listener is attached.
+ *
+ * @param eventsToEnable the desired events to enable
+ * @see #processEvent(AWTEvent)
+ * @see #disableEvents(long)
+ * @see AWTEvent
+ * @since 1.1
+ */
+ protected final void enableEvents(long eventsToEnable)
+ {
+ // Update the counter for hierarchy (bounds) listeners.
+ if ((eventsToEnable & AWTEvent.HIERARCHY_EVENT_MASK) != 0
+ && (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) == 0)
+ {
+ // Need to lock the tree, otherwise we might end up inconsistent.
+ synchronized (getTreeLock())
+ {
+ numHierarchyListeners++;
+ if (parent != null)
+ parent.updateHierarchyListenerCount
+ (AWTEvent.HIERARCHY_EVENT_MASK,
+ 1);
+ }
+ }
+ if ((eventsToEnable & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0
+ && (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) == 0)
+ {
+ // Need to lock the tree, otherwise we might end up inconsistent.
+ synchronized (getTreeLock())
+ {
+ numHierarchyBoundsListeners++;
+ if (parent != null)
+ parent.updateHierarchyListenerCount
+ (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
+ 1);
+ }
+ }
+
+ eventMask |= eventsToEnable;
+ newEventsOnly = true;
+
+ // Only heavyweight peers handle this.
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ if (p != null)
+ p.setEventMask(eventMask);
+
+ }
+
+ /**
+ * Disables the specified events. The events to disable are specified
+ * by OR-ing together the desired masks from <code>AWTEvent</code>.
+ *
+ * @param eventsToDisable the desired events to disable
+ * @see #enableEvents(long)
+ * @since 1.1
+ */
+ protected final void disableEvents(long eventsToDisable)
+ {
+ // Update the counter for hierarchy (bounds) listeners.
+ if ((eventsToDisable & AWTEvent.HIERARCHY_EVENT_MASK) != 0
+ && (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0)
+ {
+ // Need to lock the tree, otherwise we might end up inconsistent.
+ synchronized (getTreeLock())
+ {
+ numHierarchyListeners--;
+ if (parent != null)
+ parent.updateHierarchyListenerCount
+ (AWTEvent.HIERARCHY_EVENT_MASK,
+ -1);
+ }
+ }
+ if ((eventsToDisable & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0
+ && (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0)
+ {
+ // Need to lock the tree, otherwise we might end up inconsistent.
+ synchronized (getTreeLock())
+ {
+ numHierarchyBoundsListeners--;
+ if (parent != null)
+ parent.updateHierarchyListenerCount
+ (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
+ -1);
+ }
+ }
+
+ eventMask &= ~eventsToDisable;
+
+ // Only heavyweight peers handle this.
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ if (p != null)
+ p.setEventMask(eventMask);
+
+ }
+
+ /**
+ * This is called by the EventQueue if two events with the same event id
+ * and owner component are queued. Returns a new combined event, or null if
+ * no combining is done. The coelesced events are currently mouse moves
+ * (intermediate ones are discarded) and paint events (a merged paint is
+ * created in place of the two events).
+ *
+ * @param existingEvent the event on the queue
+ * @param newEvent the new event that might be entered on the queue
+ * @return null if both events are kept, or the replacement coelesced event
+ */
+ protected AWTEvent coalesceEvents(AWTEvent existingEvent, AWTEvent newEvent)
+ {
+ AWTEvent coalesced = null;
+ switch (existingEvent.id)
+ {
+ case MouseEvent.MOUSE_MOVED:
+ case MouseEvent.MOUSE_DRAGGED:
+ // Just drop the old (intermediate) event and return the new one.
+ MouseEvent me1 = (MouseEvent) existingEvent;
+ MouseEvent me2 = (MouseEvent) newEvent;
+ if (me1.getModifiers() == me2.getModifiers())
+ coalesced = newEvent;
+ break;
+ case PaintEvent.PAINT:
+ case PaintEvent.UPDATE:
+ // For heavyweights the EventQueue should ask the peer.
+ if (peer == null || peer instanceof LightweightPeer)
+ {
+ PaintEvent pe1 = (PaintEvent) existingEvent;
+ PaintEvent pe2 = (PaintEvent) newEvent;
+ Rectangle r1 = pe1.getUpdateRect();
+ Rectangle r2 = pe2.getUpdateRect();
+ if (r1.contains(r2))
+ coalesced = existingEvent;
+ else if (r2.contains(r1))
+ coalesced = newEvent;
+ }
+ else
+ {
+ // Replace the event and let the heavyweight figure out the expanding
+ // of the repaint area.
+ coalesced = newEvent;
+ }
+ break;
+ default:
+ coalesced = null;
+ }
+ return coalesced;
+ }
+
+ /**
+ * Processes the specified event. In this class, this method simply
+ * calls one of the more specific event handlers.
+ *
+ * @param e the event to process
+ * @throws NullPointerException if e is null
+ * @see #processComponentEvent(ComponentEvent)
+ * @see #processFocusEvent(FocusEvent)
+ * @see #processKeyEvent(KeyEvent)
+ * @see #processMouseEvent(MouseEvent)
+ * @see #processMouseMotionEvent(MouseEvent)
+ * @see #processInputMethodEvent(InputMethodEvent)
+ * @see #processHierarchyEvent(HierarchyEvent)
+ * @see #processMouseWheelEvent(MouseWheelEvent)
+ * @since 1.1
+ */
+ protected void processEvent(AWTEvent e)
+ {
+ /* Note: the order of these if statements are
+ important. Subclasses must be checked first. Eg. MouseEvent
+ must be checked before ComponentEvent, since a MouseEvent
+ object is also an instance of a ComponentEvent. */
+
+ if (e instanceof FocusEvent)
+ processFocusEvent((FocusEvent) e);
+ else if (e instanceof MouseWheelEvent)
+ processMouseWheelEvent((MouseWheelEvent) e);
+ else if (e instanceof MouseEvent)
+ {
+ if (e.id == MouseEvent.MOUSE_MOVED
+ || e.id == MouseEvent.MOUSE_DRAGGED)
+ processMouseMotionEvent((MouseEvent) e);
+ else
+ processMouseEvent((MouseEvent) e);
+ }
+ else if (e instanceof KeyEvent)
+ processKeyEvent((KeyEvent) e);
+ else if (e instanceof InputMethodEvent)
+ processInputMethodEvent((InputMethodEvent) e);
+ else if (e instanceof ComponentEvent)
+ processComponentEvent((ComponentEvent) e);
+ else if (e instanceof HierarchyEvent)
+ {
+ if (e.id == HierarchyEvent.HIERARCHY_CHANGED)
+ processHierarchyEvent((HierarchyEvent) e);
+ else
+ processHierarchyBoundsEvent((HierarchyEvent) e);
+ }
+ }
+
+ /**
+ * Called when a component event is dispatched and component events are
+ * enabled. This method passes the event along to any listeners
+ * that are attached.
+ *
+ * @param e the <code>ComponentEvent</code> to process
+ * @throws NullPointerException if e is null
+ * @see ComponentListener
+ * @see #addComponentListener(ComponentListener)
+ * @see #enableEvents(long)
+ * @since 1.1
+ */
+ protected void processComponentEvent(ComponentEvent e)
+ {
+ if (componentListener == null)
+ return;
+ switch (e.id)
+ {
+ case ComponentEvent.COMPONENT_HIDDEN:
+ componentListener.componentHidden(e);
+ break;
+ case ComponentEvent.COMPONENT_MOVED:
+ componentListener.componentMoved(e);
+ break;
+ case ComponentEvent.COMPONENT_RESIZED:
+ componentListener.componentResized(e);
+ break;
+ case ComponentEvent.COMPONENT_SHOWN:
+ componentListener.componentShown(e);
+ break;
+ }
+ }
+
+ /**
+ * Called when a focus event is dispatched and component events are
+ * enabled. This method passes the event along to any listeners
+ * that are attached.
+ *
+ * @param e the <code>FocusEvent</code> to process
+ * @throws NullPointerException if e is null
+ * @see FocusListener
+ * @see #addFocusListener(FocusListener)
+ * @see #enableEvents(long)
+ * @since 1.1
+ */
+ protected void processFocusEvent(FocusEvent e)
+ {
+ if (focusListener == null)
+ return;
+
+ switch (e.id)
+ {
+ case FocusEvent.FOCUS_GAINED:
+ focusListener.focusGained(e);
+ break;
+ case FocusEvent.FOCUS_LOST:
+ focusListener.focusLost(e);
+ break;
+ }
+ }
+
+ /**
+ * Called when a key event is dispatched and component events are
+ * enabled. This method passes the event along to any listeners
+ * that are attached.
+ *
+ * @param e the <code>KeyEvent</code> to process
+ * @throws NullPointerException if e is null
+ * @see KeyListener
+ * @see #addKeyListener(KeyListener)
+ * @see #enableEvents(long)
+ * @since 1.1
+ */
+ protected void processKeyEvent(KeyEvent e)
+ {
+ if (keyListener == null)
+ return;
+ switch (e.id)
+ {
+ case KeyEvent.KEY_PRESSED:
+ keyListener.keyPressed(e);
+ break;
+ case KeyEvent.KEY_RELEASED:
+ keyListener.keyReleased(e);
+ break;
+ case KeyEvent.KEY_TYPED:
+ keyListener.keyTyped(e);
+ break;
+ }
+ }
+
+ /**
+ * Called when a regular mouse event is dispatched and component events are
+ * enabled. This method passes the event along to any listeners
+ * that are attached.
+ *
+ * @param e the <code>MouseEvent</code> to process
+ * @throws NullPointerException if e is null
+ * @see MouseListener
+ * @see #addMouseListener(MouseListener)
+ * @see #enableEvents(long)
+ * @since 1.1
+ */
+ protected void processMouseEvent(MouseEvent e)
+ {
+ if (mouseListener == null)
+ return;
+ switch (e.id)
+ {
+ case MouseEvent.MOUSE_CLICKED:
+ mouseListener.mouseClicked(e);
+ break;
+ case MouseEvent.MOUSE_ENTERED:
+ if( isLightweight() )
+ setCursor( getCursor() );
+ mouseListener.mouseEntered(e);
+ break;
+ case MouseEvent.MOUSE_EXITED:
+ mouseListener.mouseExited(e);
+ break;
+ case MouseEvent.MOUSE_PRESSED:
+ mouseListener.mousePressed(e);
+ break;
+ case MouseEvent.MOUSE_RELEASED:
+ mouseListener.mouseReleased(e);
+ break;
+ }
+ }
+
+ /**
+ * Called when a mouse motion event is dispatched and component events are
+ * enabled. This method passes the event along to any listeners
+ * that are attached.
+ *
+ * @param e the <code>MouseMotionEvent</code> to process
+ * @throws NullPointerException if e is null
+ * @see MouseMotionListener
+ * @see #addMouseMotionListener(MouseMotionListener)
+ * @see #enableEvents(long)
+ * @since 1.1
+ */
+ protected void processMouseMotionEvent(MouseEvent e)
+ {
+ if (mouseMotionListener == null)
+ return;
+ switch (e.id)
+ {
+ case MouseEvent.MOUSE_DRAGGED:
+ mouseMotionListener.mouseDragged(e);
+ break;
+ case MouseEvent.MOUSE_MOVED:
+ mouseMotionListener.mouseMoved(e);
+ break;
+ }
+ e.consume();
+ }
+
+ /**
+ * Called when a mouse wheel event is dispatched and component events are
+ * enabled. This method passes the event along to any listeners that are
+ * attached.
+ *
+ * @param e the <code>MouseWheelEvent</code> to process
+ * @throws NullPointerException if e is null
+ * @see MouseWheelListener
+ * @see #addMouseWheelListener(MouseWheelListener)
+ * @see #enableEvents(long)
+ * @since 1.4
+ */
+ protected void processMouseWheelEvent(MouseWheelEvent e)
+ {
+ if (mouseWheelListener != null
+ && e.id == MouseEvent.MOUSE_WHEEL)
+ {
+ mouseWheelListener.mouseWheelMoved(e);
+ e.consume();
+ }
+ }
+
+ /**
+ * Called when an input method event is dispatched and component events are
+ * enabled. This method passes the event along to any listeners that are
+ * attached.
+ *
+ * @param e the <code>InputMethodEvent</code> to process
+ * @throws NullPointerException if e is null
+ * @see InputMethodListener
+ * @see #addInputMethodListener(InputMethodListener)
+ * @see #enableEvents(long)
+ * @since 1.2
+ */
+ protected void processInputMethodEvent(InputMethodEvent e)
+ {
+ if (inputMethodListener == null)
+ return;
+ switch (e.id)
+ {
+ case InputMethodEvent.CARET_POSITION_CHANGED:
+ inputMethodListener.caretPositionChanged(e);
+ break;
+ case InputMethodEvent.INPUT_METHOD_TEXT_CHANGED:
+ inputMethodListener.inputMethodTextChanged(e);
+ break;
+ }
+ }
+
+ /**
+ * Called when a hierarchy change event is dispatched and component events
+ * are enabled. This method passes the event along to any listeners that are
+ * attached.
+ *
+ * @param e the <code>HierarchyEvent</code> to process
+ * @throws NullPointerException if e is null
+ * @see HierarchyListener
+ * @see #addHierarchyListener(HierarchyListener)
+ * @see #enableEvents(long)
+ * @since 1.3
+ */
+ protected void processHierarchyEvent(HierarchyEvent e)
+ {
+ if (hierarchyListener == null)
+ return;
+ if (e.id == HierarchyEvent.HIERARCHY_CHANGED)
+ hierarchyListener.hierarchyChanged(e);
+ }
+
+ /**
+ * Called when a hierarchy bounds event is dispatched and component events
+ * are enabled. This method passes the event along to any listeners that are
+ * attached.
+ *
+ * @param e the <code>HierarchyEvent</code> to process
+ * @throws NullPointerException if e is null
+ * @see HierarchyBoundsListener
+ * @see #addHierarchyBoundsListener(HierarchyBoundsListener)
+ * @see #enableEvents(long)
+ * @since 1.3
+ */
+ protected void processHierarchyBoundsEvent(HierarchyEvent e)
+ {
+ if (hierarchyBoundsListener == null)
+ return;
+ switch (e.id)
+ {
+ case HierarchyEvent.ANCESTOR_MOVED:
+ hierarchyBoundsListener.ancestorMoved(e);
+ break;
+ case HierarchyEvent.ANCESTOR_RESIZED:
+ hierarchyBoundsListener.ancestorResized(e);
+ break;
+ }
+ }
+
+ /**
+ * AWT 1.0 event handler.
+ *
+ * This method calls one of the event-specific handler methods. For
+ * example for key events, either {@link #keyDown(Event,int)}
+ * or {@link #keyUp(Event,int)} is called. A derived
+ * component can override one of these event-specific methods if it
+ * only needs to handle certain event types. Otherwise it can
+ * override handleEvent itself and handle any event.
+ *
+ * @param evt the event to handle
+ * @return true if the event was handled, false otherwise
+ * @deprecated use {@link #processEvent(AWTEvent)} instead
+ */
+ public boolean handleEvent (Event evt)
+ {
+ switch (evt.id)
+ {
+ // Handle key events.
+ case Event.KEY_ACTION:
+ case Event.KEY_PRESS:
+ return keyDown (evt, evt.key);
+ case Event.KEY_ACTION_RELEASE:
+ case Event.KEY_RELEASE:
+ return keyUp (evt, evt.key);
+
+ // Handle mouse events.
+ case Event.MOUSE_DOWN:
+ return mouseDown (evt, evt.x, evt.y);
+ case Event.MOUSE_UP:
+ return mouseUp (evt, evt.x, evt.y);
+ case Event.MOUSE_MOVE:
+ return mouseMove (evt, evt.x, evt.y);
+ case Event.MOUSE_DRAG:
+ return mouseDrag (evt, evt.x, evt.y);
+ case Event.MOUSE_ENTER:
+ return mouseEnter (evt, evt.x, evt.y);
+ case Event.MOUSE_EXIT:
+ return mouseExit (evt, evt.x, evt.y);
+
+ // Handle focus events.
+ case Event.GOT_FOCUS:
+ return gotFocus (evt, evt.arg);
+ case Event.LOST_FOCUS:
+ return lostFocus (evt, evt.arg);
+
+ // Handle action event.
+ case Event.ACTION_EVENT:
+ return action (evt, evt.arg);
+ }
+ // Unknown event.
+ return false;
+ }
+
+ /**
+ * AWT 1.0 MOUSE_DOWN event handler. This method is meant to be
+ * overridden by components providing their own MOUSE_DOWN handler.
+ * The default implementation simply returns false.
+ *
+ * @param evt the event to handle
+ * @param x the x coordinate, ignored
+ * @param y the y coordinate, ignored
+ * @return false
+ * @deprecated use {@link #processMouseEvent(MouseEvent)} instead
+ */
+ public boolean mouseDown(Event evt, int x, int y)
+ {
+ return false;
+ }
+
+ /**
+ * AWT 1.0 MOUSE_DRAG event handler. This method is meant to be
+ * overridden by components providing their own MOUSE_DRAG handler.
+ * The default implementation simply returns false.
+ *
+ * @param evt the event to handle
+ * @param x the x coordinate, ignored
+ * @param y the y coordinate, ignored
+ * @return false
+ * @deprecated use {@link #processMouseMotionEvent(MouseEvent)} instead
+ */
+ public boolean mouseDrag(Event evt, int x, int y)
+ {
+ return false;
+ }
+
+ /**
+ * AWT 1.0 MOUSE_UP event handler. This method is meant to be
+ * overridden by components providing their own MOUSE_UP handler.
+ * The default implementation simply returns false.
+ *
+ * @param evt the event to handle
+ * @param x the x coordinate, ignored
+ * @param y the y coordinate, ignored
+ * @return false
+ * @deprecated use {@link #processMouseEvent(MouseEvent)} instead
+ */
+ public boolean mouseUp(Event evt, int x, int y)
+ {
+ return false;
+ }
+
+ /**
+ * AWT 1.0 MOUSE_MOVE event handler. This method is meant to be
+ * overridden by components providing their own MOUSE_MOVE handler.
+ * The default implementation simply returns false.
+ *
+ * @param evt the event to handle
+ * @param x the x coordinate, ignored
+ * @param y the y coordinate, ignored
+ * @return false
+ * @deprecated use {@link #processMouseMotionEvent(MouseEvent)} instead
+ */
+ public boolean mouseMove(Event evt, int x, int y)
+ {
+ return false;
+ }
+
+ /**
+ * AWT 1.0 MOUSE_ENTER event handler. This method is meant to be
+ * overridden by components providing their own MOUSE_ENTER handler.
+ * The default implementation simply returns false.
+ *
+ * @param evt the event to handle
+ * @param x the x coordinate, ignored
+ * @param y the y coordinate, ignored
+ * @return false
+ * @deprecated use {@link #processMouseEvent(MouseEvent)} instead
+ */
+ public boolean mouseEnter(Event evt, int x, int y)
+ {
+ return false;
+ }
+
+ /**
+ * AWT 1.0 MOUSE_EXIT event handler. This method is meant to be
+ * overridden by components providing their own MOUSE_EXIT handler.
+ * The default implementation simply returns false.
+ *
+ * @param evt the event to handle
+ * @param x the x coordinate, ignored
+ * @param y the y coordinate, ignored
+ * @return false
+ * @deprecated use {@link #processMouseEvent(MouseEvent)} instead
+ */
+ public boolean mouseExit(Event evt, int x, int y)
+ {
+ return false;
+ }
+
+ /**
+ * AWT 1.0 KEY_PRESS and KEY_ACTION event handler. This method is
+ * meant to be overridden by components providing their own key
+ * press handler. The default implementation simply returns false.
+ *
+ * @param evt the event to handle
+ * @param key the key pressed, ignored
+ * @return false
+ * @deprecated use {@link #processKeyEvent(KeyEvent)} instead
+ */
+ public boolean keyDown(Event evt, int key)
+ {
+ return false;
+ }
+
+ /**
+ * AWT 1.0 KEY_RELEASE and KEY_ACTION_RELEASE event handler. This
+ * method is meant to be overridden by components providing their
+ * own key release handler. The default implementation simply
+ * returns false.
+ *
+ * @param evt the event to handle
+ * @param key the key pressed, ignored
+ * @return false
+ * @deprecated use {@link #processKeyEvent(KeyEvent)} instead
+ */
+ public boolean keyUp(Event evt, int key)
+ {
+ return false;
+ }
+
+ /**
+ * AWT 1.0 ACTION_EVENT event handler. This method is meant to be
+ * overridden by components providing their own action event
+ * handler. The default implementation simply returns false.
+ *
+ * @param evt the event to handle
+ * @param what the object acted on, ignored
+ * @return false
+ * @deprecated in classes which support actions, use
+ * <code>processActionEvent(ActionEvent)</code> instead
+ */
+ public boolean action(Event evt, Object what)
+ {
+ return false;
+ }
+
+ /**
+ * Called when the parent of this Component is made visible or when
+ * the Component is added to an already visible Container and needs
+ * to be shown. A native peer - if any - is created at this
+ * time. This method is called automatically by the AWT system and
+ * should not be called by user level code.
+ *
+ * @see #isDisplayable()
+ * @see #removeNotify()
+ */
+ public void addNotify()
+ {
+ // We need to lock the tree here to avoid races and inconsistencies.
+ synchronized (getTreeLock())
+ {
+ if (peer == null)
+ peer = getToolkit().createComponent(this);
+ else if (parent != null && parent.isLightweight())
+ new HeavyweightInLightweightListener(parent);
+ // Now that all the children has gotten their peers, we should
+ // have the event mask needed for this component and its
+ //lightweight subcomponents.
+ peer.setEventMask(eventMask);
+
+ // We used to leave the invalidate() to the peer. However, I put it
+ // back here for 2 reasons: 1) The RI does call invalidate() from
+ // addNotify(); 2) The peer shouldn't be bother with validation too
+ // much.
+ invalidate();
+
+ if (dropTarget != null)
+ dropTarget.addNotify(peer);
+
+ // Fetch the peerFont for later installation in validate().
+ peerFont = getFont();
+
+ // Notify hierarchy listeners.
+ long flags = HierarchyEvent.DISPLAYABILITY_CHANGED;
+ if (isHierarchyVisible())
+ flags |= HierarchyEvent.SHOWING_CHANGED;
+ fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, this, parent,
+ flags);
+ }
+ }
+
+ /**
+ * Called to inform this component is has been removed from its
+ * container. Its native peer - if any - is destroyed at this time.
+ * This method is called automatically by the AWT system and should
+ * not be called by user level code.
+ *
+ * @see #isDisplayable()
+ * @see #addNotify()
+ */
+ public void removeNotify()
+ {
+ // We need to lock the tree here to avoid races and inconsistencies.
+ synchronized (getTreeLock())
+ {
+ // We null our peer field before disposing of it, such that if we're
+ // not the event dispatch thread and the dispatch thread is awoken by
+ // the dispose call, there will be no race checking the peer's null
+ // status.
+
+ ComponentPeer tmp = peer;
+ peer = null;
+ peerFont = null;
+ if (tmp != null)
+ {
+ tmp.hide();
+ tmp.dispose();
+ }
+
+ // Notify hierarchy listeners.
+ long flags = HierarchyEvent.DISPLAYABILITY_CHANGED;
+ if (isHierarchyVisible())
+ flags |= HierarchyEvent.SHOWING_CHANGED;
+ fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, this, parent,
+ flags);
+ }
+ }
+
+ /**
+ * AWT 1.0 GOT_FOCUS event handler. This method is meant to be
+ * overridden by components providing their own GOT_FOCUS handler.
+ * The default implementation simply returns false.
+ *
+ * @param evt the event to handle
+ * @param what the Object focused, ignored
+ * @return false
+ * @deprecated use {@link #processFocusEvent(FocusEvent)} instead
+ */
+ public boolean gotFocus(Event evt, Object what)
+ {
+ return false;
+ }
+
+ /**
+ * AWT 1.0 LOST_FOCUS event handler. This method is meant to be
+ * overridden by components providing their own LOST_FOCUS handler.
+ * The default implementation simply returns false.
+ *
+ * @param evt the event to handle
+ * @param what the Object focused, ignored
+ * @return false
+ * @deprecated use {@link #processFocusEvent(FocusEvent)} instead
+ */
+ public boolean lostFocus(Event evt, Object what)
+ {
+ return false;
+ }
+
+ /**
+ * Tests whether or not this component is in the group that can be
+ * traversed using the keyboard traversal mechanism (such as the TAB key).
+ *
+ * @return true if the component is traversed via the TAB key
+ * @see #setFocusable(boolean)
+ * @since 1.1
+ * @deprecated use {@link #isFocusable()} instead
+ */
+ public boolean isFocusTraversable()
+ {
+ return enabled && visible && (peer == null || isLightweight() || peer.isFocusTraversable());
+ }
+
+ /**
+ * Tests if this component can receive focus.
+ *
+ * @return true if this component can receive focus
+ * @since 1.4
+ */
+ public boolean isFocusable()
+ {
+ return focusable;
+ }
+
+ /**
+ * Specify whether this component can receive focus. This method also
+ * sets the {@link #isFocusTraversableOverridden} field to 1, which
+ * appears to be the undocumented way {@link
+ * DefaultFocusTraversalPolicy#accept(Component)} determines whether to
+ * respect the {@link #isFocusable()} method of the component.
+ *
+ * @param focusable the new focusable status
+ * @since 1.4
+ */
+ public void setFocusable(boolean focusable)
+ {
+ firePropertyChange("focusable", this.focusable, focusable);
+ this.focusable = focusable;
+ this.isFocusTraversableOverridden = 1;
+ }
+
+ /**
+ * Sets the focus traversal keys for one of the three focus
+ * traversal directions supported by Components:
+ * {@link KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS},
+ * {@link KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS}, or
+ * {@link KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS}. Normally, the
+ * default values should match the operating system's native
+ * choices. To disable a given traversal, use
+ * <code>Collections.EMPTY_SET</code>. The event dispatcher will
+ * consume PRESSED, RELEASED, and TYPED events for the specified
+ * key, although focus can only transfer on PRESSED or RELEASED.
+ *
+ * <p>The defaults are:
+ * <table>
+ * <th><td>Identifier</td><td>Meaning</td><td>Default</td></th>
+ * <tr><td>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</td>
+ * <td>Normal forward traversal</td>
+ * <td>TAB on KEY_PRESSED, Ctrl-TAB on KEY_PRESSED</td></tr>
+ * <tr><td>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</td>
+ * <td>Normal backward traversal</td>
+ * <td>Shift-TAB on KEY_PRESSED, Ctrl-Shift-TAB on KEY_PRESSED</td></tr>
+ * <tr><td>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</td>
+ * <td>Go up a traversal cycle</td><td>None</td></tr>
+ * </table>
+ *
+ * If keystrokes is null, this component's focus traversal key set
+ * is inherited from one of its ancestors. If none of its ancestors
+ * has its own set of focus traversal keys, the focus traversal keys
+ * are set to the defaults retrieved from the current
+ * KeyboardFocusManager. If not null, the set must contain only
+ * AWTKeyStrokes that are not already focus keys and are not
+ * KEY_TYPED events.
+ *
+ * @param id one of FORWARD_TRAVERSAL_KEYS, BACKWARD_TRAVERSAL_KEYS, or
+ * UP_CYCLE_TRAVERSAL_KEYS
+ * @param keystrokes a set of keys, or null
+ * @throws IllegalArgumentException if id or keystrokes is invalid
+ * @see #getFocusTraversalKeys(int)
+ * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
+ * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
+ * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
+ * @since 1.4
+ */
+ public void setFocusTraversalKeys(int id,
+ Set<? extends AWTKeyStroke> keystrokes)
+ {
+ if (keystrokes == null)
+ {
+ Container parent = getParent ();
+
+ while (parent != null)
+ {
+ if (parent.areFocusTraversalKeysSet (id))
+ {
+ keystrokes = parent.getFocusTraversalKeys (id);
+ break;
+ }
+ parent = parent.getParent ();
+ }
+
+ if (keystrokes == null)
+ keystrokes = KeyboardFocusManager.getCurrentKeyboardFocusManager ().
+ getDefaultFocusTraversalKeys (id);
+ }
+
+ Set sa;
+ Set sb;
+ String name;
+ switch (id)
+ {
+ case KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS:
+ sa = getFocusTraversalKeys
+ (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
+ sb = getFocusTraversalKeys
+ (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
+ name = "forwardFocusTraversalKeys";
+ break;
+ case KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS:
+ sa = getFocusTraversalKeys
+ (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
+ sb = getFocusTraversalKeys
+ (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
+ name = "backwardFocusTraversalKeys";
+ break;
+ case KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS:
+ sa = getFocusTraversalKeys
+ (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
+ sb = getFocusTraversalKeys
+ (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
+ name = "upCycleFocusTraversalKeys";
+ break;
+ default:
+ throw new IllegalArgumentException ();
+ }
+
+ int i = keystrokes.size ();
+ Iterator iter = keystrokes.iterator ();
+
+ while (--i >= 0)
+ {
+ Object o = iter.next ();
+ if (!(o instanceof AWTKeyStroke)
+ || sa.contains (o) || sb.contains (o)
+ || ((AWTKeyStroke) o).keyCode == KeyEvent.VK_UNDEFINED)
+ throw new IllegalArgumentException ();
+ }
+
+ if (focusTraversalKeys == null)
+ focusTraversalKeys = new Set[3];
+
+ keystrokes = Collections.unmodifiableSet (new HashSet (keystrokes));
+ firePropertyChange (name, focusTraversalKeys[id], keystrokes);
+
+ focusTraversalKeys[id] = keystrokes;
+ }
+
+ /**
+ * Returns the set of keys for a given focus traversal action, as
+ * defined in <code>setFocusTraversalKeys</code>. If not set, this
+ * is inherited from the parent component, which may have gotten it
+ * from the KeyboardFocusManager.
+ *
+ * @param id one of FORWARD_TRAVERSAL_KEYS, BACKWARD_TRAVERSAL_KEYS,
+ * or UP_CYCLE_TRAVERSAL_KEYS
+ *
+ * @return set of traversal keys
+ *
+ * @throws IllegalArgumentException if id is invalid
+ *
+ * @see #setFocusTraversalKeys (int, Set)
+ * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
+ * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
+ * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
+ *
+ * @since 1.4
+ */
+ public Set<AWTKeyStroke> getFocusTraversalKeys (int id)
+ {
+ if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS)
+ throw new IllegalArgumentException();
+
+ Set<AWTKeyStroke> s = null;
+
+ if (focusTraversalKeys != null)
+ s = focusTraversalKeys[id];
+
+ if (s == null && parent != null)
+ s = parent.getFocusTraversalKeys (id);
+
+ return s == null ? (KeyboardFocusManager.getCurrentKeyboardFocusManager()
+ .getDefaultFocusTraversalKeys(id)) : s;
+ }
+
+ /**
+ * Tests whether the focus traversal keys for a given action are explicitly
+ * set or inherited.
+ *
+ * @param id one of FORWARD_TRAVERSAL_KEYS, BACKWARD_TRAVERSAL_KEYS,
+ * or UP_CYCLE_TRAVERSAL_KEYS
+ * @return true if that set is explicitly specified
+ * @throws IllegalArgumentException if id is invalid
+ * @see #getFocusTraversalKeys (int)
+ * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
+ * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
+ * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
+ * @since 1.4
+ */
+ public boolean areFocusTraversalKeysSet (int id)
+ {
+ if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
+ id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS)
+ throw new IllegalArgumentException ();
+
+ return focusTraversalKeys != null && focusTraversalKeys[id] != null;
+ }
+
+ /**
+ * Enable or disable focus traversal keys on this Component. If
+ * they are, then the keyboard focus manager consumes and acts on
+ * key press and release events that trigger focus traversal, and
+ * discards the corresponding key typed events. If focus traversal
+ * keys are disabled, then all key events that would otherwise
+ * trigger focus traversal are sent to this Component.
+ *
+ * @param focusTraversalKeysEnabled the new value of the flag
+ * @see #getFocusTraversalKeysEnabled ()
+ * @see #setFocusTraversalKeys (int, Set)
+ * @see #getFocusTraversalKeys (int)
+ * @since 1.4
+ */
+ public void setFocusTraversalKeysEnabled (boolean focusTraversalKeysEnabled)
+ {
+ firePropertyChange ("focusTraversalKeysEnabled",
+ this.focusTraversalKeysEnabled,
+ focusTraversalKeysEnabled);
+ this.focusTraversalKeysEnabled = focusTraversalKeysEnabled;
+ }
+
+ /**
+ * Check whether or not focus traversal keys are enabled on this
+ * Component. If they are, then the keyboard focus manager consumes
+ * and acts on key press and release events that trigger focus
+ * traversal, and discards the corresponding key typed events. If
+ * focus traversal keys are disabled, then all key events that would
+ * otherwise trigger focus traversal are sent to this Component.
+ *
+ * @return true if focus traversal keys are enabled
+ * @see #setFocusTraversalKeysEnabled (boolean)
+ * @see #setFocusTraversalKeys (int, Set)
+ * @see #getFocusTraversalKeys (int)
+ * @since 1.4
+ */
+ public boolean getFocusTraversalKeysEnabled ()
+ {
+ return focusTraversalKeysEnabled;
+ }
+
+ /**
+ * Request that this Component be given the keyboard input focus and
+ * that its top-level ancestor become the focused Window.
+ *
+ * For the request to be granted, the Component must be focusable,
+ * displayable and showing and the top-level Window to which it
+ * belongs must be focusable. If the request is initially denied on
+ * the basis that the top-level Window is not focusable, the request
+ * will be remembered and granted when the Window does become
+ * focused.
+ *
+ * Never assume that this Component is the focus owner until it
+ * receives a FOCUS_GAINED event.
+ *
+ * The behaviour of this method is platform-dependent.
+ * {@link #requestFocusInWindow()} should be used instead.
+ *
+ * @see #requestFocusInWindow ()
+ * @see FocusEvent
+ * @see #addFocusListener (FocusListener)
+ * @see #isFocusable ()
+ * @see #isDisplayable ()
+ * @see KeyboardFocusManager#clearGlobalFocusOwner ()
+ */
+ public void requestFocus ()
+ {
+ requestFocusImpl(false, true);
+ }
+
+ /**
+ * Request that this Component be given the keyboard input focus and
+ * that its top-level ancestor become the focused Window.
+ *
+ * For the request to be granted, the Component must be focusable,
+ * displayable and showing and the top-level Window to which it
+ * belongs must be focusable. If the request is initially denied on
+ * the basis that the top-level Window is not focusable, the request
+ * will be remembered and granted when the Window does become
+ * focused.
+ *
+ * Never assume that this Component is the focus owner until it
+ * receives a FOCUS_GAINED event.
+ *
+ * The behaviour of this method is platform-dependent.
+ * {@link #requestFocusInWindow()} should be used instead.
+ *
+ * If the return value is false, the request is guaranteed to fail.
+ * If the return value is true, the request will succeed unless it
+ * is vetoed or something in the native windowing system intervenes,
+ * preventing this Component's top-level ancestor from becoming
+ * focused. This method is meant to be called by derived
+ * lightweight Components that want to avoid unnecessary repainting
+ * when they know a given focus transfer need only be temporary.
+ *
+ * @param temporary true if the focus request is temporary
+ * @return true if the request has a chance of success
+ * @see #requestFocusInWindow ()
+ * @see FocusEvent
+ * @see #addFocusListener (FocusListener)
+ * @see #isFocusable ()
+ * @see #isDisplayable ()
+ * @see KeyboardFocusManager#clearGlobalFocusOwner ()
+ * @since 1.4
+ */
+ protected boolean requestFocus (boolean temporary)
+ {
+ return requestFocusImpl(temporary, true);
+ }
+
+ /**
+ * Request that this component be given the keyboard input focus, if
+ * its top-level ancestor is the currently focused Window. A
+ * <code>FOCUS_GAINED</code> event will be fired if and only if this
+ * request is successful. To be successful, the component must be
+ * displayable, showing, and focusable, and its ancestor top-level
+ * Window must be focused.
+ *
+ * If the return value is false, the request is guaranteed to fail.
+ * If the return value is true, the request will succeed unless it
+ * is vetoed or something in the native windowing system intervenes,
+ * preventing this Component's top-level ancestor from becoming
+ * focused.
+ *
+ * @return true if the request has a chance of success
+ * @see #requestFocus ()
+ * @see FocusEvent
+ * @see #addFocusListener (FocusListener)
+ * @see #isFocusable ()
+ * @see #isDisplayable ()
+ * @see KeyboardFocusManager#clearGlobalFocusOwner ()
+ * @since 1.4
+ */
+ public boolean requestFocusInWindow ()
+ {
+ return requestFocusImpl(false, false);
+ }
+
+ /**
+ * Request that this component be given the keyboard input focus, if
+ * its top-level ancestor is the currently focused Window. A
+ * <code>FOCUS_GAINED</code> event will be fired if and only if this
+ * request is successful. To be successful, the component must be
+ * displayable, showing, and focusable, and its ancestor top-level
+ * Window must be focused.
+ *
+ * If the return value is false, the request is guaranteed to fail.
+ * If the return value is true, the request will succeed unless it
+ * is vetoed or something in the native windowing system intervenes,
+ * preventing this Component's top-level ancestor from becoming
+ * focused. This method is meant to be called by derived
+ * lightweight Components that want to avoid unnecessary repainting
+ * when they know a given focus transfer need only be temporary.
+ *
+ * @param temporary true if the focus request is temporary
+ * @return true if the request has a chance of success
+ * @see #requestFocus ()
+ * @see FocusEvent
+ * @see #addFocusListener (FocusListener)
+ * @see #isFocusable ()
+ * @see #isDisplayable ()
+ * @see KeyboardFocusManager#clearGlobalFocusOwner ()
+ * @since 1.4
+ */
+ protected boolean requestFocusInWindow (boolean temporary)
+ {
+ return requestFocusImpl(temporary, false);
+ }
+
+ /**
+ * Helper method for all 4 requestFocus variants.
+ *
+ * @param temporary indicates if the focus change is temporary
+ * @param focusWindow indicates if the window focus may be changed
+ *
+ * @return <code>false</code> if the request has been definitely denied,
+ * <code>true</code> otherwise
+ */
+ private boolean requestFocusImpl(boolean temporary, boolean focusWindow)
+ {
+ boolean retval = false;
+
+ // Don't try to focus non-focusable and non-visible components.
+ if (isFocusable() && isVisible())
+ {
+ ComponentPeer myPeer = peer;
+ if (peer != null)
+ {
+ // Find Window ancestor and find out if we're showing while
+ // doing this.
+ boolean showing = true;
+ Component window = this;
+ while (! (window instanceof Window))
+ {
+ if (! window.isVisible())
+ showing = false;
+ window = window.parent;
+ }
+ // Don't allow focus when there is no window or the window
+ // is not focusable.
+ if (window != null && ((Window) window).isFocusableWindow()
+ && showing)
+ {
+ // Search for nearest heavy ancestor (including this
+ // component).
+ Component heavyweightParent = this;
+ while (heavyweightParent.peer instanceof LightweightPeer)
+ heavyweightParent = heavyweightParent.parent;
+
+ // Don't allow focus on lightweight components without
+ // visible heavyweight ancestor
+ if (heavyweightParent != null && heavyweightParent.isVisible())
+ {
+ // Don't allow focus when heavyweightParent has no peer.
+ myPeer = heavyweightParent.peer;
+ if (myPeer != null)
+ {
+ // Register lightweight focus request.
+ if (heavyweightParent != this)
+ {
+ KeyboardFocusManager
+ .addLightweightFocusRequest(heavyweightParent,
+ this);
+ }
+
+ // Try to focus the component.
+ long time = EventQueue.getMostRecentEventTime();
+ boolean success = myPeer.requestFocus(this, temporary,
+ focusWindow,
+ time);
+ if (! success)
+ {
+ // Dequeue key events if focus request failed.
+ KeyboardFocusManager kfm =
+ KeyboardFocusManager.getCurrentKeyboardFocusManager();
+ kfm.dequeueKeyEvents(time, this);
+ }
+ retval = success;
+ }
+ }
+ }
+ }
+ }
+ return retval;
+ }
+
+ /**
+ * Transfers focus to the next component in the focus traversal
+ * order, as though this were the current focus owner.
+ *
+ * @see #requestFocus()
+ * @since 1.1
+ */
+ public void transferFocus ()
+ {
+ nextFocus ();
+ }
+
+ /**
+ * Returns the root container that owns the focus cycle where this
+ * component resides. A focus cycle root is in two cycles, one as
+ * the ancestor, and one as the focusable element; this call always
+ * returns the ancestor.
+ *
+ * @return the ancestor container that owns the focus cycle
+ * @since 1.4
+ */
+ public Container getFocusCycleRootAncestor ()
+ {
+ Container parent = getParent ();
+
+ while (parent != null && !parent.isFocusCycleRoot())
+ parent = parent.getParent ();
+
+ return parent;
+ }
+
+ /**
+ * Tests if the container is the ancestor of the focus cycle that
+ * this component belongs to.
+ *
+ * @param c the container to test
+ * @return true if c is the focus cycle root
+ * @since 1.4
+ */
+ public boolean isFocusCycleRoot (Container c)
+ {
+ return c == getFocusCycleRootAncestor ();
+ }
+
+ /**
+ * AWT 1.0 focus event processor. Transfers focus to the next
+ * component in the focus traversal order, as though this were the
+ * current focus owner.
+ *
+ * @deprecated use {@link #transferFocus ()} instead
+ */
+ public void nextFocus ()
+ {
+ // Find the nearest valid (== showing && focusable && enabled) focus
+ // cycle root ancestor and the focused component in it.
+ Container focusRoot = getFocusCycleRootAncestor();
+ Component focusComp = this;
+ while (focusRoot != null
+ && ! (focusRoot.isShowing() && focusRoot.isFocusable()
+ && focusRoot.isEnabled()))
+ {
+ focusComp = focusRoot;
+ focusRoot = focusComp.getFocusCycleRootAncestor();
+ }
+
+ if (focusRoot != null)
+ {
+ // First try to get the componentBefore from the policy.
+ FocusTraversalPolicy policy = focusRoot.getFocusTraversalPolicy();
+ Component nextFocus = policy.getComponentAfter(focusRoot, focusComp);
+
+ // If this fails, then ask for the defaultComponent.
+ if (nextFocus == null)
+ nextFocus = policy.getDefaultComponent(focusRoot);
+
+ // Request focus on this component, if not null.
+ if (nextFocus != null)
+ nextFocus.requestFocus();
+ }
+ }
+
+ /**
+ * Transfers focus to the previous component in the focus traversal
+ * order, as though this were the current focus owner.
+ *
+ * @see #requestFocus ()
+ * @since 1.4
+ */
+ public void transferFocusBackward ()
+ {
+ // Find the nearest valid (== showing && focusable && enabled) focus
+ // cycle root ancestor and the focused component in it.
+ Container focusRoot = getFocusCycleRootAncestor();
+ Component focusComp = this;
+ while (focusRoot != null
+ && ! (focusRoot.isShowing() && focusRoot.isFocusable()
+ && focusRoot.isEnabled()))
+ {
+ focusComp = focusRoot;
+ focusRoot = focusComp.getFocusCycleRootAncestor();
+ }
+
+ if (focusRoot != null)
+ {
+ // First try to get the componentBefore from the policy.
+ FocusTraversalPolicy policy = focusRoot.getFocusTraversalPolicy();
+ Component nextFocus = policy.getComponentBefore(focusRoot, focusComp);
+
+ // If this fails, then ask for the defaultComponent.
+ if (nextFocus == null)
+ nextFocus = policy.getDefaultComponent(focusRoot);
+
+ // Request focus on this component, if not null.
+ if (nextFocus != null)
+ nextFocus.requestFocus();
+ }
+ }
+
+ /**
+ * Transfers focus to the focus cycle root of this component.
+ * However, if this is a Window, the default focus owner in the
+ * window in the current focus cycle is focused instead.
+ *
+ * @see #requestFocus()
+ * @see #isFocusCycleRoot(Container)
+ * @since 1.4
+ */
+ public void transferFocusUpCycle ()
+ {
+ // Find the nearest focus cycle root ancestor that is itself
+ // focusable, showing and enabled.
+ Container focusCycleRoot = getFocusCycleRootAncestor();
+ while (focusCycleRoot != null &&
+ ! (focusCycleRoot.isShowing() && focusCycleRoot.isFocusable()
+ && focusCycleRoot.isEnabled()))
+ {
+ focusCycleRoot = focusCycleRoot.getFocusCycleRootAncestor();
+ }
+
+ KeyboardFocusManager fm =
+ KeyboardFocusManager.getCurrentKeyboardFocusManager();
+
+ if (focusCycleRoot != null)
+ {
+ // If we found a focus cycle root, then we make this the new
+ // focused component, and make it's focus cycle root the new
+ // global focus cycle root. If the found root has no focus cycle
+ // root ancestor itself, then the component will be both the focused
+ // component and the new global focus cycle root.
+ Container focusCycleAncestor =
+ focusCycleRoot.getFocusCycleRootAncestor();
+ Container globalFocusCycleRoot;
+ if (focusCycleAncestor == null)
+ globalFocusCycleRoot = focusCycleRoot;
+ else
+ globalFocusCycleRoot = focusCycleAncestor;
+
+ fm.setGlobalCurrentFocusCycleRoot(globalFocusCycleRoot);
+ focusCycleRoot.requestFocus();
+ }
+ else
+ {
+ // If this component has no applicable focus cycle root, we try
+ // find the nearest window and set this as the new global focus cycle
+ // root and the default focus component of this window the new focused
+ // component.
+ Container cont;
+ if (this instanceof Container)
+ cont = (Container) this;
+ else
+ cont = getParent();
+
+ while (cont != null && !(cont instanceof Window))
+ cont = cont.getParent();
+
+ if (cont != null)
+ {
+ FocusTraversalPolicy policy = cont.getFocusTraversalPolicy();
+ Component focusComp = policy.getDefaultComponent(cont);
+ if (focusComp != null)
+ {
+ fm.setGlobalCurrentFocusCycleRoot(cont);
+ focusComp.requestFocus();
+ }
+ }
+ }
+ }
+
+ /**
+ * Tests if this component is the focus owner. Use {@link
+ * #isFocusOwner ()} instead.
+ *
+ * @return true if this component owns focus
+ * @since 1.2
+ */
+ public boolean hasFocus ()
+ {
+ KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
+
+ Component focusOwner = manager.getFocusOwner ();
+
+ return this == focusOwner;
+ }
+
+ /**
+ * Tests if this component is the focus owner.
+ *
+ * @return true if this component owns focus
+ * @since 1.4
+ */
+ public boolean isFocusOwner()
+ {
+ return hasFocus ();
+ }
+
+ /**
+ * Adds the specified popup menu to this component.
+ *
+ * @param popup the popup menu to be added
+ *
+ * @see #remove(MenuComponent)
+ *
+ * @since 1.1
+ */
+ public synchronized void add(PopupMenu popup)
+ {
+ if (popups == null)
+ popups = new Vector();
+ popups.add(popup);
+
+ if (popup.parent != null)
+ popup.parent.remove(popup);
+ popup.parent = this;
+ if (peer != null)
+ popup.addNotify();
+ }
+
+ /**
+ * Removes the specified popup menu from this component.
+ *
+ * @param popup the popup menu to remove
+ * @see #add(PopupMenu)
+ * @since 1.1
+ */
+ public synchronized void remove(MenuComponent popup)
+ {
+ if (popups != null)
+ popups.remove(popup);
+ }
+
+ /**
+ * Returns a debugging string representing this component. The string may
+ * be empty but not null.
+ *
+ * @return a string representing this component
+ */
+ protected String paramString()
+ {
+ CPStringBuilder param = new CPStringBuilder();
+ String name = getName();
+ if (name != null)
+ param.append(name).append(",");
+ param.append(x).append(",").append(y).append(",").append(width)
+ .append("x").append(height);
+ if (! isValid())
+ param.append(",invalid");
+ if (! isVisible())
+ param.append(",invisible");
+ if (! isEnabled())
+ param.append(",disabled");
+ if (! isOpaque())
+ param.append(",translucent");
+ if (isDoubleBuffered())
+ param.append(",doublebuffered");
+ if (parent == null)
+ param.append(",parent=null");
+ else
+ param.append(",parent=").append(parent.getName());
+ return param.toString();
+ }
+
+ /**
+ * Returns a string representation of this component. This is implemented
+ * as <code>getClass().getName() + '[' + paramString() + ']'</code>.
+ *
+ * @return a string representation of this component
+ */
+ public String toString()
+ {
+ return getClass().getName() + '[' + paramString() + ']';
+ }
+
+ /**
+ * Prints a listing of this component to <code>System.out</code>.
+ *
+ * @see #list(PrintStream)
+ */
+ public void list()
+ {
+ list(System.out, 0);
+ }
+
+ /**
+ * Prints a listing of this component to the specified print stream.
+ *
+ * @param out the <code>PrintStream</code> to print to
+ */
+ public void list(PrintStream out)
+ {
+ list(out, 0);
+ }
+
+ /**
+ * Prints a listing of this component to the specified print stream,
+ * starting at the specified indentation point.
+ *
+ * @param out the <code>PrintStream</code> to print to
+ * @param indent the indentation point
+ */
+ public void list(PrintStream out, int indent)
+ {
+ for (int i = 0; i < indent; ++i)
+ out.print(' ');
+ out.println(toString());
+ }
+
+ /**
+ * Prints a listing of this component to the specified print writer.
+ *
+ * @param out the <code>PrintWrinter</code> to print to
+ * @since 1.1
+ */
+ public void list(PrintWriter out)
+ {
+ list(out, 0);
+ }
+
+ /**
+ * Prints a listing of this component to the specified print writer,
+ * starting at the specified indentation point.
+ *
+ * @param out the <code>PrintWriter</code> to print to
+ * @param indent the indentation point
+ * @since 1.1
+ */
+ public void list(PrintWriter out, int indent)
+ {
+ for (int i = 0; i < indent; ++i)
+ out.print(' ');
+ out.println(toString());
+ }
+
+ /**
+ * Adds the specified property listener to this component. This is harmless
+ * if the listener is null, but if the listener has already been registered,
+ * it will now be registered twice. The property listener ignores inherited
+ * properties. Recognized properties include:<br>
+ * <ul>
+ * <li>the font (<code>"font"</code>)</li>
+ * <li>the background color (<code>"background"</code>)</li>
+ * <li>the foreground color (<code>"foreground"</code>)</li>
+ * <li>the focusability (<code>"focusable"</code>)</li>
+ * <li>the focus key traversal enabled state
+ * (<code>"focusTraversalKeysEnabled"</code>)</li>
+ * <li>the set of forward traversal keys
+ * (<code>"forwardFocusTraversalKeys"</code>)</li>
+ * <li>the set of backward traversal keys
+ * (<code>"backwardFocusTraversalKeys"</code>)</li>
+ * <li>the set of up-cycle traversal keys
+ * (<code>"upCycleFocusTraversalKeys"</code>)</li>
+ * </ul>
+ *
+ * @param listener the new listener to add
+ * @see #removePropertyChangeListener(PropertyChangeListener)
+ * @see #getPropertyChangeListeners()
+ * @see #addPropertyChangeListener(String, PropertyChangeListener)
+ * @since 1.1
+ */
+ public void addPropertyChangeListener(PropertyChangeListener listener)
+ {
+ if (changeSupport == null)
+ changeSupport = new PropertyChangeSupport(this);
+ changeSupport.addPropertyChangeListener(listener);
+ }
+
+ /**
+ * Removes the specified property listener from the component. This is
+ * harmless if the listener was not previously registered.
+ *
+ * @param listener the listener to remove
+ * @see #addPropertyChangeListener(PropertyChangeListener)
+ * @see #getPropertyChangeListeners()
+ * @see #removePropertyChangeListener(String, PropertyChangeListener)
+ * @since 1.1
+ */
+ public void removePropertyChangeListener(PropertyChangeListener listener)
+ {
+ if (changeSupport != null)
+ changeSupport.removePropertyChangeListener(listener);
+ }
+
+ /**
+ * Returns an array of all specified listeners registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addPropertyChangeListener(PropertyChangeListener)
+ * @see #removePropertyChangeListener(PropertyChangeListener)
+ * @see #getPropertyChangeListeners(String)
+ * @since 1.4
+ */
+ public PropertyChangeListener[] getPropertyChangeListeners()
+ {
+ return changeSupport == null ? new PropertyChangeListener[0]
+ : changeSupport.getPropertyChangeListeners();
+ }
+
+ /**
+ * Adds the specified property listener to this component. This is harmless
+ * if the listener is null, but if the listener has already been registered,
+ * it will now be registered twice. The property listener ignores inherited
+ * properties. The listener is keyed to a single property. Recognized
+ * properties include:<br>
+ * <ul>
+ * <li>the font (<code>"font"</code>)</li>
+ * <li>the background color (<code>"background"</code>)</li>
+ * <li>the foreground color (<code>"foreground"</code>)</li>
+ * <li>the focusability (<code>"focusable"</code>)</li>
+ * <li>the focus key traversal enabled state
+ * (<code>"focusTraversalKeysEnabled"</code>)</li>
+ * <li>the set of forward traversal keys
+ * (<code>"forwardFocusTraversalKeys"</code>)</li>
+p * <li>the set of backward traversal keys
+ * (<code>"backwardFocusTraversalKeys"</code>)</li>
+ * <li>the set of up-cycle traversal keys
+ * (<code>"upCycleFocusTraversalKeys"</code>)</li>
+ * </ul>
+ *
+ * @param propertyName the property name to filter on
+ * @param listener the new listener to add
+ * @see #removePropertyChangeListener(String, PropertyChangeListener)
+ * @see #getPropertyChangeListeners(String)
+ * @see #addPropertyChangeListener(PropertyChangeListener)
+ * @since 1.1
+ */
+ public void addPropertyChangeListener(String propertyName,
+ PropertyChangeListener listener)
+ {
+ if (changeSupport == null)
+ changeSupport = new PropertyChangeSupport(this);
+ changeSupport.addPropertyChangeListener(propertyName, listener);
+ }
+
+ /**
+ * Removes the specified property listener on a particular property from
+ * the component. This is harmless if the listener was not previously
+ * registered.
+ *
+ * @param propertyName the property name to filter on
+ * @param listener the listener to remove
+ * @see #addPropertyChangeListener(String, PropertyChangeListener)
+ * @see #getPropertyChangeListeners(String)
+ * @see #removePropertyChangeListener(PropertyChangeListener)
+ * @since 1.1
+ */
+ public void removePropertyChangeListener(String propertyName,
+ PropertyChangeListener listener)
+ {
+ if (changeSupport != null)
+ changeSupport.removePropertyChangeListener(propertyName, listener);
+ }
+
+ /**
+ * Returns an array of all specified listeners on the named property that
+ * are registered on this component.
+ *
+ * @return an array of listeners
+ * @see #addPropertyChangeListener(String, PropertyChangeListener)
+ * @see #removePropertyChangeListener(String, PropertyChangeListener)
+ * @see #getPropertyChangeListeners()
+ * @since 1.4
+ */
+ public PropertyChangeListener[] getPropertyChangeListeners(String property)
+ {
+ return changeSupport == null ? new PropertyChangeListener[0]
+ : changeSupport.getPropertyChangeListeners(property);
+ }
+
+ /**
+ * Report a change in a bound property to any registered property listeners.
+ *
+ * @param propertyName the property that changed
+ * @param oldValue the old property value
+ * @param newValue the new property value
+ */
+ protected void firePropertyChange(String propertyName, Object oldValue,
+ Object newValue)
+ {
+ if (changeSupport != null)
+ changeSupport.firePropertyChange(propertyName, oldValue, newValue);
+ }
+
+ /**
+ * Report a change in a bound property to any registered property listeners.
+ *
+ * @param propertyName the property that changed
+ * @param oldValue the old property value
+ * @param newValue the new property value
+ */
+ protected void firePropertyChange(String propertyName, boolean oldValue,
+ boolean newValue)
+ {
+ if (changeSupport != null)
+ changeSupport.firePropertyChange(propertyName, oldValue, newValue);
+ }
+
+ /**
+ * Report a change in a bound property to any registered property listeners.
+ *
+ * @param propertyName the property that changed
+ * @param oldValue the old property value
+ * @param newValue the new property value
+ */
+ protected void firePropertyChange(String propertyName, int oldValue,
+ int newValue)
+ {
+ if (changeSupport != null)
+ changeSupport.firePropertyChange(propertyName, oldValue, newValue);
+ }
+
+ /**
+ * Report a change in a bound property to any registered property listeners.
+ *
+ * @param propertyName the property that changed
+ * @param oldValue the old property value
+ * @param newValue the new property value
+ *
+ * @since 1.5
+ */
+ public void firePropertyChange(String propertyName, byte oldValue,
+ byte newValue)
+ {
+ if (changeSupport != null)
+ changeSupport.firePropertyChange(propertyName, new Byte(oldValue),
+ new Byte(newValue));
+ }
+
+ /**
+ * Report a change in a bound property to any registered property listeners.
+ *
+ * @param propertyName the property that changed
+ * @param oldValue the old property value
+ * @param newValue the new property value
+ *
+ * @since 1.5
+ */
+ public void firePropertyChange(String propertyName, char oldValue,
+ char newValue)
+ {
+ if (changeSupport != null)
+ changeSupport.firePropertyChange(propertyName, new Character(oldValue),
+ new Character(newValue));
+ }
+
+ /**
+ * Report a change in a bound property to any registered property listeners.
+ *
+ * @param propertyName the property that changed
+ * @param oldValue the old property value
+ * @param newValue the new property value
+ *
+ * @since 1.5
+ */
+ public void firePropertyChange(String propertyName, short oldValue,
+ short newValue)
+ {
+ if (changeSupport != null)
+ changeSupport.firePropertyChange(propertyName, new Short(oldValue),
+ new Short(newValue));
+ }
+
+ /**
+ * Report a change in a bound property to any registered property listeners.
+ *
+ * @param propertyName the property that changed
+ * @param oldValue the old property value
+ * @param newValue the new property value
+ *
+ * @since 1.5
+ */
+ public void firePropertyChange(String propertyName, long oldValue,
+ long newValue)
+ {
+ if (changeSupport != null)
+ changeSupport.firePropertyChange(propertyName, new Long(oldValue),
+ new Long(newValue));
+ }
+
+ /**
+ * Report a change in a bound property to any registered property listeners.
+ *
+ * @param propertyName the property that changed
+ * @param oldValue the old property value
+ * @param newValue the new property value
+ *
+ * @since 1.5
+ */
+ public void firePropertyChange(String propertyName, float oldValue,
+ float newValue)
+ {
+ if (changeSupport != null)
+ changeSupport.firePropertyChange(propertyName, new Float(oldValue),
+ new Float(newValue));
+ }
+
+
+ /**
+ * Report a change in a bound property to any registered property listeners.
+ *
+ * @param propertyName the property that changed
+ * @param oldValue the old property value
+ * @param newValue the new property value
+ *
+ * @since 1.5
+ */
+ public void firePropertyChange(String propertyName, double oldValue,
+ double newValue)
+ {
+ if (changeSupport != null)
+ changeSupport.firePropertyChange(propertyName, new Double(oldValue),
+ new Double(newValue));
+ }
+
+ /**
+ * Sets the text layout orientation of this component. New components default
+ * to UNKNOWN (which behaves like LEFT_TO_RIGHT). This method affects only
+ * the current component, while
+ * {@link #applyComponentOrientation(ComponentOrientation)} affects the
+ * entire hierarchy.
+ *
+ * @param o the new orientation (<code>null</code> is accepted)
+ * @see #getComponentOrientation()
+ */
+ public void setComponentOrientation(ComponentOrientation o)
+ {
+
+ ComponentOrientation oldOrientation = componentOrientation;
+ componentOrientation = o;
+ firePropertyChange("componentOrientation", oldOrientation, o);
+ }
+
+ /**
+ * Determines the text layout orientation used by this component.
+ *
+ * @return the component orientation (this can be <code>null</code>)
+ * @see #setComponentOrientation(ComponentOrientation)
+ */
+ public ComponentOrientation getComponentOrientation()
+ {
+ return componentOrientation;
+ }
+
+ /**
+ * Sets the text layout orientation of this component. New components default
+ * to UNKNOWN (which behaves like LEFT_TO_RIGHT). This method affects the
+ * entire hierarchy, while
+ * {@link #setComponentOrientation(ComponentOrientation)} affects only the
+ * current component.
+ *
+ * @param o the new orientation
+ * @throws NullPointerException if o is null
+ * @see #getComponentOrientation()
+ * @since 1.4
+ */
+ public void applyComponentOrientation(ComponentOrientation o)
+ {
+ setComponentOrientation(o);
+ }
+
+ /**
+ * Returns the accessibility framework context of this class. Component is
+ * not accessible, so the default implementation returns null. Subclasses
+ * must override this behavior, and return an appropriate subclass of
+ * {@link AccessibleAWTComponent}.
+ *
+ * @return the accessibility context
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ return null;
+ }
+
+
+ // Helper methods; some are package visible for use by subclasses.
+
+ /**
+ * Subclasses should override this to return unique component names like
+ * "menuitem0".
+ *
+ * @return the generated name for this component
+ */
+ String generateName()
+ {
+ // Component is abstract.
+ return null;
+ }
+
+ /**
+ * Sets the peer for this component.
+ *
+ * @param peer the new peer
+ */
+ final void setPeer(ComponentPeer peer)
+ {
+ this.peer = peer;
+ }
+
+ /**
+ * Translate an AWT 1.1 event ({@link AWTEvent}) into an AWT 1.0
+ * event ({@link Event}).
+ *
+ * @param e an AWT 1.1 event to translate
+ *
+ * @return an AWT 1.0 event representing e
+ */
+ static Event translateEvent (AWTEvent e)
+ {
+ Object target = e.getSource ();
+ Event translated = null;
+
+ if (e instanceof WindowEvent)
+ {
+ WindowEvent we = (WindowEvent) e;
+ int id = we.id;
+ int newId = 0;
+
+ switch (id)
+ {
+ case WindowEvent.WINDOW_DEICONIFIED:
+ newId = Event.WINDOW_DEICONIFY;
+ break;
+ case WindowEvent.WINDOW_CLOSED:
+ case WindowEvent.WINDOW_CLOSING:
+ newId = Event.WINDOW_DESTROY;
+ break;
+ case WindowEvent.WINDOW_ICONIFIED:
+ newId = Event.WINDOW_ICONIFY;
+ break;
+ case WindowEvent.WINDOW_GAINED_FOCUS:
+ newId = Event.GOT_FOCUS;
+ break;
+ case WindowEvent.WINDOW_LOST_FOCUS:
+ newId = Event.LOST_FOCUS;
+ break;
+ default:
+ return null;
+ }
+
+ translated = new Event(target, 0, newId, 0, 0, 0, 0);
+ }
+ else if (e instanceof InputEvent)
+ {
+ InputEvent ie = (InputEvent) e;
+ long when = ie.getWhen ();
+
+ int oldID = 0;
+ int id = e.getID ();
+
+ int oldMods = 0;
+ int mods = ie.getModifiersEx ();
+
+ if ((mods & InputEvent.BUTTON2_DOWN_MASK) != 0)
+ oldMods |= Event.META_MASK;
+ else if ((mods & InputEvent.BUTTON3_DOWN_MASK) != 0)
+ oldMods |= Event.ALT_MASK;
+
+ if ((mods & InputEvent.SHIFT_DOWN_MASK) != 0)
+ oldMods |= Event.SHIFT_MASK;
+
+ if ((mods & InputEvent.CTRL_DOWN_MASK) != 0)
+ oldMods |= Event.CTRL_MASK;
+
+ if ((mods & InputEvent.META_DOWN_MASK) != 0)
+ oldMods |= Event.META_MASK;
+
+ if ((mods & InputEvent.ALT_DOWN_MASK) != 0)
+ oldMods |= Event.ALT_MASK;
+
+ if (e instanceof MouseEvent && !ignoreOldMouseEvents())
+ {
+ if (id == MouseEvent.MOUSE_PRESSED)
+ oldID = Event.MOUSE_DOWN;
+ else if (id == MouseEvent.MOUSE_RELEASED)
+ oldID = Event.MOUSE_UP;
+ else if (id == MouseEvent.MOUSE_MOVED)
+ oldID = Event.MOUSE_MOVE;
+ else if (id == MouseEvent.MOUSE_DRAGGED)
+ oldID = Event.MOUSE_DRAG;
+ else if (id == MouseEvent.MOUSE_ENTERED)
+ oldID = Event.MOUSE_ENTER;
+ else if (id == MouseEvent.MOUSE_EXITED)
+ oldID = Event.MOUSE_EXIT;
+ else
+ // No analogous AWT 1.0 mouse event.
+ return null;
+
+ MouseEvent me = (MouseEvent) e;
+
+ translated = new Event (target, when, oldID,
+ me.getX (), me.getY (), 0, oldMods);
+ }
+ else if (e instanceof KeyEvent)
+ {
+ if (id == KeyEvent.KEY_PRESSED)
+ oldID = Event.KEY_PRESS;
+ else if (e.getID () == KeyEvent.KEY_RELEASED)
+ oldID = Event.KEY_RELEASE;
+ else
+ // No analogous AWT 1.0 key event.
+ return null;
+
+ int oldKey = 0;
+ int newKey = ((KeyEvent) e).getKeyCode ();
+ switch (newKey)
+ {
+ case KeyEvent.VK_BACK_SPACE:
+ oldKey = Event.BACK_SPACE;
+ break;
+ case KeyEvent.VK_CAPS_LOCK:
+ oldKey = Event.CAPS_LOCK;
+ break;
+ case KeyEvent.VK_DELETE:
+ oldKey = Event.DELETE;
+ break;
+ case KeyEvent.VK_DOWN:
+ case KeyEvent.VK_KP_DOWN:
+ oldKey = Event.DOWN;
+ break;
+ case KeyEvent.VK_END:
+ oldKey = Event.END;
+ break;
+ case KeyEvent.VK_ENTER:
+ oldKey = Event.ENTER;
+ break;
+ case KeyEvent.VK_ESCAPE:
+ oldKey = Event.ESCAPE;
+ break;
+ case KeyEvent.VK_F1:
+ oldKey = Event.F1;
+ break;
+ case KeyEvent.VK_F10:
+ oldKey = Event.F10;
+ break;
+ case KeyEvent.VK_F11:
+ oldKey = Event.F11;
+ break;
+ case KeyEvent.VK_F12:
+ oldKey = Event.F12;
+ break;
+ case KeyEvent.VK_F2:
+ oldKey = Event.F2;
+ break;
+ case KeyEvent.VK_F3:
+ oldKey = Event.F3;
+ break;
+ case KeyEvent.VK_F4:
+ oldKey = Event.F4;
+ break;
+ case KeyEvent.VK_F5:
+ oldKey = Event.F5;
+ break;
+ case KeyEvent.VK_F6:
+ oldKey = Event.F6;
+ break;
+ case KeyEvent.VK_F7:
+ oldKey = Event.F7;
+ break;
+ case KeyEvent.VK_F8:
+ oldKey = Event.F8;
+ break;
+ case KeyEvent.VK_F9:
+ oldKey = Event.F9;
+ break;
+ case KeyEvent.VK_HOME:
+ oldKey = Event.HOME;
+ break;
+ case KeyEvent.VK_INSERT:
+ oldKey = Event.INSERT;
+ break;
+ case KeyEvent.VK_LEFT:
+ case KeyEvent.VK_KP_LEFT:
+ oldKey = Event.LEFT;
+ break;
+ case KeyEvent.VK_NUM_LOCK:
+ oldKey = Event.NUM_LOCK;
+ break;
+ case KeyEvent.VK_PAUSE:
+ oldKey = Event.PAUSE;
+ break;
+ case KeyEvent.VK_PAGE_DOWN:
+ oldKey = Event.PGDN;
+ break;
+ case KeyEvent.VK_PAGE_UP:
+ oldKey = Event.PGUP;
+ break;
+ case KeyEvent.VK_PRINTSCREEN:
+ oldKey = Event.PRINT_SCREEN;
+ break;
+ case KeyEvent.VK_RIGHT:
+ case KeyEvent.VK_KP_RIGHT:
+ oldKey = Event.RIGHT;
+ break;
+ case KeyEvent.VK_SCROLL_LOCK:
+ oldKey = Event.SCROLL_LOCK;
+ break;
+ case KeyEvent.VK_TAB:
+ oldKey = Event.TAB;
+ break;
+ case KeyEvent.VK_UP:
+ case KeyEvent.VK_KP_UP:
+ oldKey = Event.UP;
+ break;
+ default:
+ oldKey = ((KeyEvent) e).getKeyChar();
+ }
+
+ translated = new Event (target, when, oldID,
+ 0, 0, oldKey, oldMods);
+ }
+ }
+ else if (e instanceof AdjustmentEvent)
+ {
+ AdjustmentEvent ae = (AdjustmentEvent) e;
+ int type = ae.getAdjustmentType();
+ int oldType;
+ if (type == AdjustmentEvent.BLOCK_DECREMENT)
+ oldType = Event.SCROLL_PAGE_UP;
+ else if (type == AdjustmentEvent.BLOCK_INCREMENT)
+ oldType = Event.SCROLL_PAGE_DOWN;
+ else if (type == AdjustmentEvent.TRACK)
+ oldType = Event.SCROLL_ABSOLUTE;
+ else if (type == AdjustmentEvent.UNIT_DECREMENT)
+ oldType = Event.SCROLL_LINE_UP;
+ else if (type == AdjustmentEvent.UNIT_INCREMENT)
+ oldType = Event.SCROLL_LINE_DOWN;
+ else
+ oldType = type;
+ translated = new Event(target, oldType, new Integer(ae.getValue()));
+ }
+ else if (e instanceof ActionEvent)
+ translated = new Event (target, Event.ACTION_EVENT,
+ ((ActionEvent) e).getActionCommand ());
+
+ return translated;
+ }
+
+ /**
+ * Implementation of dispatchEvent. Allows trusted package classes
+ * to dispatch additional events first. This implementation first
+ * translates <code>e</code> to an AWT 1.0 event and sends the
+ * result to {@link #postEvent}. If the AWT 1.0 event is not
+ * handled, and events of type <code>e</code> are enabled for this
+ * component, e is passed on to {@link #processEvent}.
+ *
+ * @param e the event to dispatch
+ */
+ void dispatchEventImpl(AWTEvent e)
+ {
+ // Update the component's knowledge about the size.
+ // Important: Please look at the big comment in ComponentReshapeEvent
+ // to learn why we did it this way. If you change this code, make
+ // sure that the peer->AWT bounds update still works.
+ // (for instance: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29448 )
+ if (e instanceof ComponentReshapeEvent)
+ {
+ ComponentReshapeEvent reshape = (ComponentReshapeEvent) e;
+ x = reshape.x;
+ y = reshape.y;
+ width = reshape.width;
+ height = reshape.height;
+ return;
+ }
+
+ // Retarget focus events before dispatching it to the KeyboardFocusManager
+ // in order to handle lightweight components properly.
+ boolean dispatched = false;
+ if (! e.isFocusManagerEvent)
+ {
+ e = KeyboardFocusManager.retargetFocusEvent(e);
+ dispatched = KeyboardFocusManager.getCurrentKeyboardFocusManager()
+ .dispatchEvent(e);
+ }
+
+ if (! dispatched)
+ {
+ // Give toolkit a chance to dispatch the event
+ // to globally registered listeners.
+ Toolkit.getDefaultToolkit().globalDispatchEvent(e);
+
+ if (newEventsOnly)
+ {
+ if (eventTypeEnabled(e.id))
+ processEvent(e);
+ }
+ else
+ {
+ Event oldEvent = translateEvent(e);
+ if (oldEvent != null)
+ postEvent (oldEvent);
+ }
+ if (peer != null)
+ peer.handleEvent(e);
+ }
+ }
+
+ /**
+ * Tells whether or not an event type is enabled.
+ */
+ boolean eventTypeEnabled (int type)
+ {
+ if (type > AWTEvent.RESERVED_ID_MAX)
+ return true;
+
+ switch (type)
+ {
+ case HierarchyEvent.HIERARCHY_CHANGED:
+ return (hierarchyListener != null
+ || (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0);
+
+ case HierarchyEvent.ANCESTOR_MOVED:
+ case HierarchyEvent.ANCESTOR_RESIZED:
+ return (hierarchyBoundsListener != null
+ || (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0);
+
+ case ComponentEvent.COMPONENT_HIDDEN:
+ case ComponentEvent.COMPONENT_MOVED:
+ case ComponentEvent.COMPONENT_RESIZED:
+ case ComponentEvent.COMPONENT_SHOWN:
+ return (componentListener != null
+ || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0);
+
+ case KeyEvent.KEY_PRESSED:
+ case KeyEvent.KEY_RELEASED:
+ case KeyEvent.KEY_TYPED:
+ return (keyListener != null
+ || (eventMask & AWTEvent.KEY_EVENT_MASK) != 0);
+
+ case MouseEvent.MOUSE_CLICKED:
+ case MouseEvent.MOUSE_ENTERED:
+ case MouseEvent.MOUSE_EXITED:
+ case MouseEvent.MOUSE_PRESSED:
+ case MouseEvent.MOUSE_RELEASED:
+ return (mouseListener != null
+ || (eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0);
+ case MouseEvent.MOUSE_MOVED:
+ case MouseEvent.MOUSE_DRAGGED:
+ return (mouseMotionListener != null
+ || (eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0);
+ case MouseEvent.MOUSE_WHEEL:
+ return (mouseWheelListener != null
+ || (eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0);
+
+ case FocusEvent.FOCUS_GAINED:
+ case FocusEvent.FOCUS_LOST:
+ return (focusListener != null
+ || (eventMask & AWTEvent.FOCUS_EVENT_MASK) != 0);
+
+ case InputMethodEvent.INPUT_METHOD_TEXT_CHANGED:
+ case InputMethodEvent.CARET_POSITION_CHANGED:
+ return (inputMethodListener != null
+ || (eventMask & AWTEvent.INPUT_METHOD_EVENT_MASK) != 0);
+
+ case PaintEvent.PAINT:
+ case PaintEvent.UPDATE:
+ return (eventMask & AWTEvent.PAINT_EVENT_MASK) != 0;
+
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Returns <code>true</code> when this component and all of its ancestors
+ * are visible, <code>false</code> otherwise.
+ *
+ * @return <code>true</code> when this component and all of its ancestors
+ * are visible, <code>false</code> otherwise
+ */
+ boolean isHierarchyVisible()
+ {
+ boolean visible = isVisible();
+ Component comp = parent;
+ while (comp != null && visible)
+ {
+ comp = comp.parent;
+ if (comp != null)
+ visible = visible && comp.isVisible();
+ }
+ return visible;
+ }
+
+ /**
+ * Returns the mouse pointer position relative to this Component's
+ * top-left corner.
+ *
+ * @return relative mouse pointer position
+ *
+ * @throws HeadlessException if in a headless environment
+ */
+ public Point getMousePosition() throws HeadlessException
+ {
+ return getMousePositionHelper(true);
+ }
+
+ Point getMousePositionHelper(boolean allowChildren) throws HeadlessException
+ {
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException("can't get mouse position"
+ + " in headless environment");
+ if (!isShowing())
+ return null;
+
+ Component parent = this;
+ int windowRelativeXOffset = 0;
+ int windowRelativeYOffset = 0;
+ while (parent != null && !(parent instanceof Window))
+ {
+ windowRelativeXOffset += parent.getX();
+ windowRelativeYOffset += parent.getY();
+ parent = parent.getParent();
+ }
+ if (parent == null)
+ return null;
+
+ Window window = (Window) parent;
+ if (!Toolkit.getDefaultToolkit()
+ .getMouseInfoPeer().isWindowUnderMouse(window))
+ return null;
+
+ PointerInfo info = MouseInfo.getPointerInfo();
+ Point mouseLocation = info.getLocation();
+ Point windowLocation = window.getLocationOnScreen();
+
+ int x = mouseLocation.x - windowLocation.x;
+ int y = mouseLocation.y - windowLocation.y;
+
+ if (!mouseOverComponent(window.getComponentAt(x, y), allowChildren))
+ return null;
+
+ return new Point(x - windowRelativeXOffset, y - windowRelativeYOffset);
+ }
+
+ boolean mouseOverComponent(Component component, boolean allowChildren)
+ {
+ return component == this;
+ }
+
+ /**
+ * This method is used to implement transferFocus(). CHILD is the child
+ * making the request. This is overridden by Container; when called for an
+ * ordinary component there is no child and so we always return null.
+ *
+ * FIXME: is this still needed, in light of focus traversal policies?
+ *
+ * @param child the component making the request
+ * @return the next component to focus on
+ */
+ Component findNextFocusComponent(Component child)
+ {
+ return null;
+ }
+
+ /**
+ * Deserializes this component. This regenerates all serializable listeners
+ * which were registered originally.
+ *
+ * @param s the stream to read from
+ * @throws ClassNotFoundException if deserialization fails
+ * @throws IOException if the stream fails
+ */
+ private void readObject(ObjectInputStream s)
+ throws ClassNotFoundException, IOException
+ {
+ s.defaultReadObject();
+ String key = (String) s.readObject();
+ while (key != null)
+ {
+ Object listener = s.readObject();
+ if ("componentL".equals(key))
+ addComponentListener((ComponentListener) listener);
+ else if ("focusL".equals(key))
+ addFocusListener((FocusListener) listener);
+ else if ("keyL".equals(key))
+ addKeyListener((KeyListener) listener);
+ else if ("mouseL".equals(key))
+ addMouseListener((MouseListener) listener);
+ else if ("mouseMotionL".equals(key))
+ addMouseMotionListener((MouseMotionListener) listener);
+ else if ("inputMethodL".equals(key))
+ addInputMethodListener((InputMethodListener) listener);
+ else if ("hierarchyL".equals(key))
+ addHierarchyListener((HierarchyListener) listener);
+ else if ("hierarchyBoundsL".equals(key))
+ addHierarchyBoundsListener((HierarchyBoundsListener) listener);
+ else if ("mouseWheelL".equals(key))
+ addMouseWheelListener((MouseWheelListener) listener);
+ key = (String) s.readObject();
+ }
+ }
+
+ /**
+ * Serializes this component. This ignores all listeners which do not
+ * implement Serializable, but includes those that do.
+ *
+ * @param s the stream to write to
+ * @throws IOException if the stream fails
+ */
+ private void writeObject(ObjectOutputStream s) throws IOException
+ {
+ s.defaultWriteObject();
+ AWTEventMulticaster.save(s, "componentL", componentListener);
+ AWTEventMulticaster.save(s, "focusL", focusListener);
+ AWTEventMulticaster.save(s, "keyL", keyListener);
+ AWTEventMulticaster.save(s, "mouseL", mouseListener);
+ AWTEventMulticaster.save(s, "mouseMotionL", mouseMotionListener);
+ AWTEventMulticaster.save(s, "inputMethodL", inputMethodListener);
+ AWTEventMulticaster.save(s, "hierarchyL", hierarchyListener);
+ AWTEventMulticaster.save(s, "hierarchyBoundsL", hierarchyBoundsListener);
+ AWTEventMulticaster.save(s, "mouseWheelL", mouseWheelListener);
+ s.writeObject(null);
+ }
+
+
+ // Nested classes.
+
+ /**
+ * This class fixes the bounds for a Heavyweight component that
+ * is placed inside a Lightweight container. When the lightweight is
+ * moved or resized, setBounds for the lightweight peer does nothing.
+ * Therefore, it was never moved on the screen. This class is
+ * attached to the lightweight, and it adjusts the position and size
+ * of the peer when notified.
+ * This is the same for show and hide.
+ */
+ class HeavyweightInLightweightListener
+ implements ComponentListener
+ {
+
+ /**
+ * Constructor. Adds component listener to lightweight parent.
+ *
+ * @param parent - the lightweight container.
+ */
+ public HeavyweightInLightweightListener(Container parent)
+ {
+ parent.addComponentListener(this);
+ }
+
+ /**
+ * This method is called when the component is resized.
+ *
+ * @param event the <code>ComponentEvent</code> indicating the resize
+ */
+ public void componentResized(ComponentEvent event)
+ {
+ // Nothing to do here, componentMoved will be called.
+ }
+
+ /**
+ * This method is called when the component is moved.
+ *
+ * @param event the <code>ComponentEvent</code> indicating the move
+ */
+ public void componentMoved(ComponentEvent event)
+ {
+ if (peer != null)
+ peer.setBounds(x, y, width, height);
+ }
+
+ /**
+ * This method is called when the component is made visible.
+ *
+ * @param event the <code>ComponentEvent</code> indicating the visibility
+ */
+ public void componentShown(ComponentEvent event)
+ {
+ if (isShowing())
+ peer.show();
+ }
+
+ /**
+ * This method is called when the component is hidden.
+ *
+ * @param event the <code>ComponentEvent</code> indicating the visibility
+ */
+ public void componentHidden(ComponentEvent event)
+ {
+ if (isShowing())
+ peer.hide();
+ }
+ }
+
+ /**
+ * This class provides accessibility support for subclasses of container.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.3
+ * @status updated to 1.4
+ */
+ protected abstract class AccessibleAWTComponent extends AccessibleContext
+ implements Serializable, AccessibleComponent
+ {
+ /**
+ * Compatible with JDK 1.3+.
+ */
+ private static final long serialVersionUID = 642321655757800191L;
+
+ /**
+ * Converts show/hide events to PropertyChange events, and is registered
+ * as a component listener on this component.
+ *
+ * @serial the component handler
+ */
+ protected ComponentListener accessibleAWTComponentHandler
+ = new AccessibleAWTComponentHandler();
+
+ /**
+ * Converts focus events to PropertyChange events, and is registered
+ * as a focus listener on this component.
+ *
+ * @serial the focus handler
+ */
+ protected FocusListener accessibleAWTFocusHandler
+ = new AccessibleAWTFocusHandler();
+
+ /**
+ * The default constructor.
+ */
+ protected AccessibleAWTComponent()
+ {
+ Component.this.addComponentListener(accessibleAWTComponentHandler);
+ Component.this.addFocusListener(accessibleAWTFocusHandler);
+ }
+
+ /**
+ * Adds a global property change listener to the accessible component.
+ *
+ * @param l the listener to add
+ * @see #ACCESSIBLE_NAME_PROPERTY
+ * @see #ACCESSIBLE_DESCRIPTION_PROPERTY
+ * @see #ACCESSIBLE_STATE_PROPERTY
+ * @see #ACCESSIBLE_VALUE_PROPERTY
+ * @see #ACCESSIBLE_SELECTION_PROPERTY
+ * @see #ACCESSIBLE_TEXT_PROPERTY
+ * @see #ACCESSIBLE_VISIBLE_DATA_PROPERTY
+ */
+ public void addPropertyChangeListener(PropertyChangeListener l)
+ {
+ Component.this.addPropertyChangeListener(l);
+ super.addPropertyChangeListener(l);
+ }
+
+ /**
+ * Removes a global property change listener from this accessible
+ * component.
+ *
+ * @param l the listener to remove
+ */
+ public void removePropertyChangeListener(PropertyChangeListener l)
+ {
+ Component.this.removePropertyChangeListener(l);
+ super.removePropertyChangeListener(l);
+ }
+
+ /**
+ * Returns the accessible name of this component. It is almost always
+ * wrong to return getName(), since it is not localized. In fact, for
+ * things like buttons, this should be the text of the button, not the
+ * name of the object. The tooltip text might also be appropriate.
+ *
+ * @return the name
+ * @see #setAccessibleName(String)
+ */
+ public String getAccessibleName()
+ {
+ return accessibleName;
+ }
+
+ /**
+ * Returns a brief description of this accessible context. This should
+ * be localized.
+ *
+ * @return a description of this component
+ * @see #setAccessibleDescription(String)
+ */
+ public String getAccessibleDescription()
+ {
+ return accessibleDescription;
+ }
+
+ /**
+ * Returns the role of this component.
+ *
+ * @return the accessible role
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.AWT_COMPONENT;
+ }
+
+ /**
+ * Returns a state set describing this component's state.
+ *
+ * @return a new state set
+ * @see AccessibleState
+ */
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ AccessibleStateSet s = new AccessibleStateSet();
+ if (Component.this.isEnabled())
+ s.add(AccessibleState.ENABLED);
+ if (isFocusable())
+ s.add(AccessibleState.FOCUSABLE);
+ if (isFocusOwner())
+ s.add(AccessibleState.FOCUSED);
+ // Note: While the java.awt.Component has an 'opaque' property, it
+ // seems that it is not added to the accessible state set here, even
+ // if this property is true. However, it is handled for
+ // javax.swing.JComponent, so we add it there.
+ if (Component.this.isShowing())
+ s.add(AccessibleState.SHOWING);
+ if (Component.this.isVisible())
+ s.add(AccessibleState.VISIBLE);
+ return s;
+ }
+
+ /**
+ * Returns the parent of this component, if it is accessible.
+ *
+ * @return the accessible parent
+ */
+ public Accessible getAccessibleParent()
+ {
+ if (accessibleParent == null)
+ {
+ Container parent = getParent();
+ accessibleParent = parent instanceof Accessible
+ ? (Accessible) parent : null;
+ }
+ return accessibleParent;
+ }
+
+ /**
+ * Returns the index of this component in its accessible parent.
+ *
+ * @return the index, or -1 if the parent is not accessible
+ * @see #getAccessibleParent()
+ */
+ public int getAccessibleIndexInParent()
+ {
+ if (getAccessibleParent() == null)
+ return -1;
+ AccessibleContext context
+ = ((Component) accessibleParent).getAccessibleContext();
+ if (context == null)
+ return -1;
+ for (int i = context.getAccessibleChildrenCount(); --i >= 0; )
+ if (context.getAccessibleChild(i) == Component.this)
+ return i;
+ return -1;
+ }
+
+ /**
+ * Returns the number of children of this component which implement
+ * Accessible. Subclasses must override this if they can have children.
+ *
+ * @return the number of accessible children, default 0
+ */
+ public int getAccessibleChildrenCount()
+ {
+ return 0;
+ }
+
+ /**
+ * Returns the ith accessible child. Subclasses must override this if
+ * they can have children.
+ *
+ * @return the ith accessible child, or null
+ * @see #getAccessibleChildrenCount()
+ */
+ public Accessible getAccessibleChild(int i)
+ {
+ return null;
+ }
+
+ /**
+ * Returns the locale of this component.
+ *
+ * @return the locale
+ * @throws IllegalComponentStateException if the locale is unknown
+ */
+ public Locale getLocale()
+ {
+ return Component.this.getLocale();
+ }
+
+ /**
+ * Returns this, since it is an accessible component.
+ *
+ * @return the accessible component
+ */
+ public AccessibleComponent getAccessibleComponent()
+ {
+ return this;
+ }
+
+ /**
+ * Gets the background color.
+ *
+ * @return the background color
+ * @see #setBackground(Color)
+ */
+ public Color getBackground()
+ {
+ return Component.this.getBackground();
+ }
+
+ /**
+ * Sets the background color.
+ *
+ * @param c the background color
+ * @see #getBackground()
+ * @see #isOpaque()
+ */
+ public void setBackground(Color c)
+ {
+ Component.this.setBackground(c);
+ }
+
+ /**
+ * Gets the foreground color.
+ *
+ * @return the foreground color
+ * @see #setForeground(Color)
+ */
+ public Color getForeground()
+ {
+ return Component.this.getForeground();
+ }
+
+ /**
+ * Sets the foreground color.
+ *
+ * @param c the foreground color
+ * @see #getForeground()
+ */
+ public void setForeground(Color c)
+ {
+ Component.this.setForeground(c);
+ }
+
+ /**
+ * Gets the cursor.
+ *
+ * @return the cursor
+ * @see #setCursor(Cursor)
+ */
+ public Cursor getCursor()
+ {
+ return Component.this.getCursor();
+ }
+
+ /**
+ * Sets the cursor.
+ *
+ * @param cursor the cursor
+ * @see #getCursor()
+ */
+ public void setCursor(Cursor cursor)
+ {
+ Component.this.setCursor(cursor);
+ }
+
+ /**
+ * Gets the font.
+ *
+ * @return the font
+ * @see #setFont(Font)
+ */
+ public Font getFont()
+ {
+ return Component.this.getFont();
+ }
+
+ /**
+ * Sets the font.
+ *
+ * @param f the font
+ * @see #getFont()
+ */
+ public void setFont(Font f)
+ {
+ Component.this.setFont(f);
+ }
+
+ /**
+ * Gets the font metrics for a font.
+ *
+ * @param f the font to look up
+ * @return its metrics
+ * @throws NullPointerException if f is null
+ * @see #getFont()
+ */
+ public FontMetrics getFontMetrics(Font f)
+ {
+ return Component.this.getFontMetrics(f);
+ }
+
+ /**
+ * Tests if the component is enabled.
+ *
+ * @return true if the component is enabled
+ * @see #setEnabled(boolean)
+ * @see #getAccessibleStateSet()
+ * @see AccessibleState#ENABLED
+ */
+ public boolean isEnabled()
+ {
+ return Component.this.isEnabled();
+ }
+
+ /**
+ * Set whether the component is enabled.
+ *
+ * @param b the new enabled status
+ * @see #isEnabled()
+ */
+ public void setEnabled(boolean b)
+ {
+ Component.this.setEnabled(b);
+ }
+
+ /**
+ * Test whether the component is visible (not necesarily showing).
+ *
+ * @return true if it is visible
+ * @see #setVisible(boolean)
+ * @see #getAccessibleStateSet()
+ * @see AccessibleState#VISIBLE
+ */
+ public boolean isVisible()
+ {
+ return Component.this.isVisible();
+ }
+
+ /**
+ * Sets the visibility of this component.
+ *
+ * @param b the desired visibility
+ * @see #isVisible()
+ */
+ public void setVisible(boolean b)
+ {
+ Component.this.setVisible(b);
+ }
+
+ /**
+ * Tests if the component is showing.
+ *
+ * @return true if this is showing
+ */
+ public boolean isShowing()
+ {
+ return Component.this.isShowing();
+ }
+
+ /**
+ * Tests if the point is contained in this component.
+ *
+ * @param p the point to check
+ * @return true if it is contained
+ * @throws NullPointerException if p is null
+ */
+ public boolean contains(Point p)
+ {
+ return Component.this.contains(p.x, p.y);
+ }
+
+ /**
+ * Returns the location of this object on the screen, or null if it is
+ * not showing.
+ *
+ * @return the location relative to screen coordinates, if showing
+ * @see #getBounds()
+ * @see #getLocation()
+ */
+ public Point getLocationOnScreen()
+ {
+ return Component.this.isShowing() ? Component.this.getLocationOnScreen()
+ : null;
+ }
+
+ /**
+ * Returns the location of this object relative to its parent's coordinate
+ * system, or null if it is not showing.
+ *
+ * @return the location
+ * @see #getBounds()
+ * @see #getLocationOnScreen()
+ */
+ public Point getLocation()
+ {
+ return Component.this.getLocation();
+ }
+
+ /**
+ * Sets the location of this relative to its parent's coordinate system.
+ *
+ * @param p the location
+ * @throws NullPointerException if p is null
+ * @see #getLocation()
+ */
+ public void setLocation(Point p)
+ {
+ Component.this.setLocation(p.x, p.y);
+ }
+
+ /**
+ * Gets the bounds of this component, or null if it is not on screen.
+ *
+ * @return the bounds
+ * @see #contains(Point)
+ * @see #setBounds(Rectangle)
+ */
+ public Rectangle getBounds()
+ {
+ return Component.this.getBounds();
+ }
+
+ /**
+ * Sets the bounds of this component.
+ *
+ * @param r the bounds
+ * @throws NullPointerException if r is null
+ * @see #getBounds()
+ */
+ public void setBounds(Rectangle r)
+ {
+ Component.this.setBounds(r.x, r.y, r.width, r.height);
+ }
+
+ /**
+ * Gets the size of this component, or null if it is not showing.
+ *
+ * @return the size
+ * @see #setSize(Dimension)
+ */
+ public Dimension getSize()
+ {
+ return Component.this.getSize();
+ }
+
+ /**
+ * Sets the size of this component.
+ *
+ * @param d the size
+ * @throws NullPointerException if d is null
+ * @see #getSize()
+ */
+ public void setSize(Dimension d)
+ {
+ Component.this.setSize(d.width, d.height);
+ }
+
+ /**
+ * Returns the Accessible child at a point relative to the coordinate
+ * system of this component, if one exists, or null. Since components
+ * have no children, subclasses must override this to get anything besides
+ * null.
+ *
+ * @param p the point to check
+ * @return the accessible child at that point
+ * @throws NullPointerException if p is null
+ */
+ public Accessible getAccessibleAt(Point p)
+ {
+ return null;
+ }
+
+ /**
+ * Tests whether this component can accept focus.
+ *
+ * @return true if this is focus traversable
+ * @see #getAccessibleStateSet ()
+ * @see AccessibleState#FOCUSABLE
+ * @see AccessibleState#FOCUSED
+ */
+ public boolean isFocusTraversable ()
+ {
+ return Component.this.isFocusTraversable ();
+ }
+
+ /**
+ * Requests focus for this component.
+ *
+ * @see #isFocusTraversable ()
+ */
+ public void requestFocus ()
+ {
+ Component.this.requestFocus ();
+ }
+
+ /**
+ * Adds a focus listener.
+ *
+ * @param l the listener to add
+ */
+ public void addFocusListener(FocusListener l)
+ {
+ Component.this.addFocusListener(l);
+ }
+
+ /**
+ * Removes a focus listener.
+ *
+ * @param l the listener to remove
+ */
+ public void removeFocusListener(FocusListener l)
+ {
+ Component.this.removeFocusListener(l);
+ }
+
+ /**
+ * Converts component changes into property changes.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.3
+ * @status updated to 1.4
+ */
+ protected class AccessibleAWTComponentHandler implements ComponentListener
+ {
+ /**
+ * Default constructor.
+ */
+ protected AccessibleAWTComponentHandler()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Convert a component hidden to a property change.
+ *
+ * @param e the event to convert
+ */
+ public void componentHidden(ComponentEvent e)
+ {
+ AccessibleAWTComponent.this.firePropertyChange
+ (ACCESSIBLE_STATE_PROPERTY, AccessibleState.VISIBLE, null);
+ }
+
+ /**
+ * Convert a component shown to a property change.
+ *
+ * @param e the event to convert
+ */
+ public void componentShown(ComponentEvent e)
+ {
+ AccessibleAWTComponent.this.firePropertyChange
+ (ACCESSIBLE_STATE_PROPERTY, null, AccessibleState.VISIBLE);
+ }
+
+ /**
+ * Moving a component does not affect properties.
+ *
+ * @param e ignored
+ */
+ public void componentMoved(ComponentEvent e)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Resizing a component does not affect properties.
+ *
+ * @param e ignored
+ */
+ public void componentResized(ComponentEvent e)
+ {
+ // Nothing to do here.
+ }
+ } // class AccessibleAWTComponentHandler
+
+ /**
+ * Converts focus changes into property changes.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.3
+ * @status updated to 1.4
+ */
+ protected class AccessibleAWTFocusHandler implements FocusListener
+ {
+ /**
+ * Default constructor.
+ */
+ protected AccessibleAWTFocusHandler()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Convert a focus gained to a property change.
+ *
+ * @param e the event to convert
+ */
+ public void focusGained(FocusEvent e)
+ {
+ AccessibleAWTComponent.this.firePropertyChange
+ (ACCESSIBLE_STATE_PROPERTY, null, AccessibleState.FOCUSED);
+ }
+
+ /**
+ * Convert a focus lost to a property change.
+ *
+ * @param e the event to convert
+ */
+ public void focusLost(FocusEvent e)
+ {
+ AccessibleAWTComponent.this.firePropertyChange
+ (ACCESSIBLE_STATE_PROPERTY, AccessibleState.FOCUSED, null);
+ }
+ } // class AccessibleAWTComponentHandler
+ } // class AccessibleAWTComponent
+
+ /**
+ * This class provides support for blitting offscreen surfaces to a
+ * component.
+ *
+ * @see BufferStrategy
+ *
+ * @since 1.4
+ */
+ protected class BltBufferStrategy extends BufferStrategy
+ {
+ /**
+ * The capabilities of the image buffer.
+ */
+ protected BufferCapabilities caps;
+
+ /**
+ * The back buffers used in this strategy.
+ */
+ protected VolatileImage[] backBuffers;
+
+ /**
+ * Whether or not the image buffer resources are allocated and
+ * ready to be drawn into.
+ */
+ protected boolean validatedContents;
+
+ /**
+ * The width of the back buffers.
+ */
+ protected int width;
+
+ /**
+ * The height of the back buffers.
+ */
+ protected int height;
+
+ /**
+ * The front buffer.
+ */
+ private VolatileImage frontBuffer;
+
+ /**
+ * Creates a blitting buffer strategy.
+ *
+ * @param numBuffers the number of buffers, including the front
+ * buffer
+ * @param caps the capabilities of this strategy
+ */
+ protected BltBufferStrategy(int numBuffers, BufferCapabilities caps)
+ {
+ this.caps = caps;
+ createBackBuffers(numBuffers - 1);
+ width = getWidth();
+ height = getHeight();
+ }
+
+ /**
+ * Initializes the backBuffers field with an array of numBuffers
+ * VolatileImages.
+ *
+ * @param numBuffers the number of backbuffers to create
+ */
+ protected void createBackBuffers(int numBuffers)
+ {
+ GraphicsConfiguration c =
+ GraphicsEnvironment.getLocalGraphicsEnvironment()
+ .getDefaultScreenDevice().getDefaultConfiguration();
+
+ backBuffers = new VolatileImage[numBuffers];
+
+ for (int i = 0; i < numBuffers; i++)
+ backBuffers[i] = c.createCompatibleVolatileImage(width, height);
+ }
+
+ /**
+ * Retrieves the capabilities of this buffer strategy.
+ *
+ * @return the capabilities of this buffer strategy
+ */
+ public BufferCapabilities getCapabilities()
+ {
+ return caps;
+ }
+
+ /**
+ * Retrieves a graphics object that can be used to draw into this
+ * strategy's image buffer.
+ *
+ * @return a graphics object
+ */
+ public Graphics getDrawGraphics()
+ {
+ // Return the backmost buffer's graphics.
+ return backBuffers[0].getGraphics();
+ }
+
+ /**
+ * Bring the contents of the back buffer to the front buffer.
+ */
+ public void show()
+ {
+ GraphicsConfiguration c =
+ GraphicsEnvironment.getLocalGraphicsEnvironment()
+ .getDefaultScreenDevice().getDefaultConfiguration();
+
+ // draw the front buffer.
+ getGraphics().drawImage(backBuffers[backBuffers.length - 1],
+ width, height, null);
+
+ BufferCapabilities.FlipContents f = getCapabilities().getFlipContents();
+
+ // blit the back buffers.
+ for (int i = backBuffers.length - 1; i > 0 ; i--)
+ backBuffers[i] = backBuffers[i - 1];
+
+ // create new backmost buffer.
+ if (f == BufferCapabilities.FlipContents.UNDEFINED)
+ backBuffers[0] = c.createCompatibleVolatileImage(width, height);
+
+ // create new backmost buffer and clear it to the background
+ // color.
+ if (f == BufferCapabilities.FlipContents.BACKGROUND)
+ {
+ backBuffers[0] = c.createCompatibleVolatileImage(width, height);
+ backBuffers[0].getGraphics().clearRect(0, 0, width, height);
+ }
+
+ // FIXME: set the backmost buffer to the prior contents of the
+ // front buffer. How do we retrieve the contents of the front
+ // buffer?
+ //
+ // if (f == BufferCapabilities.FlipContents.PRIOR)
+
+ // set the backmost buffer to a copy of the new front buffer.
+ if (f == BufferCapabilities.FlipContents.COPIED)
+ backBuffers[0] = backBuffers[backBuffers.length - 1];
+ }
+
+ /**
+ * Re-create the image buffer resources if they've been lost.
+ */
+ protected void revalidate()
+ {
+ GraphicsConfiguration c =
+ GraphicsEnvironment.getLocalGraphicsEnvironment()
+ .getDefaultScreenDevice().getDefaultConfiguration();
+
+ for (int i = 0; i < backBuffers.length; i++)
+ {
+ int result = backBuffers[i].validate(c);
+ if (result == VolatileImage.IMAGE_INCOMPATIBLE)
+ backBuffers[i] = c.createCompatibleVolatileImage(width, height);
+ }
+ validatedContents = true;
+ }
+
+ /**
+ * Returns whether or not the image buffer resources have been
+ * lost.
+ *
+ * @return true if the resources have been lost, false otherwise
+ */
+ public boolean contentsLost()
+ {
+ for (int i = 0; i < backBuffers.length; i++)
+ {
+ if (backBuffers[i].contentsLost())
+ {
+ validatedContents = false;
+ return true;
+ }
+ }
+ // we know that the buffer resources are valid now because we
+ // just checked them
+ validatedContents = true;
+ return false;
+ }
+
+ /**
+ * Returns whether or not the image buffer resources have been
+ * restored.
+ *
+ * @return true if the resources have been restored, false
+ * otherwise
+ */
+ public boolean contentsRestored()
+ {
+ GraphicsConfiguration c =
+ GraphicsEnvironment.getLocalGraphicsEnvironment()
+ .getDefaultScreenDevice().getDefaultConfiguration();
+
+ boolean imageRestored = false;
+
+ for (int i = 0; i < backBuffers.length; i++)
+ {
+ int result = backBuffers[i].validate(c);
+ if (result == VolatileImage.IMAGE_RESTORED)
+ imageRestored = true;
+ else if (result == VolatileImage.IMAGE_INCOMPATIBLE)
+ return false;
+ }
+ // we know that the buffer resources are valid now because we
+ // just checked them
+ validatedContents = true;
+ return imageRestored;
+ }
+ }
+
+ /**
+ * This class provides support for flipping component buffers. It
+ * can only be used on Canvases and Windows.
+ *
+ * @since 1.4
+ */
+ protected class FlipBufferStrategy extends BufferStrategy
+ {
+ /**
+ * The number of buffers.
+ */
+ protected int numBuffers;
+
+ /**
+ * The capabilities of this buffering strategy.
+ */
+ protected BufferCapabilities caps;
+
+ /**
+ * An Image reference to the drawing buffer.
+ */
+ protected Image drawBuffer;
+
+ /**
+ * A VolatileImage reference to the drawing buffer.
+ */
+ protected VolatileImage drawVBuffer;
+
+ /**
+ * Whether or not the image buffer resources are allocated and
+ * ready to be drawn into.
+ */
+ protected boolean validatedContents;
+
+ /**
+ * The width of the back buffer.
+ */
+ private int width;
+
+ /**
+ * The height of the back buffer.
+ */
+ private int height;
+
+ /**
+ * Creates a flipping buffer strategy. The only supported
+ * strategy for FlipBufferStrategy itself is a double-buffer page
+ * flipping strategy. It forms the basis for more complex derived
+ * strategies.
+ *
+ * @param numBuffers the number of buffers
+ * @param caps the capabilities of this buffering strategy
+ *
+ * @throws AWTException if the requested
+ * number-of-buffers/capabilities combination is not supported
+ */
+ protected FlipBufferStrategy(int numBuffers, BufferCapabilities caps)
+ throws AWTException
+ {
+ this.caps = caps;
+ width = getWidth();
+ height = getHeight();
+
+ if (numBuffers > 1)
+ createBuffers(numBuffers, caps);
+ else
+ {
+ drawVBuffer = peer.createVolatileImage(width, height);
+ drawBuffer = drawVBuffer;
+ }
+ }
+
+ /**
+ * Creates a multi-buffer flipping strategy. The number of
+ * buffers must be greater than one and the buffer capabilities
+ * must specify page flipping.
+ *
+ * @param numBuffers the number of flipping buffers; must be
+ * greater than one
+ * @param caps the buffering capabilities; caps.isPageFlipping()
+ * must return true
+ *
+ * @throws IllegalArgumentException if numBuffers is not greater
+ * than one or if the page flipping capability is not requested
+ *
+ * @throws AWTException if the requested flipping strategy is not
+ * supported
+ */
+ protected void createBuffers(int numBuffers, BufferCapabilities caps)
+ throws AWTException
+ {
+ if (numBuffers <= 1)
+ throw new IllegalArgumentException("FlipBufferStrategy.createBuffers:"
+ + " numBuffers must be greater than"
+ + " one.");
+
+ if (!caps.isPageFlipping())
+ throw new IllegalArgumentException("FlipBufferStrategy.createBuffers:"
+ + " flipping must be a specified"
+ + " capability.");
+
+ peer.createBuffers(numBuffers, caps);
+ }
+
+ /**
+ * Return a direct reference to the back buffer image.
+ *
+ * @return a direct reference to the back buffer image.
+ */
+ protected Image getBackBuffer()
+ {
+ return peer.getBackBuffer();
+ }
+
+ /**
+ * Perform a flip operation to transfer the contents of the back
+ * buffer to the front buffer.
+ */
+ protected void flip(BufferCapabilities.FlipContents flipAction)
+ {
+ peer.flip(flipAction);
+ }
+
+ /**
+ * Release the back buffer's resources.
+ */
+ protected void destroyBuffers()
+ {
+ peer.destroyBuffers();
+ }
+
+ /**
+ * Retrieves the capabilities of this buffer strategy.
+ *
+ * @return the capabilities of this buffer strategy
+ */
+ public BufferCapabilities getCapabilities()
+ {
+ return caps;
+ }
+
+ /**
+ * Retrieves a graphics object that can be used to draw into this
+ * strategy's image buffer.
+ *
+ * @return a graphics object
+ */
+ public Graphics getDrawGraphics()
+ {
+ return drawVBuffer.getGraphics();
+ }
+
+ /**
+ * Re-create the image buffer resources if they've been lost.
+ */
+ protected void revalidate()
+ {
+ GraphicsConfiguration c =
+ GraphicsEnvironment.getLocalGraphicsEnvironment()
+ .getDefaultScreenDevice().getDefaultConfiguration();
+
+ if (drawVBuffer.validate(c) == VolatileImage.IMAGE_INCOMPATIBLE)
+ drawVBuffer = peer.createVolatileImage(width, height);
+ validatedContents = true;
+ }
+
+ /**
+ * Returns whether or not the image buffer resources have been
+ * lost.
+ *
+ * @return true if the resources have been lost, false otherwise
+ */
+ public boolean contentsLost()
+ {
+ if (drawVBuffer.contentsLost())
+ {
+ validatedContents = false;
+ return true;
+ }
+ // we know that the buffer resources are valid now because we
+ // just checked them
+ validatedContents = true;
+ return false;
+ }
+
+ /**
+ * Returns whether or not the image buffer resources have been
+ * restored.
+ *
+ * @return true if the resources have been restored, false
+ * otherwise
+ */
+ public boolean contentsRestored()
+ {
+ GraphicsConfiguration c =
+ GraphicsEnvironment.getLocalGraphicsEnvironment()
+ .getDefaultScreenDevice().getDefaultConfiguration();
+
+ int result = drawVBuffer.validate(c);
+
+ boolean imageRestored = false;
+
+ if (result == VolatileImage.IMAGE_RESTORED)
+ imageRestored = true;
+ else if (result == VolatileImage.IMAGE_INCOMPATIBLE)
+ return false;
+
+ // we know that the buffer resources are valid now because we
+ // just checked them
+ validatedContents = true;
+ return imageRestored;
+ }
+
+ /**
+ * Bring the contents of the back buffer to the front buffer.
+ */
+ public void show()
+ {
+ flip(caps.getFlipContents());
+ }
+ }
+}