1 /* JComponent.java -- Every component in swing inherits from this class.
2 Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
41 import java.applet.Applet;
42 import java.awt.AWTEvent;
43 import java.awt.Color;
44 import java.awt.Component;
45 import java.awt.Container;
46 import java.awt.Dimension;
47 import java.awt.EventQueue;
48 import java.awt.FocusTraversalPolicy;
50 import java.awt.Graphics;
51 import java.awt.Graphics2D;
52 import java.awt.Image;
53 import java.awt.Insets;
54 import java.awt.Point;
55 import java.awt.Rectangle;
56 import java.awt.Shape;
57 import java.awt.Window;
58 import java.awt.dnd.DropTarget;
59 import java.awt.event.ActionEvent;
60 import java.awt.event.ActionListener;
61 import java.awt.event.ContainerEvent;
62 import java.awt.event.ContainerListener;
63 import java.awt.event.FocusEvent;
64 import java.awt.event.FocusListener;
65 import java.awt.event.KeyEvent;
66 import java.awt.event.MouseEvent;
67 import java.awt.peer.LightweightPeer;
68 import java.beans.PropertyChangeEvent;
69 import java.beans.PropertyChangeListener;
70 import java.beans.PropertyVetoException;
71 import java.beans.VetoableChangeListener;
72 import java.io.Serializable;
73 import java.util.ArrayList;
74 import java.util.EventListener;
75 import java.util.Hashtable;
76 import java.util.Locale;
79 import javax.accessibility.Accessible;
80 import javax.accessibility.AccessibleContext;
81 import javax.accessibility.AccessibleExtendedComponent;
82 import javax.accessibility.AccessibleKeyBinding;
83 import javax.accessibility.AccessibleRole;
84 import javax.accessibility.AccessibleState;
85 import javax.accessibility.AccessibleStateSet;
86 import javax.swing.border.Border;
87 import javax.swing.border.CompoundBorder;
88 import javax.swing.border.TitledBorder;
89 import javax.swing.event.AncestorEvent;
90 import javax.swing.event.AncestorListener;
91 import javax.swing.event.EventListenerList;
92 import javax.swing.plaf.ComponentUI;
95 * The base class of all Swing components.
96 * It contains generic methods to manage events, properties and sizes. Actual
97 * drawing of the component is channeled to a look-and-feel class that is
98 * implemented elsewhere.
100 * @author Ronald Veldema (rveldema&064;cs.vu.nl)
101 * @author Graydon Hoare (graydon&064;redhat.com)
103 public abstract class JComponent extends Container implements Serializable
105 private static final long serialVersionUID = -7908749299918704233L;
108 * The accessible context of this <code>JComponent</code>.
110 protected AccessibleContext accessibleContext;
113 * Basic accessibility support for <code>JComponent</code> derived
116 public abstract class AccessibleJComponent
117 extends AccessibleAWTContainer
118 implements AccessibleExtendedComponent
121 * Receives notification if the focus on the JComponent changes and
122 * fires appropriate PropertyChangeEvents to listeners registered with
123 * the AccessibleJComponent.
125 protected class AccessibleFocusHandler
126 implements FocusListener
129 * Creates a new AccessibleFocusHandler.
131 protected AccessibleFocusHandler()
133 // Nothing to do here.
137 * Receives notification when the JComponent gained focus and fires
138 * a PropertyChangeEvent to listeners registered on the
139 * AccessibleJComponent with a property name of
140 * {@link AccessibleContext#ACCESSIBLE_STATE_PROPERTY} and a new value
141 * of {@link AccessibleState#FOCUSED}.
143 public void focusGained(FocusEvent event)
145 AccessibleJComponent.this.firePropertyChange
146 (AccessibleContext.ACCESSIBLE_STATE_PROPERTY, null,
147 AccessibleState.FOCUSED);
151 * Receives notification when the JComponent lost focus and fires
152 * a PropertyChangeEvent to listeners registered on the
153 * AccessibleJComponent with a property name of
154 * {@link AccessibleContext#ACCESSIBLE_STATE_PROPERTY} and an old value
155 * of {@link AccessibleState#FOCUSED}.
157 public void focusLost(FocusEvent valevent)
159 AccessibleJComponent.this.firePropertyChange
160 (AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
161 AccessibleState.FOCUSED, null);
166 * Receives notification if there are child components are added or removed
167 * from the JComponent and fires appropriate PropertyChangeEvents to
168 * interested listeners on the AccessibleJComponent.
170 protected class AccessibleContainerHandler
171 implements ContainerListener
174 * Creates a new AccessibleContainerHandler.
176 protected AccessibleContainerHandler()
178 // Nothing to do here.
182 * Receives notification when a child component is added to the
183 * JComponent and fires a PropertyChangeEvent on listeners registered
184 * with the AccessibleJComponent with a property name of
185 * {@link AccessibleContext#ACCESSIBLE_CHILD_PROPERTY}.
187 * @param event the container event
189 public void componentAdded(ContainerEvent event)
191 Component c = event.getChild();
192 if (c != null && c instanceof Accessible)
194 AccessibleContext childCtx = c.getAccessibleContext();
195 AccessibleJComponent.this.firePropertyChange
196 (AccessibleContext.ACCESSIBLE_CHILD_PROPERTY, null, childCtx);
201 * Receives notification when a child component is removed from the
202 * JComponent and fires a PropertyChangeEvent on listeners registered
203 * with the AccessibleJComponent with a property name of
204 * {@link AccessibleContext#ACCESSIBLE_CHILD_PROPERTY}.
206 * @param event the container event
208 public void componentRemoved(ContainerEvent event)
210 Component c = event.getChild();
211 if (c != null && c instanceof Accessible)
213 AccessibleContext childCtx = c.getAccessibleContext();
214 AccessibleJComponent.this.firePropertyChange
215 (AccessibleContext.ACCESSIBLE_CHILD_PROPERTY, childCtx, null);
220 private static final long serialVersionUID = -7047089700479897799L;
223 * Receives notification when a child component is added to the
224 * JComponent and fires a PropertyChangeEvent on listeners registered
225 * with the AccessibleJComponent.
227 * @specnote AccessibleAWTContainer has a protected field with the same
228 * name. Looks like a bug or nasty misdesign to me.
230 protected ContainerListener accessibleContainerHandler;
233 * Receives notification if the focus on the JComponent changes and
234 * fires appropriate PropertyChangeEvents to listeners registered with
235 * the AccessibleJComponent.
237 * @specnote AccessibleAWTComponent has a protected field
238 * accessibleAWTFocusHandler. Looks like a bug or nasty misdesign
241 protected FocusListener accessibleFocusHandler;
244 * Creates a new AccessibleJComponent.
246 protected AccessibleJComponent()
248 // Nothing to do here.
252 * Adds a property change listener to the list of registered listeners.
254 * This sets up the {@link #accessibleContainerHandler} and
255 * {@link #accessibleFocusHandler} fields and calls
256 * <code>super.addPropertyChangeListener(listener)</code>.
258 * @param listener the listener to add
260 public void addPropertyChangeListener(PropertyChangeListener listener)
262 // Tests seem to indicate that this method also sets up the other two
264 if (accessibleContainerHandler == null)
266 accessibleContainerHandler = new AccessibleContainerHandler();
267 addContainerListener(accessibleContainerHandler);
269 if (accessibleFocusHandler == null)
271 accessibleFocusHandler = new AccessibleFocusHandler();
272 addFocusListener(accessibleFocusHandler);
274 super.addPropertyChangeListener(listener);
278 * Removes a property change listener from the list of registered listeners.
280 * This uninstalls the {@link #accessibleContainerHandler} and
281 * {@link #accessibleFocusHandler} fields and calls
282 * <code>super.removePropertyChangeListener(listener)</code>.
284 * @param listener the listener to remove
286 public void removePropertyChangeListener(PropertyChangeListener listener)
288 // Tests seem to indicate that this method also resets the other two
290 if (accessibleContainerHandler != null)
292 removeContainerListener(accessibleContainerHandler);
293 accessibleContainerHandler = null;
295 if (accessibleFocusHandler != null)
297 removeFocusListener(accessibleFocusHandler);
298 accessibleFocusHandler = null;
300 super.removePropertyChangeListener(listener);
304 * Returns the number of accessible children of this object.
306 * @return the number of accessible children of this object
308 public int getAccessibleChildrenCount()
310 // TODO: The functionality should be performed in the superclass.
311 // Find out why this is overridden. However, it is very well possible
312 // that this is left over from times when there was no such superclass
314 return super.getAccessibleChildrenCount();
318 * Returns the accessible child component at index <code>i</code>.
320 * @param i the index of the accessible child to return
322 * @return the accessible child component at index <code>i</code>
324 public Accessible getAccessibleChild(int i)
326 // TODO: The functionality should be performed in the superclass.
327 // Find out why this is overridden. However, it is very well possible
328 // that this is left over from times when there was no such superclass
330 return super.getAccessibleChild(i);
334 * Returns the accessible state set of this component.
336 * @return the accessible state set of this component
338 public AccessibleStateSet getAccessibleStateSet()
340 // Note: While the java.awt.Component has an 'opaque' property, it
341 // seems that it is not added to the accessible state set there, even
342 // if this property is true. However, it is handled for JComponent, so
344 AccessibleStateSet state = super.getAccessibleStateSet();
346 state.add(AccessibleState.OPAQUE);
351 * Returns the localized name for this object. Generally this should
352 * almost never return {@link Component#getName()} since that is not
353 * a localized name. If the object is some kind of text component (like
354 * a menu item), then the value of the object may be returned. Also, if
355 * the object has a tooltip, the value of the tooltip may also be
358 * @return the localized name for this object or <code>null</code> if this
361 public String getAccessibleName()
363 String name = super.getAccessibleName();
365 // There are two fallbacks provided by the JComponent in the case the
366 // superclass returns null:
367 // - If the component is inside a titled border, then it inherits the
368 // name from the border title.
369 // - If the component is not inside a titled border but has a label
370 // (via JLabel.setLabelFor()), then it gets the name from the label's
371 // accessible context.
375 name = getTitledBorderText();
380 Object l = getClientProperty(JLabel.LABEL_PROPERTY);
381 if (l instanceof Accessible)
383 AccessibleContext labelCtx =
384 ((Accessible) l).getAccessibleContext();
385 name = labelCtx.getAccessibleName();
393 * Returns the localized description of this object.
395 * @return the localized description of this object or <code>null</code>
396 * if this object has no description
398 public String getAccessibleDescription()
400 // There are two fallbacks provided by the JComponent in the case the
401 // superclass returns null:
402 // - If the component has a tooltip, then inherit the description from
404 // - If the component is not inside a titled border but has a label
405 // (via JLabel.setLabelFor()), then it gets the name from the label's
406 // accessible context.
407 String descr = super.getAccessibleDescription();
411 descr = getToolTipText();
416 Object l = getClientProperty(JLabel.LABEL_PROPERTY);
417 if (l instanceof Accessible)
419 AccessibleContext labelCtx =
420 ((Accessible) l).getAccessibleContext();
421 descr = labelCtx.getAccessibleName();
429 * Returns the accessible role of this component.
431 * @return the accessible role of this component
433 * @see AccessibleRole
435 public AccessibleRole getAccessibleRole()
437 return AccessibleRole.SWING_COMPONENT;
441 * Recursivly searches a border hierarchy (starting at <code>border) for
442 * a titled border and returns the title if one is found, <code>null</code>
445 * @param border the border to start search from
447 * @return the border title of a possibly found titled border
449 protected String getBorderTitle(Border border)
452 if (border instanceof CompoundBorder)
454 CompoundBorder compound = (CompoundBorder) border;
455 Border inner = compound.getInsideBorder();
456 title = getBorderTitle(inner);
459 Border outer = compound.getOutsideBorder();
460 title = getBorderTitle(outer);
463 else if (border instanceof TitledBorder)
465 TitledBorder titled = (TitledBorder) border;
466 title = titled.getTitle();
472 * Returns the tooltip text for this accessible component.
474 * @return the tooltip text for this accessible component
476 public String getToolTipText()
478 return JComponent.this.getToolTipText();
482 * Returns the title of the border of this accessible component if
483 * this component has a titled border, otherwise returns <code>null</code>.
485 * @return the title of the border of this accessible component if
486 * this component has a titled border, otherwise returns
489 public String getTitledBorderText()
491 return getBorderTitle(getBorder());
495 * Returns the keybindings associated with this accessible component or
496 * <code>null</code> if the component does not support key bindings.
498 * @return the keybindings associated with this accessible component
500 public AccessibleKeyBinding getAccessibleKeyBinding()
502 // The reference implementation seems to always return null here,
503 // independent of the key bindings of the JComponent. So do we.
509 * An explicit value for the component's preferred size; if not set by a
510 * user, this is calculated on the fly by delegating to the {@link
511 * ComponentUI#getPreferredSize} method on the {@link #ui} property.
513 Dimension preferredSize;
516 * An explicit value for the component's minimum size; if not set by a
517 * user, this is calculated on the fly by delegating to the {@link
518 * ComponentUI#getMinimumSize} method on the {@link #ui} property.
520 Dimension minimumSize;
523 * An explicit value for the component's maximum size; if not set by a
524 * user, this is calculated on the fly by delegating to the {@link
525 * ComponentUI#getMaximumSize} method on the {@link #ui} property.
527 Dimension maximumSize;
530 * A value between 0.0 and 1.0 indicating the preferred horizontal
531 * alignment of the component, relative to its siblings. The values
532 * {@link #LEFT_ALIGNMENT}, {@link #CENTER_ALIGNMENT}, and {@link
533 * #RIGHT_ALIGNMENT} can also be used, as synonyms for <code>0.0</code>,
534 * <code>0.5</code>, and <code>1.0</code>, respectively. Not all layout
535 * managers use this property.
537 * @see #getAlignmentX
538 * @see #setAlignmentX
539 * @see javax.swing.OverlayLayout
540 * @see javax.swing.BoxLayout
542 float alignmentX = -1.0F;
545 * A value between 0.0 and 1.0 indicating the preferred vertical
546 * alignment of the component, relative to its siblings. The values
547 * {@link #TOP_ALIGNMENT}, {@link #CENTER_ALIGNMENT}, and {@link
548 * #BOTTOM_ALIGNMENT} can also be used, as synonyms for <code>0.0</code>,
549 * <code>0.5</code>, and <code>1.0</code>, respectively. Not all layout
550 * managers use this property.
552 * @see #getAlignmentY
553 * @see #setAlignmentY
554 * @see javax.swing.OverlayLayout
555 * @see javax.swing.BoxLayout
557 float alignmentY = -1.0F;
560 * The border painted around this component.
567 * The text to show in the tooltip associated with this component.
569 * @see #setToolTipText
570 * @see #getToolTipText()
575 * <p>Whether to double buffer this component when painting. This flag
576 * should generally be <code>true</code>, to ensure good painting
579 * <p>All children of a double buffered component are painted into the
580 * double buffer automatically, so only the top widget in a window needs
581 * to be double buffered.</p>
583 * @see #setDoubleBuffered
584 * @see #isDoubleBuffered
587 boolean doubleBuffered = true;
590 * A set of flags indicating which debugging graphics facilities should
591 * be enabled on this component. The values should be a combination of
592 * {@link DebugGraphics#NONE_OPTION}, {@link DebugGraphics#LOG_OPTION},
593 * {@link DebugGraphics#FLASH_OPTION}, or {@link
594 * DebugGraphics#BUFFERED_OPTION}.
596 * @see #setDebugGraphicsOptions
597 * @see #getDebugGraphicsOptions
599 * @see #getComponentGraphics
601 int debugGraphicsOptions;
604 * <p>This property controls two independent behaviors simultaneously.</p>
606 * <p>First, it controls whether to fill the background of this widget
607 * when painting its body. This affects calls to {@link
608 * JComponent#paintComponent}, which in turn calls {@link
609 * ComponentUI#update} on the component's {@link #ui} property. If the
610 * component is opaque during this call, the background will be filled
611 * before calling {@link ComponentUI#paint}. This happens merely as a
612 * convenience; you may fill the component's background yourself too,
613 * but there is no need to do so if you will be filling with the same
616 * <p>Second, it the opaque property informs swing's repaint system
617 * whether it will be necessary to paint the components "underneath" this
618 * component, in Z-order. If the component is opaque, it is considered to
619 * completely occlude components "underneath" it, so they will not be
620 * repainted along with the opaque component.</p>
622 * <p>The default value for this property is <code>false</code>, but most
623 * components will want to set it to <code>true</code> when installing UI
624 * defaults in {@link ComponentUI#installUI}.</p>
628 * @see #paintComponent
630 boolean opaque = false;
633 * The user interface delegate for this component. Event delivery and
634 * repainting of the component are usually delegated to this object.
640 protected ComponentUI ui;
643 * A hint to the focus system that this component should or should not
644 * get focus. If this is <code>false</code>, swing will not try to
645 * request focus on this component; if <code>true</code>, swing might
646 * try to request focus, but the request might fail. Thus it is only
647 * a hint guiding swing's behavior.
649 * @see #requestFocus()
650 * @see #isRequestFocusEnabled
651 * @see #setRequestFocusEnabled
653 boolean requestFocusEnabled;
656 * Flag indicating behavior of this component when the mouse is dragged
657 * outside the component and the mouse <em>stops moving</em>. If
658 * <code>true</code>, synthetic mouse events will be delivered on regular
659 * timed intervals, continuing off in the direction the mouse exited the
660 * component, until the mouse is released or re-enters the component.
662 * @see #setAutoscrolls
663 * @see #getAutoscrolls
665 boolean autoscrolls = false;
668 * Indicates whether the current paint call is already double buffered or
671 static boolean isPaintingDoubleBuffered = false;
674 * Listeners for events other than {@link PropertyChangeEvent} are
675 * handled by this listener list. PropertyChangeEvents are handled in
676 * {@link #changeSupport}.
678 protected EventListenerList listenerList = new EventListenerList();
681 * Storage for "client properties", which are key/value pairs associated
682 * with this component by a "client", such as a user application or a
683 * layout manager. This is lazily constructed when the component gets its
684 * first client property.
686 private Hashtable clientProperties;
688 private InputMap inputMap_whenFocused;
689 private InputMap inputMap_whenAncestorOfFocused;
690 private ComponentInputMap inputMap_whenInFocusedWindow;
691 private ActionMap actionMap;
693 private boolean verifyInputWhenFocusTarget;
694 private InputVerifier inputVerifier;
696 private TransferHandler transferHandler;
699 * Indicates if this component is currently painting a tile or not.
701 private boolean paintingTile;
704 * A temporary buffer used for fast dragging of components.
706 private Image dragBuffer;
709 * Indicates if the dragBuffer is already initialized.
711 private boolean dragBufferInitialized;
714 * A cached Rectangle object to be reused. Be careful when you use that,
715 * so that it doesn't get modified in another context within the same
718 private static transient Rectangle rectCache;
721 * The default locale of the component.
723 * @see #getDefaultLocale
724 * @see #setDefaultLocale
726 private static Locale defaultLocale;
728 public static final String TOOL_TIP_TEXT_KEY = "ToolTipText";
731 * Constant used to indicate that no condition has been assigned to a
734 * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
736 public static final int UNDEFINED_CONDITION = -1;
739 * Constant used to indicate that an action should be performed only when
740 * the component has focus.
742 * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
744 public static final int WHEN_FOCUSED = 0;
747 * Constant used to indicate that an action should be performed only when
748 * the component is an ancestor of the component which has focus.
750 * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
752 public static final int WHEN_ANCESTOR_OF_FOCUSED_COMPONENT = 1;
755 * Constant used to indicate that an action should be performed only when
756 * the component is in the window which has focus.
758 * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
760 public static final int WHEN_IN_FOCUSED_WINDOW = 2;
763 * Indicates if this component is completely dirty or not. This is used
764 * by the RepaintManager's
765 * {@link RepaintManager#isCompletelyDirty(JComponent)} method.
767 boolean isCompletelyDirty = false;
770 * Indicates if the opaque property has been set by a client program or by
773 * @see #setUIProperty(String, Object)
774 * @see LookAndFeel#installProperty(JComponent, String, Object)
776 private boolean clientOpaqueSet = false;
779 * Indicates if the autoscrolls property has been set by a client program or
782 * @see #setUIProperty(String, Object)
783 * @see LookAndFeel#installProperty(JComponent, String, Object)
785 private boolean clientAutoscrollsSet = false;
788 * Creates a new <code>JComponent</code> instance.
793 setDropTarget(new DropTarget());
794 defaultLocale = Locale.getDefault();
795 debugGraphicsOptions = DebugGraphics.NONE_OPTION;
796 setRequestFocusEnabled(true);
800 * Helper to lazily construct and return the client properties table.
802 * @return The current client properties table
804 * @see #clientProperties
805 * @see #getClientProperty
806 * @see #putClientProperty
808 private Hashtable getClientProperties()
810 if (clientProperties == null)
811 clientProperties = new Hashtable();
812 return clientProperties;
816 * Get a client property associated with this component and a particular
819 * @param key The key with which to look up the client property
821 * @return A client property associated with this object and key
823 * @see #clientProperties
824 * @see #getClientProperties
825 * @see #putClientProperty
827 public final Object getClientProperty(Object key)
829 return getClientProperties().get(key);
833 * Add a client property <code>value</code> to this component, associated
834 * with <code>key</code>. If there is an existing client property
835 * associated with <code>key</code>, it will be replaced. A
836 * {@link PropertyChangeEvent} is sent to registered listeners (with the
837 * name of the property being <code>key.toString()</code>).
839 * @param key The key of the client property association to add
840 * @param value The value of the client property association to add
842 * @see #clientProperties
843 * @see #getClientProperties
844 * @see #getClientProperty
846 public final void putClientProperty(Object key, Object value)
848 Hashtable t = getClientProperties();
849 Object old = t.get(key);
854 firePropertyChange(key.toString(), old, value);
858 * Unregister an <code>AncestorListener</code>.
860 * @param listener The listener to unregister
862 * @see #addAncestorListener
864 public void removeAncestorListener(AncestorListener listener)
866 listenerList.remove(AncestorListener.class, listener);
870 * Unregister a <code>VetoableChangeChangeListener</code>.
872 * @param listener The listener to unregister
874 * @see #addVetoableChangeListener
876 public void removeVetoableChangeListener(VetoableChangeListener listener)
878 listenerList.remove(VetoableChangeListener.class, listener);
882 * Register an <code>AncestorListener</code>.
884 * @param listener The listener to register
886 * @see #removeVetoableChangeListener
888 public void addAncestorListener(AncestorListener listener)
890 listenerList.add(AncestorListener.class, listener);
894 * Register a <code>PropertyChangeListener</code> for a specific, named
895 * property. To listen to all property changes, regardless of name, use
896 * {@link #addPropertyChangeListener(PropertyChangeListener)} instead.
898 * @param propertyName The property name to listen to
899 * @param listener The listener to register
901 * @see #removePropertyChangeListener(String, PropertyChangeListener)
902 * @see #changeSupport
904 public void addPropertyChangeListener(String propertyName,
905 PropertyChangeListener listener)
907 listenerList.add(PropertyChangeListener.class, listener);
911 * Register a <code>VetoableChangeListener</code>.
913 * @param listener The listener to register
915 * @see #removeVetoableChangeListener
918 public void addVetoableChangeListener(VetoableChangeListener listener)
920 listenerList.add(VetoableChangeListener.class, listener);
924 * Returns all registered {@link EventListener}s of the given
925 * <code>listenerType</code>.
927 * @param listenerType the class of listeners to filter (<code>null</code>
930 * @return An array of registered listeners.
932 * @throws ClassCastException if <code>listenerType</code> does not implement
933 * the {@link EventListener} interface.
934 * @throws NullPointerException if <code>listenerType</code> is
937 * @see #getAncestorListeners()
942 public EventListener[] getListeners(Class listenerType)
944 if (listenerType == PropertyChangeListener.class)
945 return getPropertyChangeListeners();
947 return listenerList.getListeners(listenerType);
951 * Return all registered <code>AncestorListener</code> objects.
953 * @return The set of <code>AncestorListener</code> objects in {@link
956 public AncestorListener[] getAncestorListeners()
958 return (AncestorListener[]) getListeners(AncestorListener.class);
962 * Return all registered <code>VetoableChangeListener</code> objects.
964 * @return The set of <code>VetoableChangeListener</code> objects in {@link
967 public VetoableChangeListener[] getVetoableChangeListeners()
969 return (VetoableChangeListener[]) getListeners(VetoableChangeListener.class);
973 * A variant of {@link #firePropertyChange(String,Object,Object)}
974 * for properties with <code>boolean</code> values.
976 * @specnote It seems that in JDK1.5 all property related methods have been
977 * moved to java.awt.Component, except this and 2 others. We call
978 * super here. I guess this will also be removed in one of the next
981 public void firePropertyChange(String propertyName, boolean oldValue,
984 super.firePropertyChange(propertyName, oldValue, newValue);
988 * A variant of {@link #firePropertyChange(String,Object,Object)}
989 * for properties with <code>char</code> values.
991 * @specnote It seems that in JDK1.5 all property related methods have been
992 * moved to java.awt.Component, except this and 2 others. We call
993 * super here. I guess this will also be removed in one of the next
996 public void firePropertyChange(String propertyName, char oldValue,
999 super.firePropertyChange(propertyName, oldValue, newValue);
1003 * A variant of {@link #firePropertyChange(String,Object,Object)}
1004 * for properties with <code>int</code> values.
1006 * @specnote It seems that in JDK1.5 all property related methods have been
1007 * moved to java.awt.Component, except this and 2 others. We call
1008 * super here. I guess this will also be removed in one of the next
1011 public void firePropertyChange(String propertyName, int oldValue,
1014 super.firePropertyChange(propertyName, oldValue, newValue);
1018 * Call {@link VetoableChangeListener#vetoableChange} on all listeners
1019 * registered to listen to a given property. Any method which changes
1020 * the specified property of this component should call this method.
1022 * @param propertyName The property which changed
1023 * @param oldValue The old value of the property
1024 * @param newValue The new value of the property
1026 * @throws PropertyVetoException if the change was vetoed by a listener
1028 * @see #addVetoableChangeListener
1029 * @see #removeVetoableChangeListener
1031 protected void fireVetoableChange(String propertyName, Object oldValue,
1033 throws PropertyVetoException
1035 VetoableChangeListener[] listeners = getVetoableChangeListeners();
1037 PropertyChangeEvent evt =
1038 new PropertyChangeEvent(this, propertyName, oldValue, newValue);
1040 for (int i = 0; i < listeners.length; i++)
1041 listeners[i].vetoableChange(evt);
1045 * Get the value of the accessibleContext property for this component.
1047 * @return the current value of the property
1049 public AccessibleContext getAccessibleContext()
1055 * Get the value of the {@link #alignmentX} property.
1057 * @return The current value of the property.
1059 * @see #setAlignmentX
1062 public float getAlignmentX()
1064 float ret = alignmentX;
1066 // alignment has not been set explicitly.
1067 ret = super.getAlignmentX();
1073 * Get the value of the {@link #alignmentY} property.
1075 * @return The current value of the property.
1077 * @see #setAlignmentY
1080 public float getAlignmentY()
1082 float ret = alignmentY;
1084 // alignment has not been set explicitly.
1085 ret = super.getAlignmentY();
1091 * Get the current value of the {@link #autoscrolls} property.
1093 * @return The current value of the property
1095 public boolean getAutoscrolls()
1101 * Set the value of the {@link #border} property.
1103 * @param newBorder The new value of the property
1107 public void setBorder(Border newBorder)
1109 Border oldBorder = getBorder();
1110 if (oldBorder == newBorder)
1114 firePropertyChange("border", oldBorder, newBorder);
1119 * Get the value of the {@link #border} property.
1121 * @return The property's current value
1125 public Border getBorder()
1131 * Get the component's current bounding box. If a rectangle is provided,
1132 * use this as the return value (adjusting its fields in place);
1133 * otherwise (of <code>null</code> is provided) return a new {@link
1136 * @param rv Optional return value to use
1138 * @return A rectangle bounding the component
1140 public Rectangle getBounds(Rectangle rv)
1143 return new Rectangle(getX(), getY(), getWidth(), getHeight());
1146 rv.setBounds(getX(), getY(), getWidth(), getHeight());
1152 * Prepares a graphics context for painting this object. If {@link
1153 * #debugGraphicsOptions} is not equal to {@link
1154 * DebugGraphics#NONE_OPTION}, produce a new {@link DebugGraphics} object
1155 * wrapping the parameter. Otherwise configure the parameter with this
1156 * component's foreground color and font.
1158 * @param g The graphics context to wrap or configure
1160 * @return A graphics context to paint this object with
1162 * @see #debugGraphicsOptions
1165 protected Graphics getComponentGraphics(Graphics g)
1168 int options = getDebugGraphicsOptions();
1169 if (options != DebugGraphics.NONE_OPTION)
1171 if (!(g2 instanceof DebugGraphics))
1172 g2 = new DebugGraphics(g);
1173 DebugGraphics dg = (DebugGraphics) g2;
1174 dg.setDebugOptions(dg.getDebugOptions() | options);
1176 g2.setFont(this.getFont());
1177 g2.setColor(this.getForeground());
1182 * Get the value of the {@link #debugGraphicsOptions} property.
1184 * @return The current value of the property.
1186 * @see #setDebugGraphicsOptions
1187 * @see #debugGraphicsOptions
1189 public int getDebugGraphicsOptions()
1191 String option = System.getProperty("gnu.javax.swing.DebugGraphics");
1192 int options = debugGraphicsOptions;
1193 if (option != null && option.length() != 0)
1198 if (option.equals("LOG"))
1199 options |= DebugGraphics.LOG_OPTION;
1200 else if (option.equals("FLASH"))
1201 options |= DebugGraphics.FLASH_OPTION;
1207 * Get the component's insets, which are calculated from
1208 * the {@link #border} property. If the border is <code>null</code>,
1209 * calls {@link Container#getInsets}.
1211 * @return The component's current insets
1213 public Insets getInsets()
1216 return super.getInsets();
1217 return getBorder().getBorderInsets(this);
1221 * Get the component's insets, which are calculated from the {@link
1222 * #border} property. If the border is <code>null</code>, calls {@link
1223 * Container#getInsets}. The passed-in {@link Insets} value will be
1224 * used as the return value, if possible.
1226 * @param insets Return value object to reuse, if possible
1228 * @return The component's current insets
1230 public Insets getInsets(Insets insets)
1232 Insets t = getInsets();
1237 insets.left = t.left;
1238 insets.right = t.right;
1240 insets.bottom = t.bottom;
1245 * Get the component's location. The passed-in {@link Point} value
1246 * will be used as the return value, if possible.
1248 * @param rv Return value object to reuse, if possible
1250 * @return The component's current location
1252 public Point getLocation(Point rv)
1255 return new Point(getX(), getY());
1257 rv.setLocation(getX(), getY());
1262 * Get the component's maximum size. If the {@link #maximumSize} property
1263 * has been explicitly set, it is returned. If the {@link #maximumSize}
1264 * property has not been set but the {@link #ui} property has been, the
1265 * result of {@link ComponentUI#getMaximumSize} is returned. If neither
1266 * property has been set, the result of {@link Container#getMaximumSize}
1269 * @return The maximum size of the component
1272 * @see #setMaximumSize
1274 public Dimension getMaximumSize()
1276 if (maximumSize != null)
1281 Dimension s = ui.getMaximumSize(this);
1286 Dimension p = super.getMaximumSize();
1291 * Get the component's minimum size. If the {@link #minimumSize} property
1292 * has been explicitly set, it is returned. If the {@link #minimumSize}
1293 * property has not been set but the {@link #ui} property has been, the
1294 * result of {@link ComponentUI#getMinimumSize} is returned. If neither
1295 * property has been set, the result of {@link Container#getMinimumSize}
1298 * @return The minimum size of the component
1301 * @see #setMinimumSize
1303 public Dimension getMinimumSize()
1305 if (minimumSize != null)
1310 Dimension s = ui.getMinimumSize(this);
1315 Dimension p = super.getMinimumSize();
1320 * Get the component's preferred size. If the {@link #preferredSize}
1321 * property has been explicitly set, it is returned. If the {@link
1322 * #preferredSize} property has not been set but the {@link #ui} property
1323 * has been, the result of {@link ComponentUI#getPreferredSize} is
1324 * returned. If neither property has been set, the result of {@link
1325 * Container#getPreferredSize} is returned.
1327 * @return The preferred size of the component
1329 * @see #preferredSize
1330 * @see #setPreferredSize
1332 public Dimension getPreferredSize()
1334 Dimension prefSize = null;
1335 if (preferredSize != null)
1336 prefSize = new Dimension(preferredSize);
1338 else if (ui != null)
1340 Dimension s = ui.getPreferredSize(this);
1345 if (prefSize == null)
1346 prefSize = super.getPreferredSize();
1352 * Checks if a maximum size was explicitely set on the component.
1354 * @return <code>true</code> if a maximum size was set,
1355 * <code>false</code> otherwise
1359 public boolean isMaximumSizeSet()
1361 return maximumSize != null;
1365 * Checks if a minimum size was explicitely set on the component.
1367 * @return <code>true</code> if a minimum size was set,
1368 * <code>false</code> otherwise
1372 public boolean isMinimumSizeSet()
1374 return minimumSize != null;
1378 * Checks if a preferred size was explicitely set on the component.
1380 * @return <code>true</code> if a preferred size was set,
1381 * <code>false</code> otherwise
1385 public boolean isPreferredSizeSet()
1387 return preferredSize != null;
1391 * Return the value of the <code>nextFocusableComponent</code> property.
1393 * @return The current value of the property, or <code>null</code>
1394 * if none has been set.
1396 * @deprecated See {@link java.awt.FocusTraversalPolicy}
1398 public Component getNextFocusableComponent()
1400 Container focusRoot = this;
1401 if (! this.isFocusCycleRoot())
1402 focusRoot = getFocusCycleRootAncestor();
1404 FocusTraversalPolicy policy = focusRoot.getFocusTraversalPolicy();
1405 return policy.getComponentAfter(focusRoot, this);
1409 * Return the set of {@link KeyStroke} objects which are registered
1410 * to initiate actions on this component.
1412 * @return An array of the registered keystrokes
1414 public KeyStroke[] getRegisteredKeyStrokes()
1420 * Returns the first ancestor of this component which is a {@link JRootPane}.
1421 * Equivalent to calling <code>SwingUtilities.getRootPane(this);</code>.
1423 * @return An ancestral JRootPane, or <code>null</code> if none exists.
1425 public JRootPane getRootPane()
1427 JRootPane p = SwingUtilities.getRootPane(this);
1432 * Get the component's size. The passed-in {@link Dimension} value
1433 * will be used as the return value, if possible.
1435 * @param rv Return value object to reuse, if possible
1437 * @return The component's current size
1439 public Dimension getSize(Dimension rv)
1442 return new Dimension(getWidth(), getHeight());
1445 rv.setSize(getWidth(), getHeight());
1451 * Return the <code>toolTip</code> property of this component, creating it and
1452 * setting it if it is currently <code>null</code>. This method can be
1453 * overridden in subclasses which wish to control the exact form of
1456 * @return The current toolTip
1458 public JToolTip createToolTip()
1460 JToolTip toolTip = new JToolTip();
1461 toolTip.setComponent(this);
1462 toolTip.setTipText(toolTipText);
1468 * Return the location at which the {@link #toolTipText} property should be
1469 * displayed, when triggered by a particular mouse event.
1471 * @param event The event the tooltip is being presented in response to
1473 * @return The point at which to display a tooltip, or <code>null</code>
1474 * if swing is to choose a default location.
1476 public Point getToolTipLocation(MouseEvent event)
1482 * Set the value of the {@link #toolTipText} property.
1484 * @param text The new property value
1486 * @see #getToolTipText()
1488 public void setToolTipText(String text)
1492 ToolTipManager.sharedInstance().unregisterComponent(this);
1497 // XXX: The tip text doesn't get updated unless you set it to null
1498 // and then to something not-null. This is consistent with the behaviour
1499 // of Sun's ToolTipManager.
1501 String oldText = toolTipText;
1504 if (oldText == null)
1505 ToolTipManager.sharedInstance().registerComponent(this);
1509 * Get the value of the {@link #toolTipText} property.
1511 * @return The current property value
1513 * @see #setToolTipText
1515 public String getToolTipText()
1521 * Get the value of the {@link #toolTipText} property, in response to a
1522 * particular mouse event.
1524 * @param event The mouse event which triggered the tooltip
1526 * @return The current property value
1528 * @see #setToolTipText
1530 public String getToolTipText(MouseEvent event)
1532 return getToolTipText();
1536 * Return the top level ancestral container (usually a {@link
1537 * java.awt.Window} or {@link java.applet.Applet}) which this component is
1538 * contained within, or <code>null</code> if no ancestors exist.
1540 * @return The top level container, if it exists
1542 public Container getTopLevelAncestor()
1544 Container c = getParent();
1545 for (Container peek = c; peek != null; peek = peek.getParent())
1551 * Compute the component's visible rectangle, which is defined
1552 * recursively as either the component's bounds, if it has no parent, or
1553 * the intersection of the component's bounds with the visible rectangle
1556 * @param rect The return value slot to place the visible rectangle in
1558 public void computeVisibleRect(Rectangle rect)
1560 Component c = getParent();
1561 if (c != null && c instanceof JComponent)
1563 ((JComponent) c).computeVisibleRect(rect);
1564 rect.translate(-getX(), -getY());
1565 rect = SwingUtilities.computeIntersection(0, 0, getWidth(),
1569 rect.setRect(0, 0, getWidth(), getHeight());
1573 * Return the component's visible rectangle in a new {@link Rectangle},
1574 * rather than via a return slot.
1576 * @return the component's visible rectangle
1578 * @see #computeVisibleRect(Rectangle)
1580 public Rectangle getVisibleRect()
1582 Rectangle r = new Rectangle();
1583 computeVisibleRect(r);
1588 * <p>Requests that this component receive input focus, giving window
1589 * focus to the top level ancestor of this component. Only works on
1590 * displayable, focusable, visible components.</p>
1592 * <p>This method should not be called by clients; it is intended for
1593 * focus implementations. Use {@link Component#requestFocus()} instead.</p>
1595 * @see Component#requestFocus()
1597 public void grabFocus()
1603 * Get the value of the {@link #doubleBuffered} property.
1605 * @return The property's current value
1607 public boolean isDoubleBuffered()
1609 return doubleBuffered;
1613 * Return <code>true</code> if the provided component has no native peer;
1614 * in other words, if it is a "lightweight component".
1616 * @param c The component to test for lightweight-ness
1618 * @return Whether or not the component is lightweight
1620 public static boolean isLightweightComponent(Component c)
1622 return c.getPeer() instanceof LightweightPeer;
1626 * Return <code>true</code> if you wish this component to manage its own
1627 * focus. In particular: if you want this component to be sent
1628 * <code>TAB</code> and <code>SHIFT+TAB</code> key events, and to not
1629 * have its children considered as focus transfer targets. If
1630 * <code>true</code>, focus traversal around this component changes to
1631 * <code>CTRL+TAB</code> and <code>CTRL+SHIFT+TAB</code>.
1633 * @return <code>true</code> if you want this component to manage its own
1634 * focus, otherwise (by default) <code>false</code>
1636 * @deprecated 1.4 Use {@link Component#setFocusTraversalKeys(int, Set)} and
1637 * {@link Container#setFocusCycleRoot(boolean)} instead
1639 public boolean isManagingFocus()
1645 * Return the current value of the {@link #opaque} property.
1647 * @return The current property value
1649 public boolean isOpaque()
1655 * Return <code>true</code> if the component can guarantee that none of its
1656 * children will overlap in Z-order. This is a hint to the painting system.
1657 * The default is to return <code>true</code>, but some components such as
1658 * {@link JLayeredPane} should override this to return <code>false</code>.
1660 * @return Whether the component tiles its children
1662 public boolean isOptimizedDrawingEnabled()
1668 * Return <code>true</code> if this component is currently painting a tile,
1669 * this means that paint() is called again on another child component. This
1670 * method returns <code>false</code> if this component does not paint a tile
1671 * or if the last tile is currently painted.
1673 * @return whether the component is painting a tile
1675 public boolean isPaintingTile()
1677 return paintingTile;
1681 * Get the value of the {@link #requestFocusEnabled} property.
1683 * @return The current value of the property
1685 public boolean isRequestFocusEnabled()
1687 return requestFocusEnabled;
1691 * Return <code>true</code> if this component is a validation root; this
1692 * will cause calls to {@link #invalidate()} in this component's children
1693 * to be "captured" at this component, and not propagate to its parents.
1694 * For most components this should return <code>false</code>, but some
1695 * components such as {@link JViewport} will want to return
1696 * <code>true</code>.
1698 * @return Whether this component is a validation root
1700 public boolean isValidateRoot()
1706 * <p>Paint the component. This is a delicate process, and should only be
1707 * called from the repaint thread, under control of the {@link
1708 * RepaintManager}. Client code should usually call {@link #repaint()} to
1709 * trigger painting.</p>
1711 * <p>The body of the <code>paint</code> call involves calling {@link
1712 * #paintComponent}, {@link #paintBorder}, and {@link #paintChildren} in
1713 * order. If you want to customize painting behavior, you should override
1714 * one of these methods rather than <code>paint</code>.</p>
1716 * <p>For more details on the painting sequence, see <a
1717 * href="http://java.sun.com/products/jfc/tsc/articles/painting/index.html">
1718 * this article</a>.</p>
1720 * @param g The graphics context to paint with
1722 * @see #paintImmediately(Rectangle)
1724 public void paint(Graphics g)
1726 RepaintManager rm = RepaintManager.currentManager(this);
1727 // We do a little stunt act here to switch on double buffering if it's
1728 // not already on. If we are not already doublebuffered, then we jump
1729 // into the method paintDoubleBuffered, which turns on the double buffer
1730 // and then calls paint(g) again. In the second call we go into the else
1731 // branch of this if statement and actually paint things to the double
1732 // buffer. When this method completes, the call stack unwinds back to
1733 // paintDoubleBuffered, where the buffer contents is finally drawn to the
1735 if (!isPaintingDoubleBuffered && isDoubleBuffered()
1736 && rm.isDoubleBufferingEnabled())
1738 Rectangle clip = g.getClipBounds();
1739 paintDoubleBuffered(clip);
1743 if (getClientProperty("bufferedDragging") != null
1744 && dragBuffer == null)
1746 initializeDragBuffer();
1748 else if (getClientProperty("bufferedDragging") == null
1749 && dragBuffer != null)
1754 if (g.getClip() == null)
1755 g.setClip(0, 0, getWidth(), getHeight());
1756 if (dragBuffer != null && dragBufferInitialized)
1758 g.drawImage(dragBuffer, 0, 0, this);
1762 Graphics g2 = getComponentGraphics(g);
1766 Rectangle clip = g2.getClipBounds();
1768 || (clip.x == 0 && clip.y == 0 && clip.width == getWidth()
1769 && clip.height == getHeight()))
1770 RepaintManager.currentManager(this).markCompletelyClean(this);
1776 * Initializes the drag buffer by creating a new image and painting this
1777 * component into it.
1779 private void initializeDragBuffer()
1781 dragBufferInitialized = false;
1782 // Allocate new dragBuffer if the current one is too small.
1783 if (dragBuffer == null || dragBuffer.getWidth(this) < getWidth()
1784 || dragBuffer.getHeight(this) < getHeight())
1786 dragBuffer = createImage(getWidth(), getHeight());
1788 Graphics g = dragBuffer.getGraphics();
1791 dragBufferInitialized = true;
1795 * Paint the component's border. This usually means calling {@link
1796 * Border#paintBorder} on the {@link #border} property, if it is
1797 * non-<code>null</code>. You may override this if you wish to customize
1798 * border painting behavior. The border is painted after the component's
1799 * body, but before the component's children.
1801 * @param g The graphics context with which to paint the border
1804 * @see #paintChildren
1805 * @see #paintComponent
1807 protected void paintBorder(Graphics g)
1809 if (getBorder() != null)
1810 getBorder().paintBorder(this, g, 0, 0, getWidth(), getHeight());
1814 * Paint the component's children. This usually means calling {@link
1815 * Container#paint}, which recursively calls {@link #paint} on any of the
1816 * component's children, with appropriate changes to coordinate space and
1817 * clipping region. You may override this if you wish to customize
1818 * children painting behavior. The children are painted after the
1819 * component's body and border.
1821 * @param g The graphics context with which to paint the children
1825 * @see #paintComponent
1827 protected void paintChildren(Graphics g)
1829 if (getComponentCount() > 0)
1831 if (isOptimizedDrawingEnabled())
1832 paintChildrenOptimized(g);
1834 paintChildrenWithOverlap(g);
1839 * Paints the children of this JComponent in the case when the component
1840 * is not marked as optimizedDrawingEnabled, that means the container cannot
1841 * guarantee that it's children are tiled. For this case we must
1842 * perform a more complex optimization to determine the minimal rectangle
1843 * to be painted for each child component.
1845 * @param g the graphics context to use
1847 private void paintChildrenWithOverlap(Graphics g)
1849 Shape originalClip = g.getClip();
1850 Rectangle inner = SwingUtilities.calculateInnerArea(this, rectCache);
1851 g.clipRect(inner.x, inner.y, inner.width, inner.height);
1852 Component[] children = getComponents();
1854 // Find the rectangles that need to be painted for each child component.
1855 // We push on this list arrays that have the Rectangles to be painted as
1856 // the first elements and the component to be painted as the last one.
1857 // Later we go through that list in reverse order and paint the rectangles.
1858 ArrayList paintRegions = new ArrayList(children.length);
1859 ArrayList paintRectangles = new ArrayList();
1860 ArrayList newPaintRects = new ArrayList();
1861 paintRectangles.add(g.getClipBounds());
1862 ArrayList componentRectangles = new ArrayList();
1864 // Go through children from top to bottom and find out their paint
1866 for (int index = 0; paintRectangles.size() > 0 &&
1867 index < children.length; index++)
1869 Component comp = children[index];
1870 if (! comp.isVisible())
1873 Rectangle compBounds = comp.getBounds();
1874 boolean isOpaque = comp instanceof JComponent
1875 && ((JComponent) comp).isOpaque();
1877 // Add all the current paint rectangles that intersect with the
1878 // component to the component's paint rectangle array.
1879 for (int i = paintRectangles.size() - 1; i >= 0; i--)
1881 Rectangle r = (Rectangle) paintRectangles.get(i);
1882 if (r.intersects(compBounds))
1884 Rectangle compRect = r.intersection(compBounds);
1885 componentRectangles.add(compRect);
1886 // If the component is opaque, split up each paint rect and
1887 // add paintRect - compBounds to the newPaintRects array.
1891 Rectangle rect = new Rectangle();
1893 // The north retangle.
1894 x = Math.max(compBounds.x, r.x);
1896 w = Math.min(compBounds.width, r.width + r.x - x);
1897 h = compBounds.y - r.y;
1898 rect.setBounds(x, y, w, h);
1899 if (! rect.isEmpty())
1901 newPaintRects.add(rect);
1902 rect = new Rectangle();
1905 // The south rectangle.
1906 x = Math.max(compBounds.x, r.x);
1907 y = compBounds.y + compBounds.height;
1908 w = Math.min(compBounds.width, r.width + r.x - x);
1909 h = r.height - (compBounds.y - r.y) - compBounds.height;
1910 rect.setBounds(x, y, w, h);
1911 if (! rect.isEmpty())
1913 newPaintRects.add(rect);
1914 rect = new Rectangle();
1917 // The west rectangle.
1920 w = compBounds.x - r.x;
1922 rect.setBounds(x, y, w, h);
1923 if (! rect.isEmpty())
1925 newPaintRects.add(rect);
1926 rect = new Rectangle();
1929 // The east rectangle.
1930 x = compBounds.x + compBounds.width;
1932 w = r.width - (compBounds.x - r.x) - compBounds.width;
1934 rect.setBounds(x, y, w, h);
1935 if (! rect.isEmpty())
1937 newPaintRects.add(rect);
1942 // Not opaque, need to reuse the current paint rectangles
1943 // for the next component.
1944 newPaintRects.add(r);
1950 newPaintRects.add(r);
1954 // Replace the paintRectangles with the new split up
1956 paintRectangles.clear();
1957 paintRectangles.addAll(newPaintRects);
1958 newPaintRects.clear();
1960 // Store paint rectangles if there are any for the current component.
1961 int compRectsSize = componentRectangles.size();
1962 if (compRectsSize > 0)
1964 componentRectangles.add(comp);
1965 paintRegions.add(componentRectangles);
1966 componentRectangles = new ArrayList();
1970 // paintingTile becomes true just before we start painting the component's
1972 paintingTile = true;
1974 // We must go through the painting regions backwards, because the
1975 // topmost components have been added first, followed by the components
1977 int prEndIndex = paintRegions.size() - 1;
1978 for (int i = prEndIndex; i >= 0; i--)
1980 // paintingTile must be set to false before we begin to start painting
1983 paintingTile = false;
1985 ArrayList paintingRects = (ArrayList) paintRegions.get(i);
1986 // The last element is always the component.
1987 Component c = (Component) paintingRects.get(paintingRects.size() - 1);
1988 int endIndex = paintingRects.size() - 2;
1989 for (int j = 0; j <= endIndex; j++)
1991 Rectangle cBounds = c.getBounds();
1992 Rectangle bounds = (Rectangle) paintingRects.get(j);
1993 Rectangle oldClip = g.getClipBounds();
1994 if (oldClip == null)
1997 boolean translated = false;
2001 g.translate(cBounds.x, cBounds.y);
2008 g.translate(-cBounds.x, -cBounds.y);
2013 g.setClip(originalClip);
2017 * Paints the children of this container when it is marked as
2018 * optimizedDrawingEnabled. In this case the container can guarantee that
2019 * it's children are tiled, which allows for a much more efficient
2020 * algorithm to determine the minimum rectangles to be painted for
2023 * @param g the graphics context to use
2025 private void paintChildrenOptimized(Graphics g)
2027 Shape originalClip = g.getClip();
2028 Rectangle inner = SwingUtilities.calculateInnerArea(this, rectCache);
2029 g.clipRect(inner.x, inner.y, inner.width, inner.height);
2030 Component[] children = getComponents();
2032 // paintingTile becomes true just before we start painting the component's
2034 paintingTile = true;
2035 for (int i = children.length - 1; i >= 0; i--) //children.length; i++)
2037 // paintingTile must be set to false before we begin to start painting
2039 if (i == children.length - 1)
2040 paintingTile = false;
2042 if (!children[i].isVisible())
2045 Rectangle bounds = children[i].getBounds(rectCache);
2046 Rectangle oldClip = g.getClipBounds();
2047 if (oldClip == null)
2050 if (!g.hitClip(bounds.x, bounds.y, bounds.width, bounds.height))
2053 boolean translated = false;
2056 g.clipRect(bounds.x, bounds.y, bounds.width, bounds.height);
2057 g.translate(bounds.x, bounds.y);
2059 children[i].paint(g);
2064 g.translate(-bounds.x, -bounds.y);
2068 g.setClip(originalClip);
2072 * Paint the component's body. This usually means calling {@link
2073 * ComponentUI#update} on the {@link #ui} property of the component, if
2074 * it is non-<code>null</code>. You may override this if you wish to
2075 * customize the component's body-painting behavior. The component's body
2076 * is painted first, before the border and children.
2078 * @param g The graphics context with which to paint the body
2082 * @see #paintChildren
2084 protected void paintComponent(Graphics g)
2089 if (!(g instanceof Graphics2D))
2091 ui.update(g2, this);
2092 if (!(g instanceof Graphics2D))
2098 * A variant of {@link #paintImmediately(Rectangle)} which takes
2099 * integer parameters.
2101 * @param x The left x coordinate of the dirty region
2102 * @param y The top y coordinate of the dirty region
2103 * @param w The width of the dirty region
2104 * @param h The height of the dirty region
2106 public void paintImmediately(int x, int y, int w, int h)
2108 paintImmediately(new Rectangle(x, y, w, h));
2112 * Transform the provided dirty rectangle for this component into the
2113 * appropriate ancestral {@link JRootPane} and call {@link #paint} on
2114 * that root pane. This method is called from the {@link RepaintManager}
2115 * and should always be called within the painting thread.
2117 * <p>This method will acquire a double buffer from the {@link
2118 * RepaintManager} if the component's {@link #doubleBuffered} property is
2119 * <code>true</code> and the <code>paint</code> call is the
2120 * <em>first</em> recursive <code>paint</code> call inside swing.</p>
2122 * <p>The method will also modify the provided {@link Graphics} context
2123 * via the {@link #getComponentGraphics} method. If you want to customize
2124 * the graphics object used for painting, you should override that method
2125 * rather than <code>paint</code>.</p>
2127 * @param r The dirty rectangle to paint
2129 public void paintImmediately(Rectangle r)
2131 // Try to find a root pane for this component.
2132 //Component root = findPaintRoot(r);
2133 Component root = findPaintRoot(r);
2134 // If no paint root is found, then this component is completely overlapped
2135 // by another component and we don't need repainting.
2138 if (root == null || !root.isShowing())
2141 Rectangle rootClip = SwingUtilities.convertRectangle(this, r, root);
2142 if (root instanceof JComponent)
2143 ((JComponent) root).paintImmediately2(rootClip);
2145 root.repaint(rootClip.x, rootClip.y, rootClip.width, rootClip.height);
2149 * Performs the actual work of paintImmediatly on the repaint root.
2151 * @param r the area to be repainted
2153 void paintImmediately2(Rectangle r)
2155 RepaintManager rm = RepaintManager.currentManager(this);
2156 if (rm.isDoubleBufferingEnabled() && isDoubleBuffered())
2157 paintDoubleBuffered(r);
2163 * Gets the root of the component given. If a parent of the
2164 * component is an instance of Applet, then the applet is
2165 * returned. The applet is considered the root for painting
2166 * and adding/removing components. Otherwise, the root Window
2167 * is returned if it exists.
2169 * @param comp - The component to get the root for.
2170 * @return the parent root. An applet if it is a parent,
2171 * or the root window. If neither exist, null is returned.
2173 private Component getRoot(Component comp)
2177 while (comp != null)
2179 if (app == null && comp instanceof Window)
2181 else if (comp instanceof Applet)
2182 app = (Applet) comp;
2183 comp = comp.getParent();
2190 * Performs double buffered repainting.
2192 private void paintDoubleBuffered(Rectangle r)
2194 RepaintManager rm = RepaintManager.currentManager(this);
2196 // Paint on the offscreen buffer.
2197 Component root = getRoot(this);
2198 Image buffer = rm.getOffscreenBuffer(this, root.getWidth(),
2200 //Rectangle targetClip = SwingUtilities.convertRectangle(this, r, root);
2201 Point translation = SwingUtilities.convertPoint(this, 0, 0, root);
2202 Graphics g2 = buffer.getGraphics();
2203 g2.translate(translation.x, translation.y);
2204 g2.setClip(r.x, r.y, r.width, r.height);
2205 g2 = getComponentGraphics(g2);
2206 isPaintingDoubleBuffered = true;
2213 isPaintingDoubleBuffered = false;
2217 // Paint the buffer contents on screen.
2218 rm.commitBuffer(root, new Rectangle(translation.x + r.x,
2219 translation.y + r.y, r.width,
2224 * Performs normal painting without double buffering.
2226 * @param r the area that should be repainted
2228 void paintSimple(Rectangle r)
2230 Graphics g = getGraphics();
2231 Graphics g2 = getComponentGraphics(g);
2240 * Return a string representation for this component, for use in
2243 * @return A string describing this component.
2245 protected String paramString()
2247 StringBuffer sb = new StringBuffer();
2248 sb.append(super.paramString());
2249 sb.append(",alignmentX=").append(getAlignmentX());
2250 sb.append(",alignmentY=").append(getAlignmentY());
2251 sb.append(",border=");
2252 if (getBorder() != null)
2253 sb.append(getBorder());
2254 sb.append(",maximumSize=");
2255 if (getMaximumSize() != null)
2256 sb.append(getMaximumSize());
2257 sb.append(",minimumSize=");
2258 if (getMinimumSize() != null)
2259 sb.append(getMinimumSize());
2260 sb.append(",preferredSize=");
2261 if (getPreferredSize() != null)
2262 sb.append(getPreferredSize());
2263 return sb.toString();
2267 * A variant of {@link
2268 * #registerKeyboardAction(ActionListener,String,KeyStroke,int)} which
2269 * provides <code>null</code> for the command name.
2271 public void registerKeyboardAction(ActionListener act,
2275 registerKeyboardAction(act, null, stroke, cond);
2279 * There is some charmingly undocumented behavior sun seems to be using
2280 * to simulate the old register/unregister keyboard binding API. It's not
2281 * clear to me why this matters, but we shall endeavour to follow suit.
2283 * Two main thing seem to be happening when you do registerKeyboardAction():
2285 * - no actionMap() entry gets created, just an entry in inputMap()
2287 * - the inputMap() entry is a proxy class which invokes the the
2288 * binding's actionListener as a target, and which clobbers the command
2289 * name sent in the ActionEvent, providing the binding command name
2292 * This much you can work out just by asking the input and action maps
2293 * what they contain after making bindings, and watching the event which
2294 * gets delivered to the recipient. Beyond that, it seems to be a
2295 * sun-private solution so I will only immitate it as much as it matters
2296 * to external observers.
2298 private static class ActionListenerProxy
2299 extends AbstractAction
2301 ActionListener target;
2302 String bindingCommandName;
2304 public ActionListenerProxy(ActionListener li,
2308 bindingCommandName = cmd;
2311 public void actionPerformed(ActionEvent e)
2313 ActionEvent derivedEvent = new ActionEvent(e.getSource(),
2317 target.actionPerformed(derivedEvent);
2323 * An obsolete method to register a keyboard action on this component.
2324 * You should use <code>getInputMap</code> and <code>getActionMap</code>
2325 * to fetch mapping tables from keystrokes to commands, and commands to
2326 * actions, respectively, and modify those mappings directly.
2328 * @param act The action to be registered
2329 * @param cmd The command to deliver in the delivered {@link
2330 * java.awt.event.ActionEvent}
2331 * @param stroke The keystroke to register on
2332 * @param cond One of the values {@link #UNDEFINED_CONDITION},
2333 * {@link #WHEN_ANCESTOR_OF_FOCUSED_COMPONENT}, {@link #WHEN_FOCUSED}, or
2334 * {@link #WHEN_IN_FOCUSED_WINDOW}, indicating the condition which must
2335 * be met for the action to be fired
2337 * @see #unregisterKeyboardAction
2338 * @see #getConditionForKeyStroke
2339 * @see #resetKeyboardActions
2341 public void registerKeyboardAction(ActionListener act,
2346 getInputMap(cond).put(stroke, new ActionListenerProxy(act, cmd));
2349 public final void setInputMap(int condition, InputMap map)
2351 enableEvents(AWTEvent.KEY_EVENT_MASK);
2355 inputMap_whenFocused = map;
2358 case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT:
2359 inputMap_whenAncestorOfFocused = map;
2362 case WHEN_IN_FOCUSED_WINDOW:
2363 if (map != null && !(map instanceof ComponentInputMap))
2365 IllegalArgumentException("WHEN_IN_FOCUSED_WINDOW " +
2366 "InputMap must be a ComponentInputMap");
2367 inputMap_whenInFocusedWindow = (ComponentInputMap)map;
2370 case UNDEFINED_CONDITION:
2372 throw new IllegalArgumentException();
2376 public final InputMap getInputMap(int condition)
2378 enableEvents(AWTEvent.KEY_EVENT_MASK);
2382 if (inputMap_whenFocused == null)
2383 inputMap_whenFocused = new InputMap();
2384 return inputMap_whenFocused;
2386 case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT:
2387 if (inputMap_whenAncestorOfFocused == null)
2388 inputMap_whenAncestorOfFocused = new InputMap();
2389 return inputMap_whenAncestorOfFocused;
2391 case WHEN_IN_FOCUSED_WINDOW:
2392 if (inputMap_whenInFocusedWindow == null)
2393 inputMap_whenInFocusedWindow = new ComponentInputMap(this);
2394 return inputMap_whenInFocusedWindow;
2396 case UNDEFINED_CONDITION:
2402 public final InputMap getInputMap()
2404 return getInputMap(WHEN_FOCUSED);
2407 public final ActionMap getActionMap()
2409 if (actionMap == null)
2410 actionMap = new ActionMap();
2414 public final void setActionMap(ActionMap map)
2420 * Return the condition that determines whether a registered action
2421 * occurs in response to the specified keystroke.
2423 * As of 1.3 KeyStrokes can be registered with multiple simultaneous
2426 * @param ks The keystroke to return the condition of
2428 * @return One of the values {@link #UNDEFINED_CONDITION}, {@link
2429 * #WHEN_ANCESTOR_OF_FOCUSED_COMPONENT}, {@link #WHEN_FOCUSED}, or {@link
2430 * #WHEN_IN_FOCUSED_WINDOW}
2432 * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
2433 * @see #unregisterKeyboardAction
2434 * @see #resetKeyboardActions
2436 public int getConditionForKeyStroke(KeyStroke ks)
2438 if (inputMap_whenFocused != null
2439 && inputMap_whenFocused.get(ks) != null)
2440 return WHEN_FOCUSED;
2441 else if (inputMap_whenAncestorOfFocused != null
2442 && inputMap_whenAncestorOfFocused.get(ks) != null)
2443 return WHEN_ANCESTOR_OF_FOCUSED_COMPONENT;
2444 else if (inputMap_whenInFocusedWindow != null
2445 && inputMap_whenInFocusedWindow.get(ks) != null)
2446 return WHEN_IN_FOCUSED_WINDOW;
2448 return UNDEFINED_CONDITION;
2452 * Get the ActionListener (typically an {@link Action} object) which is
2453 * associated with a particular keystroke.
2455 * @param ks The keystroke to retrieve the action of
2457 * @return The action associated with the specified keystroke
2459 public ActionListener getActionForKeyStroke(KeyStroke ks)
2461 Object cmd = getInputMap().get(ks);
2464 if (cmd instanceof ActionListenerProxy)
2465 return (ActionListenerProxy) cmd;
2466 else if (cmd instanceof String)
2467 return getActionMap().get(cmd);
2473 * A hook for subclasses which want to customize event processing.
2475 protected void processComponentKeyEvent(KeyEvent e)
2477 // This method does nothing, it is meant to be overridden by subclasses.
2481 * Override the default key dispatch system from Component to hook into
2482 * the swing {@link InputMap} / {@link ActionMap} system.
2485 * href="http://java.sun.com/products/jfc/tsc/special_report/kestrel/keybindings.html">
2486 * this report</a> for more details, it's somewhat complex.
2488 protected void processKeyEvent(KeyEvent e)
2490 // let the AWT event processing send KeyEvents to registered listeners
2491 super.processKeyEvent(e);
2492 processComponentKeyEvent(e);
2497 // Input maps are checked in this order:
2498 // 1. The focused component's WHEN_FOCUSED map is checked.
2499 // 2. The focused component's WHEN_ANCESTOR_OF_FOCUSED_COMPONENT map.
2500 // 3. The WHEN_ANCESTOR_OF_FOCUSED_COMPONENT maps of the focused
2501 // component's parent, then its parent's parent, and so on.
2502 // Note: Input maps for disabled components are skipped.
2503 // 4. The WHEN_IN_FOCUSED_WINDOW maps of all the enabled components in
2504 // the focused window are searched.
2506 KeyStroke keyStroke = KeyStroke.getKeyStrokeForEvent(e);
2507 boolean pressed = e.getID() == KeyEvent.KEY_PRESSED;
2509 if (processKeyBinding(keyStroke, e, WHEN_FOCUSED, pressed))
2511 // This is step 1 from above comment.
2515 else if (processKeyBinding
2516 (keyStroke, e, WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, pressed))
2518 // This is step 2 from above comment.
2523 // This is step 3 from above comment.
2524 Container current = getParent();
2525 while (current != null)
2527 // If current is a JComponent, see if it handles the event in its
2528 // WHEN_ANCESTOR_OF_FOCUSED_COMPONENT maps.
2529 if ((current instanceof JComponent) &&
2530 ((JComponent)current).processKeyBinding
2531 (keyStroke, e,WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, pressed))
2537 // Stop when we've tried a top-level container and it didn't handle it
2538 if (current instanceof Window || current instanceof Applet)
2541 // Move up the hierarchy
2542 current = current.getParent();
2545 // Current being null means the JComponent does not currently have a
2546 // top-level ancestor, in which case we don't need to check
2547 // WHEN_IN_FOCUSED_WINDOW bindings.
2548 if (current == null || e.isConsumed())
2551 // This is step 4 from above comment. KeyboardManager maintains mappings
2552 // related to WHEN_IN_FOCUSED_WINDOW bindings so that we don't have to
2553 // traverse the containment hierarchy each time.
2554 if (KeyboardManager.getManager().processKeyStroke(current, keyStroke, e))
2558 protected boolean processKeyBinding(KeyStroke ks,
2566 InputMap map = getInputMap(condition);
2569 Object cmd = map.get(ks);
2572 if (cmd instanceof ActionListenerProxy)
2575 act = (Action) getActionMap().get(cmd);
2578 if (act != null && act.isEnabled())
2579 return SwingUtilities.notifyAction(act, ks, e, this, e.getModifiers());
2585 * Remove a keyboard action registry.
2587 * @param aKeyStroke The keystroke to unregister
2589 * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
2590 * @see #getConditionForKeyStroke
2591 * @see #resetKeyboardActions
2593 public void unregisterKeyboardAction(KeyStroke aKeyStroke)
2595 ActionMap am = getActionMap();
2596 // This loops through the conditions WHEN_FOCUSED,
2597 // WHEN_ANCESTOR_OF_FOCUSED_COMPONENT and WHEN_IN_FOCUSED_WINDOW.
2598 for (int cond = 0; cond < 3; cond++)
2600 InputMap im = getInputMap(cond);
2603 Object action = im.get(aKeyStroke);
2604 if (action != null && am != null)
2606 im.remove(aKeyStroke);
2613 * Reset all keyboard action registries.
2615 * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
2616 * @see #unregisterKeyboardAction
2617 * @see #getConditionForKeyStroke
2619 public void resetKeyboardActions()
2621 if (inputMap_whenFocused != null)
2622 inputMap_whenFocused.clear();
2623 if (inputMap_whenAncestorOfFocused != null)
2624 inputMap_whenAncestorOfFocused.clear();
2625 if (inputMap_whenInFocusedWindow != null)
2626 inputMap_whenInFocusedWindow.clear();
2627 if (actionMap != null)
2632 * Mark the described region of this component as dirty in the current
2633 * {@link RepaintManager}. This will queue an asynchronous repaint using
2634 * the system painting thread in the near future.
2637 * @param x coordinate of the region to mark as dirty
2638 * @param y coordinate of the region to mark as dirty
2639 * @param width dimension of the region to mark as dirty
2640 * @param height dimension of the region to mark as dirty
2642 public void repaint(long tm, int x, int y, int width, int height)
2644 RepaintManager.currentManager(this).addDirtyRegion(this, x, y, width,
2649 * Mark the described region of this component as dirty in the current
2650 * {@link RepaintManager}. This will queue an asynchronous repaint using
2651 * the system painting thread in the near future.
2653 * @param r The rectangle to mark as dirty
2655 public void repaint(Rectangle r)
2657 RepaintManager.currentManager(this).addDirtyRegion(this, r.x, r.y, r.width,
2662 * Request focus on the default component of this component's {@link
2663 * FocusTraversalPolicy}.
2665 * @return The result of {@link #requestFocus()}
2667 * @deprecated Use {@link #requestFocus()} on the default component provided
2668 * from the {@link FocusTraversalPolicy} instead.
2670 public boolean requestDefaultFocus()
2676 * Queue a an invalidation and revalidation of this component, using
2677 * {@link RepaintManager#addInvalidComponent}.
2679 public void revalidate()
2681 if (! EventQueue.isDispatchThread())
2682 SwingUtilities.invokeLater(new Runnable()
2692 RepaintManager.currentManager(this).addInvalidComponent(this);
2697 * Calls <code>scrollRectToVisible</code> on the component's parent.
2698 * Components which can service this call should override.
2700 * @param r The rectangle to make visible
2702 public void scrollRectToVisible(Rectangle r)
2704 Component p = getParent();
2705 if (p instanceof JComponent)
2706 ((JComponent) p).scrollRectToVisible(r);
2710 * Set the value of the {@link #alignmentX} property.
2712 * @param a The new value of the property
2714 public void setAlignmentX(float a)
2725 * Set the value of the {@link #alignmentY} property.
2727 * @param a The new value of the property
2729 public void setAlignmentY(float a)
2740 * Set the value of the {@link #autoscrolls} property.
2742 * @param a The new value of the property
2744 public void setAutoscrolls(boolean a)
2747 clientAutoscrollsSet = true;
2751 * Set the value of the {@link #debugGraphicsOptions} property.
2753 * @param debugOptions The new value of the property
2755 public void setDebugGraphicsOptions(int debugOptions)
2757 debugGraphicsOptions = debugOptions;
2761 * Set the value of the {@link #doubleBuffered} property.
2763 * @param db The new value of the property
2765 public void setDoubleBuffered(boolean db)
2767 doubleBuffered = db;
2771 * Set the value of the <code>enabled</code> property.
2773 * @param enable The new value of the property
2775 public void setEnabled(boolean enable)
2777 if (enable == isEnabled())
2779 super.setEnabled(enable);
2780 firePropertyChange("enabled", !enable, enable);
2785 * Set the value of the <code>font</code> property.
2787 * @param f The new value of the property
2789 public void setFont(Font f)
2799 * Set the value of the <code>background</code> property.
2801 * @param bg The new value of the property
2803 public void setBackground(Color bg)
2805 if (bg == getBackground())
2807 super.setBackground(bg);
2812 * Set the value of the <code>foreground</code> property.
2814 * @param fg The new value of the property
2816 public void setForeground(Color fg)
2818 if (fg == getForeground())
2820 super.setForeground(fg);
2825 * Set the value of the {@link #maximumSize} property. The passed value is
2826 * copied, the later direct changes on the argument have no effect on the
2829 * @param max The new value of the property
2831 public void setMaximumSize(Dimension max)
2833 Dimension oldMaximumSize = maximumSize;
2835 maximumSize = new Dimension(max);
2838 firePropertyChange("maximumSize", oldMaximumSize, maximumSize);
2842 * Set the value of the {@link #minimumSize} property. The passed value is
2843 * copied, the later direct changes on the argument have no effect on the
2846 * @param min The new value of the property
2848 public void setMinimumSize(Dimension min)
2850 Dimension oldMinimumSize = minimumSize;
2852 minimumSize = new Dimension(min);
2855 firePropertyChange("minimumSize", oldMinimumSize, minimumSize);
2859 * Set the value of the {@link #preferredSize} property. The passed value is
2860 * copied, the later direct changes on the argument have no effect on the
2863 * @param pref The new value of the property
2865 public void setPreferredSize(Dimension pref)
2867 Dimension oldPreferredSize = preferredSize;
2869 preferredSize = new Dimension(pref);
2871 preferredSize = null;
2872 firePropertyChange("preferredSize", oldPreferredSize, preferredSize);
2876 * Set the specified component to be the next component in the
2877 * focus cycle, overriding the {@link FocusTraversalPolicy} for
2880 * @param aComponent The component to set as the next focusable
2882 * @deprecated Use FocusTraversalPolicy instead
2884 public void setNextFocusableComponent(Component aComponent)
2886 Container focusRoot = this;
2887 if (! this.isFocusCycleRoot())
2888 focusRoot = getFocusCycleRootAncestor();
2890 FocusTraversalPolicy policy = focusRoot.getFocusTraversalPolicy();
2891 if (policy instanceof CompatibilityFocusTraversalPolicy)
2893 policy = new CompatibilityFocusTraversalPolicy(policy);
2894 focusRoot.setFocusTraversalPolicy(policy);
2896 CompatibilityFocusTraversalPolicy p =
2897 (CompatibilityFocusTraversalPolicy) policy;
2899 Component old = getNextFocusableComponent();
2902 p.removeNextFocusableComponent(this, old);
2905 if (aComponent != null)
2907 p.addNextFocusableComponent(this, aComponent);
2912 * Set the value of the {@link #requestFocusEnabled} property.
2914 * @param e The new value of the property
2916 public void setRequestFocusEnabled(boolean e)
2918 requestFocusEnabled = e;
2922 * Get the value of the {@link #transferHandler} property.
2924 * @return The current value of the property
2926 * @see #setTransferHandler
2929 public TransferHandler getTransferHandler()
2931 return transferHandler;
2935 * Set the value of the {@link #transferHandler} property.
2937 * @param newHandler The new value of the property
2939 * @see #getTransferHandler
2942 public void setTransferHandler(TransferHandler newHandler)
2944 if (transferHandler == newHandler)
2947 TransferHandler oldHandler = transferHandler;
2948 transferHandler = newHandler;
2949 firePropertyChange("transferHandler", oldHandler, newHandler);
2953 * Set if the component should paint all pixels withing its bounds.
2954 * If this property is set to false, the component expects the cleared
2957 * @param isOpaque if true, paint all pixels. If false, expect the clean
2960 * @see ComponentUI#update
2962 public void setOpaque(boolean isOpaque)
2964 boolean oldOpaque = opaque;
2966 clientOpaqueSet = true;
2967 firePropertyChange("opaque", oldOpaque, opaque);
2971 * Set the value of the visible property.
2973 * If the value is changed, then the AncestorListeners of this component
2974 * and all its children (recursivly) are notified.
2976 * @param v The new value of the property
2978 public void setVisible(boolean v)
2980 // No need to do anything if the actual value doesn't change.
2981 if (isVisible() == v)
2984 super.setVisible(v);
2986 // Notify AncestorListeners.
2988 fireAncestorEvent(this, AncestorEvent.ANCESTOR_ADDED);
2990 fireAncestorEvent(this, AncestorEvent.ANCESTOR_REMOVED);
2992 Container parent = getParent();
2994 parent.repaint(getX(), getY(), getWidth(), getHeight());
2999 * Call {@link #paint}.
3001 * @param g The graphics context to paint into
3003 public void update(Graphics g)
3009 * Get the value of the UIClassID property. This property should be a key
3010 * in the {@link UIDefaults} table managed by {@link UIManager}, the
3011 * value of which is the name of a class to load for the component's
3012 * {@link #ui} property.
3014 * @return A "symbolic" name which will map to a class to use for the
3015 * component's UI, such as <code>"ComponentUI"</code>
3020 public String getUIClassID()
3022 return "ComponentUI";
3026 * Install a new UI delegate as the component's {@link #ui} property. In
3027 * the process, this will call {@link ComponentUI#uninstallUI} on any
3028 * existing value for the {@link #ui} property, and {@link
3029 * ComponentUI#installUI} on the new UI delegate.
3031 * @param newUI The new UI delegate to install
3034 * @see #getUIClassID
3036 protected void setUI(ComponentUI newUI)
3039 ui.uninstallUI(this);
3041 ComponentUI oldUI = ui;
3047 firePropertyChange("UI", oldUI, newUI);
3053 * This method should be overridden in subclasses. In JComponent, the
3054 * method does nothing. In subclasses, it should a UI delegate
3055 * (corresponding to the symbolic name returned from {@link
3056 * #getUIClassID}) from the {@link UIManager}, and calls {@link #setUI}
3057 * with the new delegate.
3059 public void updateUI()
3061 // Nothing to do here.
3064 public static Locale getDefaultLocale()
3066 return defaultLocale;
3069 public static void setDefaultLocale(Locale l)
3075 * Returns the currently set input verifier for this component.
3077 * @return the input verifier, or <code>null</code> if none
3079 public InputVerifier getInputVerifier()
3081 return inputVerifier;
3085 * Sets the input verifier to use by this component.
3087 * @param verifier the input verifier, or <code>null</code>
3089 public void setInputVerifier(InputVerifier verifier)
3091 InputVerifier oldVerifier = inputVerifier;
3092 inputVerifier = verifier;
3093 firePropertyChange("inputVerifier", oldVerifier, verifier);
3099 public boolean getVerifyInputWhenFocusTarget()
3101 return verifyInputWhenFocusTarget;
3107 public void setVerifyInputWhenFocusTarget(boolean verifyInputWhenFocusTarget)
3109 if (this.verifyInputWhenFocusTarget == verifyInputWhenFocusTarget)
3112 this.verifyInputWhenFocusTarget = verifyInputWhenFocusTarget;
3113 firePropertyChange("verifyInputWhenFocusTarget",
3114 ! verifyInputWhenFocusTarget,
3115 verifyInputWhenFocusTarget);
3119 * Requests that this component gets the input focus if the
3120 * requestFocusEnabled property is set to <code>true</code>.
3121 * This also means that this component's top-level window becomes
3122 * the focused window, if that is not already the case.
3124 * The preconditions that have to be met to become a focus owner is that
3125 * the component must be displayable, visible and focusable.
3127 * Note that this signals only a request for becoming focused. There are
3128 * situations in which it is not possible to get the focus. So developers
3129 * should not assume that the component has the focus until it receives
3130 * a {@link java.awt.event.FocusEvent} with a value of
3131 * {@link java.awt.event.FocusEvent#FOCUS_GAINED}.
3133 * @see Component#requestFocus()
3135 public void requestFocus()
3137 if (isRequestFocusEnabled())
3138 super.requestFocus();
3142 * This method is overridden to make it public so that it can be used
3143 * by look and feel implementations.
3145 * You should not use this method directly. Instead you are strongly
3146 * encouraged to call {@link #requestFocus()} or
3147 * {@link #requestFocusInWindow()} instead.
3149 * @param temporary if the focus change is temporary
3151 * @return <code>false</code> if the focus change request will definitly
3152 * fail, <code>true</code> if it will likely succeed
3154 * @see Component#requestFocus(boolean)
3158 public boolean requestFocus(boolean temporary)
3160 return super.requestFocus(temporary);
3164 * Requests that this component gets the input focus if the top level
3165 * window that contains this component has the focus and the
3166 * requestFocusEnabled property is set to <code>true</code>.
3168 * The preconditions that have to be met to become a focus owner is that
3169 * the component must be displayable, visible and focusable.
3171 * Note that this signals only a request for becoming focused. There are
3172 * situations in which it is not possible to get the focus. So developers
3173 * should not assume that the component has the focus until it receives
3174 * a {@link java.awt.event.FocusEvent} with a value of
3175 * {@link java.awt.event.FocusEvent#FOCUS_GAINED}.
3177 * @return <code>false</code> if the focus change request will definitly
3178 * fail, <code>true</code> if it will likely succeed
3180 * @see Component#requestFocusInWindow()
3182 public boolean requestFocusInWindow()
3184 if (isRequestFocusEnabled())
3185 return super.requestFocusInWindow();
3191 * This method is overridden to make it public so that it can be used
3192 * by look and feel implementations.
3194 * You should not use this method directly. Instead you are strongly
3195 * encouraged to call {@link #requestFocus()} or
3196 * {@link #requestFocusInWindow()} instead.
3198 * @param temporary if the focus change is temporary
3200 * @return <code>false</code> if the focus change request will definitly
3201 * fail, <code>true</code> if it will likely succeed
3203 * @see Component#requestFocus(boolean)
3207 protected boolean requestFocusInWindow(boolean temporary)
3209 return super.requestFocusInWindow(temporary);
3213 * Receives notification if this component is added to a parent component.
3215 * Notification is sent to all registered AncestorListeners about the
3218 * This method sets up ActionListeners for all registered KeyStrokes of
3219 * this component in the chain of parent components.
3221 * A PropertyChange event is fired to indicate that the ancestor property
3224 * This method is used internally and should not be used in applications.
3226 public void addNotify()
3228 // Register the WHEN_IN_FOCUSED_WINDOW keyboard bindings
3229 // Note that here we unregister all bindings associated with
3230 // this component and then re-register them. This may be more than
3231 // necessary if the top-level ancestor hasn't changed. Should
3232 // maybe improve this.
3233 KeyboardManager km = KeyboardManager.getManager();
3234 km.clearBindingsForComp(this);
3235 km.registerEntireMap((ComponentInputMap)
3236 this.getInputMap(WHEN_IN_FOCUSED_WINDOW));
3239 // Notify AncestorListeners.
3240 fireAncestorEvent(this, AncestorEvent.ANCESTOR_ADDED);
3242 // fire property change event for 'ancestor'
3243 firePropertyChange("ancestor", null, getParent());
3247 * Receives notification that this component no longer has a parent.
3249 * This method sends an AncestorEvent to all registered AncestorListeners,
3250 * notifying them that the parent is gone.
3252 * The keybord actions of this component are removed from the parent and
3255 * A PropertyChangeEvent is fired to indicate that the 'ancestor' property
3258 * This method is called before the component is actually removed from
3259 * its parent, so the parent is still visible through
3260 * {@link Component#getParent}.
3262 public void removeNotify()
3264 super.removeNotify();
3266 KeyboardManager.getManager().clearBindingsForComp(this);
3268 // Notify ancestor listeners.
3269 fireAncestorEvent(this, AncestorEvent.ANCESTOR_REMOVED);
3271 // fire property change event for 'ancestor'
3272 firePropertyChange("ancestor", getParent(), null);
3276 * Returns <code>true</code> if the coordinates (x, y) lie within
3277 * the bounds of this component and <code>false</code> otherwise.
3278 * x and y are relative to the coordinate space of the component.
3280 * @param x the X coordinate of the point to check
3281 * @param y the Y coordinate of the point to check
3283 * @return <code>true</code> if the specified point lies within the bounds
3284 * of this component, <code>false</code> otherwise
3286 public boolean contains(int x, int y)
3289 return super.contains(x, y);
3291 return ui.contains(this, x, y);
3295 * Disables this component.
3297 * @deprecated replaced by {@link #setEnabled(boolean)}
3299 public void disable()
3305 * Enables this component.
3307 * @deprecated replaced by {@link #setEnabled(boolean)}
3309 public void enable()
3315 * Returns the Graphics context for this component. This can be used
3316 * to draw on a component.
3318 * @return the Graphics context for this component
3320 public Graphics getGraphics()
3322 return super.getGraphics();
3326 * Returns the X coordinate of the upper left corner of this component.
3327 * Prefer this method over {@link #getBounds} or {@link #getLocation}
3328 * because it does not cause any heap allocation.
3330 * @return the X coordinate of the upper left corner of the component
3334 return super.getX();
3338 * Returns the Y coordinate of the upper left corner of this component.
3339 * Prefer this method over {@link #getBounds} or {@link #getLocation}
3340 * because it does not cause any heap allocation.
3342 * @return the Y coordinate of the upper left corner of the component
3346 return super.getY();
3350 * Returns the height of this component. Prefer this method over
3351 * {@link #getBounds} or {@link #getSize} because it does not cause
3352 * any heap allocation.
3354 * @return the height of the component
3356 public int getHeight()
3358 return super.getHeight();
3362 * Returns the width of this component. Prefer this method over
3363 * {@link #getBounds} or {@link #getSize} because it does not cause
3364 * any heap allocation.
3366 * @return the width of the component
3368 public int getWidth()
3370 return super.getWidth();
3374 * Prints this component to the given Graphics context. A call to this
3375 * method results in calls to the methods {@link #printComponent},
3376 * {@link #printBorder} and {@link #printChildren} in this order.
3378 * Double buffering is temporarily turned off so the painting goes directly
3379 * to the supplied Graphics context.
3381 * @param g the Graphics context to print onto
3383 public void print(Graphics g)
3385 boolean doubleBufferState = isDoubleBuffered();
3386 setDoubleBuffered(false);
3390 setDoubleBuffered(doubleBufferState);
3394 * Prints this component to the given Graphics context. This invokes
3397 * @param g the Graphics context to print onto
3399 public void printAll(Graphics g)
3405 * Prints this component to the specified Graphics context. The default
3406 * behaviour is to invoke {@link #paintComponent}. Override this
3407 * if you want special behaviour for printing.
3409 * @param g the Graphics context to print onto
3413 protected void printComponent(Graphics g)
3419 * Print this component's children to the specified Graphics context.
3420 * The default behaviour is to invoke {@link #paintChildren}. Override this
3421 * if you want special behaviour for printing.
3423 * @param g the Graphics context to print onto
3427 protected void printChildren(Graphics g)
3433 * Print this component's border to the specified Graphics context.
3434 * The default behaviour is to invoke {@link #paintBorder}. Override this
3435 * if you want special behaviour for printing.
3437 * @param g the Graphics context to print onto
3441 protected void printBorder(Graphics g)
3447 * Processes mouse motion event, like dragging and moving.
3449 * @param ev the MouseEvent describing the mouse motion
3451 protected void processMouseMotionEvent(MouseEvent ev)
3453 super.processMouseMotionEvent(ev);
3457 * Moves and resizes the component.
3459 * @param x the new horizontal location
3460 * @param y the new vertial location
3461 * @param w the new width
3462 * @param h the new height
3464 public void reshape(int x, int y, int w, int h)
3468 super.reshape(x, y, w, h);
3469 // Notify AncestorListeners.
3470 if (oldX != getX() || oldY != getY())
3471 fireAncestorEvent(this, AncestorEvent.ANCESTOR_MOVED);
3475 * Fires an AncestorEvent to this component's and all of its child
3476 * component's AncestorListeners.
3478 * @param ancestor the component that triggered the event
3479 * @param id the kind of ancestor event that should be fired
3481 void fireAncestorEvent(JComponent ancestor, int id)
3483 // Fire event for registered ancestor listeners of this component.
3484 AncestorListener[] listeners = getAncestorListeners();
3485 if (listeners.length > 0)
3487 AncestorEvent ev = new AncestorEvent(this, id,
3488 ancestor, ancestor.getParent());
3489 for (int i = 0; i < listeners.length; i++)
3493 case AncestorEvent.ANCESTOR_MOVED:
3494 listeners[i].ancestorMoved(ev);
3496 case AncestorEvent.ANCESTOR_ADDED:
3497 listeners[i].ancestorAdded(ev);
3499 case AncestorEvent.ANCESTOR_REMOVED:
3500 listeners[i].ancestorRemoved(ev);
3505 // Dispatch event to all children.
3506 Component[] children = getComponents();
3507 for (int i = 0; i < children.length; i++)
3509 if (!(children[i] instanceof JComponent))
3511 JComponent jc = (JComponent) children[i];
3512 jc.fireAncestorEvent(ancestor, id);
3517 * Finds a suitable paint root for painting this component. This method first
3518 * checks if this component is overlapped using
3519 * {@link #findOverlapFreeParent(Rectangle)}. The returned paint root is then
3520 * feeded to {@link #findOpaqueParent(Component)} to find the nearest opaque
3521 * component for this paint root. If no paint is necessary, then we return
3522 * <code>null</code>.
3524 * @param c the clip of this component
3526 * @return the paint root or <code>null</code> if no painting is necessary
3528 private Component findPaintRoot(Rectangle c)
3530 Component p = findOverlapFreeParent(c);
3533 Component root = findOpaqueParent(p);
3538 * Scans the containment hierarchy upwards for components that overlap the
3539 * this component in the specified clip. This method returns
3540 * <code>this</code>, if no component overlaps this component. It returns
3541 * <code>null</code> if another component completely covers this component
3542 * in the specified clip (no repaint necessary). If another component partly
3543 * overlaps this component in the specified clip, then the parent of this
3544 * component is returned (this is the component that must be used as repaint
3545 * root). For efficient lookup, the method
3546 * {@link #isOptimizedDrawingEnabled()} is used.
3548 * @param clip the clip of this component
3550 * @return the paint root, or <code>null</code> if no paint is necessary
3552 private Component findOverlapFreeParent(Rectangle clip)
3554 Rectangle currentClip = clip;
3555 Component found = this;
3556 Container parent = this;
3557 while (parent != null && !(parent instanceof Window))
3559 Container newParent = parent.getParent();
3560 if (newParent == null || newParent instanceof Window)
3562 // If the parent is optimizedDrawingEnabled, then its children are
3563 // tiled and cannot have an overlapping child. Go directly to next
3565 if ((newParent instanceof JComponent
3566 && ((JComponent) newParent).isOptimizedDrawingEnabled()))
3572 // If the parent is not optimizedDrawingEnabled, we must paint the
3574 Rectangle target = SwingUtilities.convertRectangle(found,
3578 currentClip = target;
3585 * Finds the nearest component to <code>c</code> (upwards in the containment
3586 * hierarchy), that is opaque. If <code>c</code> itself is opaque,
3587 * this returns <code>c</code> itself.
3589 * @param c the start component for the search
3590 * @return the nearest component to <code>c</code> (upwards in the containment
3591 * hierarchy), that is opaque; If <code>c</code> itself is opaque,
3592 * this returns <code>c</code> itself
3594 private Component findOpaqueParent(Component c)
3596 Component found = c;
3599 if ((found instanceof JComponent) && ((JComponent) found).isOpaque())
3601 else if (!(found instanceof JComponent))
3603 Container p = found.getParent();
3613 * This is the method that gets called when the WHEN_IN_FOCUSED_WINDOW map
3616 * @param changed the JComponent associated with the WHEN_IN_FOCUSED_WINDOW
3619 void updateComponentInputMap(ComponentInputMap changed)
3621 // Since you can change a component's input map via
3622 // setInputMap, we have to check if <code>changed</code>
3623 // is still in our WHEN_IN_FOCUSED_WINDOW map hierarchy
3624 InputMap curr = getInputMap(WHEN_IN_FOCUSED_WINDOW);
3625 while (curr != null && curr != changed)
3626 curr = curr.getParent();
3628 // If curr is null then changed is not in the hierarchy
3632 // Now we have to update the keyboard manager's hashtable
3633 KeyboardManager km = KeyboardManager.getManager();
3635 // This is a poor strategy, should be improved. We currently
3636 // delete all the old bindings for the component and then register
3637 // the current bindings.
3638 km.clearBindingsForComp(changed.getComponent());
3639 km.registerEntireMap((ComponentInputMap)
3640 getInputMap(WHEN_IN_FOCUSED_WINDOW));
3645 * {@link LookAndFeel#installProperty(JComponent, String, Object)}.
3647 * @param propertyName the name of the property
3648 * @param value the value of the property
3650 * @throws IllegalArgumentException if the specified property cannot be set
3652 * @throws ClassCastException if the property value does not match the
3654 * @throws NullPointerException if <code>c</code> or
3655 * <code>propertyValue</code> is <code>null</code>
3657 void setUIProperty(String propertyName, Object value)
3659 if (propertyName.equals("opaque"))
3661 if (! clientOpaqueSet)
3663 setOpaque(((Boolean) value).booleanValue());
3664 clientOpaqueSet = false;
3667 else if (propertyName.equals("autoscrolls"))
3669 if (! clientAutoscrollsSet)
3671 setAutoscrolls(((Boolean) value).booleanValue());
3672 clientAutoscrollsSet = false;
3677 throw new IllegalArgumentException
3678 ("Unsupported property for LookAndFeel.installProperty(): "