Merge from mainline
[official-gcc.git] / libjava / classpath / javax / swing / JComponent.java
blob747eba54db4a0e4334766ec63ba7b2f785b8b2c4
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)
9 any later version.
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
19 02110-1301 USA.
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
24 combination.
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. */
39 package javax.swing;
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;
49 import java.awt.Font;
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.geom.Rectangle2D;
68 import java.awt.peer.LightweightPeer;
69 import java.beans.PropertyChangeEvent;
70 import java.beans.PropertyChangeListener;
71 import java.beans.PropertyVetoException;
72 import java.beans.VetoableChangeListener;
73 import java.io.Serializable;
74 import java.util.EventListener;
75 import java.util.Hashtable;
76 import java.util.Locale;
77 import java.util.Set;
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.AccessibleStateSet;
85 import javax.swing.border.Border;
86 import javax.swing.border.CompoundBorder;
87 import javax.swing.border.TitledBorder;
88 import javax.swing.event.AncestorEvent;
89 import javax.swing.event.AncestorListener;
90 import javax.swing.event.EventListenerList;
91 import javax.swing.event.SwingPropertyChangeSupport;
92 import javax.swing.plaf.ComponentUI;
94 /**
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;
107 /**
108 * Accessibility support is currently missing.
110 protected AccessibleContext accessibleContext;
113 * Basic accessibility support for <code>JComponent</code> derived
114 * widgets.
116 public abstract class AccessibleJComponent
117 extends AccessibleAWTContainer
118 implements AccessibleExtendedComponent
121 * Accessibility support for <code>JComponent</code>'s focus handler.
123 protected class AccessibleFocusHandler
124 implements FocusListener
126 protected AccessibleFocusHandler()
128 // TODO: Implement this properly.
130 public void focusGained(FocusEvent event)
132 // TODO: Implement this properly.
134 public void focusLost(FocusEvent valevent)
136 // TODO: Implement this properly.
141 * Accessibility support for <code>JComponent</code>'s container handler.
143 protected class AccessibleContainerHandler
144 implements ContainerListener
146 protected AccessibleContainerHandler()
148 // TODO: Implement this properly.
150 public void componentAdded(ContainerEvent event)
152 // TODO: Implement this properly.
154 public void componentRemoved(ContainerEvent valevent)
156 // TODO: Implement this properly.
160 private static final long serialVersionUID = -7047089700479897799L;
162 protected ContainerListener accessibleContainerHandler;
163 protected FocusListener accessibleFocusHandler;
166 * Manages the property change listeners;
168 private SwingPropertyChangeSupport changeSupport;
170 protected AccessibleJComponent()
172 changeSupport = new SwingPropertyChangeSupport(this);
176 * Adds a property change listener to the list of registered listeners.
178 * @param listener the listener to add
180 public void addPropertyChangeListener(PropertyChangeListener listener)
182 changeSupport.addPropertyChangeListener(listener);
186 * Removes a propery change listener from the list of registered listeners.
188 * @param listener the listener to remove
190 public void removePropertyChangeListener(PropertyChangeListener listener)
192 changeSupport.removePropertyChangeListener(listener);
196 * Returns the number of accessible children of this object.
198 * @return the number of accessible children of this object
200 public int getAccessibleChildrenCount()
202 int count = 0;
203 Component[] children = getComponents();
204 for (int i = 0; i < children.length; ++i)
206 if (children[i] instanceof Accessible)
207 count++;
209 return count;
213 * Returns the accessible child component at index <code>i</code>.
215 * @param i the index of the accessible child to return
217 * @return the accessible child component at index <code>i</code>
219 public Accessible getAccessibleChild(int i)
221 int index = 0;
222 Component[] children = getComponents();
223 Accessible found = null;
224 for (int j = 0; index != i; j++)
226 if (children[j] instanceof Accessible)
227 index++;
228 if (index == i)
229 found = (Accessible) children[index];
231 // TODO: Figure out what to do when i is not a valid index.
232 return found;
236 * Returns the accessible state set of this component.
238 * @return the accessible state set of this component
240 public AccessibleStateSet getAccessibleStateSet()
242 // FIXME: Figure out which states should be set here, and which are
243 // inherited from the super class.
244 return super.getAccessibleStateSet();
248 * Returns the localized name for this object. Generally this should
249 * almost never return {@link Component#getName()} since that is not
250 * a localized name. If the object is some kind of text component (like
251 * a menu item), then the value of the object may be returned. Also, if
252 * the object has a tooltip, the value of the tooltip may also be
253 * appropriate.
255 * @return the localized name for this object or <code>null</code> if this
256 * object has no name
258 public String getAccessibleName()
260 // TODO: Figure out what exactly to return here. It's possible that this
261 // method simply should return null.
262 return null;
266 * Returns the localized description of this object.
268 * @return the localized description of this object or <code>null</code>
269 * if this object has no description
271 public String getAccessibleDescription()
273 // TODO: Figure out what exactly to return here. It's possible that this
274 // method simply should return null.
275 return null;
279 * Returns the accessible role of this component.
281 * @return the accessible role of this component
283 * @see AccessibleRole
285 public AccessibleRole getAccessibleRole()
287 // TODO: Check if this is correct.
288 return AccessibleRole.SWING_COMPONENT;
292 * Recursivly searches a border hierarchy (starting at <code>border) for
293 * a titled border and returns the title if one is found, <code>null</code>
294 * otherwise.
296 * @param border the border to start search from
298 * @return the border title of a possibly found titled border
300 protected String getBorderTitle(Border border)
302 String title = null;
303 if (border instanceof CompoundBorder)
305 CompoundBorder compound = (CompoundBorder) border;
306 Border inner = compound.getInsideBorder();
307 title = getBorderTitle(inner);
308 if (title == null)
310 Border outer = compound.getOutsideBorder();
311 title = getBorderTitle(outer);
314 else if (border instanceof TitledBorder)
316 TitledBorder titled = (TitledBorder) border;
317 title = titled.getTitle();
319 return title;
323 * Returns the tooltip text for this accessible component.
325 * @return the tooltip text for this accessible component
327 public String getToolTipText()
329 return JComponent.this.getToolTipText();
333 * Returns the title of the border of this accessible component if
334 * this component has a titled border, otherwise returns <code>null</code>.
336 * @return the title of the border of this accessible component if
337 * this component has a titled border, otherwise returns
338 * <code>null</code>
340 public String getTitledBorderText()
342 return getBorderTitle(getBorder());
346 * Returns the keybindings associated with this accessible component or
347 * <code>null</code> if the component does not support key bindings.
349 * @return the keybindings associated with this accessible component
351 public AccessibleKeyBinding getAccessibleKeyBinding()
353 // TODO: Implement this properly.
354 return null;
358 /**
359 * An explicit value for the component's preferred size; if not set by a
360 * user, this is calculated on the fly by delegating to the {@link
361 * ComponentUI#getPreferredSize} method on the {@link #ui} property.
363 Dimension preferredSize;
365 /**
366 * An explicit value for the component's minimum size; if not set by a
367 * user, this is calculated on the fly by delegating to the {@link
368 * ComponentUI#getMinimumSize} method on the {@link #ui} property.
370 Dimension minimumSize;
372 /**
373 * An explicit value for the component's maximum size; if not set by a
374 * user, this is calculated on the fly by delegating to the {@link
375 * ComponentUI#getMaximumSize} method on the {@link #ui} property.
377 Dimension maximumSize;
380 * A value between 0.0 and 1.0 indicating the preferred horizontal
381 * alignment of the component, relative to its siblings. The values
382 * {@link #LEFT_ALIGNMENT}, {@link #CENTER_ALIGNMENT}, and {@link
383 * #RIGHT_ALIGNMENT} can also be used, as synonyms for <code>0.0</code>,
384 * <code>0.5</code>, and <code>1.0</code>, respectively. Not all layout
385 * managers use this property.
387 * @see #getAlignmentX
388 * @see #setAlignmentX
389 * @see javax.swing.OverlayLayout
390 * @see javax.swing.BoxLayout
392 float alignmentX = -1.0F;
395 * A value between 0.0 and 1.0 indicating the preferred vertical
396 * alignment of the component, relative to its siblings. The values
397 * {@link #TOP_ALIGNMENT}, {@link #CENTER_ALIGNMENT}, and {@link
398 * #BOTTOM_ALIGNMENT} can also be used, as synonyms for <code>0.0</code>,
399 * <code>0.5</code>, and <code>1.0</code>, respectively. Not all layout
400 * managers use this property.
402 * @see #getAlignmentY
403 * @see #setAlignmentY
404 * @see javax.swing.OverlayLayout
405 * @see javax.swing.BoxLayout
407 float alignmentY = -1.0F;
409 /**
410 * The border painted around this component.
412 * @see #paintBorder
414 Border border;
416 /**
417 * The text to show in the tooltip associated with this component.
419 * @see #setToolTipText
420 * @see #getToolTipText()
422 String toolTipText;
424 /**
425 * <p>Whether to double buffer this component when painting. This flag
426 * should generally be <code>true</code>, to ensure good painting
427 * performance.</p>
429 * <p>All children of a double buffered component are painted into the
430 * double buffer automatically, so only the top widget in a window needs
431 * to be double buffered.</p>
433 * @see #setDoubleBuffered
434 * @see #isDoubleBuffered
435 * @see #paint
437 boolean doubleBuffered = true;
440 * A set of flags indicating which debugging graphics facilities should
441 * be enabled on this component. The values should be a combination of
442 * {@link DebugGraphics#NONE_OPTION}, {@link DebugGraphics#LOG_OPTION},
443 * {@link DebugGraphics#FLASH_OPTION}, or {@link
444 * DebugGraphics#BUFFERED_OPTION}.
446 * @see #setDebugGraphicsOptions
447 * @see #getDebugGraphicsOptions
448 * @see DebugGraphics
449 * @see #getComponentGraphics
451 int debugGraphicsOptions;
453 /**
454 * <p>This property controls two independent behaviors simultaneously.</p>
456 * <p>First, it controls whether to fill the background of this widget
457 * when painting its body. This affects calls to {@link
458 * JComponent#paintComponent}, which in turn calls {@link
459 * ComponentUI#update} on the component's {@link #ui} property. If the
460 * component is opaque during this call, the background will be filled
461 * before calling {@link ComponentUI#paint}. This happens merely as a
462 * convenience; you may fill the component's background yourself too,
463 * but there is no need to do so if you will be filling with the same
464 * color.</p>
466 * <p>Second, it the opaque property informs swing's repaint system
467 * whether it will be necessary to paint the components "underneath" this
468 * component, in Z-order. If the component is opaque, it is considered to
469 * completely occlude components "underneath" it, so they will not be
470 * repainted along with the opaque component.</p>
472 * <p>The default value for this property is <code>false</code>, but most
473 * components will want to set it to <code>true</code> when installing UI
474 * defaults in {@link ComponentUI#installUI}.</p>
476 * @see #setOpaque
477 * @see #isOpaque
478 * @see #paintComponent
480 boolean opaque = false;
482 /**
483 * The user interface delegate for this component. Event delivery and
484 * repainting of the component are usually delegated to this object.
486 * @see #setUI
487 * @see #getUIClassID
488 * @see #updateUI
490 protected ComponentUI ui;
493 * A hint to the focus system that this component should or should not
494 * get focus. If this is <code>false</code>, swing will not try to
495 * request focus on this component; if <code>true</code>, swing might
496 * try to request focus, but the request might fail. Thus it is only
497 * a hint guiding swing's behavior.
499 * @see #requestFocus()
500 * @see #isRequestFocusEnabled
501 * @see #setRequestFocusEnabled
503 boolean requestFocusEnabled;
506 * Flag indicating behavior of this component when the mouse is dragged
507 * outside the component and the mouse <em>stops moving</em>. If
508 * <code>true</code>, synthetic mouse events will be delivered on regular
509 * timed intervals, continuing off in the direction the mouse exited the
510 * component, until the mouse is released or re-enters the component.
512 * @see #setAutoscrolls
513 * @see #getAutoscrolls
515 boolean autoscrolls = false;
518 * Indicates whether the current paint call is already double buffered or
519 * not.
521 static boolean isPaintingDoubleBuffered = false;
524 * Listeners for events other than {@link PropertyChangeEvent} are
525 * handled by this listener list. PropertyChangeEvents are handled in
526 * {@link #changeSupport}.
528 protected EventListenerList listenerList = new EventListenerList();
530 /**
531 * Support for {@link PropertyChangeEvent} events. This is constructed
532 * lazily when the component gets its first {@link
533 * PropertyChangeListener} subscription; until then it's an empty slot.
535 private SwingPropertyChangeSupport changeSupport;
538 /**
539 * Storage for "client properties", which are key/value pairs associated
540 * with this component by a "client", such as a user application or a
541 * layout manager. This is lazily constructed when the component gets its
542 * first client property.
544 private Hashtable clientProperties;
546 private InputMap inputMap_whenFocused;
547 private InputMap inputMap_whenAncestorOfFocused;
548 private ComponentInputMap inputMap_whenInFocusedWindow;
549 private ActionMap actionMap;
550 /** @since 1.3 */
551 private boolean verifyInputWhenFocusTarget;
552 private InputVerifier inputVerifier;
554 private TransferHandler transferHandler;
557 * Indicates if this component is currently painting a tile or not.
559 private boolean paintingTile;
562 * A cached Rectangle object to be reused. Be careful when you use that,
563 * so that it doesn't get modified in another context within the same
564 * method call chain.
566 private static transient Rectangle rectCache;
569 * The default locale of the component.
571 * @see #getDefaultLocale
572 * @see #setDefaultLocale
574 private static Locale defaultLocale;
576 public static final String TOOL_TIP_TEXT_KEY = "ToolTipText";
579 * Constant used to indicate that no condition has been assigned to a
580 * particular action.
582 * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
584 public static final int UNDEFINED_CONDITION = -1;
587 * Constant used to indicate that an action should be performed only when
588 * the component has focus.
590 * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
592 public static final int WHEN_FOCUSED = 0;
595 * Constant used to indicate that an action should be performed only when
596 * the component is an ancestor of the component which has focus.
598 * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
600 public static final int WHEN_ANCESTOR_OF_FOCUSED_COMPONENT = 1;
603 * Constant used to indicate that an action should be performed only when
604 * the component is in the window which has focus.
606 * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
608 public static final int WHEN_IN_FOCUSED_WINDOW = 2;
611 * Indicates if this component is completely dirty or not. This is used
612 * by the RepaintManager's
613 * {@link RepaintManager#isCompletelyDirty(JComponent)} method.
615 boolean isCompletelyDirty = false;
618 * Creates a new <code>JComponent</code> instance.
620 public JComponent()
622 super();
623 setDropTarget(new DropTarget());
624 defaultLocale = Locale.getDefault();
625 debugGraphicsOptions = DebugGraphics.NONE_OPTION;
626 setRequestFocusEnabled(true);
630 * Helper to lazily construct and return the client properties table.
632 * @return The current client properties table
634 * @see #clientProperties
635 * @see #getClientProperty
636 * @see #putClientProperty
638 private Hashtable getClientProperties()
640 if (clientProperties == null)
641 clientProperties = new Hashtable();
642 return clientProperties;
646 * Get a client property associated with this component and a particular
647 * key.
649 * @param key The key with which to look up the client property
651 * @return A client property associated with this object and key
653 * @see #clientProperties
654 * @see #getClientProperties
655 * @see #putClientProperty
657 public final Object getClientProperty(Object key)
659 return getClientProperties().get(key);
663 * Add a client property <code>value</code> to this component, associated
664 * with <code>key</code>. If there is an existing client property
665 * associated with <code>key</code>, it will be replaced. A
666 * {@link PropertyChangeEvent} is sent to registered listeners (with the
667 * name of the property being <code>key.toString()</code>).
669 * @param key The key of the client property association to add
670 * @param value The value of the client property association to add
672 * @see #clientProperties
673 * @see #getClientProperties
674 * @see #getClientProperty
676 public final void putClientProperty(Object key, Object value)
678 Hashtable t = getClientProperties();
679 Object old = t.get(key);
680 if (value != null)
681 t.put(key, value);
682 else
683 t.remove(key);
684 firePropertyChange(key.toString(), old, value);
688 * Unregister an <code>AncestorListener</code>.
690 * @param listener The listener to unregister
692 * @see #addAncestorListener
694 public void removeAncestorListener(AncestorListener listener)
696 listenerList.remove(AncestorListener.class, listener);
700 * Unregister a <code>PropertyChangeListener</code>.
702 * @param listener The listener to register
704 * @see #addPropertyChangeListener(PropertyChangeListener)
705 * @see #changeSupport
707 public void removePropertyChangeListener(PropertyChangeListener listener)
709 if (changeSupport != null)
710 changeSupport.removePropertyChangeListener(listener);
714 * Unregister a <code>PropertyChangeListener</code>.
716 * @param propertyName The property name to unregister the listener from
717 * @param listener The listener to unregister
719 * @see #addPropertyChangeListener(String, PropertyChangeListener)
720 * @see #changeSupport
722 public void removePropertyChangeListener(String propertyName,
723 PropertyChangeListener listener)
725 if (changeSupport != null)
726 changeSupport.removePropertyChangeListener(propertyName, listener);
730 * Unregister a <code>VetoableChangeChangeListener</code>.
732 * @param listener The listener to unregister
734 * @see #addVetoableChangeListener
736 public void removeVetoableChangeListener(VetoableChangeListener listener)
738 listenerList.remove(VetoableChangeListener.class, listener);
742 * Register an <code>AncestorListener</code>.
744 * @param listener The listener to register
746 * @see #removeVetoableChangeListener
748 public void addAncestorListener(AncestorListener listener)
750 listenerList.add(AncestorListener.class, listener);
754 * Register a <code>PropertyChangeListener</code>. This listener will
755 * receive any PropertyChangeEvent, regardless of property name. To
756 * listen to a specific property name, use {@link
757 * #addPropertyChangeListener(String,PropertyChangeListener)} instead.
759 * @param listener The listener to register
761 * @see #removePropertyChangeListener(PropertyChangeListener)
762 * @see #changeSupport
764 public void addPropertyChangeListener(PropertyChangeListener listener)
766 if (changeSupport == null)
767 changeSupport = new SwingPropertyChangeSupport(this);
768 changeSupport.addPropertyChangeListener(listener);
772 * Register a <code>PropertyChangeListener</code> for a specific, named
773 * property. To listen to all property changes, regardless of name, use
774 * {@link #addPropertyChangeListener(PropertyChangeListener)} instead.
776 * @param propertyName The property name to listen to
777 * @param listener The listener to register
779 * @see #removePropertyChangeListener(String, PropertyChangeListener)
780 * @see #changeSupport
782 public void addPropertyChangeListener(String propertyName,
783 PropertyChangeListener listener)
785 listenerList.add(PropertyChangeListener.class, listener);
789 * Register a <code>VetoableChangeListener</code>.
791 * @param listener The listener to register
793 * @see #removeVetoableChangeListener
794 * @see #listenerList
796 public void addVetoableChangeListener(VetoableChangeListener listener)
798 listenerList.add(VetoableChangeListener.class, listener);
802 * Returns all registered {@link EventListener}s of the given
803 * <code>listenerType</code>.
805 * @param listenerType the class of listeners to filter (<code>null</code>
806 * not permitted).
808 * @return An array of registered listeners.
810 * @throws ClassCastException if <code>listenerType</code> does not implement
811 * the {@link EventListener} interface.
812 * @throws NullPointerException if <code>listenerType</code> is
813 * <code>null</code>.
815 * @see #getAncestorListeners()
816 * @see #listenerList
818 * @since 1.3
820 public EventListener[] getListeners(Class listenerType)
822 return listenerList.getListeners(listenerType);
826 * Return all registered <code>AncestorListener</code> objects.
828 * @return The set of <code>AncestorListener</code> objects in {@link
829 * #listenerList}
831 public AncestorListener[] getAncestorListeners()
833 return (AncestorListener[]) getListeners(AncestorListener.class);
837 * Return all registered <code>VetoableChangeListener</code> objects.
839 * @return The set of <code>VetoableChangeListener</code> objects in {@link
840 * #listenerList}
842 public VetoableChangeListener[] getVetoableChangeListeners()
844 return (VetoableChangeListener[]) getListeners(VetoableChangeListener.class);
848 * Return all <code>PropertyChangeListener</code> objects registered to listen
849 * for a particular property.
851 * @param property The property to return the listeners of
853 * @return The set of <code>PropertyChangeListener</code> objects in
854 * {@link #changeSupport} registered to listen on the specified property
856 public PropertyChangeListener[] getPropertyChangeListeners(String property)
858 return changeSupport == null ? new PropertyChangeListener[0]
859 : changeSupport.getPropertyChangeListeners(property);
863 * A variant of {@link #firePropertyChange(String,Object,Object)}
864 * for properties with <code>boolean</code> values.
866 public void firePropertyChange(String propertyName, boolean oldValue,
867 boolean newValue)
869 if (changeSupport != null)
870 changeSupport.firePropertyChange(propertyName, Boolean.valueOf(oldValue),
871 Boolean.valueOf(newValue));
875 * A variant of {@link #firePropertyChange(String,Object,Object)}
876 * for properties with <code>byte</code> values.
878 public void firePropertyChange(String propertyName, byte oldValue,
879 byte newValue)
881 if (changeSupport != null)
882 changeSupport.firePropertyChange(propertyName, new Byte(oldValue),
883 new Byte(newValue));
887 * A variant of {@link #firePropertyChange(String,Object,Object)}
888 * for properties with <code>char</code> values.
890 public void firePropertyChange(String propertyName, char oldValue,
891 char newValue)
893 if (changeSupport != null)
894 changeSupport.firePropertyChange(propertyName, new Character(oldValue),
895 new Character(newValue));
899 * A variant of {@link #firePropertyChange(String,Object,Object)}
900 * for properties with <code>double</code> values.
902 public void firePropertyChange(String propertyName, double oldValue,
903 double newValue)
905 if (changeSupport != null)
906 changeSupport.firePropertyChange(propertyName, new Double(oldValue),
907 new Double(newValue));
911 * A variant of {@link #firePropertyChange(String,Object,Object)}
912 * for properties with <code>float</code> values.
914 public void firePropertyChange(String propertyName, float oldValue,
915 float newValue)
917 if (changeSupport != null)
918 changeSupport.firePropertyChange(propertyName, new Float(oldValue),
919 new Float(newValue));
923 * A variant of {@link #firePropertyChange(String,Object,Object)}
924 * for properties with <code>int</code> values.
926 public void firePropertyChange(String propertyName, int oldValue,
927 int newValue)
929 if (changeSupport != null)
930 changeSupport.firePropertyChange(propertyName, new Integer(oldValue),
931 new Integer(newValue));
935 * A variant of {@link #firePropertyChange(String,Object,Object)}
936 * for properties with <code>long</code> values.
938 public void firePropertyChange(String propertyName, long oldValue,
939 long newValue)
941 if (changeSupport != null)
942 changeSupport.firePropertyChange(propertyName, new Long(oldValue),
943 new Long(newValue));
947 * Call {@link PropertyChangeListener#propertyChange} on all listeners
948 * registered to listen to a given property. Any method which changes
949 * the specified property of this component should call this method.
951 * @param propertyName The property which changed
952 * @param oldValue The old value of the property
953 * @param newValue The new value of the property
955 * @see #changeSupport
956 * @see #addPropertyChangeListener(PropertyChangeListener)
957 * @see #removePropertyChangeListener(PropertyChangeListener)
959 protected void firePropertyChange(String propertyName, Object oldValue,
960 Object newValue)
962 if (changeSupport != null)
963 changeSupport.firePropertyChange(propertyName, oldValue, newValue);
967 * A variant of {@link #firePropertyChange(String,Object,Object)}
968 * for properties with <code>short</code> values.
970 public void firePropertyChange(String propertyName, short oldValue,
971 short newValue)
973 if (changeSupport != null)
974 changeSupport.firePropertyChange(propertyName, new Short(oldValue),
975 new Short(newValue));
979 * Call {@link VetoableChangeListener#vetoableChange} on all listeners
980 * registered to listen to a given property. Any method which changes
981 * the specified property of this component should call this method.
983 * @param propertyName The property which changed
984 * @param oldValue The old value of the property
985 * @param newValue The new value of the property
987 * @throws PropertyVetoException if the change was vetoed by a listener
989 * @see #addVetoableChangeListener
990 * @see #removeVetoableChangeListener
992 protected void fireVetoableChange(String propertyName, Object oldValue,
993 Object newValue)
994 throws PropertyVetoException
996 VetoableChangeListener[] listeners = getVetoableChangeListeners();
998 PropertyChangeEvent evt =
999 new PropertyChangeEvent(this, propertyName, oldValue, newValue);
1001 for (int i = 0; i < listeners.length; i++)
1002 listeners[i].vetoableChange(evt);
1006 * Get the value of the accessibleContext property for this component.
1008 * @return the current value of the property
1010 public AccessibleContext getAccessibleContext()
1012 return null;
1016 * Get the value of the {@link #alignmentX} property.
1018 * @return The current value of the property.
1020 * @see #setAlignmentX
1021 * @see #alignmentY
1023 public float getAlignmentX()
1025 float ret = alignmentX;
1026 if (alignmentX < 0)
1027 // alignment has not been set explicitly.
1028 ret = super.getAlignmentX();
1030 return ret;
1034 * Get the value of the {@link #alignmentY} property.
1036 * @return The current value of the property.
1038 * @see #setAlignmentY
1039 * @see #alignmentX
1041 public float getAlignmentY()
1043 float ret = alignmentY;
1044 if (alignmentY < 0)
1045 // alignment has not been set explicitly.
1046 ret = super.getAlignmentY();
1048 return ret;
1052 * Get the current value of the {@link #autoscrolls} property.
1054 * @return The current value of the property
1056 public boolean getAutoscrolls()
1058 return autoscrolls;
1062 * Set the value of the {@link #border} property.
1064 * @param newBorder The new value of the property
1066 * @see #getBorder
1068 public void setBorder(Border newBorder)
1070 Border oldBorder = getBorder();
1071 if (oldBorder == newBorder)
1072 return;
1074 border = newBorder;
1075 firePropertyChange("border", oldBorder, newBorder);
1076 repaint();
1080 * Get the value of the {@link #border} property.
1082 * @return The property's current value
1084 * @see #setBorder
1086 public Border getBorder()
1088 return border;
1092 * Get the component's current bounding box. If a rectangle is provided,
1093 * use this as the return value (adjusting its fields in place);
1094 * otherwise (of <code>null</code> is provided) return a new {@link
1095 * Rectangle}.
1097 * @param rv Optional return value to use
1099 * @return A rectangle bounding the component
1101 public Rectangle getBounds(Rectangle rv)
1103 if (rv == null)
1104 return new Rectangle(getX(), getY(), getWidth(), getHeight());
1105 else
1107 rv.setBounds(getX(), getY(), getWidth(), getHeight());
1108 return rv;
1113 * Prepares a graphics context for painting this object. If {@link
1114 * #debugGraphicsOptions} is not equal to {@link
1115 * DebugGraphics#NONE_OPTION}, produce a new {@link DebugGraphics} object
1116 * wrapping the parameter. Otherwise configure the parameter with this
1117 * component's foreground color and font.
1119 * @param g The graphics context to wrap or configure
1121 * @return A graphics context to paint this object with
1123 * @see #debugGraphicsOptions
1124 * @see #paint
1126 protected Graphics getComponentGraphics(Graphics g)
1128 Graphics g2 = g;
1129 int options = getDebugGraphicsOptions();
1130 if (options != DebugGraphics.NONE_OPTION)
1132 if (!(g2 instanceof DebugGraphics))
1133 g2 = new DebugGraphics(g);
1134 DebugGraphics dg = (DebugGraphics) g2;
1135 dg.setDebugOptions(dg.getDebugOptions() | options);
1137 g2.setFont(this.getFont());
1138 g2.setColor(this.getForeground());
1139 return g2;
1143 * Get the value of the {@link #debugGraphicsOptions} property.
1145 * @return The current value of the property.
1147 * @see #setDebugGraphicsOptions
1148 * @see #debugGraphicsOptions
1150 public int getDebugGraphicsOptions()
1152 String option = System.getProperty("gnu.javax.swing.DebugGraphics");
1153 int options = debugGraphicsOptions;
1154 if (option != null && option.length() != 0)
1156 if (options < 0)
1157 options = 0;
1159 if (option.equals("LOG"))
1160 options |= DebugGraphics.LOG_OPTION;
1161 else if (option.equals("FLASH"))
1162 options |= DebugGraphics.FLASH_OPTION;
1164 return options;
1168 * Get the component's insets, which are calculated from
1169 * the {@link #border} property. If the border is <code>null</code>,
1170 * calls {@link Container#getInsets}.
1172 * @return The component's current insets
1174 public Insets getInsets()
1176 if (border == null)
1177 return super.getInsets();
1178 return getBorder().getBorderInsets(this);
1182 * Get the component's insets, which are calculated from the {@link
1183 * #border} property. If the border is <code>null</code>, calls {@link
1184 * Container#getInsets}. The passed-in {@link Insets} value will be
1185 * used as the return value, if possible.
1187 * @param insets Return value object to reuse, if possible
1189 * @return The component's current insets
1191 public Insets getInsets(Insets insets)
1193 Insets t = getInsets();
1195 if (insets == null)
1196 return t;
1198 insets.left = t.left;
1199 insets.right = t.right;
1200 insets.top = t.top;
1201 insets.bottom = t.bottom;
1202 return insets;
1206 * Get the component's location. The passed-in {@link Point} value
1207 * will be used as the return value, if possible.
1209 * @param rv Return value object to reuse, if possible
1211 * @return The component's current location
1213 public Point getLocation(Point rv)
1215 if (rv == null)
1216 return new Point(getX(), getY());
1218 rv.setLocation(getX(), getY());
1219 return rv;
1223 * Get the component's maximum size. If the {@link #maximumSize} property
1224 * has been explicitly set, it is returned. If the {@link #maximumSize}
1225 * property has not been set but the {@link #ui} property has been, the
1226 * result of {@link ComponentUI#getMaximumSize} is returned. If neither
1227 * property has been set, the result of {@link Container#getMaximumSize}
1228 * is returned.
1230 * @return The maximum size of the component
1232 * @see #maximumSize
1233 * @see #setMaximumSize
1235 public Dimension getMaximumSize()
1237 if (maximumSize != null)
1238 return maximumSize;
1240 if (ui != null)
1242 Dimension s = ui.getMaximumSize(this);
1243 if (s != null)
1244 return s;
1247 Dimension p = super.getMaximumSize();
1248 return p;
1252 * Get the component's minimum size. If the {@link #minimumSize} property
1253 * has been explicitly set, it is returned. If the {@link #minimumSize}
1254 * property has not been set but the {@link #ui} property has been, the
1255 * result of {@link ComponentUI#getMinimumSize} is returned. If neither
1256 * property has been set, the result of {@link Container#getMinimumSize}
1257 * is returned.
1259 * @return The minimum size of the component
1261 * @see #minimumSize
1262 * @see #setMinimumSize
1264 public Dimension getMinimumSize()
1266 if (minimumSize != null)
1267 return minimumSize;
1269 if (ui != null)
1271 Dimension s = ui.getMinimumSize(this);
1272 if (s != null)
1273 return s;
1276 Dimension p = super.getMinimumSize();
1277 return p;
1281 * Get the component's preferred size. If the {@link #preferredSize}
1282 * property has been explicitly set, it is returned. If the {@link
1283 * #preferredSize} property has not been set but the {@link #ui} property
1284 * has been, the result of {@link ComponentUI#getPreferredSize} is
1285 * returned. If neither property has been set, the result of {@link
1286 * Container#getPreferredSize} is returned.
1288 * @return The preferred size of the component
1290 * @see #preferredSize
1291 * @see #setPreferredSize
1293 public Dimension getPreferredSize()
1295 Dimension prefSize = null;
1296 if (preferredSize != null)
1297 prefSize = new Dimension(preferredSize);
1299 else if (ui != null)
1301 Dimension s = ui.getPreferredSize(this);
1302 if (s != null)
1303 prefSize = s;
1306 if (prefSize == null)
1307 prefSize = super.getPreferredSize();
1309 return prefSize;
1313 * Checks if a maximum size was explicitely set on the component.
1315 * @return <code>true</code> if a maximum size was set,
1316 * <code>false</code> otherwise
1318 * @since 1.3
1320 public boolean isMaximumSizeSet()
1322 return maximumSize != null;
1326 * Checks if a minimum size was explicitely set on the component.
1328 * @return <code>true</code> if a minimum size was set,
1329 * <code>false</code> otherwise
1331 * @since 1.3
1333 public boolean isMinimumSizeSet()
1335 return minimumSize != null;
1339 * Checks if a preferred size was explicitely set on the component.
1341 * @return <code>true</code> if a preferred size was set,
1342 * <code>false</code> otherwise
1344 * @since 1.3
1346 public boolean isPreferredSizeSet()
1348 return preferredSize != null;
1352 * Return the value of the <code>nextFocusableComponent</code> property.
1354 * @return The current value of the property, or <code>null</code>
1355 * if none has been set.
1357 * @deprecated See {@link java.awt.FocusTraversalPolicy}
1359 public Component getNextFocusableComponent()
1361 return null;
1365 * Return the set of {@link KeyStroke} objects which are registered
1366 * to initiate actions on this component.
1368 * @return An array of the registered keystrokes
1370 public KeyStroke[] getRegisteredKeyStrokes()
1372 return null;
1376 * Returns the first ancestor of this component which is a {@link JRootPane}.
1377 * Equivalent to calling <code>SwingUtilities.getRootPane(this);</code>.
1379 * @return An ancestral JRootPane, or <code>null</code> if none exists.
1381 public JRootPane getRootPane()
1383 JRootPane p = SwingUtilities.getRootPane(this);
1384 return p;
1388 * Get the component's size. The passed-in {@link Dimension} value
1389 * will be used as the return value, if possible.
1391 * @param rv Return value object to reuse, if possible
1393 * @return The component's current size
1395 public Dimension getSize(Dimension rv)
1397 if (rv == null)
1398 return new Dimension(getWidth(), getHeight());
1399 else
1401 rv.setSize(getWidth(), getHeight());
1402 return rv;
1407 * Return the <code>toolTip</code> property of this component, creating it and
1408 * setting it if it is currently <code>null</code>. This method can be
1409 * overridden in subclasses which wish to control the exact form of
1410 * tooltip created.
1412 * @return The current toolTip
1414 public JToolTip createToolTip()
1416 JToolTip toolTip = new JToolTip();
1417 toolTip.setComponent(this);
1418 toolTip.setTipText(toolTipText);
1420 return toolTip;
1424 * Return the location at which the {@link #toolTipText} property should be
1425 * displayed, when triggered by a particular mouse event.
1427 * @param event The event the tooltip is being presented in response to
1429 * @return The point at which to display a tooltip, or <code>null</code>
1430 * if swing is to choose a default location.
1432 public Point getToolTipLocation(MouseEvent event)
1434 return null;
1438 * Set the value of the {@link #toolTipText} property.
1440 * @param text The new property value
1442 * @see #getToolTipText()
1444 public void setToolTipText(String text)
1446 if (text == null)
1448 ToolTipManager.sharedInstance().unregisterComponent(this);
1449 toolTipText = null;
1450 return;
1453 // XXX: The tip text doesn't get updated unless you set it to null
1454 // and then to something not-null. This is consistent with the behaviour
1455 // of Sun's ToolTipManager.
1457 String oldText = toolTipText;
1458 toolTipText = text;
1460 if (oldText == null)
1461 ToolTipManager.sharedInstance().registerComponent(this);
1465 * Get the value of the {@link #toolTipText} property.
1467 * @return The current property value
1469 * @see #setToolTipText
1471 public String getToolTipText()
1473 return toolTipText;
1477 * Get the value of the {@link #toolTipText} property, in response to a
1478 * particular mouse event.
1480 * @param event The mouse event which triggered the tooltip
1482 * @return The current property value
1484 * @see #setToolTipText
1486 public String getToolTipText(MouseEvent event)
1488 return getToolTipText();
1492 * Return the top level ancestral container (usually a {@link
1493 * java.awt.Window} or {@link java.applet.Applet}) which this component is
1494 * contained within, or <code>null</code> if no ancestors exist.
1496 * @return The top level container, if it exists
1498 public Container getTopLevelAncestor()
1500 Container c = getParent();
1501 for (Container peek = c; peek != null; peek = peek.getParent())
1502 c = peek;
1503 return c;
1507 * Compute the component's visible rectangle, which is defined
1508 * recursively as either the component's bounds, if it has no parent, or
1509 * the intersection of the component's bounds with the visible rectangle
1510 * of its parent.
1512 * @param rect The return value slot to place the visible rectangle in
1514 public void computeVisibleRect(Rectangle rect)
1516 Component c = getParent();
1517 if (c != null && c instanceof JComponent)
1519 ((JComponent) c).computeVisibleRect(rect);
1520 rect.translate(-getX(), -getY());
1521 Rectangle2D.intersect(rect,
1522 new Rectangle(0, 0, getWidth(), getHeight()),
1523 rect);
1525 else
1526 rect.setRect(0, 0, getWidth(), getHeight());
1530 * Return the component's visible rectangle in a new {@link Rectangle},
1531 * rather than via a return slot.
1533 * @return The component's visible rectangle
1535 * @see #computeVisibleRect(Rectangle)
1537 public Rectangle getVisibleRect()
1539 Rectangle r = new Rectangle();
1540 computeVisibleRect(r);
1541 return r;
1545 * <p>Requests that this component receive input focus, giving window
1546 * focus to the top level ancestor of this component. Only works on
1547 * displayable, focusable, visible components.</p>
1549 * <p>This method should not be called by clients; it is intended for
1550 * focus implementations. Use {@link Component#requestFocus()} instead.</p>
1552 * @see Component#requestFocus()
1554 public void grabFocus()
1556 // TODO: Implement this properly.
1560 * Get the value of the {@link #doubleBuffered} property.
1562 * @return The property's current value
1564 public boolean isDoubleBuffered()
1566 return doubleBuffered;
1570 * Return <code>true</code> if the provided component has no native peer;
1571 * in other words, if it is a "lightweight component".
1573 * @param c The component to test for lightweight-ness
1575 * @return Whether or not the component is lightweight
1577 public static boolean isLightweightComponent(Component c)
1579 return c.getPeer() instanceof LightweightPeer;
1583 * Return <code>true</code> if you wish this component to manage its own
1584 * focus. In particular: if you want this component to be sent
1585 * <code>TAB</code> and <code>SHIFT+TAB</code> key events, and to not
1586 * have its children considered as focus transfer targets. If
1587 * <code>true</code>, focus traversal around this component changes to
1588 * <code>CTRL+TAB</code> and <code>CTRL+SHIFT+TAB</code>.
1590 * @return <code>true</code> if you want this component to manage its own
1591 * focus, otherwise (by default) <code>false</code>
1593 * @deprecated 1.4 Use {@link Component#setFocusTraversalKeys(int, Set)} and
1594 * {@link Container#setFocusCycleRoot(boolean)} instead
1596 public boolean isManagingFocus()
1598 return false;
1602 * Return the current value of the {@link #opaque} property.
1604 * @return The current property value
1606 public boolean isOpaque()
1608 return opaque;
1612 * Return <code>true</code> if the component can guarantee that none of its
1613 * children will overlap in Z-order. This is a hint to the painting system.
1614 * The default is to return <code>true</code>, but some components such as
1615 * {@link JLayeredPane} should override this to return <code>false</code>.
1617 * @return Whether the component tiles its children
1619 public boolean isOptimizedDrawingEnabled()
1621 return true;
1625 * Return <code>true</code> if this component is currently painting a tile,
1626 * this means that paint() is called again on another child component. This
1627 * method returns <code>false</code> if this component does not paint a tile
1628 * or if the last tile is currently painted.
1630 * @return whether the component is painting a tile
1632 public boolean isPaintingTile()
1634 return paintingTile;
1638 * Get the value of the {@link #requestFocusEnabled} property.
1640 * @return The current value of the property
1642 public boolean isRequestFocusEnabled()
1644 return requestFocusEnabled;
1648 * Return <code>true</code> if this component is a validation root; this
1649 * will cause calls to {@link #invalidate()} in this component's children
1650 * to be "captured" at this component, and not propagate to its parents.
1651 * For most components this should return <code>false</code>, but some
1652 * components such as {@link JViewport} will want to return
1653 * <code>true</code>.
1655 * @return Whether this component is a validation root
1657 public boolean isValidateRoot()
1659 return false;
1663 * <p>Paint the component. This is a delicate process, and should only be
1664 * called from the repaint thread, under control of the {@link
1665 * RepaintManager}. Client code should usually call {@link #repaint()} to
1666 * trigger painting.</p>
1668 * <p>The body of the <code>paint</code> call involves calling {@link
1669 * #paintComponent}, {@link #paintBorder}, and {@link #paintChildren} in
1670 * order. If you want to customize painting behavior, you should override
1671 * one of these methods rather than <code>paint</code>.</p>
1673 * <p>For more details on the painting sequence, see <a
1674 * href="http://java.sun.com/products/jfc/tsc/articles/painting/index.html">
1675 * this article</a>.</p>
1677 * @param g The graphics context to paint with
1679 * @see #paintImmediately(Rectangle)
1681 public void paint(Graphics g)
1683 RepaintManager rm = RepaintManager.currentManager(this);
1684 // We do a little stunt act here to switch on double buffering if it's
1685 // not already on. If we are not already doublebuffered, then we jump
1686 // into the method paintDoubleBuffered, which turns on the double buffer
1687 // and then calls paint(g) again. In the second call we go into the else
1688 // branch of this if statement and actually paint things to the double
1689 // buffer. When this method completes, the call stack unwinds back to
1690 // paintDoubleBuffered, where the buffer contents is finally drawn to the
1691 // screen.
1692 if (!isPaintingDoubleBuffered && isDoubleBuffered()
1693 && rm.isDoubleBufferingEnabled())
1694 paintDoubleBuffered(g);
1695 else
1697 if (g.getClip() == null)
1698 g.setClip(0, 0, getWidth(), getHeight());
1699 Graphics g2 = getComponentGraphics(g);
1700 paintComponent(g2);
1701 paintBorder(g2);
1702 paintChildren(g2);
1703 Rectangle clip = g2.getClipBounds();
1704 if (clip.x == 0 && clip.y == 0 && clip.width == getWidth()
1705 && clip.height == getHeight())
1706 RepaintManager.currentManager(this).markCompletelyClean(this);
1711 * Paint the component's border. This usually means calling {@link
1712 * Border#paintBorder} on the {@link #border} property, if it is
1713 * non-<code>null</code>. You may override this if you wish to customize
1714 * border painting behavior. The border is painted after the component's
1715 * body, but before the component's children.
1717 * @param g The graphics context with which to paint the border
1719 * @see #paint
1720 * @see #paintChildren
1721 * @see #paintComponent
1723 protected void paintBorder(Graphics g)
1725 if (getBorder() != null)
1726 getBorder().paintBorder(this, g, 0, 0, getWidth(), getHeight());
1730 * Paint the component's children. This usually means calling {@link
1731 * Container#paint}, which recursively calls {@link #paint} on any of the
1732 * component's children, with appropriate changes to coordinate space and
1733 * clipping region. You may override this if you wish to customize
1734 * children painting behavior. The children are painted after the
1735 * component's body and border.
1737 * @param g The graphics context with which to paint the children
1739 * @see #paint
1740 * @see #paintBorder
1741 * @see #paintComponent
1743 protected void paintChildren(Graphics g)
1745 Shape originalClip = g.getClip();
1746 Rectangle inner = SwingUtilities.calculateInnerArea(this, rectCache);
1747 g.clipRect(inner.x, inner.y, inner.width, inner.height);
1748 Component[] children = getComponents();
1750 // Find the bottommost component that needs to be painted. This is a
1751 // component that completely covers the current clip and is opaque. In
1752 // this case we don't need to paint the components below it.
1753 int startIndex = children.length - 1;
1754 // No need to check for overlapping components when this component is
1755 // optimizedDrawingEnabled (== it tiles its children).
1756 if (! isOptimizedDrawingEnabled())
1758 Rectangle clip = g.getClipBounds();
1759 for (int i = 0; i < children.length; i++)
1761 Rectangle childBounds = children[i].getBounds();
1762 if (children[i].isOpaque()
1763 && SwingUtilities.isRectangleContainingRectangle(childBounds,
1764 g.getClipBounds()))
1766 startIndex = i;
1767 break;
1771 // paintingTile becomes true just before we start painting the component's
1772 // children.
1773 paintingTile = true;
1774 for (int i = startIndex; i >= 0; --i)
1776 // paintingTile must be set to false before we begin to start painting
1777 // the last tile.
1778 if (i == 0)
1779 paintingTile = false;
1781 if (!children[i].isVisible())
1782 continue;
1784 Rectangle bounds = children[i].getBounds(rectCache);
1785 Rectangle oldClip = g.getClipBounds();
1786 if (oldClip == null)
1787 oldClip = bounds;
1789 if (!g.hitClip(bounds.x, bounds.y, bounds.width, bounds.height))
1790 continue;
1792 boolean translated = false;
1795 g.clipRect(bounds.x, bounds.y, bounds.width, bounds.height);
1796 g.translate(bounds.x, bounds.y);
1797 translated = true;
1798 children[i].paint(g);
1800 finally
1802 if (translated)
1803 g.translate(-bounds.x, -bounds.y);
1804 g.setClip(oldClip);
1807 g.setClip(originalClip);
1811 * Paint the component's body. This usually means calling {@link
1812 * ComponentUI#update} on the {@link #ui} property of the component, if
1813 * it is non-<code>null</code>. You may override this if you wish to
1814 * customize the component's body-painting behavior. The component's body
1815 * is painted first, before the border and children.
1817 * @param g The graphics context with which to paint the body
1819 * @see #paint
1820 * @see #paintBorder
1821 * @see #paintChildren
1823 protected void paintComponent(Graphics g)
1825 if (ui != null)
1827 Graphics g2 = g;
1828 if (!(g instanceof Graphics2D))
1829 g2 = g.create();
1830 ui.update(g2, this);
1831 if (!(g instanceof Graphics2D))
1832 g2.dispose();
1837 * A variant of {@link #paintImmediately(Rectangle)} which takes
1838 * integer parameters.
1840 * @param x The left x coordinate of the dirty region
1841 * @param y The top y coordinate of the dirty region
1842 * @param w The width of the dirty region
1843 * @param h The height of the dirty region
1845 public void paintImmediately(int x, int y, int w, int h)
1847 paintImmediately(new Rectangle(x, y, w, h));
1851 * Transform the provided dirty rectangle for this component into the
1852 * appropriate ancestral {@link JRootPane} and call {@link #paint} on
1853 * that root pane. This method is called from the {@link RepaintManager}
1854 * and should always be called within the painting thread.
1856 * <p>This method will acquire a double buffer from the {@link
1857 * RepaintManager} if the component's {@link #doubleBuffered} property is
1858 * <code>true</code> and the <code>paint</code> call is the
1859 * <em>first</em> recursive <code>paint</code> call inside swing.</p>
1861 * <p>The method will also modify the provided {@link Graphics} context
1862 * via the {@link #getComponentGraphics} method. If you want to customize
1863 * the graphics object used for painting, you should override that method
1864 * rather than <code>paint</code>.</p>
1866 * @param r The dirty rectangle to paint
1868 public void paintImmediately(Rectangle r)
1870 // Try to find a root pane for this component.
1871 //Component root = findPaintRoot(r);
1872 Component root = findPaintRoot(r);
1873 // If no paint root is found, then this component is completely overlapped
1874 // by another component and we don't need repainting.
1875 if (root == null)
1876 return;
1877 if (root == null || !root.isShowing())
1878 return;
1880 Rectangle rootClip = SwingUtilities.convertRectangle(this, r, root);
1881 if (root instanceof JComponent)
1882 ((JComponent) root).paintImmediately2(rootClip);
1883 else
1884 root.repaint(rootClip.x, rootClip.y, rootClip.width, rootClip.height);
1888 * Performs the actual work of paintImmediatly on the repaint root.
1890 * @param r the area to be repainted
1892 void paintImmediately2(Rectangle r)
1894 RepaintManager rm = RepaintManager.currentManager(this);
1895 Graphics g = getGraphics();
1896 g.setClip(r.x, r.y, r.width, r.height);
1897 if (rm.isDoubleBufferingEnabled() && isDoubleBuffered())
1898 paintDoubleBuffered(g);
1899 else
1900 paintSimple(g);
1901 g.dispose();
1905 * Performs double buffered repainting.
1907 * @param g the graphics context to paint to
1909 void paintDoubleBuffered(Graphics g)
1912 Rectangle r = g.getClipBounds();
1913 if (r == null)
1914 r = new Rectangle(0, 0, getWidth(), getHeight());
1915 RepaintManager rm = RepaintManager.currentManager(this);
1917 // Paint on the offscreen buffer.
1918 Image buffer = rm.getOffscreenBuffer(this, getWidth(), getHeight());
1919 Graphics g2 = buffer.getGraphics();
1920 g2 = getComponentGraphics(g2);
1921 g2.setClip(r.x, r.y, r.width, r.height);
1922 isPaintingDoubleBuffered = true;
1925 paint(g2);
1927 finally
1929 isPaintingDoubleBuffered = false;
1930 g2.dispose();
1933 // Paint the buffer contents on screen.
1934 g.drawImage(buffer, 0, 0, this);
1938 * Performs normal painting without double buffering.
1940 * @param g the graphics context to use
1942 void paintSimple(Graphics g)
1944 Graphics g2 = getComponentGraphics(g);
1945 paint(g2);
1949 * Return a string representation for this component, for use in
1950 * debugging.
1952 * @return A string describing this component.
1954 protected String paramString()
1956 StringBuffer sb = new StringBuffer();
1957 sb.append(super.paramString());
1958 sb.append(",alignmentX=").append(getAlignmentX());
1959 sb.append(",alignmentY=").append(getAlignmentY());
1960 sb.append(",border=");
1961 if (getBorder() != null)
1962 sb.append(getBorder());
1963 sb.append(",maximumSize=");
1964 if (getMaximumSize() != null)
1965 sb.append(getMaximumSize());
1966 sb.append(",minimumSize=");
1967 if (getMinimumSize() != null)
1968 sb.append(getMinimumSize());
1969 sb.append(",preferredSize=");
1970 if (getPreferredSize() != null)
1971 sb.append(getPreferredSize());
1972 return sb.toString();
1976 * A variant of {@link
1977 * #registerKeyboardAction(ActionListener,String,KeyStroke,int)} which
1978 * provides <code>null</code> for the command name.
1980 public void registerKeyboardAction(ActionListener act,
1981 KeyStroke stroke,
1982 int cond)
1984 registerKeyboardAction(act, null, stroke, cond);
1988 * There is some charmingly undocumented behavior sun seems to be using
1989 * to simulate the old register/unregister keyboard binding API. It's not
1990 * clear to me why this matters, but we shall endeavour to follow suit.
1992 * Two main thing seem to be happening when you do registerKeyboardAction():
1994 * - no actionMap() entry gets created, just an entry in inputMap()
1996 * - the inputMap() entry is a proxy class which invokes the the
1997 * binding's actionListener as a target, and which clobbers the command
1998 * name sent in the ActionEvent, providing the binding command name
1999 * instead.
2001 * This much you can work out just by asking the input and action maps
2002 * what they contain after making bindings, and watching the event which
2003 * gets delivered to the recipient. Beyond that, it seems to be a
2004 * sun-private solution so I will only immitate it as much as it matters
2005 * to external observers.
2007 private static class ActionListenerProxy
2008 extends AbstractAction
2010 ActionListener target;
2011 String bindingCommandName;
2013 public ActionListenerProxy(ActionListener li,
2014 String cmd)
2016 target = li;
2017 bindingCommandName = cmd;
2020 public void actionPerformed(ActionEvent e)
2022 ActionEvent derivedEvent = new ActionEvent(e.getSource(),
2023 e.getID(),
2024 bindingCommandName,
2025 e.getModifiers());
2026 target.actionPerformed(derivedEvent);
2032 * An obsolete method to register a keyboard action on this component.
2033 * You should use <code>getInputMap</code> and <code>getActionMap</code>
2034 * to fetch mapping tables from keystrokes to commands, and commands to
2035 * actions, respectively, and modify those mappings directly.
2037 * @param act The action to be registered
2038 * @param cmd The command to deliver in the delivered {@link
2039 * java.awt.event.ActionEvent}
2040 * @param stroke The keystroke to register on
2041 * @param cond One of the values {@link #UNDEFINED_CONDITION},
2042 * {@link #WHEN_ANCESTOR_OF_FOCUSED_COMPONENT}, {@link #WHEN_FOCUSED}, or
2043 * {@link #WHEN_IN_FOCUSED_WINDOW}, indicating the condition which must
2044 * be met for the action to be fired
2046 * @see #unregisterKeyboardAction
2047 * @see #getConditionForKeyStroke
2048 * @see #resetKeyboardActions
2050 public void registerKeyboardAction(ActionListener act,
2051 String cmd,
2052 KeyStroke stroke,
2053 int cond)
2055 getInputMap(cond).put(stroke, new ActionListenerProxy(act, cmd));
2058 public final void setInputMap(int condition, InputMap map)
2060 enableEvents(AWTEvent.KEY_EVENT_MASK);
2061 switch (condition)
2063 case WHEN_FOCUSED:
2064 inputMap_whenFocused = map;
2065 break;
2067 case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT:
2068 inputMap_whenAncestorOfFocused = map;
2069 break;
2071 case WHEN_IN_FOCUSED_WINDOW:
2072 if (map != null && !(map instanceof ComponentInputMap))
2073 throw new
2074 IllegalArgumentException("WHEN_IN_FOCUSED_WINDOW " +
2075 "InputMap must be a ComponentInputMap");
2076 inputMap_whenInFocusedWindow = (ComponentInputMap)map;
2077 break;
2079 case UNDEFINED_CONDITION:
2080 default:
2081 throw new IllegalArgumentException();
2085 public final InputMap getInputMap(int condition)
2087 enableEvents(AWTEvent.KEY_EVENT_MASK);
2088 switch (condition)
2090 case WHEN_FOCUSED:
2091 if (inputMap_whenFocused == null)
2092 inputMap_whenFocused = new InputMap();
2093 return inputMap_whenFocused;
2095 case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT:
2096 if (inputMap_whenAncestorOfFocused == null)
2097 inputMap_whenAncestorOfFocused = new InputMap();
2098 return inputMap_whenAncestorOfFocused;
2100 case WHEN_IN_FOCUSED_WINDOW:
2101 if (inputMap_whenInFocusedWindow == null)
2102 inputMap_whenInFocusedWindow = new ComponentInputMap(this);
2103 return inputMap_whenInFocusedWindow;
2105 case UNDEFINED_CONDITION:
2106 default:
2107 return null;
2111 public final InputMap getInputMap()
2113 return getInputMap(WHEN_FOCUSED);
2116 public final ActionMap getActionMap()
2118 if (actionMap == null)
2119 actionMap = new ActionMap();
2120 return actionMap;
2123 public final void setActionMap(ActionMap map)
2125 actionMap = map;
2129 * Return the condition that determines whether a registered action
2130 * occurs in response to the specified keystroke.
2132 * @param ks The keystroke to return the condition of
2134 * @return One of the values {@link #UNDEFINED_CONDITION}, {@link
2135 * #WHEN_ANCESTOR_OF_FOCUSED_COMPONENT}, {@link #WHEN_FOCUSED}, or {@link
2136 * #WHEN_IN_FOCUSED_WINDOW}
2138 * @deprecated As of 1.3 KeyStrokes can be registered with multiple
2139 * simultaneous conditions.
2141 * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
2142 * @see #unregisterKeyboardAction
2143 * @see #resetKeyboardActions
2145 public int getConditionForKeyStroke(KeyStroke ks)
2147 if (inputMap_whenFocused != null
2148 && inputMap_whenFocused.get(ks) != null)
2149 return WHEN_FOCUSED;
2150 else if (inputMap_whenAncestorOfFocused != null
2151 && inputMap_whenAncestorOfFocused.get(ks) != null)
2152 return WHEN_ANCESTOR_OF_FOCUSED_COMPONENT;
2153 else if (inputMap_whenInFocusedWindow != null
2154 && inputMap_whenInFocusedWindow.get(ks) != null)
2155 return WHEN_IN_FOCUSED_WINDOW;
2156 else
2157 return UNDEFINED_CONDITION;
2161 * Get the ActionListener (typically an {@link Action} object) which is
2162 * associated with a particular keystroke.
2164 * @param ks The keystroke to retrieve the action of
2166 * @return The action associated with the specified keystroke
2168 * @deprecated Use {@link #getActionMap()}
2170 public ActionListener getActionForKeyStroke(KeyStroke ks)
2172 Object cmd = getInputMap().get(ks);
2173 if (cmd != null)
2175 if (cmd instanceof ActionListenerProxy)
2176 return (ActionListenerProxy) cmd;
2177 else if (cmd instanceof String)
2178 return getActionMap().get(cmd);
2180 return null;
2184 * A hook for subclasses which want to customize event processing.
2186 protected void processComponentKeyEvent(KeyEvent e)
2188 // This method does nothing, it is meant to be overridden by subclasses.
2192 * Override the default key dispatch system from Component to hook into
2193 * the swing {@link InputMap} / {@link ActionMap} system.
2195 * See <a
2196 * href="http://java.sun.com/products/jfc/tsc/special_report/kestrel/keybindings.html">
2197 * this report</a> for more details, it's somewhat complex.
2199 protected void processKeyEvent(KeyEvent e)
2201 // let the AWT event processing send KeyEvents to registered listeners
2202 super.processKeyEvent(e);
2203 processComponentKeyEvent(e);
2205 if (e.isConsumed())
2206 return;
2208 // Input maps are checked in this order:
2209 // 1. The focused component's WHEN_FOCUSED map is checked.
2210 // 2. The focused component's WHEN_ANCESTOR_OF_FOCUSED_COMPONENT map.
2211 // 3. The WHEN_ANCESTOR_OF_FOCUSED_COMPONENT maps of the focused
2212 // component's parent, then its parent's parent, and so on.
2213 // Note: Input maps for disabled components are skipped.
2214 // 4. The WHEN_IN_FOCUSED_WINDOW maps of all the enabled components in
2215 // the focused window are searched.
2217 KeyStroke keyStroke = KeyStroke.getKeyStrokeForEvent(e);
2218 boolean pressed = e.getID() == KeyEvent.KEY_PRESSED;
2220 if (processKeyBinding(keyStroke, e, WHEN_FOCUSED, pressed))
2222 // This is step 1 from above comment.
2223 e.consume();
2224 return;
2226 else if (processKeyBinding
2227 (keyStroke, e, WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, pressed))
2229 // This is step 2 from above comment.
2230 e.consume();
2231 return;
2234 // This is step 3 from above comment.
2235 Container current = getParent();
2236 while (current != null)
2238 // If current is a JComponent, see if it handles the event in its
2239 // WHEN_ANCESTOR_OF_FOCUSED_COMPONENT maps.
2240 if ((current instanceof JComponent) &&
2241 ((JComponent)current).processKeyBinding
2242 (keyStroke, e,WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, pressed))
2244 e.consume();
2245 return;
2248 // Stop when we've tried a top-level container and it didn't handle it
2249 if (current instanceof Window || current instanceof Applet)
2250 break;
2252 // Move up the hierarchy
2253 current = current.getParent();
2256 // Current being null means the JComponent does not currently have a
2257 // top-level ancestor, in which case we don't need to check
2258 // WHEN_IN_FOCUSED_WINDOW bindings.
2259 if (current == null || e.isConsumed())
2260 return;
2262 // This is step 4 from above comment. KeyboardManager maintains mappings
2263 // related to WHEN_IN_FOCUSED_WINDOW bindings so that we don't have to
2264 // traverse the containment hierarchy each time.
2265 if (KeyboardManager.getManager().processKeyStroke(current, keyStroke, e))
2266 e.consume();
2269 protected boolean processKeyBinding(KeyStroke ks,
2270 KeyEvent e,
2271 int condition,
2272 boolean pressed)
2274 if (isEnabled())
2276 Action act = null;
2277 InputMap map = getInputMap(condition);
2278 if (map != null)
2280 Object cmd = map.get(ks);
2281 if (cmd != null)
2283 if (cmd instanceof ActionListenerProxy)
2284 act = (Action) cmd;
2285 else
2286 act = (Action) getActionMap().get(cmd);
2289 if (act != null && act.isEnabled())
2290 return SwingUtilities.notifyAction(act, ks, e, this, e.getModifiers());
2292 return false;
2296 * Remove a keyboard action registry.
2298 * @param aKeyStroke The keystroke to unregister
2300 * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
2301 * @see #getConditionForKeyStroke
2302 * @see #resetKeyboardActions
2304 public void unregisterKeyboardAction(KeyStroke aKeyStroke)
2306 // FIXME: Must be implemented.
2311 * Reset all keyboard action registries.
2313 * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
2314 * @see #unregisterKeyboardAction
2315 * @see #getConditionForKeyStroke
2317 public void resetKeyboardActions()
2319 if (inputMap_whenFocused != null)
2320 inputMap_whenFocused.clear();
2321 if (inputMap_whenAncestorOfFocused != null)
2322 inputMap_whenAncestorOfFocused.clear();
2323 if (inputMap_whenInFocusedWindow != null)
2324 inputMap_whenInFocusedWindow.clear();
2325 if (actionMap != null)
2326 actionMap.clear();
2330 * Mark the described region of this component as dirty in the current
2331 * {@link RepaintManager}. This will queue an asynchronous repaint using
2332 * the system painting thread in the near future.
2334 * @param tm ignored
2335 * @param x coordinate of the region to mark as dirty
2336 * @param y coordinate of the region to mark as dirty
2337 * @param width dimension of the region to mark as dirty
2338 * @param height dimension of the region to mark as dirty
2340 public void repaint(long tm, int x, int y, int width, int height)
2342 Rectangle dirty = new Rectangle(x, y, width, height);
2343 Rectangle vis = getVisibleRect();
2344 dirty = dirty.intersection(vis);
2345 RepaintManager.currentManager(this).addDirtyRegion(this, dirty.x, dirty.y,
2346 dirty.width,
2347 dirty.height);
2351 * Mark the described region of this component as dirty in the current
2352 * {@link RepaintManager}. This will queue an asynchronous repaint using
2353 * the system painting thread in the near future.
2355 * @param r The rectangle to mark as dirty
2357 public void repaint(Rectangle r)
2359 repaint((long) 0, (int) r.getX(), (int) r.getY(), (int) r.getWidth(),
2360 (int) r.getHeight());
2364 * Request focus on the default component of this component's {@link
2365 * FocusTraversalPolicy}.
2367 * @return The result of {@link #requestFocus()}
2369 * @deprecated Use {@link #requestFocus()} on the default component provided
2370 * from the {@link FocusTraversalPolicy} instead.
2372 public boolean requestDefaultFocus()
2374 return false;
2378 * Queue a an invalidation and revalidation of this component, using
2379 * {@link RepaintManager#addInvalidComponent}.
2381 public void revalidate()
2383 if (! EventQueue.isDispatchThread())
2384 SwingUtilities.invokeLater(new Runnable()
2386 public void run()
2388 revalidate();
2391 else
2393 invalidate();
2394 RepaintManager.currentManager(this).addInvalidComponent(this);
2399 * Calls <code>scrollRectToVisible</code> on the component's parent.
2400 * Components which can service this call should override.
2402 * @param r The rectangle to make visible
2404 public void scrollRectToVisible(Rectangle r)
2406 Component p = getParent();
2407 if (p instanceof JComponent)
2408 ((JComponent) p).scrollRectToVisible(r);
2412 * Set the value of the {@link #alignmentX} property.
2414 * @param a The new value of the property
2416 public void setAlignmentX(float a)
2418 if (a < 0.0F)
2419 alignmentX = 0.0F;
2420 else if (a > 1.0)
2421 alignmentX = 1.0F;
2422 else
2423 alignmentX = a;
2427 * Set the value of the {@link #alignmentY} property.
2429 * @param a The new value of the property
2431 public void setAlignmentY(float a)
2433 if (a < 0.0F)
2434 alignmentY = 0.0F;
2435 else if (a > 1.0)
2436 alignmentY = 1.0F;
2437 else
2438 alignmentY = a;
2442 * Set the value of the {@link #autoscrolls} property.
2444 * @param a The new value of the property
2446 public void setAutoscrolls(boolean a)
2448 autoscrolls = a;
2452 * Set the value of the {@link #debugGraphicsOptions} property.
2454 * @param debugOptions The new value of the property
2456 public void setDebugGraphicsOptions(int debugOptions)
2458 debugGraphicsOptions = debugOptions;
2462 * Set the value of the {@link #doubleBuffered} property.
2464 * @param db The new value of the property
2466 public void setDoubleBuffered(boolean db)
2468 doubleBuffered = db;
2472 * Set the value of the <code>enabled</code> property.
2474 * @param enable The new value of the property
2476 public void setEnabled(boolean enable)
2478 if (enable == isEnabled())
2479 return;
2480 super.setEnabled(enable);
2481 firePropertyChange("enabled", !enable, enable);
2482 repaint();
2486 * Set the value of the <code>font</code> property.
2488 * @param f The new value of the property
2490 public void setFont(Font f)
2492 if (f == getFont())
2493 return;
2494 super.setFont(f);
2495 revalidate();
2496 repaint();
2500 * Set the value of the <code>background</code> property.
2502 * @param bg The new value of the property
2504 public void setBackground(Color bg)
2506 if (bg == getBackground())
2507 return;
2508 super.setBackground(bg);
2509 repaint();
2513 * Set the value of the <code>foreground</code> property.
2515 * @param fg The new value of the property
2517 public void setForeground(Color fg)
2519 if (fg == getForeground())
2520 return;
2521 super.setForeground(fg);
2522 repaint();
2526 * Set the value of the {@link #maximumSize} property. The passed value is
2527 * copied, the later direct changes on the argument have no effect on the
2528 * property value.
2530 * @param max The new value of the property
2532 public void setMaximumSize(Dimension max)
2534 Dimension oldMaximumSize = maximumSize;
2535 if (max != null)
2536 maximumSize = new Dimension(max);
2537 else
2538 maximumSize = null;
2539 firePropertyChange("maximumSize", oldMaximumSize, maximumSize);
2543 * Set the value of the {@link #minimumSize} property. The passed value is
2544 * copied, the later direct changes on the argument have no effect on the
2545 * property value.
2547 * @param min The new value of the property
2549 public void setMinimumSize(Dimension min)
2551 Dimension oldMinimumSize = minimumSize;
2552 if (min != null)
2553 minimumSize = new Dimension(min);
2554 else
2555 minimumSize = null;
2556 firePropertyChange("minimumSize", oldMinimumSize, minimumSize);
2560 * Set the value of the {@link #preferredSize} property. The passed value is
2561 * copied, the later direct changes on the argument have no effect on the
2562 * property value.
2564 * @param pref The new value of the property
2566 public void setPreferredSize(Dimension pref)
2568 Dimension oldPreferredSize = preferredSize;
2569 if (pref != null)
2570 preferredSize = new Dimension(pref);
2571 else
2572 preferredSize = null;
2573 firePropertyChange("preferredSize", oldPreferredSize, preferredSize);
2577 * Set the specified component to be the next component in the
2578 * focus cycle, overriding the {@link FocusTraversalPolicy} for
2579 * this component.
2581 * @param aComponent The component to set as the next focusable
2583 * @deprecated Use FocusTraversalPolicy instead
2585 public void setNextFocusableComponent(Component aComponent)
2587 // TODO: Implement this properly.
2591 * Set the value of the {@link #requestFocusEnabled} property.
2593 * @param e The new value of the property
2595 public void setRequestFocusEnabled(boolean e)
2597 requestFocusEnabled = e;
2601 * Get the value of the {@link #transferHandler} property.
2603 * @return The current value of the property
2605 * @see #setTransferHandler
2608 public TransferHandler getTransferHandler()
2610 return transferHandler;
2614 * Set the value of the {@link #transferHandler} property.
2616 * @param newHandler The new value of the property
2618 * @see #getTransferHandler
2621 public void setTransferHandler(TransferHandler newHandler)
2623 if (transferHandler == newHandler)
2624 return;
2626 TransferHandler oldHandler = transferHandler;
2627 transferHandler = newHandler;
2628 firePropertyChange("transferHandler", oldHandler, newHandler);
2632 * Set the value of the {@link #opaque} property.
2634 * @param isOpaque The new value of the property
2636 * @see ComponentUI#update
2638 public void setOpaque(boolean isOpaque)
2640 boolean oldOpaque = opaque;
2641 opaque = isOpaque;
2642 firePropertyChange("opaque", oldOpaque, opaque);
2646 * Set the value of the visible property.
2648 * If the value is changed, then the AncestorListeners of this component
2649 * and all its children (recursivly) are notified.
2651 * @param v The new value of the property
2653 public void setVisible(boolean v)
2655 // No need to do anything if the actual value doesn't change.
2656 if (isVisible() == v)
2657 return;
2659 super.setVisible(v);
2661 // Notify AncestorListeners.
2662 if (v == true)
2663 fireAncestorEvent(this, AncestorEvent.ANCESTOR_ADDED);
2664 else
2665 fireAncestorEvent(this, AncestorEvent.ANCESTOR_REMOVED);
2667 Container parent = getParent();
2668 if (parent != null)
2669 parent.repaint(getX(), getY(), getWidth(), getHeight());
2670 revalidate();
2674 * Call {@link #paint}.
2676 * @param g The graphics context to paint into
2678 public void update(Graphics g)
2680 paint(g);
2684 * Get the value of the UIClassID property. This property should be a key
2685 * in the {@link UIDefaults} table managed by {@link UIManager}, the
2686 * value of which is the name of a class to load for the component's
2687 * {@link #ui} property.
2689 * @return A "symbolic" name which will map to a class to use for the
2690 * component's UI, such as <code>"ComponentUI"</code>
2692 * @see #setUI
2693 * @see #updateUI
2695 public String getUIClassID()
2697 return "ComponentUI";
2701 * Install a new UI delegate as the component's {@link #ui} property. In
2702 * the process, this will call {@link ComponentUI#uninstallUI} on any
2703 * existing value for the {@link #ui} property, and {@link
2704 * ComponentUI#installUI} on the new UI delegate.
2706 * @param newUI The new UI delegate to install
2708 * @see #updateUI
2709 * @see #getUIClassID
2711 protected void setUI(ComponentUI newUI)
2713 if (ui != null)
2714 ui.uninstallUI(this);
2716 ComponentUI oldUI = ui;
2717 ui = newUI;
2719 if (ui != null)
2720 ui.installUI(this);
2722 firePropertyChange("UI", oldUI, newUI);
2723 revalidate();
2724 repaint();
2728 * This method should be overridden in subclasses. In JComponent, the
2729 * method does nothing. In subclasses, it should a UI delegate
2730 * (corresponding to the symbolic name returned from {@link
2731 * #getUIClassID}) from the {@link UIManager}, and calls {@link #setUI}
2732 * with the new delegate.
2734 public void updateUI()
2736 // Nothing to do here.
2739 public static Locale getDefaultLocale()
2741 return defaultLocale;
2744 public static void setDefaultLocale(Locale l)
2746 defaultLocale = l;
2750 * Returns the currently set input verifier for this component.
2752 * @return the input verifier, or <code>null</code> if none
2754 public InputVerifier getInputVerifier()
2756 return inputVerifier;
2760 * Sets the input verifier to use by this component.
2762 * @param verifier the input verifier, or <code>null</code>
2764 public void setInputVerifier(InputVerifier verifier)
2766 InputVerifier oldVerifier = inputVerifier;
2767 inputVerifier = verifier;
2768 firePropertyChange("inputVerifier", oldVerifier, verifier);
2772 * @since 1.3
2774 public boolean getVerifyInputWhenFocusTarget()
2776 return verifyInputWhenFocusTarget;
2780 * @since 1.3
2782 public void setVerifyInputWhenFocusTarget(boolean verifyInputWhenFocusTarget)
2784 if (this.verifyInputWhenFocusTarget == verifyInputWhenFocusTarget)
2785 return;
2787 this.verifyInputWhenFocusTarget = verifyInputWhenFocusTarget;
2788 firePropertyChange("verifyInputWhenFocusTarget",
2789 ! verifyInputWhenFocusTarget,
2790 verifyInputWhenFocusTarget);
2794 * Requests that this component gets the input focus if the
2795 * requestFocusEnabled property is set to <code>true</code>.
2796 * This also means that this component's top-level window becomes
2797 * the focused window, if that is not already the case.
2799 * The preconditions that have to be met to become a focus owner is that
2800 * the component must be displayable, visible and focusable.
2802 * Note that this signals only a request for becoming focused. There are
2803 * situations in which it is not possible to get the focus. So developers
2804 * should not assume that the component has the focus until it receives
2805 * a {@link java.awt.event.FocusEvent} with a value of
2806 * {@link java.awt.event.FocusEvent#FOCUS_GAINED}.
2808 * @see Component#requestFocus()
2810 public void requestFocus()
2812 if (isRequestFocusEnabled())
2813 super.requestFocus();
2817 * This method is overridden to make it public so that it can be used
2818 * by look and feel implementations.
2820 * You should not use this method directly. Instead you are strongly
2821 * encouraged to call {@link #requestFocus()} or
2822 * {@link #requestFocusInWindow()} instead.
2824 * @param temporary if the focus change is temporary
2826 * @return <code>false</code> if the focus change request will definitly
2827 * fail, <code>true</code> if it will likely succeed
2829 * @see Component#requestFocus(boolean)
2831 * @since 1.4
2833 public boolean requestFocus(boolean temporary)
2835 return super.requestFocus(temporary);
2839 * Requests that this component gets the input focus if the top level
2840 * window that contains this component has the focus and the
2841 * requestFocusEnabled property is set to <code>true</code>.
2843 * The preconditions that have to be met to become a focus owner is that
2844 * the component must be displayable, visible and focusable.
2846 * Note that this signals only a request for becoming focused. There are
2847 * situations in which it is not possible to get the focus. So developers
2848 * should not assume that the component has the focus until it receives
2849 * a {@link java.awt.event.FocusEvent} with a value of
2850 * {@link java.awt.event.FocusEvent#FOCUS_GAINED}.
2852 * @return <code>false</code> if the focus change request will definitly
2853 * fail, <code>true</code> if it will likely succeed
2855 * @see Component#requestFocusInWindow()
2857 public boolean requestFocusInWindow()
2859 if (isRequestFocusEnabled())
2860 return super.requestFocusInWindow();
2861 else
2862 return false;
2866 * This method is overridden to make it public so that it can be used
2867 * by look and feel implementations.
2869 * You should not use this method directly. Instead you are strongly
2870 * encouraged to call {@link #requestFocus()} or
2871 * {@link #requestFocusInWindow()} instead.
2873 * @param temporary if the focus change is temporary
2875 * @return <code>false</code> if the focus change request will definitly
2876 * fail, <code>true</code> if it will likely succeed
2878 * @see Component#requestFocus(boolean)
2880 * @since 1.4
2882 public boolean requestFocusInWindow(boolean temporary)
2884 return super.requestFocusInWindow(temporary);
2888 * Receives notification if this component is added to a parent component.
2890 * Notification is sent to all registered AncestorListeners about the
2891 * new parent.
2893 * This method sets up ActionListeners for all registered KeyStrokes of
2894 * this component in the chain of parent components.
2896 * A PropertyChange event is fired to indicate that the ancestor property
2897 * has changed.
2899 * This method is used internally and should not be used in applications.
2901 public void addNotify()
2903 // Register the WHEN_IN_FOCUSED_WINDOW keyboard bindings
2904 // Note that here we unregister all bindings associated with
2905 // this component and then re-register them. This may be more than
2906 // necessary if the top-level ancestor hasn't changed. Should
2907 // maybe improve this.
2908 KeyboardManager km = KeyboardManager.getManager();
2909 km.clearBindingsForComp(this);
2910 km.registerEntireMap((ComponentInputMap)
2911 this.getInputMap(WHEN_IN_FOCUSED_WINDOW));
2912 super.addNotify();
2914 // Notify AncestorListeners.
2915 fireAncestorEvent(this, AncestorEvent.ANCESTOR_ADDED);
2917 // fire property change event for 'ancestor'
2918 firePropertyChange("ancestor", null, getParent());
2922 * Receives notification that this component no longer has a parent.
2924 * This method sends an AncestorEvent to all registered AncestorListeners,
2925 * notifying them that the parent is gone.
2927 * The keybord actions of this component are removed from the parent and
2928 * its ancestors.
2930 * A PropertyChangeEvent is fired to indicate that the 'ancestor' property
2931 * has changed.
2933 * This method is called before the component is actually removed from
2934 * its parent, so the parent is still visible through
2935 * {@link Component#getParent}.
2937 public void removeNotify()
2939 super.removeNotify();
2941 KeyboardManager.getManager().clearBindingsForComp(this);
2943 // Notify ancestor listeners.
2944 fireAncestorEvent(this, AncestorEvent.ANCESTOR_REMOVED);
2946 // fire property change event for 'ancestor'
2947 firePropertyChange("ancestor", getParent(), null);
2951 * Returns <code>true</code> if the coordinates (x, y) lie within
2952 * the bounds of this component and <code>false</code> otherwise.
2953 * x and y are relative to the coordinate space of the component.
2955 * @param x the X coordinate of the point to check
2956 * @param y the Y coordinate of the point to check
2958 * @return <code>true</code> if the specified point lies within the bounds
2959 * of this component, <code>false</code> otherwise
2961 public boolean contains(int x, int y)
2963 if (ui == null)
2964 return super.contains(x, y);
2965 else
2966 return ui.contains(this, x, y);
2970 * Disables this component.
2972 * @deprecated replaced by {@link #setEnabled(boolean)}
2974 public void disable()
2976 super.disable();
2980 * Enables this component.
2982 * @deprecated replaced by {@link #setEnabled(boolean)}
2984 public void enable()
2986 super.enable();
2990 * Returns the Graphics context for this component. This can be used
2991 * to draw on a component.
2993 * @return the Graphics context for this component
2995 public Graphics getGraphics()
2997 return super.getGraphics();
3001 * Returns the X coordinate of the upper left corner of this component.
3002 * Prefer this method over {@link #getBounds} or {@link #getLocation}
3003 * because it does not cause any heap allocation.
3005 * @return the X coordinate of the upper left corner of the component
3007 public int getX()
3009 return super.getX();
3013 * Returns the Y coordinate of the upper left corner of this component.
3014 * Prefer this method over {@link #getBounds} or {@link #getLocation}
3015 * because it does not cause any heap allocation.
3017 * @return the Y coordinate of the upper left corner of the component
3019 public int getY()
3021 return super.getY();
3025 * Returns the height of this component. Prefer this method over
3026 * {@link #getBounds} or {@link #getSize} because it does not cause
3027 * any heap allocation.
3029 * @return the height of the component
3031 public int getHeight()
3033 return super.getHeight();
3037 * Returns the width of this component. Prefer this method over
3038 * {@link #getBounds} or {@link #getSize} because it does not cause
3039 * any heap allocation.
3041 * @return the width of the component
3043 public int getWidth()
3045 return super.getWidth();
3049 * Return all <code>PropertyChangeListener</code> objects registered.
3051 * @return The set of <code>PropertyChangeListener</code> objects
3053 public PropertyChangeListener[] getPropertyChangeListeners()
3055 if (changeSupport == null)
3056 return new PropertyChangeListener[0];
3057 else
3058 return changeSupport.getPropertyChangeListeners();
3062 * Prints this component to the given Graphics context. A call to this
3063 * method results in calls to the methods {@link #printComponent},
3064 * {@link #printBorder} and {@link #printChildren} in this order.
3066 * Double buffering is temporarily turned off so the painting goes directly
3067 * to the supplied Graphics context.
3069 * @param g the Graphics context to print onto
3071 public void print(Graphics g)
3073 boolean doubleBufferState = isDoubleBuffered();
3074 setDoubleBuffered(false);
3075 printComponent(g);
3076 printBorder(g);
3077 printChildren(g);
3078 setDoubleBuffered(doubleBufferState);
3082 * Prints this component to the given Graphics context. This invokes
3083 * {@link #print}.
3085 * @param g the Graphics context to print onto
3087 public void printAll(Graphics g)
3089 print(g);
3093 * Prints this component to the specified Graphics context. The default
3094 * behaviour is to invoke {@link #paintComponent}. Override this
3095 * if you want special behaviour for printing.
3097 * @param g the Graphics context to print onto
3099 * @since 1.3
3101 public void printComponent(Graphics g)
3103 paintComponent(g);
3107 * Print this component's children to the specified Graphics context.
3108 * The default behaviour is to invoke {@link #paintChildren}. Override this
3109 * if you want special behaviour for printing.
3111 * @param g the Graphics context to print onto
3113 * @since 1.3
3115 public void printChildren(Graphics g)
3117 paintChildren(g);
3121 * Print this component's border to the specified Graphics context.
3122 * The default behaviour is to invoke {@link #paintBorder}. Override this
3123 * if you want special behaviour for printing.
3125 * @param g the Graphics context to print onto
3127 * @since 1.3
3129 public void printBorder(Graphics g)
3131 paintBorder(g);
3135 * Processes mouse motion event, like dragging and moving.
3137 * @param ev the MouseEvent describing the mouse motion
3139 protected void processMouseMotionEvent(MouseEvent ev)
3141 super.processMouseMotionEvent(ev);
3145 * Moves and resizes the component.
3147 * @param x the new horizontal location
3148 * @param y the new vertial location
3149 * @param w the new width
3150 * @param h the new height
3152 public void reshape(int x, int y, int w, int h)
3154 int oldX = getX();
3155 int oldY = getY();
3156 super.reshape(x, y, w, h);
3157 // Notify AncestorListeners.
3158 if (oldX != getX() || oldY != getY())
3159 fireAncestorEvent(this, AncestorEvent.ANCESTOR_MOVED);
3163 * Fires an AncestorEvent to this component's and all of its child
3164 * component's AncestorListeners.
3166 * @param ancestor the component that triggered the event
3167 * @param id the kind of ancestor event that should be fired
3169 void fireAncestorEvent(JComponent ancestor, int id)
3171 // Fire event for registered ancestor listeners of this component.
3172 AncestorListener[] listeners = getAncestorListeners();
3173 if (listeners.length > 0)
3175 AncestorEvent ev = new AncestorEvent(this, id,
3176 ancestor, ancestor.getParent());
3177 for (int i = 0; i < listeners.length; i++)
3179 switch (id)
3181 case AncestorEvent.ANCESTOR_MOVED:
3182 listeners[i].ancestorMoved(ev);
3183 break;
3184 case AncestorEvent.ANCESTOR_ADDED:
3185 listeners[i].ancestorAdded(ev);
3186 break;
3187 case AncestorEvent.ANCESTOR_REMOVED:
3188 listeners[i].ancestorRemoved(ev);
3189 break;
3193 // Dispatch event to all children.
3194 Component[] children = getComponents();
3195 for (int i = 0; i < children.length; i++)
3197 if (!(children[i] instanceof JComponent))
3198 continue;
3199 JComponent jc = (JComponent) children[i];
3200 jc.fireAncestorEvent(ancestor, id);
3205 * Finds a suitable paint root for painting this component. This method first
3206 * checks if this component is overlapped using
3207 * {@link #findOverlapFreeParent(Rectangle)}. The returned paint root is then
3208 * feeded to {@link #findOpaqueParent(Component)} to find the nearest opaque
3209 * component for this paint root. If no paint is necessary, then we return
3210 * <code>null</code>.
3212 * @param c the clip of this component
3214 * @return the paint root or <code>null</code> if no painting is necessary
3216 private Component findPaintRoot(Rectangle c)
3218 Component p = findOverlapFreeParent(c);
3219 if (p == null)
3220 return null;
3221 Component root = findOpaqueParent(p);
3222 return root;
3226 * Scans the containment hierarchy upwards for components that overlap the
3227 * this component in the specified clip. This method returns
3228 * <code>this</code>, if no component overlaps this component. It returns
3229 * <code>null</code> if another component completely covers this component
3230 * in the specified clip (no repaint necessary). If another component partly
3231 * overlaps this component in the specified clip, then the parent of this
3232 * component is returned (this is the component that must be used as repaint
3233 * root). For efficient lookup, the method
3234 * {@link #isOptimizedDrawingEnabled()} is used.
3236 * @param clip the clip of this component
3238 * @return the paint root, or <code>null</code> if no paint is necessary
3240 private Component findOverlapFreeParent(Rectangle clip)
3242 Rectangle currentClip = clip;
3243 Component found = this;
3244 Container parent = this;
3245 while (parent != null && !(parent instanceof Window))
3247 Container newParent = parent.getParent();
3248 if (newParent == null)
3249 break;
3250 // If the parent is optimizedDrawingEnabled, then its children are
3251 // tiled and cannot have an overlapping child. Go directly to next
3252 // parent.
3253 if (newParent instanceof JComponent
3254 && ((JComponent) newParent).isOptimizedDrawingEnabled())
3256 parent = newParent;
3257 continue;
3260 // First we must check if the new parent itself somehow clips the
3261 // target rectangle. This can happen in JViewports.
3262 Rectangle parRect = new Rectangle(0, 0, newParent.getWidth(),
3263 newParent.getHeight());
3264 Rectangle target = SwingUtilities.convertRectangle(found,
3265 currentClip,
3266 newParent);
3267 if (! target.intersection(parRect).equals(target))
3269 found = newParent;
3270 currentClip = target;
3271 parent = newParent;
3272 continue;
3275 // Otherwise we must check if one of the children of this parent
3276 // overlaps with the current component.
3277 Component[] children = newParent.getComponents();
3278 // This flag is used to skip components that are 'below' the component
3279 // in question.
3280 boolean skip = true;
3281 for (int i = children.length - 1; i >= 0; i--)
3283 boolean nextSkip = skip;
3284 if (children[i] == parent)
3285 nextSkip = false;
3286 if (skip)
3287 continue;
3288 skip = nextSkip;
3289 Component c = children[i];
3290 Rectangle compBounds = c.getBounds();
3291 // If the component completely overlaps the clip in question, we
3292 // don't need to repaint. Return null.
3293 if (compBounds.contains(target))
3294 return null;
3295 if (compBounds.intersects(target))
3297 // We found a parent whose children overlap with our current
3298 // component. Make this the current component.
3299 found = newParent;
3300 currentClip = target;
3301 break;
3304 parent = newParent;
3306 return found;
3310 * Finds the nearest component to <code>c</code> (upwards in the containment
3311 * hierarchy), that is opaque. If <code>c</code> itself is opaque,
3312 * this returns <code>c</code> itself.
3314 * @param c the start component for the search
3315 * @return the nearest component to <code>c</code> (upwards in the containment
3316 * hierarchy), that is opaque; If <code>c</code> itself is opaque,
3317 * this returns <code>c</code> itself
3319 private Component findOpaqueParent(Component c)
3321 Component found = c;
3322 while (true)
3324 if ((found instanceof JComponent) && ((JComponent) found).isOpaque())
3325 break;
3326 else if (!(found instanceof JComponent))
3327 break;
3328 Container p = found.getParent();
3329 if (p == null)
3330 break;
3331 else
3332 found = p;
3334 return found;
3338 * This is the method that gets called when the WHEN_IN_FOCUSED_WINDOW map
3339 * is changed.
3341 * @param changed the JComponent associated with the WHEN_IN_FOCUSED_WINDOW
3342 * map
3344 void updateComponentInputMap(ComponentInputMap changed)
3346 // Since you can change a component's input map via
3347 // setInputMap, we have to check if <code>changed</code>
3348 // is still in our WHEN_IN_FOCUSED_WINDOW map hierarchy
3349 InputMap curr = getInputMap(WHEN_IN_FOCUSED_WINDOW);
3350 while (curr != null && curr != changed)
3351 curr = curr.getParent();
3353 // If curr is null then changed is not in the hierarchy
3354 if (curr == null)
3355 return;
3357 // Now we have to update the keyboard manager's hashtable
3358 KeyboardManager km = KeyboardManager.getManager();
3360 // This is a poor strategy, should be improved. We currently
3361 // delete all the old bindings for the component and then register
3362 // the current bindings.
3363 km.clearBindingsForComp(changed.getComponent());
3364 km.registerEntireMap((ComponentInputMap)
3365 getInputMap(WHEN_IN_FOCUSED_WINDOW));