1 /* JComponent.java -- Every component in swing inherits from this class.
2 Copyright (C) 2002, 2004, 2005 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
.FlowLayout
;
49 import java
.awt
.FocusTraversalPolicy
;
51 import java
.awt
.Graphics
;
52 import java
.awt
.Graphics2D
;
53 import java
.awt
.Image
;
54 import java
.awt
.Insets
;
55 import java
.awt
.Point
;
56 import java
.awt
.Rectangle
;
57 import java
.awt
.Shape
;
58 import java
.awt
.Window
;
59 import java
.awt
.dnd
.DropTarget
;
60 import java
.awt
.event
.ActionEvent
;
61 import java
.awt
.event
.ActionListener
;
62 import java
.awt
.event
.ContainerEvent
;
63 import java
.awt
.event
.ContainerListener
;
64 import java
.awt
.event
.FocusEvent
;
65 import java
.awt
.event
.FocusListener
;
66 import java
.awt
.event
.KeyEvent
;
67 import java
.awt
.event
.MouseEvent
;
68 import java
.awt
.geom
.Rectangle2D
;
69 import java
.awt
.peer
.LightweightPeer
;
70 import java
.beans
.PropertyChangeEvent
;
71 import java
.beans
.PropertyChangeListener
;
72 import java
.beans
.PropertyVetoException
;
73 import java
.beans
.VetoableChangeListener
;
74 import java
.io
.Serializable
;
75 import java
.util
.EventListener
;
76 import java
.util
.Hashtable
;
77 import java
.util
.Locale
;
80 import javax
.accessibility
.Accessible
;
81 import javax
.accessibility
.AccessibleContext
;
82 import javax
.accessibility
.AccessibleExtendedComponent
;
83 import javax
.accessibility
.AccessibleKeyBinding
;
84 import javax
.accessibility
.AccessibleRole
;
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
.event
.SwingPropertyChangeSupport
;
93 import javax
.swing
.plaf
.ComponentUI
;
96 * The base class of all Swing components.
97 * It contains generic methods to manage events, properties and sizes. Actual
98 * drawing of the component is channeled to a look-and-feel class that is
99 * implemented elsewhere.
101 * @author Ronald Veldema (rveldema&064;cs.vu.nl)
102 * @author Graydon Hoare (graydon&064;redhat.com)
104 public abstract class JComponent
extends Container
implements Serializable
106 private static final long serialVersionUID
= -7908749299918704233L;
109 * Accessibility support is currently missing.
111 protected AccessibleContext accessibleContext
;
114 * Basic accessibility support for <code>JComponent</code> derived
117 public abstract class AccessibleJComponent
118 extends AccessibleAWTContainer
119 implements AccessibleExtendedComponent
122 * Accessibility support for <code>JComponent</code>'s focus handler.
124 protected class AccessibleFocusHandler
125 implements FocusListener
127 protected AccessibleFocusHandler()
129 // TODO: Implement this properly.
131 public void focusGained(FocusEvent event
)
133 // TODO: Implement this properly.
135 public void focusLost(FocusEvent valevent
)
137 // TODO: Implement this properly.
142 * Accessibility support for <code>JComponent</code>'s container handler.
144 protected class AccessibleContainerHandler
145 implements ContainerListener
147 protected AccessibleContainerHandler()
149 // TODO: Implement this properly.
151 public void componentAdded(ContainerEvent event
)
153 // TODO: Implement this properly.
155 public void componentRemoved(ContainerEvent valevent
)
157 // TODO: Implement this properly.
161 private static final long serialVersionUID
= -7047089700479897799L;
163 protected ContainerListener accessibleContainerHandler
;
164 protected FocusListener accessibleFocusHandler
;
167 * Manages the property change listeners;
169 private SwingPropertyChangeSupport changeSupport
;
171 protected AccessibleJComponent()
173 changeSupport
= new SwingPropertyChangeSupport(this);
177 * Adds a property change listener to the list of registered listeners.
179 * @param listener the listener to add
181 public void addPropertyChangeListener(PropertyChangeListener listener
)
183 changeSupport
.addPropertyChangeListener(listener
);
187 * Removes a propery change listener from the list of registered listeners.
189 * @param listener the listener to remove
191 public void removePropertyChangeListener(PropertyChangeListener listener
)
193 changeSupport
.removePropertyChangeListener(listener
);
197 * Returns the number of accessible children of this object.
199 * @return the number of accessible children of this object
201 public int getAccessibleChildrenCount()
204 Component
[] children
= getComponents();
205 for (int i
= 0; i
< children
.length
; ++i
)
207 if (children
[i
] instanceof Accessible
)
214 * Returns the accessible child component at index <code>i</code>.
216 * @param i the index of the accessible child to return
218 * @return the accessible child component at index <code>i</code>
220 public Accessible
getAccessibleChild(int i
)
223 Component
[] children
= getComponents();
224 Accessible found
= null;
225 for (int j
= 0; index
!= i
; j
++)
227 if (children
[j
] instanceof Accessible
)
230 found
= (Accessible
) children
[index
];
232 // TODO: Figure out what to do when i is not a valid index.
237 * Returns the accessible state set of this component.
239 * @return the accessible state set of this component
241 public AccessibleStateSet
getAccessibleStateSet()
243 // FIXME: Figure out which states should be set here, and which are
244 // inherited from the super class.
245 return super.getAccessibleStateSet();
249 * Returns the localized name for this object. Generally this should
250 * almost never return {@link Component#getName()} since that is not
251 * a localized name. If the object is some kind of text component (like
252 * a menu item), then the value of the object may be returned. Also, if
253 * the object has a tooltip, the value of the tooltip may also be
256 * @return the localized name for this object or <code>null</code> if this
259 public String
getAccessibleName()
261 // TODO: Figure out what exactly to return here. It's possible that this
262 // method simply should return null.
267 * Returns the localized description of this object.
269 * @return the localized description of this object or <code>null</code>
270 * if this object has no description
272 public String
getAccessibleDescription()
274 // TODO: Figure out what exactly to return here. It's possible that this
275 // method simply should return null.
280 * Returns the accessible role of this component.
282 * @return the accessible role of this component
284 * @see AccessibleRole
286 public AccessibleRole
getAccessibleRole()
288 // TODO: Check if this is correct.
289 return AccessibleRole
.SWING_COMPONENT
;
293 * Recursivly searches a border hierarchy (starting at <code>border) for
294 * a titled border and returns the title if one is found, <code>null</code>
297 * @param border the border to start search from
299 * @return the border title of a possibly found titled border
301 protected String
getBorderTitle(Border border
)
304 if (border
instanceof CompoundBorder
)
306 CompoundBorder compound
= (CompoundBorder
) border
;
307 Border inner
= compound
.getInsideBorder();
308 title
= getBorderTitle(inner
);
311 Border outer
= compound
.getOutsideBorder();
312 title
= getBorderTitle(outer
);
315 else if (border
instanceof TitledBorder
)
317 TitledBorder titled
= (TitledBorder
) border
;
318 title
= titled
.getTitle();
324 * Returns the tooltip text for this accessible component.
326 * @return the tooltip text for this accessible component
328 public String
getToolTipText()
330 return JComponent
.this.getToolTipText();
334 * Returns the title of the border of this accessible component if
335 * this component has a titled border, otherwise returns <code>null</code>.
337 * @return the title of the border of this accessible component if
338 * this component has a titled border, otherwise returns
341 public String
getTitledBorderText()
343 return getBorderTitle(getBorder());
347 * Returns the keybindings associated with this accessible component or
348 * <code>null</code> if the component does not support key bindings.
350 * @return the keybindings associated with this accessible component
352 public AccessibleKeyBinding
getAccessibleKeyBinding()
354 // TODO: Implement this properly.
360 * An explicit value for the component's preferred size; if not set by a
361 * user, this is calculated on the fly by delegating to the {@link
362 * ComponentUI#getPreferredSize} method on the {@link #ui} property.
364 Dimension preferredSize
;
367 * An explicit value for the component's minimum size; if not set by a
368 * user, this is calculated on the fly by delegating to the {@link
369 * ComponentUI#getMinimumSize} method on the {@link #ui} property.
371 Dimension minimumSize
;
374 * An explicit value for the component's maximum size; if not set by a
375 * user, this is calculated on the fly by delegating to the {@link
376 * ComponentUI#getMaximumSize} method on the {@link #ui} property.
378 Dimension maximumSize
;
381 * A value between 0.0 and 1.0 indicating the preferred horizontal
382 * alignment of the component, relative to its siblings. The values
383 * {@link #LEFT_ALIGNMENT}, {@link #CENTER_ALIGNMENT}, and {@link
384 * #RIGHT_ALIGNMENT} can also be used, as synonyms for <code>0.0</code>,
385 * <code>0.5</code>, and <code>1.0</code>, respectively. Not all layout
386 * managers use this property.
388 * @see #getAlignmentX
389 * @see #setAlignmentX
390 * @see javax.swing.OverlayLayout
391 * @see javax.swing.BoxLayout
393 float alignmentX
= -1.0F
;
396 * A value between 0.0 and 1.0 indicating the preferred vertical
397 * alignment of the component, relative to its siblings. The values
398 * {@link #TOP_ALIGNMENT}, {@link #CENTER_ALIGNMENT}, and {@link
399 * #BOTTOM_ALIGNMENT} can also be used, as synonyms for <code>0.0</code>,
400 * <code>0.5</code>, and <code>1.0</code>, respectively. Not all layout
401 * managers use this property.
403 * @see #getAlignmentY
404 * @see #setAlignmentY
405 * @see javax.swing.OverlayLayout
406 * @see javax.swing.BoxLayout
408 float alignmentY
= -1.0F
;
411 * The border painted around this component.
418 * The text to show in the tooltip associated with this component.
420 * @see #setToolTipText
421 * @see #getToolTipText()
426 * <p>Whether to double buffer this component when painting. This flag
427 * should generally be <code>true</code>, to ensure good painting
430 * <p>All children of a double buffered component are painted into the
431 * double buffer automatically, so only the top widget in a window needs
432 * to be double buffered.</p>
434 * @see #setDoubleBuffered
435 * @see #isDoubleBuffered
438 boolean doubleBuffered
= true;
441 * A set of flags indicating which debugging graphics facilities should
442 * be enabled on this component. The values should be a combination of
443 * {@link DebugGraphics#NONE_OPTION}, {@link DebugGraphics#LOG_OPTION},
444 * {@link DebugGraphics#FLASH_OPTION}, or {@link
445 * DebugGraphics#BUFFERED_OPTION}.
447 * @see #setDebugGraphicsOptions
448 * @see #getDebugGraphicsOptions
450 * @see #getComponentGraphics
452 int debugGraphicsOptions
;
455 * <p>This property controls two independent behaviors simultaneously.</p>
457 * <p>First, it controls whether to fill the background of this widget
458 * when painting its body. This affects calls to {@link
459 * JComponent#paintComponent}, which in turn calls {@link
460 * ComponentUI#update} on the component's {@link #ui} property. If the
461 * component is opaque during this call, the background will be filled
462 * before calling {@link ComponentUI#paint}. This happens merely as a
463 * convenience; you may fill the component's background yourself too,
464 * but there is no need to do so if you will be filling with the same
467 * <p>Second, it the opaque property informs swing's repaint system
468 * whether it will be necessary to paint the components "underneath" this
469 * component, in Z-order. If the component is opaque, it is considered to
470 * completely occlude components "underneath" it, so they will not be
471 * repainted along with the opaque component.</p>
473 * <p>The default value for this property is <code>false</code>, but most
474 * components will want to set it to <code>true</code> when installing UI
475 * defaults in {@link ComponentUI#installUI}.</p>
479 * @see #paintComponent
481 boolean opaque
= false;
484 * The user interface delegate for this component. Event delivery and
485 * repainting of the component are usually delegated to this object.
491 protected ComponentUI ui
;
494 * A hint to the focus system that this component should or should not
495 * get focus. If this is <code>false</code>, swing will not try to
496 * request focus on this component; if <code>true</code>, swing might
497 * try to request focus, but the request might fail. Thus it is only
498 * a hint guiding swing's behavior.
500 * @see #requestFocus()
501 * @see #isRequestFocusEnabled
502 * @see #setRequestFocusEnabled
504 boolean requestFocusEnabled
;
507 * Flag indicating behavior of this component when the mouse is dragged
508 * outside the component and the mouse <em>stops moving</em>. If
509 * <code>true</code>, synthetic mouse events will be delivered on regular
510 * timed intervals, continuing off in the direction the mouse exited the
511 * component, until the mouse is released or re-enters the component.
513 * @see #setAutoscrolls
514 * @see #getAutoscrolls
516 boolean autoscrolls
= false;
519 * Indicates whether the current paint call is already double buffered or
522 static boolean isPaintingDoubleBuffered
= false;
525 * Listeners for events other than {@link PropertyChangeEvent} are
526 * handled by this listener list. PropertyChangeEvents are handled in
527 * {@link #changeSupport}.
529 protected EventListenerList listenerList
= new EventListenerList();
532 * Support for {@link PropertyChangeEvent} events. This is constructed
533 * lazily when the component gets its first {@link
534 * PropertyChangeListener} subscription; until then it's an empty slot.
536 private SwingPropertyChangeSupport changeSupport
;
540 * Storage for "client properties", which are key/value pairs associated
541 * with this component by a "client", such as a user application or a
542 * layout manager. This is lazily constructed when the component gets its
543 * first client property.
545 private Hashtable clientProperties
;
547 private InputMap inputMap_whenFocused
;
548 private InputMap inputMap_whenAncestorOfFocused
;
549 private ComponentInputMap inputMap_whenInFocusedWindow
;
550 private ActionMap actionMap
;
552 private boolean verifyInputWhenFocusTarget
;
553 private InputVerifier inputVerifier
;
555 private TransferHandler transferHandler
;
558 * Indicates if this component is currently painting a tile or not.
560 private boolean paintingTile
;
563 * A cached Rectangle object to be reused. Be careful when you use that,
564 * so that it doesn't get modified in another context within the same
567 private static transient Rectangle rectCache
;
570 * The default locale of the component.
572 * @see #getDefaultLocale
573 * @see #setDefaultLocale
575 private static Locale defaultLocale
;
577 public static final String TOOL_TIP_TEXT_KEY
= "ToolTipText";
580 * Constant used to indicate that no condition has been assigned to a
583 * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
585 public static final int UNDEFINED_CONDITION
= -1;
588 * Constant used to indicate that an action should be performed only when
589 * the component has focus.
591 * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
593 public static final int WHEN_FOCUSED
= 0;
596 * Constant used to indicate that an action should be performed only when
597 * the component is an ancestor of the component which has focus.
599 * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
601 public static final int WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
= 1;
604 * Constant used to indicate that an action should be performed only when
605 * the component is in the window which has focus.
607 * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
609 public static final int WHEN_IN_FOCUSED_WINDOW
= 2;
612 * Indicates if this component is completely dirty or not. This is used
613 * by the RepaintManager's
614 * {@link RepaintManager#isCompletelyDirty(JComponent)} method.
616 boolean isCompletelyDirty
= false;
619 * Creates a new <code>JComponent</code> instance.
624 super.setLayout(new FlowLayout());
625 setDropTarget(new DropTarget());
626 defaultLocale
= Locale
.getDefault();
627 debugGraphicsOptions
= DebugGraphics
.NONE_OPTION
;
628 setRequestFocusEnabled(true);
632 * Helper to lazily construct and return the client properties table.
634 * @return The current client properties table
636 * @see #clientProperties
637 * @see #getClientProperty
638 * @see #putClientProperty
640 private Hashtable
getClientProperties()
642 if (clientProperties
== null)
643 clientProperties
= new Hashtable();
644 return clientProperties
;
648 * Get a client property associated with this component and a particular
651 * @param key The key with which to look up the client property
653 * @return A client property associated with this object and key
655 * @see #clientProperties
656 * @see #getClientProperties
657 * @see #putClientProperty
659 public final Object
getClientProperty(Object key
)
661 return getClientProperties().get(key
);
665 * Add a client property <code>value</code> to this component, associated
666 * with <code>key</code>. If there is an existing client property
667 * associated with <code>key</code>, it will be replaced. A
668 * {@link PropertyChangeEvent} is sent to registered listeners (with the
669 * name of the property being <code>key.toString()</code>).
671 * @param key The key of the client property association to add
672 * @param value The value of the client property association to add
674 * @see #clientProperties
675 * @see #getClientProperties
676 * @see #getClientProperty
678 public final void putClientProperty(Object key
, Object value
)
680 Hashtable t
= getClientProperties();
681 Object old
= t
.get(key
);
686 firePropertyChange(key
.toString(), old
, value
);
690 * Unregister an <code>AncestorListener</code>.
692 * @param listener The listener to unregister
694 * @see #addAncestorListener
696 public void removeAncestorListener(AncestorListener listener
)
698 listenerList
.remove(AncestorListener
.class, listener
);
702 * Unregister a <code>PropertyChangeListener</code>.
704 * @param listener The listener to register
706 * @see #addPropertyChangeListener(PropertyChangeListener)
707 * @see #changeSupport
709 public void removePropertyChangeListener(PropertyChangeListener listener
)
711 if (changeSupport
!= null)
712 changeSupport
.removePropertyChangeListener(listener
);
716 * Unregister a <code>PropertyChangeListener</code>.
718 * @param propertyName The property name to unregister the listener from
719 * @param listener The listener to unregister
721 * @see #addPropertyChangeListener(String, PropertyChangeListener)
722 * @see #changeSupport
724 public void removePropertyChangeListener(String propertyName
,
725 PropertyChangeListener listener
)
727 if (changeSupport
!= null)
728 changeSupport
.removePropertyChangeListener(propertyName
, listener
);
732 * Unregister a <code>VetoableChangeChangeListener</code>.
734 * @param listener The listener to unregister
736 * @see #addVetoableChangeListener
738 public void removeVetoableChangeListener(VetoableChangeListener listener
)
740 listenerList
.remove(VetoableChangeListener
.class, listener
);
744 * Register an <code>AncestorListener</code>.
746 * @param listener The listener to register
748 * @see #removeVetoableChangeListener
750 public void addAncestorListener(AncestorListener listener
)
752 listenerList
.add(AncestorListener
.class, listener
);
756 * Register a <code>PropertyChangeListener</code>. This listener will
757 * receive any PropertyChangeEvent, regardless of property name. To
758 * listen to a specific property name, use {@link
759 * #addPropertyChangeListener(String,PropertyChangeListener)} instead.
761 * @param listener The listener to register
763 * @see #removePropertyChangeListener(PropertyChangeListener)
764 * @see #changeSupport
766 public void addPropertyChangeListener(PropertyChangeListener listener
)
768 if (changeSupport
== null)
769 changeSupport
= new SwingPropertyChangeSupport(this);
770 changeSupport
.addPropertyChangeListener(listener
);
774 * Register a <code>PropertyChangeListener</code> for a specific, named
775 * property. To listen to all property changes, regardless of name, use
776 * {@link #addPropertyChangeListener(PropertyChangeListener)} instead.
778 * @param propertyName The property name to listen to
779 * @param listener The listener to register
781 * @see #removePropertyChangeListener(String, PropertyChangeListener)
782 * @see #changeSupport
784 public void addPropertyChangeListener(String propertyName
,
785 PropertyChangeListener listener
)
787 listenerList
.add(PropertyChangeListener
.class, listener
);
791 * Register a <code>VetoableChangeListener</code>.
793 * @param listener The listener to register
795 * @see #removeVetoableChangeListener
798 public void addVetoableChangeListener(VetoableChangeListener listener
)
800 listenerList
.add(VetoableChangeListener
.class, listener
);
804 * Return all registered listeners of a particular type.
806 * @param listenerType The type of listener to return
808 * @return All listeners in the {@link #listenerList} which
809 * are of the specified type
813 public EventListener
[] getListeners(Class listenerType
)
815 return listenerList
.getListeners(listenerType
);
819 * Return all registered <code>AncestorListener</code> objects.
821 * @return The set of <code>AncestorListener</code> objects in {@link
824 public AncestorListener
[] getAncestorListeners()
826 return (AncestorListener
[]) getListeners(AncestorListener
.class);
830 * Return all registered <code>VetoableChangeListener</code> objects.
832 * @return The set of <code>VetoableChangeListener</code> objects in {@link
835 public VetoableChangeListener
[] getVetoableChangeListeners()
837 return (VetoableChangeListener
[]) getListeners(VetoableChangeListener
.class);
841 * Return all <code>PropertyChangeListener</code> objects registered to listen
842 * for a particular property.
844 * @param property The property to return the listeners of
846 * @return The set of <code>PropertyChangeListener</code> objects in
847 * {@link #changeSupport} registered to listen on the specified property
849 public PropertyChangeListener
[] getPropertyChangeListeners(String property
)
851 return changeSupport
== null ?
new PropertyChangeListener
[0]
852 : changeSupport
.getPropertyChangeListeners(property
);
856 * A variant of {@link #firePropertyChange(String,Object,Object)}
857 * for properties with <code>boolean</code> values.
859 public void firePropertyChange(String propertyName
, boolean oldValue
,
862 if (changeSupport
!= null)
863 changeSupport
.firePropertyChange(propertyName
, Boolean
.valueOf(oldValue
),
864 Boolean
.valueOf(newValue
));
868 * A variant of {@link #firePropertyChange(String,Object,Object)}
869 * for properties with <code>byte</code> values.
871 public void firePropertyChange(String propertyName
, byte oldValue
,
874 if (changeSupport
!= null)
875 changeSupport
.firePropertyChange(propertyName
, new Byte(oldValue
),
880 * A variant of {@link #firePropertyChange(String,Object,Object)}
881 * for properties with <code>char</code> values.
883 public void firePropertyChange(String propertyName
, char oldValue
,
886 if (changeSupport
!= null)
887 changeSupport
.firePropertyChange(propertyName
, new Character(oldValue
),
888 new Character(newValue
));
892 * A variant of {@link #firePropertyChange(String,Object,Object)}
893 * for properties with <code>double</code> values.
895 public void firePropertyChange(String propertyName
, double oldValue
,
898 if (changeSupport
!= null)
899 changeSupport
.firePropertyChange(propertyName
, new Double(oldValue
),
900 new Double(newValue
));
904 * A variant of {@link #firePropertyChange(String,Object,Object)}
905 * for properties with <code>float</code> values.
907 public void firePropertyChange(String propertyName
, float oldValue
,
910 if (changeSupport
!= null)
911 changeSupport
.firePropertyChange(propertyName
, new Float(oldValue
),
912 new Float(newValue
));
916 * A variant of {@link #firePropertyChange(String,Object,Object)}
917 * for properties with <code>int</code> values.
919 public void firePropertyChange(String propertyName
, int oldValue
,
922 if (changeSupport
!= null)
923 changeSupport
.firePropertyChange(propertyName
, new Integer(oldValue
),
924 new Integer(newValue
));
928 * A variant of {@link #firePropertyChange(String,Object,Object)}
929 * for properties with <code>long</code> values.
931 public void firePropertyChange(String propertyName
, long oldValue
,
934 if (changeSupport
!= null)
935 changeSupport
.firePropertyChange(propertyName
, new Long(oldValue
),
940 * Call {@link PropertyChangeListener#propertyChange} on all listeners
941 * registered to listen to a given property. Any method which changes
942 * the specified property of this component should call this method.
944 * @param propertyName The property which changed
945 * @param oldValue The old value of the property
946 * @param newValue The new value of the property
948 * @see #changeSupport
949 * @see #addPropertyChangeListener(PropertyChangeListener)
950 * @see #removePropertyChangeListener(PropertyChangeListener)
952 protected void firePropertyChange(String propertyName
, Object oldValue
,
955 if (changeSupport
!= null)
956 changeSupport
.firePropertyChange(propertyName
, oldValue
, newValue
);
960 * A variant of {@link #firePropertyChange(String,Object,Object)}
961 * for properties with <code>short</code> values.
963 public void firePropertyChange(String propertyName
, short oldValue
,
966 if (changeSupport
!= null)
967 changeSupport
.firePropertyChange(propertyName
, new Short(oldValue
),
968 new Short(newValue
));
972 * Call {@link VetoableChangeListener#vetoableChange} on all listeners
973 * registered to listen to a given property. Any method which changes
974 * the specified property of this component should call this method.
976 * @param propertyName The property which changed
977 * @param oldValue The old value of the property
978 * @param newValue The new value of the property
980 * @throws PropertyVetoException if the change was vetoed by a listener
982 * @see #addVetoableChangeListener
983 * @see #removeVetoableChangeListener
985 protected void fireVetoableChange(String propertyName
, Object oldValue
,
987 throws PropertyVetoException
989 VetoableChangeListener
[] listeners
= getVetoableChangeListeners();
991 PropertyChangeEvent evt
=
992 new PropertyChangeEvent(this, propertyName
, oldValue
, newValue
);
994 for (int i
= 0; i
< listeners
.length
; i
++)
995 listeners
[i
].vetoableChange(evt
);
999 * Get the value of the accessibleContext property for this component.
1001 * @return the current value of the property
1003 public AccessibleContext
getAccessibleContext()
1009 * Get the value of the {@link #alignmentX} property.
1011 * @return The current value of the property.
1013 * @see #setAlignmentX
1016 public float getAlignmentX()
1018 float ret
= alignmentX
;
1020 // alignment has not been set explicitly.
1021 ret
= super.getAlignmentX();
1027 * Get the value of the {@link #alignmentY} property.
1029 * @return The current value of the property.
1031 * @see #setAlignmentY
1034 public float getAlignmentY()
1036 float ret
= alignmentY
;
1038 // alignment has not been set explicitly.
1039 ret
= super.getAlignmentY();
1045 * Get the current value of the {@link #autoscrolls} property.
1047 * @return The current value of the property
1049 public boolean getAutoscrolls()
1055 * Set the value of the {@link #border} property.
1057 * @param newBorder The new value of the property
1061 public void setBorder(Border newBorder
)
1063 Border oldBorder
= getBorder();
1064 if (oldBorder
== newBorder
)
1068 firePropertyChange("border", oldBorder
, newBorder
);
1073 * Get the value of the {@link #border} property.
1075 * @return The property's current value
1079 public Border
getBorder()
1085 * Get the component's current bounding box. If a rectangle is provided,
1086 * use this as the return value (adjusting its fields in place);
1087 * otherwise (of <code>null</code> is provided) return a new {@link
1090 * @param rv Optional return value to use
1092 * @return A rectangle bounding the component
1094 public Rectangle
getBounds(Rectangle rv
)
1097 return new Rectangle(getX(), getY(), getWidth(), getHeight());
1100 rv
.setBounds(getX(), getY(), getWidth(), getHeight());
1106 * Prepares a graphics context for painting this object. If {@link
1107 * #debugGraphicsOptions} is not equal to {@link
1108 * DebugGraphics#NONE_OPTION}, produce a new {@link DebugGraphics} object
1109 * wrapping the parameter. Otherwise configure the parameter with this
1110 * component's foreground color and font.
1112 * @param g The graphics context to wrap or configure
1114 * @return A graphics context to paint this object with
1116 * @see #debugGraphicsOptions
1119 protected Graphics
getComponentGraphics(Graphics g
)
1122 int options
= getDebugGraphicsOptions();
1123 if (options
!= DebugGraphics
.NONE_OPTION
)
1125 if (!(g2
instanceof DebugGraphics
))
1126 g2
= new DebugGraphics(g
);
1127 DebugGraphics dg
= (DebugGraphics
) g2
;
1128 dg
.setDebugOptions(dg
.getDebugOptions() | options
);
1130 g2
.setFont(this.getFont());
1131 g2
.setColor(this.getForeground());
1136 * Get the value of the {@link #debugGraphicsOptions} property.
1138 * @return The current value of the property.
1140 * @see #setDebugGraphicsOptions
1141 * @see #debugGraphicsOptions
1143 public int getDebugGraphicsOptions()
1145 String option
= System
.getProperty("gnu.javax.swing.DebugGraphics");
1146 int options
= debugGraphicsOptions
;
1147 if (option
!= null && option
.length() != 0)
1152 if (option
.equals("LOG"))
1153 options
|= DebugGraphics
.LOG_OPTION
;
1154 else if (option
.equals("FLASH"))
1155 options
|= DebugGraphics
.FLASH_OPTION
;
1161 * Get the component's insets, which are calculated from
1162 * the {@link #border} property. If the border is <code>null</code>,
1163 * calls {@link Container#getInsets}.
1165 * @return The component's current insets
1167 public Insets
getInsets()
1170 return super.getInsets();
1171 return getBorder().getBorderInsets(this);
1175 * Get the component's insets, which are calculated from the {@link
1176 * #border} property. If the border is <code>null</code>, calls {@link
1177 * Container#getInsets}. The passed-in {@link Insets} value will be
1178 * used as the return value, if possible.
1180 * @param insets Return value object to reuse, if possible
1182 * @return The component's current insets
1184 public Insets
getInsets(Insets insets
)
1186 Insets t
= getInsets();
1191 insets
.left
= t
.left
;
1192 insets
.right
= t
.right
;
1194 insets
.bottom
= t
.bottom
;
1199 * Get the component's location. The passed-in {@link Point} value
1200 * will be used as the return value, if possible.
1202 * @param rv Return value object to reuse, if possible
1204 * @return The component's current location
1206 public Point
getLocation(Point rv
)
1209 return new Point(getX(), getY());
1211 rv
.setLocation(getX(), getY());
1216 * Get the component's maximum size. If the {@link #maximumSize} property
1217 * has been explicitly set, it is returned. If the {@link #maximumSize}
1218 * property has not been set but the {@link #ui} property has been, the
1219 * result of {@link ComponentUI#getMaximumSize} is returned. If neither
1220 * property has been set, the result of {@link Container#getMaximumSize}
1223 * @return The maximum size of the component
1226 * @see #setMaximumSize
1228 public Dimension
getMaximumSize()
1230 if (maximumSize
!= null)
1235 Dimension s
= ui
.getMaximumSize(this);
1240 Dimension p
= super.getMaximumSize();
1245 * Get the component's minimum size. If the {@link #minimumSize} property
1246 * has been explicitly set, it is returned. If the {@link #minimumSize}
1247 * property has not been set but the {@link #ui} property has been, the
1248 * result of {@link ComponentUI#getMinimumSize} is returned. If neither
1249 * property has been set, the result of {@link Container#getMinimumSize}
1252 * @return The minimum size of the component
1255 * @see #setMinimumSize
1257 public Dimension
getMinimumSize()
1259 if (minimumSize
!= null)
1264 Dimension s
= ui
.getMinimumSize(this);
1269 Dimension p
= super.getMinimumSize();
1274 * Get the component's preferred size. If the {@link #preferredSize}
1275 * property has been explicitly set, it is returned. If the {@link
1276 * #preferredSize} property has not been set but the {@link #ui} property
1277 * has been, the result of {@link ComponentUI#getPreferredSize} is
1278 * returned. If neither property has been set, the result of {@link
1279 * Container#getPreferredSize} is returned.
1281 * @return The preferred size of the component
1283 * @see #preferredSize
1284 * @see #setPreferredSize
1286 public Dimension
getPreferredSize()
1288 Dimension prefSize
= null;
1289 if (preferredSize
!= null)
1290 prefSize
= preferredSize
;
1292 else if (ui
!= null)
1294 Dimension s
= ui
.getPreferredSize(this);
1299 if (prefSize
== null)
1300 prefSize
= super.getPreferredSize();
1301 // make sure that prefSize is not smaller than minSize
1302 if (minimumSize
!= null && prefSize
!= null
1303 && (minimumSize
.width
> prefSize
.width
1304 || minimumSize
.height
> prefSize
.height
))
1305 prefSize
= new Dimension(Math
.max(minimumSize
.width
, prefSize
.width
),
1306 Math
.max(minimumSize
.height
, prefSize
.height
));
1311 * Checks if a maximum size was explicitely set on the component.
1313 * @return <code>true</code> if a maximum size was set,
1314 * <code>false</code> otherwise
1318 public boolean isMaximumSizeSet()
1320 return maximumSize
!= null;
1324 * Checks if a minimum size was explicitely set on the component.
1326 * @return <code>true</code> if a minimum size was set,
1327 * <code>false</code> otherwise
1331 public boolean isMinimumSizeSet()
1333 return minimumSize
!= null;
1337 * Checks if a preferred size was explicitely set on the component.
1339 * @return <code>true</code> if a preferred size was set,
1340 * <code>false</code> otherwise
1344 public boolean isPreferredSizeSet()
1346 return preferredSize
!= null;
1350 * Return the value of the <code>nextFocusableComponent</code> property.
1352 * @return The current value of the property, or <code>null</code>
1353 * if none has been set.
1355 * @deprecated See {@link java.awt.FocusTraversalPolicy}
1357 public Component
getNextFocusableComponent()
1363 * Return the set of {@link KeyStroke} objects which are registered
1364 * to initiate actions on this component.
1366 * @return An array of the registered keystrokes
1368 public KeyStroke
[] getRegisteredKeyStrokes()
1374 * Returns the first ancestor of this component which is a {@link JRootPane}.
1375 * Equivalent to calling <code>SwingUtilities.getRootPane(this);</code>.
1377 * @return An ancestral JRootPane, or <code>null</code> if none exists.
1379 public JRootPane
getRootPane()
1381 JRootPane p
= SwingUtilities
.getRootPane(this);
1386 * Get the component's size. The passed-in {@link Dimension} value
1387 * will be used as the return value, if possible.
1389 * @param rv Return value object to reuse, if possible
1391 * @return The component's current size
1393 public Dimension
getSize(Dimension rv
)
1396 return new Dimension(getWidth(), getHeight());
1399 rv
.setSize(getWidth(), getHeight());
1405 * Return the <code>toolTip</code> property of this component, creating it and
1406 * setting it if it is currently <code>null</code>. This method can be
1407 * overridden in subclasses which wish to control the exact form of
1410 * @return The current toolTip
1412 public JToolTip
createToolTip()
1414 JToolTip toolTip
= new JToolTip();
1415 toolTip
.setComponent(this);
1416 toolTip
.setTipText(toolTipText
);
1422 * Return the location at which the {@link #toolTipText} property should be
1423 * displayed, when triggered by a particular mouse event.
1425 * @param event The event the tooltip is being presented in response to
1427 * @return The point at which to display a tooltip, or <code>null</code>
1428 * if swing is to choose a default location.
1430 public Point
getToolTipLocation(MouseEvent event
)
1436 * Set the value of the {@link #toolTipText} property.
1438 * @param text The new property value
1440 * @see #getToolTipText()
1442 public void setToolTipText(String text
)
1446 ToolTipManager
.sharedInstance().unregisterComponent(this);
1451 // XXX: The tip text doesn't get updated unless you set it to null
1452 // and then to something not-null. This is consistent with the behaviour
1453 // of Sun's ToolTipManager.
1455 String oldText
= toolTipText
;
1458 if (oldText
== null)
1459 ToolTipManager
.sharedInstance().registerComponent(this);
1463 * Get the value of the {@link #toolTipText} property.
1465 * @return The current property value
1467 * @see #setToolTipText
1469 public String
getToolTipText()
1475 * Get the value of the {@link #toolTipText} property, in response to a
1476 * particular mouse event.
1478 * @param event The mouse event which triggered the tooltip
1480 * @return The current property value
1482 * @see #setToolTipText
1484 public String
getToolTipText(MouseEvent event
)
1486 return getToolTipText();
1490 * Return the top level ancestral container (usually a {@link
1491 * java.awt.Window} or {@link java.applet.Applet}) which this component is
1492 * contained within, or <code>null</code> if no ancestors exist.
1494 * @return The top level container, if it exists
1496 public Container
getTopLevelAncestor()
1498 Container c
= getParent();
1499 for (Container peek
= c
; peek
!= null; peek
= peek
.getParent())
1505 * Compute the component's visible rectangle, which is defined
1506 * recursively as either the component's bounds, if it has no parent, or
1507 * the intersection of the component's bounds with the visible rectangle
1510 * @param rect The return value slot to place the visible rectangle in
1512 public void computeVisibleRect(Rectangle rect
)
1514 Component c
= getParent();
1515 if (c
!= null && c
instanceof JComponent
)
1517 ((JComponent
) c
).computeVisibleRect(rect
);
1518 rect
.translate(-getX(), -getY());
1519 Rectangle2D
.intersect(rect
,
1520 new Rectangle(0, 0, getWidth(), getHeight()),
1524 rect
.setRect(0, 0, getWidth(), getHeight());
1528 * Return the component's visible rectangle in a new {@link Rectangle},
1529 * rather than via a return slot.
1531 * @return The component's visible rectangle
1533 * @see #computeVisibleRect(Rectangle)
1535 public Rectangle
getVisibleRect()
1537 Rectangle r
= new Rectangle();
1538 computeVisibleRect(r
);
1543 * <p>Requests that this component receive input focus, giving window
1544 * focus to the top level ancestor of this component. Only works on
1545 * displayable, focusable, visible components.</p>
1547 * <p>This method should not be called by clients; it is intended for
1548 * focus implementations. Use {@link Component#requestFocus()} instead.</p>
1550 * @see Component#requestFocus()
1552 public void grabFocus()
1554 // TODO: Implement this properly.
1558 * Get the value of the {@link #doubleBuffered} property.
1560 * @return The property's current value
1562 public boolean isDoubleBuffered()
1564 return doubleBuffered
;
1568 * Return <code>true</code> if the provided component has no native peer;
1569 * in other words, if it is a "lightweight component".
1571 * @param c The component to test for lightweight-ness
1573 * @return Whether or not the component is lightweight
1575 public static boolean isLightweightComponent(Component c
)
1577 return c
.getPeer() instanceof LightweightPeer
;
1581 * Return <code>true</code> if you wish this component to manage its own
1582 * focus. In particular: if you want this component to be sent
1583 * <code>TAB</code> and <code>SHIFT+TAB</code> key events, and to not
1584 * have its children considered as focus transfer targets. If
1585 * <code>true</code>, focus traversal around this component changes to
1586 * <code>CTRL+TAB</code> and <code>CTRL+SHIFT+TAB</code>.
1588 * @return <code>true</code> if you want this component to manage its own
1589 * focus, otherwise (by default) <code>false</code>
1591 * @deprecated 1.4 Use {@link Component#setFocusTraversalKeys(int, Set)} and
1592 * {@link Container#setFocusCycleRoot(boolean)} instead
1594 public boolean isManagingFocus()
1600 * Return the current value of the {@link #opaque} property.
1602 * @return The current property value
1604 public boolean isOpaque()
1610 * Return <code>true</code> if the component can guarantee that none of its
1611 * children will overlap in Z-order. This is a hint to the painting system.
1612 * The default is to return <code>true</code>, but some components such as
1613 * {@link JLayeredPane} should override this to return <code>false</code>.
1615 * @return Whether the component tiles its children
1617 public boolean isOptimizedDrawingEnabled()
1623 * Return <code>true</code> if this component is currently painting a tile,
1624 * this means that paint() is called again on another child component. This
1625 * method returns <code>false</code> if this component does not paint a tile
1626 * or if the last tile is currently painted.
1628 * @return whether the component is painting a tile
1630 public boolean isPaintingTile()
1632 return paintingTile
;
1636 * Get the value of the {@link #requestFocusEnabled} property.
1638 * @return The current value of the property
1640 public boolean isRequestFocusEnabled()
1642 return requestFocusEnabled
;
1646 * Return <code>true</code> if this component is a validation root; this
1647 * will cause calls to {@link #invalidate()} in this component's children
1648 * to be "captured" at this component, and not propagate to its parents.
1649 * For most components this should return <code>false</code>, but some
1650 * components such as {@link JViewport} will want to return
1651 * <code>true</code>.
1653 * @return Whether this component is a validation root
1655 public boolean isValidateRoot()
1661 * <p>Paint the component. This is a delicate process, and should only be
1662 * called from the repaint thread, under control of the {@link
1663 * RepaintManager}. Client code should usually call {@link #repaint()} to
1664 * trigger painting.</p>
1666 * <p>The body of the <code>paint</code> call involves calling {@link
1667 * #paintComponent}, {@link #paintBorder}, and {@link #paintChildren} in
1668 * order. If you want to customize painting behavior, you should override
1669 * one of these methods rather than <code>paint</code>.</p>
1671 * <p>For more details on the painting sequence, see <a
1672 * href="http://java.sun.com/products/jfc/tsc/articles/painting/index.html">
1673 * this article</a>.</p>
1675 * @param g The graphics context to paint with
1677 * @see #paintImmediately(Rectangle)
1679 public void paint(Graphics g
)
1681 RepaintManager rm
= RepaintManager
.currentManager(this);
1682 // We do a little stunt act here to switch on double buffering if it's
1683 // not already on. If we are not already doublebuffered, then we jump
1684 // into the method paintDoubleBuffered, which turns on the double buffer
1685 // and then calls paint(g) again. In the second call we go into the else
1686 // branch of this if statement and actually paint things to the double
1687 // buffer. When this method completes, the call stack unwinds back to
1688 // paintDoubleBuffered, where the buffer contents is finally drawn to the
1690 if (!isPaintingDoubleBuffered
&& isDoubleBuffered()
1691 && rm
.isDoubleBufferingEnabled())
1692 paintDoubleBuffered(g
);
1695 if (g
.getClip() == null)
1696 g
.setClip(0, 0, getWidth(), getHeight());
1697 Graphics g2
= getComponentGraphics(g
);
1701 Rectangle clip
= g2
.getClipBounds();
1702 if (clip
.x
== 0 && clip
.y
== 0 && clip
.width
== getWidth()
1703 && clip
.height
== getHeight())
1704 RepaintManager
.currentManager(this).markCompletelyClean(this);
1709 * Paint the component's border. This usually means calling {@link
1710 * Border#paintBorder} on the {@link #border} property, if it is
1711 * non-<code>null</code>. You may override this if you wish to customize
1712 * border painting behavior. The border is painted after the component's
1713 * body, but before the component's children.
1715 * @param g The graphics context with which to paint the border
1718 * @see #paintChildren
1719 * @see #paintComponent
1721 protected void paintBorder(Graphics g
)
1723 if (getBorder() != null)
1724 getBorder().paintBorder(this, g
, 0, 0, getWidth(), getHeight());
1728 * Paint the component's children. This usually means calling {@link
1729 * Container#paint}, which recursively calls {@link #paint} on any of the
1730 * component's children, with appropriate changes to coordinate space and
1731 * clipping region. You may override this if you wish to customize
1732 * children painting behavior. The children are painted after the
1733 * component's body and border.
1735 * @param g The graphics context with which to paint the children
1739 * @see #paintComponent
1741 protected void paintChildren(Graphics g
)
1743 Shape originalClip
= g
.getClip();
1744 Rectangle inner
= SwingUtilities
.calculateInnerArea(this, rectCache
);
1745 g
.clipRect(inner
.x
, inner
.y
, inner
.width
, inner
.height
);
1746 Component
[] children
= getComponents();
1748 // Find the bottommost component that needs to be painted. This is a
1749 // component that completely covers the current clip and is opaque. In
1750 // this case we don't need to paint the components below it.
1751 int startIndex
= children
.length
- 1;
1752 // No need to check for overlapping components when this component is
1753 // optimizedDrawingEnabled (== it tiles its children).
1754 if (! isOptimizedDrawingEnabled())
1756 Rectangle clip
= g
.getClipBounds();
1757 for (int i
= 0; i
< children
.length
; i
++)
1759 Rectangle childBounds
= children
[i
].getBounds();
1760 if (children
[i
].isOpaque()
1761 && SwingUtilities
.isRectangleContainingRectangle(childBounds
,
1769 // paintingTile becomes true just before we start painting the component's
1771 paintingTile
= true;
1772 for (int i
= startIndex
; i
>= 0; --i
)
1774 // paintingTile must be set to false before we begin to start painting
1777 paintingTile
= false;
1779 if (!children
[i
].isVisible())
1782 Rectangle bounds
= children
[i
].getBounds(rectCache
);
1783 Rectangle oldClip
= g
.getClipBounds();
1784 if (oldClip
== null)
1787 if (!g
.hitClip(bounds
.x
, bounds
.y
, bounds
.width
, bounds
.height
))
1790 boolean translated
= false;
1793 g
.clipRect(bounds
.x
, bounds
.y
, bounds
.width
, bounds
.height
);
1794 g
.translate(bounds
.x
, bounds
.y
);
1796 children
[i
].paint(g
);
1801 g
.translate(-bounds
.x
, -bounds
.y
);
1805 g
.setClip(originalClip
);
1809 * Paint the component's body. This usually means calling {@link
1810 * ComponentUI#update} on the {@link #ui} property of the component, if
1811 * it is non-<code>null</code>. You may override this if you wish to
1812 * customize the component's body-painting behavior. The component's body
1813 * is painted first, before the border and children.
1815 * @param g The graphics context with which to paint the body
1819 * @see #paintChildren
1821 protected void paintComponent(Graphics g
)
1826 if (!(g
instanceof Graphics2D
))
1828 ui
.update(g2
, this);
1829 if (!(g
instanceof Graphics2D
))
1835 * A variant of {@link #paintImmediately(Rectangle)} which takes
1836 * integer parameters.
1838 * @param x The left x coordinate of the dirty region
1839 * @param y The top y coordinate of the dirty region
1840 * @param w The width of the dirty region
1841 * @param h The height of the dirty region
1843 public void paintImmediately(int x
, int y
, int w
, int h
)
1845 paintImmediately(new Rectangle(x
, y
, w
, h
));
1849 * Transform the provided dirty rectangle for this component into the
1850 * appropriate ancestral {@link JRootPane} and call {@link #paint} on
1851 * that root pane. This method is called from the {@link RepaintManager}
1852 * and should always be called within the painting thread.
1854 * <p>This method will acquire a double buffer from the {@link
1855 * RepaintManager} if the component's {@link #doubleBuffered} property is
1856 * <code>true</code> and the <code>paint</code> call is the
1857 * <em>first</em> recursive <code>paint</code> call inside swing.</p>
1859 * <p>The method will also modify the provided {@link Graphics} context
1860 * via the {@link #getComponentGraphics} method. If you want to customize
1861 * the graphics object used for painting, you should override that method
1862 * rather than <code>paint</code>.</p>
1864 * @param r The dirty rectangle to paint
1866 public void paintImmediately(Rectangle r
)
1868 // Try to find a root pane for this component.
1869 //Component root = findPaintRoot(r);
1870 Component root
= findPaintRoot(r
);
1871 // If no paint root is found, then this component is completely overlapped
1872 // by another component and we don't need repainting.
1875 if (root
== null || !root
.isShowing())
1878 Rectangle rootClip
= SwingUtilities
.convertRectangle(this, r
, root
);
1879 if (root
instanceof JComponent
)
1880 ((JComponent
) root
).paintImmediately2(rootClip
);
1882 root
.repaint(rootClip
.x
, rootClip
.y
, rootClip
.width
, rootClip
.height
);
1886 * Performs the actual work of paintImmediatly on the repaint root.
1888 * @param r the area to be repainted
1890 void paintImmediately2(Rectangle r
)
1892 RepaintManager rm
= RepaintManager
.currentManager(this);
1893 Graphics g
= getGraphics();
1894 g
.setClip(r
.x
, r
.y
, r
.width
, r
.height
);
1895 if (rm
.isDoubleBufferingEnabled() && isDoubleBuffered())
1896 paintDoubleBuffered(g
);
1903 * Performs double buffered repainting.
1905 * @param g the graphics context to paint to
1907 void paintDoubleBuffered(Graphics g
)
1910 Rectangle r
= g
.getClipBounds();
1912 r
= new Rectangle(0, 0, getWidth(), getHeight());
1913 RepaintManager rm
= RepaintManager
.currentManager(this);
1915 // Paint on the offscreen buffer.
1916 Image buffer
= rm
.getOffscreenBuffer(this, getWidth(), getHeight());
1917 Graphics g2
= buffer
.getGraphics();
1918 g2
= getComponentGraphics(g2
);
1919 g2
.setClip(r
.x
, r
.y
, r
.width
, r
.height
);
1920 isPaintingDoubleBuffered
= true;
1927 isPaintingDoubleBuffered
= false;
1931 // Paint the buffer contents on screen.
1932 g
.drawImage(buffer
, 0, 0, this);
1936 * Performs normal painting without double buffering.
1938 * @param g the graphics context to use
1940 void paintSimple(Graphics g
)
1942 Graphics g2
= getComponentGraphics(g
);
1947 * Return a string representation for this component, for use in
1950 * @return A string describing this component.
1952 protected String
paramString()
1954 StringBuffer sb
= new StringBuffer();
1955 sb
.append(super.paramString());
1956 sb
.append(",alignmentX=").append(getAlignmentX());
1957 sb
.append(",alignmentY=").append(getAlignmentY());
1958 sb
.append(",border=");
1959 if (getBorder() != null)
1960 sb
.append(getBorder());
1961 sb
.append(",maximumSize=");
1962 if (getMaximumSize() != null)
1963 sb
.append(getMaximumSize());
1964 sb
.append(",minimumSize=");
1965 if (getMinimumSize() != null)
1966 sb
.append(getMinimumSize());
1967 sb
.append(",preferredSize=");
1968 if (getPreferredSize() != null)
1969 sb
.append(getPreferredSize());
1970 return sb
.toString();
1974 * A variant of {@link
1975 * #registerKeyboardAction(ActionListener,String,KeyStroke,int)} which
1976 * provides <code>null</code> for the command name.
1978 public void registerKeyboardAction(ActionListener act
,
1982 registerKeyboardAction(act
, null, stroke
, cond
);
1986 * There is some charmingly undocumented behavior sun seems to be using
1987 * to simulate the old register/unregister keyboard binding API. It's not
1988 * clear to me why this matters, but we shall endeavour to follow suit.
1990 * Two main thing seem to be happening when you do registerKeyboardAction():
1992 * - no actionMap() entry gets created, just an entry in inputMap()
1994 * - the inputMap() entry is a proxy class which invokes the the
1995 * binding's actionListener as a target, and which clobbers the command
1996 * name sent in the ActionEvent, providing the binding command name
1999 * This much you can work out just by asking the input and action maps
2000 * what they contain after making bindings, and watching the event which
2001 * gets delivered to the recipient. Beyond that, it seems to be a
2002 * sun-private solution so I will only immitate it as much as it matters
2003 * to external observers.
2005 private static class ActionListenerProxy
2006 extends AbstractAction
2008 ActionListener target
;
2009 String bindingCommandName
;
2011 public ActionListenerProxy(ActionListener li
,
2015 bindingCommandName
= cmd
;
2018 public void actionPerformed(ActionEvent e
)
2020 ActionEvent derivedEvent
= new ActionEvent(e
.getSource(),
2024 target
.actionPerformed(derivedEvent
);
2030 * An obsolete method to register a keyboard action on this component.
2031 * You should use <code>getInputMap</code> and <code>getActionMap</code>
2032 * to fetch mapping tables from keystrokes to commands, and commands to
2033 * actions, respectively, and modify those mappings directly.
2035 * @param act The action to be registered
2036 * @param cmd The command to deliver in the delivered {@link
2037 * java.awt.event.ActionEvent}
2038 * @param stroke The keystroke to register on
2039 * @param cond One of the values {@link #UNDEFINED_CONDITION},
2040 * {@link #WHEN_ANCESTOR_OF_FOCUSED_COMPONENT}, {@link #WHEN_FOCUSED}, or
2041 * {@link #WHEN_IN_FOCUSED_WINDOW}, indicating the condition which must
2042 * be met for the action to be fired
2044 * @see #unregisterKeyboardAction
2045 * @see #getConditionForKeyStroke
2046 * @see #resetKeyboardActions
2048 public void registerKeyboardAction(ActionListener act
,
2053 getInputMap(cond
).put(stroke
, new ActionListenerProxy(act
, cmd
));
2056 public final void setInputMap(int condition
, InputMap map
)
2058 enableEvents(AWTEvent
.KEY_EVENT_MASK
);
2062 inputMap_whenFocused
= map
;
2065 case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
:
2066 inputMap_whenAncestorOfFocused
= map
;
2069 case WHEN_IN_FOCUSED_WINDOW
:
2070 if (map
!= null && !(map
instanceof ComponentInputMap
))
2072 IllegalArgumentException("WHEN_IN_FOCUSED_WINDOW " +
2073 "InputMap must be a ComponentInputMap");
2074 inputMap_whenInFocusedWindow
= (ComponentInputMap
)map
;
2077 case UNDEFINED_CONDITION
:
2079 throw new IllegalArgumentException();
2083 public final InputMap
getInputMap(int condition
)
2085 enableEvents(AWTEvent
.KEY_EVENT_MASK
);
2089 if (inputMap_whenFocused
== null)
2090 inputMap_whenFocused
= new InputMap();
2091 return inputMap_whenFocused
;
2093 case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
:
2094 if (inputMap_whenAncestorOfFocused
== null)
2095 inputMap_whenAncestorOfFocused
= new InputMap();
2096 return inputMap_whenAncestorOfFocused
;
2098 case WHEN_IN_FOCUSED_WINDOW
:
2099 if (inputMap_whenInFocusedWindow
== null)
2100 inputMap_whenInFocusedWindow
= new ComponentInputMap(this);
2101 return inputMap_whenInFocusedWindow
;
2103 case UNDEFINED_CONDITION
:
2109 public final InputMap
getInputMap()
2111 return getInputMap(WHEN_FOCUSED
);
2114 public final ActionMap
getActionMap()
2116 if (actionMap
== null)
2117 actionMap
= new ActionMap();
2121 public final void setActionMap(ActionMap map
)
2127 * Return the condition that determines whether a registered action
2128 * occurs in response to the specified keystroke.
2130 * @param ks The keystroke to return the condition of
2132 * @return One of the values {@link #UNDEFINED_CONDITION}, {@link
2133 * #WHEN_ANCESTOR_OF_FOCUSED_COMPONENT}, {@link #WHEN_FOCUSED}, or {@link
2134 * #WHEN_IN_FOCUSED_WINDOW}
2136 * @deprecated As of 1.3 KeyStrokes can be registered with multiple
2137 * simultaneous conditions.
2139 * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
2140 * @see #unregisterKeyboardAction
2141 * @see #resetKeyboardActions
2143 public int getConditionForKeyStroke(KeyStroke ks
)
2145 if (inputMap_whenFocused
!= null
2146 && inputMap_whenFocused
.get(ks
) != null)
2147 return WHEN_FOCUSED
;
2148 else if (inputMap_whenAncestorOfFocused
!= null
2149 && inputMap_whenAncestorOfFocused
.get(ks
) != null)
2150 return WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
;
2151 else if (inputMap_whenInFocusedWindow
!= null
2152 && inputMap_whenInFocusedWindow
.get(ks
) != null)
2153 return WHEN_IN_FOCUSED_WINDOW
;
2155 return UNDEFINED_CONDITION
;
2159 * Get the ActionListener (typically an {@link Action} object) which is
2160 * associated with a particular keystroke.
2162 * @param ks The keystroke to retrieve the action of
2164 * @return The action associated with the specified keystroke
2166 * @deprecated Use {@link #getActionMap()}
2168 public ActionListener
getActionForKeyStroke(KeyStroke ks
)
2170 Object cmd
= getInputMap().get(ks
);
2173 if (cmd
instanceof ActionListenerProxy
)
2174 return (ActionListenerProxy
) cmd
;
2175 else if (cmd
instanceof String
)
2176 return getActionMap().get(cmd
);
2182 * A hook for subclasses which want to customize event processing.
2184 protected void processComponentKeyEvent(KeyEvent e
)
2186 // This method does nothing, it is meant to be overridden by subclasses.
2190 * Override the default key dispatch system from Component to hook into
2191 * the swing {@link InputMap} / {@link ActionMap} system.
2194 * href="http://java.sun.com/products/jfc/tsc/special_report/kestrel/keybindings.html">
2195 * this report</a> for more details, it's somewhat complex.
2197 protected void processKeyEvent(KeyEvent e
)
2199 // let the AWT event processing send KeyEvents to registered listeners
2200 super.processKeyEvent(e
);
2201 processComponentKeyEvent(e
);
2206 // Input maps are checked in this order:
2207 // 1. The focused component's WHEN_FOCUSED map is checked.
2208 // 2. The focused component's WHEN_ANCESTOR_OF_FOCUSED_COMPONENT map.
2209 // 3. The WHEN_ANCESTOR_OF_FOCUSED_COMPONENT maps of the focused
2210 // component's parent, then its parent's parent, and so on.
2211 // Note: Input maps for disabled components are skipped.
2212 // 4. The WHEN_IN_FOCUSED_WINDOW maps of all the enabled components in
2213 // the focused window are searched.
2215 KeyStroke keyStroke
= KeyStroke
.getKeyStrokeForEvent(e
);
2216 boolean pressed
= e
.getID() == KeyEvent
.KEY_PRESSED
;
2218 if (processKeyBinding(keyStroke
, e
, WHEN_FOCUSED
, pressed
))
2220 // This is step 1 from above comment.
2224 else if (processKeyBinding
2225 (keyStroke
, e
, WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
, pressed
))
2227 // This is step 2 from above comment.
2232 // This is step 3 from above comment.
2233 Container current
= getParent();
2234 while (current
!= null)
2236 // If current is a JComponent, see if it handles the event in its
2237 // WHEN_ANCESTOR_OF_FOCUSED_COMPONENT maps.
2238 if ((current
instanceof JComponent
) &&
2239 ((JComponent
)current
).processKeyBinding
2240 (keyStroke
, e
,WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
, pressed
))
2246 // Stop when we've tried a top-level container and it didn't handle it
2247 if (current
instanceof Window
|| current
instanceof Applet
)
2250 // Move up the hierarchy
2251 current
= current
.getParent();
2254 // Current being null means the JComponent does not currently have a
2255 // top-level ancestor, in which case we don't need to check
2256 // WHEN_IN_FOCUSED_WINDOW bindings.
2257 if (current
== null || e
.isConsumed())
2260 // This is step 4 from above comment. KeyboardManager maintains mappings
2261 // related to WHEN_IN_FOCUSED_WINDOW bindings so that we don't have to
2262 // traverse the containment hierarchy each time.
2263 if (KeyboardManager
.getManager().processKeyStroke(current
, keyStroke
, e
))
2267 protected boolean processKeyBinding(KeyStroke ks
,
2275 InputMap map
= getInputMap(condition
);
2278 Object cmd
= map
.get(ks
);
2281 if (cmd
instanceof ActionListenerProxy
)
2284 act
= (Action
) getActionMap().get(cmd
);
2287 if (act
!= null && act
.isEnabled())
2288 return SwingUtilities
.notifyAction(act
, ks
, e
, this, e
.getModifiers());
2294 * Remove a keyboard action registry.
2296 * @param aKeyStroke The keystroke to unregister
2298 * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
2299 * @see #getConditionForKeyStroke
2300 * @see #resetKeyboardActions
2302 public void unregisterKeyboardAction(KeyStroke aKeyStroke
)
2304 // FIXME: Must be implemented.
2309 * Reset all keyboard action registries.
2311 * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
2312 * @see #unregisterKeyboardAction
2313 * @see #getConditionForKeyStroke
2315 public void resetKeyboardActions()
2317 if (inputMap_whenFocused
!= null)
2318 inputMap_whenFocused
.clear();
2319 if (inputMap_whenAncestorOfFocused
!= null)
2320 inputMap_whenAncestorOfFocused
.clear();
2321 if (inputMap_whenInFocusedWindow
!= null)
2322 inputMap_whenInFocusedWindow
.clear();
2323 if (actionMap
!= null)
2328 * Mark the described region of this component as dirty in the current
2329 * {@link RepaintManager}. This will queue an asynchronous repaint using
2330 * the system painting thread in the near future.
2333 * @param x coordinate of the region to mark as dirty
2334 * @param y coordinate of the region to mark as dirty
2335 * @param width dimension of the region to mark as dirty
2336 * @param height dimension of the region to mark as dirty
2338 public void repaint(long tm
, int x
, int y
, int width
, int height
)
2340 Rectangle dirty
= new Rectangle(x
, y
, width
, height
);
2341 Rectangle vis
= getVisibleRect();
2342 dirty
= dirty
.intersection(vis
);
2343 RepaintManager
.currentManager(this).addDirtyRegion(this, dirty
.x
, dirty
.y
,
2349 * Mark the described region of this component as dirty in the current
2350 * {@link RepaintManager}. This will queue an asynchronous repaint using
2351 * the system painting thread in the near future.
2353 * @param r The rectangle to mark as dirty
2355 public void repaint(Rectangle r
)
2357 repaint((long) 0, (int) r
.getX(), (int) r
.getY(), (int) r
.getWidth(),
2358 (int) r
.getHeight());
2362 * Request focus on the default component of this component's {@link
2363 * FocusTraversalPolicy}.
2365 * @return The result of {@link #requestFocus()}
2367 * @deprecated Use {@link #requestFocus()} on the default component provided
2368 * from the {@link FocusTraversalPolicy} instead.
2370 public boolean requestDefaultFocus()
2376 * Queue a an invalidation and revalidation of this component, using
2377 * {@link RepaintManager#addInvalidComponent}.
2379 public void revalidate()
2381 if (! EventQueue
.isDispatchThread())
2382 SwingUtilities
.invokeLater(new Runnable()
2392 RepaintManager
.currentManager(this).addInvalidComponent(this);
2397 * Calls <code>scrollRectToVisible</code> on the component's parent.
2398 * Components which can service this call should override.
2400 * @param r The rectangle to make visible
2402 public void scrollRectToVisible(Rectangle r
)
2404 Component p
= getParent();
2405 if (p
instanceof JComponent
)
2406 ((JComponent
) p
).scrollRectToVisible(r
);
2410 * Set the value of the {@link #alignmentX} property.
2412 * @param a The new value of the property
2414 public void setAlignmentX(float a
)
2425 * Set the value of the {@link #alignmentY} property.
2427 * @param a The new value of the property
2429 public void setAlignmentY(float a
)
2440 * Set the value of the {@link #autoscrolls} property.
2442 * @param a The new value of the property
2444 public void setAutoscrolls(boolean a
)
2450 * Set the value of the {@link #debugGraphicsOptions} property.
2452 * @param debugOptions The new value of the property
2454 public void setDebugGraphicsOptions(int debugOptions
)
2456 debugGraphicsOptions
= debugOptions
;
2460 * Set the value of the {@link #doubleBuffered} property.
2462 * @param db The new value of the property
2464 public void setDoubleBuffered(boolean db
)
2466 doubleBuffered
= db
;
2470 * Set the value of the <code>enabled</code> property.
2472 * @param enable The new value of the property
2474 public void setEnabled(boolean enable
)
2476 if (enable
== isEnabled())
2478 super.setEnabled(enable
);
2479 firePropertyChange("enabled", !enable
, enable
);
2484 * Set the value of the <code>font</code> property.
2486 * @param f The new value of the property
2488 public void setFont(Font f
)
2498 * Set the value of the <code>background</code> property.
2500 * @param bg The new value of the property
2502 public void setBackground(Color bg
)
2504 if (bg
== getBackground())
2506 super.setBackground(bg
);
2511 * Set the value of the <code>foreground</code> property.
2513 * @param fg The new value of the property
2515 public void setForeground(Color fg
)
2517 if (fg
== getForeground())
2519 super.setForeground(fg
);
2524 * Set the value of the {@link #maximumSize} property. The passed value is
2525 * copied, the later direct changes on the argument have no effect on the
2528 * @param max The new value of the property
2530 public void setMaximumSize(Dimension max
)
2532 Dimension oldMaximumSize
= maximumSize
;
2533 maximumSize
= new Dimension(max
);
2534 firePropertyChange("maximumSize", oldMaximumSize
, maximumSize
);
2538 * Set the value of the {@link #minimumSize} property. The passed value is
2539 * copied, the later direct changes on the argument have no effect on the
2542 * @param min The new value of the property
2544 public void setMinimumSize(Dimension min
)
2546 Dimension oldMinimumSize
= minimumSize
;
2547 minimumSize
= new Dimension(min
);
2548 firePropertyChange("minimumSize", oldMinimumSize
, minimumSize
);
2552 * Set the value of the {@link #preferredSize} property. The passed value is
2553 * copied, the later direct changes on the argument have no effect on the
2556 * @param pref The new value of the property
2558 public void setPreferredSize(Dimension pref
)
2560 Dimension oldPreferredSize
= preferredSize
;
2561 preferredSize
= new Dimension(pref
);
2562 firePropertyChange("preferredSize", oldPreferredSize
, preferredSize
);
2566 * Set the specified component to be the next component in the
2567 * focus cycle, overriding the {@link FocusTraversalPolicy} for
2570 * @param aComponent The component to set as the next focusable
2572 * @deprecated Use FocusTraversalPolicy instead
2574 public void setNextFocusableComponent(Component aComponent
)
2576 // TODO: Implement this properly.
2580 * Set the value of the {@link #requestFocusEnabled} property.
2582 * @param e The new value of the property
2584 public void setRequestFocusEnabled(boolean e
)
2586 requestFocusEnabled
= e
;
2590 * Get the value of the {@link #transferHandler} property.
2592 * @return The current value of the property
2594 * @see #setTransferHandler
2597 public TransferHandler
getTransferHandler()
2599 return transferHandler
;
2603 * Set the value of the {@link #transferHandler} property.
2605 * @param newHandler The new value of the property
2607 * @see #getTransferHandler
2610 public void setTransferHandler(TransferHandler newHandler
)
2612 if (transferHandler
== newHandler
)
2615 TransferHandler oldHandler
= transferHandler
;
2616 transferHandler
= newHandler
;
2617 firePropertyChange("transferHandler", oldHandler
, newHandler
);
2621 * Set the value of the {@link #opaque} property.
2623 * @param isOpaque The new value of the property
2625 * @see ComponentUI#update
2627 public void setOpaque(boolean isOpaque
)
2629 boolean oldOpaque
= opaque
;
2631 firePropertyChange("opaque", oldOpaque
, opaque
);
2635 * Set the value of the visible property.
2637 * If the value is changed, then the AncestorListeners of this component
2638 * and all its children (recursivly) are notified.
2640 * @param v The new value of the property
2642 public void setVisible(boolean v
)
2644 // No need to do anything if the actual value doesn't change.
2645 if (isVisible() == v
)
2648 super.setVisible(v
);
2650 // Notify AncestorListeners.
2652 fireAncestorEvent(this, AncestorEvent
.ANCESTOR_ADDED
);
2654 fireAncestorEvent(this, AncestorEvent
.ANCESTOR_REMOVED
);
2656 Container parent
= getParent();
2658 parent
.repaint(getX(), getY(), getWidth(), getHeight());
2663 * Call {@link #paint}.
2665 * @param g The graphics context to paint into
2667 public void update(Graphics g
)
2673 * Get the value of the UIClassID property. This property should be a key
2674 * in the {@link UIDefaults} table managed by {@link UIManager}, the
2675 * value of which is the name of a class to load for the component's
2676 * {@link #ui} property.
2678 * @return A "symbolic" name which will map to a class to use for the
2679 * component's UI, such as <code>"ComponentUI"</code>
2684 public String
getUIClassID()
2686 return "ComponentUI";
2690 * Install a new UI delegate as the component's {@link #ui} property. In
2691 * the process, this will call {@link ComponentUI#uninstallUI} on any
2692 * existing value for the {@link #ui} property, and {@link
2693 * ComponentUI#installUI} on the new UI delegate.
2695 * @param newUI The new UI delegate to install
2698 * @see #getUIClassID
2700 protected void setUI(ComponentUI newUI
)
2703 ui
.uninstallUI(this);
2705 ComponentUI oldUI
= ui
;
2711 firePropertyChange("UI", oldUI
, newUI
);
2717 * This method should be overridden in subclasses. In JComponent, the
2718 * method does nothing. In subclasses, it should a UI delegate
2719 * (corresponding to the symbolic name returned from {@link
2720 * #getUIClassID}) from the {@link UIManager}, and calls {@link #setUI}
2721 * with the new delegate.
2723 public void updateUI()
2725 System
.out
.println("update UI not overwritten in class: " + this);
2728 public static Locale
getDefaultLocale()
2730 return defaultLocale
;
2733 public static void setDefaultLocale(Locale l
)
2739 * Returns the currently set input verifier for this component.
2741 * @return the input verifier, or <code>null</code> if none
2743 public InputVerifier
getInputVerifier()
2745 return inputVerifier
;
2749 * Sets the input verifier to use by this component.
2751 * @param verifier the input verifier, or <code>null</code>
2753 public void setInputVerifier(InputVerifier verifier
)
2755 InputVerifier oldVerifier
= inputVerifier
;
2756 inputVerifier
= verifier
;
2757 firePropertyChange("inputVerifier", oldVerifier
, verifier
);
2763 public boolean getVerifyInputWhenFocusTarget()
2765 return verifyInputWhenFocusTarget
;
2771 public void setVerifyInputWhenFocusTarget(boolean verifyInputWhenFocusTarget
)
2773 if (this.verifyInputWhenFocusTarget
== verifyInputWhenFocusTarget
)
2776 this.verifyInputWhenFocusTarget
= verifyInputWhenFocusTarget
;
2777 firePropertyChange("verifyInputWhenFocusTarget",
2778 ! verifyInputWhenFocusTarget
,
2779 verifyInputWhenFocusTarget
);
2783 * Requests that this component gets the input focus if the
2784 * requestFocusEnabled property is set to <code>true</code>.
2785 * This also means that this component's top-level window becomes
2786 * the focused window, if that is not already the case.
2788 * The preconditions that have to be met to become a focus owner is that
2789 * the component must be displayable, visible and focusable.
2791 * Note that this signals only a request for becoming focused. There are
2792 * situations in which it is not possible to get the focus. So developers
2793 * should not assume that the component has the focus until it receives
2794 * a {@link java.awt.event.FocusEvent} with a value of
2795 * {@link java.awt.event.FocusEvent#FOCUS_GAINED}.
2797 * @see Component#requestFocus()
2799 public void requestFocus()
2801 if (isRequestFocusEnabled())
2802 super.requestFocus();
2806 * This method is overridden to make it public so that it can be used
2807 * by look and feel implementations.
2809 * You should not use this method directly. Instead you are strongly
2810 * encouraged to call {@link #requestFocus()} or
2811 * {@link #requestFocusInWindow()} instead.
2813 * @param temporary if the focus change is temporary
2815 * @return <code>false</code> if the focus change request will definitly
2816 * fail, <code>true</code> if it will likely succeed
2818 * @see Component#requestFocus(boolean)
2822 public boolean requestFocus(boolean temporary
)
2824 return super.requestFocus(temporary
);
2828 * Requests that this component gets the input focus if the top level
2829 * window that contains this component has the focus and the
2830 * requestFocusEnabled property is set to <code>true</code>.
2832 * The preconditions that have to be met to become a focus owner is that
2833 * the component must be displayable, visible and focusable.
2835 * Note that this signals only a request for becoming focused. There are
2836 * situations in which it is not possible to get the focus. So developers
2837 * should not assume that the component has the focus until it receives
2838 * a {@link java.awt.event.FocusEvent} with a value of
2839 * {@link java.awt.event.FocusEvent#FOCUS_GAINED}.
2841 * @return <code>false</code> if the focus change request will definitly
2842 * fail, <code>true</code> if it will likely succeed
2844 * @see Component#requestFocusInWindow()
2846 public boolean requestFocusInWindow()
2848 if (isRequestFocusEnabled())
2849 return super.requestFocusInWindow();
2855 * This method is overridden to make it public so that it can be used
2856 * by look and feel implementations.
2858 * You should not use this method directly. Instead you are strongly
2859 * encouraged to call {@link #requestFocus()} or
2860 * {@link #requestFocusInWindow()} instead.
2862 * @param temporary if the focus change is temporary
2864 * @return <code>false</code> if the focus change request will definitly
2865 * fail, <code>true</code> if it will likely succeed
2867 * @see Component#requestFocus(boolean)
2871 public boolean requestFocusInWindow(boolean temporary
)
2873 return super.requestFocusInWindow(temporary
);
2877 * Receives notification if this component is added to a parent component.
2879 * Notification is sent to all registered AncestorListeners about the
2882 * This method sets up ActionListeners for all registered KeyStrokes of
2883 * this component in the chain of parent components.
2885 * A PropertyChange event is fired to indicate that the ancestor property
2888 * This method is used internally and should not be used in applications.
2890 public void addNotify()
2892 // Register the WHEN_IN_FOCUSED_WINDOW keyboard bindings
2893 // Note that here we unregister all bindings associated with
2894 // this component and then re-register them. This may be more than
2895 // necessary if the top-level ancestor hasn't changed. Should
2896 // maybe improve this.
2897 KeyboardManager km
= KeyboardManager
.getManager();
2898 km
.clearBindingsForComp(this);
2899 km
.registerEntireMap((ComponentInputMap
)
2900 this.getInputMap(WHEN_IN_FOCUSED_WINDOW
));
2903 // Notify AncestorListeners.
2904 fireAncestorEvent(this, AncestorEvent
.ANCESTOR_ADDED
);
2906 // fire property change event for 'ancestor'
2907 firePropertyChange("ancestor", null, getParent());
2911 * Receives notification that this component no longer has a parent.
2913 * This method sends an AncestorEvent to all registered AncestorListeners,
2914 * notifying them that the parent is gone.
2916 * The keybord actions of this component are removed from the parent and
2919 * A PropertyChangeEvent is fired to indicate that the 'ancestor' property
2922 * This method is called before the component is actually removed from
2923 * its parent, so the parent is still visible through
2924 * {@link Component#getParent}.
2926 public void removeNotify()
2928 super.removeNotify();
2930 KeyboardManager
.getManager().clearBindingsForComp(this);
2932 // Notify ancestor listeners.
2933 fireAncestorEvent(this, AncestorEvent
.ANCESTOR_REMOVED
);
2935 // fire property change event for 'ancestor'
2936 firePropertyChange("ancestor", getParent(), null);
2940 * Returns <code>true</code> if the coordinates (x, y) lie within
2941 * the bounds of this component and <code>false</code> otherwise.
2942 * x and y are relative to the coordinate space of the component.
2944 * @param x the X coordinate of the point to check
2945 * @param y the Y coordinate of the point to check
2947 * @return <code>true</code> if the specified point lies within the bounds
2948 * of this component, <code>false</code> otherwise
2950 public boolean contains(int x
, int y
)
2953 return super.contains(x
, y
);
2955 return ui
.contains(this, x
, y
);
2959 * Disables this component.
2961 * @deprecated replaced by {@link #setEnabled(boolean)}
2963 public void disable()
2969 * Enables this component.
2971 * @deprecated replaced by {@link #setEnabled(boolean)}
2973 public void enable()
2979 * Returns the Graphics context for this component. This can be used
2980 * to draw on a component.
2982 * @return the Graphics context for this component
2984 public Graphics
getGraphics()
2986 return super.getGraphics();
2990 * Returns the X coordinate of the upper left corner of this component.
2991 * Prefer this method over {@link #getBounds} or {@link #getLocation}
2992 * because it does not cause any heap allocation.
2994 * @return the X coordinate of the upper left corner of the component
2998 return super.getX();
3002 * Returns the Y coordinate of the upper left corner of this component.
3003 * Prefer this method over {@link #getBounds} or {@link #getLocation}
3004 * because it does not cause any heap allocation.
3006 * @return the Y coordinate of the upper left corner of the component
3010 return super.getY();
3014 * Returns the height of this component. Prefer this method over
3015 * {@link #getBounds} or {@link #getSize} because it does not cause
3016 * any heap allocation.
3018 * @return the height of the component
3020 public int getHeight()
3022 return super.getHeight();
3026 * Returns the width of this component. Prefer this method over
3027 * {@link #getBounds} or {@link #getSize} because it does not cause
3028 * any heap allocation.
3030 * @return the width of the component
3032 public int getWidth()
3034 return super.getWidth();
3038 * Return all <code>PropertyChangeListener</code> objects registered.
3040 * @return The set of <code>PropertyChangeListener</code> objects
3042 public PropertyChangeListener
[] getPropertyChangeListeners()
3044 if (changeSupport
== null)
3045 return new PropertyChangeListener
[0];
3047 return changeSupport
.getPropertyChangeListeners();
3051 * Prints this component to the given Graphics context. A call to this
3052 * method results in calls to the methods {@link #printComponent},
3053 * {@link #printBorder} and {@link #printChildren} in this order.
3055 * Double buffering is temporarily turned off so the painting goes directly
3056 * to the supplied Graphics context.
3058 * @param g the Graphics context to print onto
3060 public void print(Graphics g
)
3062 boolean doubleBufferState
= isDoubleBuffered();
3063 setDoubleBuffered(false);
3067 setDoubleBuffered(doubleBufferState
);
3071 * Prints this component to the given Graphics context. This invokes
3074 * @param g the Graphics context to print onto
3076 public void printAll(Graphics g
)
3082 * Prints this component to the specified Graphics context. The default
3083 * behaviour is to invoke {@link #paintComponent}. Override this
3084 * if you want special behaviour for printing.
3086 * @param g the Graphics context to print onto
3090 public void printComponent(Graphics g
)
3096 * Print this component's children to the specified Graphics context.
3097 * The default behaviour is to invoke {@link #paintChildren}. Override this
3098 * if you want special behaviour for printing.
3100 * @param g the Graphics context to print onto
3104 public void printChildren(Graphics g
)
3110 * Print this component's border to the specified Graphics context.
3111 * The default behaviour is to invoke {@link #paintBorder}. Override this
3112 * if you want special behaviour for printing.
3114 * @param g the Graphics context to print onto
3118 public void printBorder(Graphics g
)
3124 * Processes mouse motion event, like dragging and moving.
3126 * @param ev the MouseEvent describing the mouse motion
3128 protected void processMouseMotionEvent(MouseEvent ev
)
3130 super.processMouseMotionEvent(ev
);
3134 * Moves and resizes the component.
3136 * @param x the new horizontal location
3137 * @param y the new vertial location
3138 * @param w the new width
3139 * @param h the new height
3141 public void reshape(int x
, int y
, int w
, int h
)
3145 super.reshape(x
, y
, w
, h
);
3146 // Notify AncestorListeners.
3147 if (oldX
!= getX() || oldY
!= getY())
3148 fireAncestorEvent(this, AncestorEvent
.ANCESTOR_MOVED
);
3152 * Fires an AncestorEvent to this component's and all of its child
3153 * component's AncestorListeners.
3155 * @param ancestor the component that triggered the event
3156 * @param id the kind of ancestor event that should be fired
3158 void fireAncestorEvent(JComponent ancestor
, int id
)
3160 // Fire event for registered ancestor listeners of this component.
3161 AncestorListener
[] listeners
= getAncestorListeners();
3162 if (listeners
.length
> 0)
3164 AncestorEvent ev
= new AncestorEvent(this, id
,
3165 ancestor
, ancestor
.getParent());
3166 for (int i
= 0; i
< listeners
.length
; i
++)
3170 case AncestorEvent
.ANCESTOR_MOVED
:
3171 listeners
[i
].ancestorMoved(ev
);
3173 case AncestorEvent
.ANCESTOR_ADDED
:
3174 listeners
[i
].ancestorAdded(ev
);
3176 case AncestorEvent
.ANCESTOR_REMOVED
:
3177 listeners
[i
].ancestorRemoved(ev
);
3182 // Dispatch event to all children.
3183 Component
[] children
= getComponents();
3184 for (int i
= 0; i
< children
.length
; i
++)
3186 if (!(children
[i
] instanceof JComponent
))
3188 JComponent jc
= (JComponent
) children
[i
];
3189 jc
.fireAncestorEvent(ancestor
, id
);
3194 * Finds a suitable paint root for painting this component. This method first
3195 * checks if this component is overlapped using
3196 * {@link #findOverlapFreeParent(Rectangle)}. The returned paint root is then
3197 * feeded to {@link #findOpaqueParent(Component)} to find the nearest opaque
3198 * component for this paint root. If no paint is necessary, then we return
3199 * <code>null</code>.
3201 * @param c the clip of this component
3203 * @return the paint root or <code>null</code> if no painting is necessary
3205 private Component
findPaintRoot(Rectangle c
)
3207 Component p
= findOverlapFreeParent(c
);
3210 Component root
= findOpaqueParent(p
);
3215 * Scans the containment hierarchy upwards for components that overlap the
3216 * this component in the specified clip. This method returns
3217 * <code>this</code>, if no component overlaps this component. It returns
3218 * <code>null</code> if another component completely covers this component
3219 * in the specified clip (no repaint necessary). If another component partly
3220 * overlaps this component in the specified clip, then the parent of this
3221 * component is returned (this is the component that must be used as repaint
3222 * root). For efficient lookup, the method
3223 * {@link #isOptimizedDrawingEnabled()} is used.
3225 * @param clip the clip of this component
3227 * @return the paint root, or <code>null</code> if no paint is necessary
3229 private Component
findOverlapFreeParent(Rectangle clip
)
3231 Rectangle currentClip
= clip
;
3232 Component found
= this;
3233 Container parent
= this;
3234 while (parent
!= null && !(parent
instanceof Window
))
3236 Container newParent
= parent
.getParent();
3237 if (newParent
== null)
3239 // If the parent is optimizedDrawingEnabled, then its children are
3240 // tiled and cannot have an overlapping child. Go directly to next
3242 if (newParent
instanceof JComponent
3243 && ((JComponent
) newParent
).isOptimizedDrawingEnabled())
3249 // First we must check if the new parent itself somehow clips the
3250 // target rectangle. This can happen in JViewports.
3251 Rectangle parRect
= new Rectangle(0, 0, newParent
.getWidth(),
3252 newParent
.getHeight());
3253 Rectangle target
= SwingUtilities
.convertRectangle(found
,
3256 if (target
.contains(parRect
) || target
.intersects(parRect
))
3259 currentClip
= target
;
3264 // Otherwise we must check if one of the children of this parent
3265 // overlaps with the current component.
3266 Component
[] children
= newParent
.getComponents();
3267 // This flag is used to skip components that are 'below' the component
3269 boolean skip
= true;
3270 for (int i
= children
.length
- 1; i
>= 0; i
--)
3272 if (children
[i
] == parent
)
3276 Component c
= children
[i
];
3277 Rectangle compBounds
= c
.getBounds();
3278 // If the component completely overlaps the clip in question, we
3279 // don't need to repaint. Return null.
3280 if (compBounds
.contains(target
))
3282 if (compBounds
.intersects(target
))
3284 // We found a parent whose children overlap with our current
3285 // component. Make this the current component.
3287 currentClip
= target
;
3297 * Finds the nearest component to <code>c</code> (upwards in the containment
3298 * hierarchy), that is opaque. If <code>c</code> itself is opaque,
3299 * this returns <code>c</code> itself.
3301 * @param c the start component for the search
3302 * @return the nearest component to <code>c</code> (upwards in the containment
3303 * hierarchy), that is opaque; If <code>c</code> itself is opaque,
3304 * this returns <code>c</code> itself
3306 private Component
findOpaqueParent(Component c
)
3308 Component found
= c
;
3311 if ((found
instanceof JComponent
) && ((JComponent
) found
).isOpaque())
3313 else if (!(found
instanceof JComponent
))
3315 Container p
= found
.getParent();
3325 * This is the method that gets called when the WHEN_IN_FOCUSED_WINDOW map
3328 * @param changed the JComponent associated with the WHEN_IN_FOCUSED_WINDOW
3331 void updateComponentInputMap(ComponentInputMap changed
)
3333 // Since you can change a component's input map via
3334 // setInputMap, we have to check if <code>changed</code>
3335 // is still in our WHEN_IN_FOCUSED_WINDOW map hierarchy
3336 InputMap curr
= getInputMap(WHEN_IN_FOCUSED_WINDOW
);
3337 while (curr
!= null && curr
!= changed
)
3338 curr
= curr
.getParent();
3340 // If curr is null then changed is not in the hierarchy
3344 // Now we have to update the keyboard manager's hashtable
3345 KeyboardManager km
= KeyboardManager
.getManager();
3347 // This is a poor strategy, should be improved. We currently
3348 // delete all the old bindings for the component and then register
3349 // the current bindings.
3350 km
.clearBindingsForComp(changed
.getComponent());
3351 km
.registerEntireMap((ComponentInputMap
)
3352 getInputMap(WHEN_IN_FOCUSED_WINDOW
));