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