0001 /*
0002 * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
0003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004 *
0005 * This code is free software; you can redistribute it and/or modify it
0006 * under the terms of the GNU General Public License version 2 only, as
0007 * published by the Free Software Foundation. Sun designates this
0008 * particular file as subject to the "Classpath" exception as provided
0009 * by Sun in the LICENSE file that accompanied this code.
0010 *
0011 * This code is distributed in the hope that it will be useful, but WITHOUT
0012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014 * version 2 for more details (a copy is included in the LICENSE file that
0015 * accompanied this code).
0016 *
0017 * You should have received a copy of the GNU General Public License version
0018 * 2 along with this work; if not, write to the Free Software Foundation,
0019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020 *
0021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022 * CA 95054 USA or visit www.sun.com if you need additional information or
0023 * have any questions.
0024 */
0025 package javax.swing;
0026
0027 import java.util.HashSet;
0028 import java.util.Hashtable;
0029 import java.util.Dictionary;
0030 import java.util.Enumeration;
0031 import java.util.Locale;
0032 import java.util.Vector;
0033 import java.util.EventListener;
0034 import java.util.Set;
0035 import java.util.Map;
0036 import java.util.HashMap;
0037
0038 import java.awt.*;
0039 import java.awt.event.*;
0040 import java.awt.image.VolatileImage;
0041 import java.awt.Graphics2D;
0042 import java.awt.peer.LightweightPeer;
0043 import java.awt.dnd.DropTarget;
0044 import java.awt.font.FontRenderContext;
0045 import java.beans.*;
0046
0047 import java.applet.Applet;
0048
0049 import java.io.Serializable;
0050 import java.io.ObjectOutputStream;
0051 import java.io.ObjectInputStream;
0052 import java.io.IOException;
0053 import java.io.ObjectInputValidation;
0054 import java.io.InvalidObjectException;
0055
0056 import javax.swing.border.*;
0057 import javax.swing.event.*;
0058 import javax.swing.plaf.*;
0059 import static javax.swing.ClientPropertyKey.*;
0060 import javax.accessibility.*;
0061
0062 import sun.swing.SwingUtilities2;
0063 import sun.swing.UIClientPropertyKey;
0064
0065 /**
0066 * The base class for all Swing components except top-level containers.
0067 * To use a component that inherits from <code>JComponent</code>,
0068 * you must place the component in a containment hierarchy
0069 * whose root is a top-level Swing container.
0070 * Top-level Swing containers --
0071 * such as <code>JFrame</code>, <code>JDialog</code>,
0072 * and <code>JApplet</code> --
0073 * are specialized components
0074 * that provide a place for other Swing components to paint themselves.
0075 * For an explanation of containment hierarchies, see
0076 * <a
0077 href="http://java.sun.com/docs/books/tutorial/uiswing/overview/hierarchy.html">Swing Components and the Containment Hierarchy</a>,
0078 * a section in <em>The Java Tutorial</em>.
0079 *
0080 * <p>
0081 * The <code>JComponent</code> class provides:
0082 * <ul>
0083 * <li>The base class for both standard and custom components
0084 * that use the Swing architecture.
0085 * <li>A "pluggable look and feel" (L&F) that can be specified by the
0086 * programmer or (optionally) selected by the user at runtime.
0087 * The look and feel for each component is provided by a
0088 * <em>UI delegate</em> -- an object that descends from
0089 * {@link javax.swing.plaf.ComponentUI}.
0090 * See <a
0091 * href="http://java.sun.com/docs/books/tutorial/uiswing/misc/plaf.html">How
0092 * to Set the Look and Feel</a>
0093 * in <em>The Java Tutorial</em>
0094 * for more information.
0095 * <li>Comprehensive keystroke handling.
0096 * See the document <a
0097 * href="http://java.sun.com/products/jfc/tsc/special_report/kestrel/keybindings.html">Keyboard
0098 * Bindings in Swing</a>,
0099 * an article in <em>The Swing Connection</em>,
0100 * for more information.
0101 * <li>Support for tool tips --
0102 * short descriptions that pop up when the cursor lingers
0103 * over a component.
0104 * See <a
0105 * href="http://java.sun.com/docs/books/tutorial/uiswing/components/tooltip.html">How
0106 * to Use Tool Tips</a>
0107 * in <em>The Java Tutorial</em>
0108 * for more information.
0109 * <li>Support for accessibility.
0110 * <code>JComponent</code> contains all of the methods in the
0111 * <code>Accessible</code> interface,
0112 * but it doesn't actually implement the interface. That is the
0113 * responsibility of the individual classes
0114 * that extend <code>JComponent</code>.
0115 * <li>Support for component-specific properties.
0116 * With the {@link #putClientProperty}
0117 * and {@link #getClientProperty} methods,
0118 * you can associate name-object pairs
0119 * with any object that descends from <code>JComponent</code>.
0120 * <li>An infrastructure for painting
0121 * that includes double buffering and support for borders.
0122 * For more information see <a
0123 * href="http://java.sun.com/docs/books/tutorial/uiswing/overview/draw.html">Painting</a> and
0124 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/border.html">How
0125 * to Use Borders</a>,
0126 * both of which are sections in <em>The Java Tutorial</em>.
0127 * </ul>
0128 * For more information on these subjects, see the
0129 * <a href="package-summary.html#package_description">Swing package description</a>
0130 * and <em>The Java Tutorial</em> section
0131 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/components/jcomponent.html">The JComponent Class</a>.
0132 * <p>
0133 * <code>JComponent</code> and its subclasses document default values
0134 * for certain properties. For example, <code>JTable</code> documents the
0135 * default row height as 16. Each <code>JComponent</code> subclass
0136 * that has a <code>ComponentUI</code> will create the
0137 * <code>ComponentUI</code> as part of its constructor. In order
0138 * to provide a particular look and feel each
0139 * <code>ComponentUI</code> may set properties back on the
0140 * <code>JComponent</code> that created it. For example, a custom
0141 * look and feel may require <code>JTable</code>s to have a row
0142 * height of 24. The documented defaults are the value of a property
0143 * BEFORE the <code>ComponentUI</code> has been installed. If you
0144 * need a specific value for a particular property you should
0145 * explicitly set it.
0146 * <p>
0147 * In release 1.4, the focus subsystem was rearchitected.
0148 * For more information, see
0149 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
0150 * How to Use the Focus Subsystem</a>,
0151 * a section in <em>The Java Tutorial</em>.
0152 * <p>
0153 * <strong>Warning:</strong> Swing is not thread safe. For more
0154 * information see <a
0155 * href="package-summary.html#threading">Swing's Threading
0156 * Policy</a>.
0157 * <p>
0158 * <strong>Warning:</strong>
0159 * Serialized objects of this class will not be compatible with
0160 * future Swing releases. The current serialization support is
0161 * appropriate for short term storage or RMI between applications running
0162 * the same version of Swing. As of 1.4, support for long term storage
0163 * of all JavaBeans<sup><font size="-2">TM</font></sup>
0164 * has been added to the <code>java.beans</code> package.
0165 * Please see {@link java.beans.XMLEncoder}.
0166 *
0167 * @see KeyStroke
0168 * @see Action
0169 * @see #setBorder
0170 * @see #registerKeyboardAction
0171 * @see JOptionPane
0172 * @see #setDebugGraphicsOptions
0173 * @see #setToolTipText
0174 * @see #setAutoscrolls
0175 *
0176 * @version 2.291, 05/05/07
0177 * @author Hans Muller
0178 * @author Arnaud Weber
0179 */
0180 public abstract class JComponent extends Container implements
0181 Serializable, TransferHandler.HasGetTransferHandler {
0182 /**
0183 * @see #getUIClassID
0184 * @see #writeObject
0185 */
0186 private static final String uiClassID = "ComponentUI";
0187
0188 /**
0189 * @see #readObject
0190 */
0191 private static final Hashtable readObjectCallbacks = new Hashtable(
0192 1);
0193
0194 /**
0195 * Keys to use for forward focus traversal when the JComponent is
0196 * managing focus.
0197 */
0198 private static Set<KeyStroke> managingFocusForwardTraversalKeys;
0199
0200 /**
0201 * Keys to use for backward focus traversal when the JComponent is
0202 * managing focus.
0203 */
0204 private static Set<KeyStroke> managingFocusBackwardTraversalKeys;
0205
0206 // Following are the possible return values from getObscuredState.
0207 private static final int NOT_OBSCURED = 0;
0208 private static final int PARTIALLY_OBSCURED = 1;
0209 private static final int COMPLETELY_OBSCURED = 2;
0210
0211 /**
0212 * Set to true when DebugGraphics has been loaded.
0213 */
0214 static boolean DEBUG_GRAPHICS_LOADED;
0215
0216 /**
0217 * Key used to look up a value from the AppContext to determine the
0218 * JComponent the InputVerifier is running for. That is, if
0219 * AppContext.get(INPUT_VERIFIER_SOURCE_KEY) returns non-null, it
0220 * indicates the EDT is calling into the InputVerifier from the
0221 * returned component.
0222 */
0223 private static final Object INPUT_VERIFIER_SOURCE_KEY = new StringBuilder(
0224 "InputVerifierSourceKey");
0225
0226 /* The following fields support set methods for the corresponding
0227 * java.awt.Component properties.
0228 */
0229 private boolean isAlignmentXSet;
0230 private float alignmentX;
0231 private boolean isAlignmentYSet;
0232 private float alignmentY;
0233
0234 /**
0235 * Backing store for JComponent properties and listeners
0236 */
0237
0238 /** The look and feel delegate for this component. */
0239 protected transient ComponentUI ui;
0240 /** A list of event listeners for this component. */
0241 protected EventListenerList listenerList = new EventListenerList();
0242
0243 private transient ArrayTable clientProperties;
0244 private VetoableChangeSupport vetoableChangeSupport;
0245 /**
0246 * Whether or not autoscroll has been enabled.
0247 */
0248 private boolean autoscrolls;
0249 private Border border;
0250 private int flags;
0251
0252 /* Input verifier for this component */
0253 private InputVerifier inputVerifier = null;
0254
0255 private boolean verifyInputWhenFocusTarget = true;
0256
0257 /**
0258 * Set in <code>_paintImmediately</code>.
0259 * Will indicate the child that initiated the painting operation.
0260 * If <code>paintingChild</code> is opaque, no need to paint
0261 * any child components after <code>paintingChild</code>.
0262 * Test used in <code>paintChildren</code>.
0263 */
0264 transient Component paintingChild;
0265
0266 /**
0267 * Constant used for <code>registerKeyboardAction</code> that
0268 * means that the command should be invoked when
0269 * the component has the focus.
0270 */
0271 public static final int WHEN_FOCUSED = 0;
0272
0273 /**
0274 * Constant used for <code>registerKeyboardAction</code> that
0275 * means that the command should be invoked when the receiving
0276 * component is an ancestor of the focused component or is
0277 * itself the focused component.
0278 */
0279 public static final int WHEN_ANCESTOR_OF_FOCUSED_COMPONENT = 1;
0280
0281 /**
0282 * Constant used for <code>registerKeyboardAction</code> that
0283 * means that the command should be invoked when
0284 * the receiving component is in the window that has the focus
0285 * or is itself the focused component.
0286 */
0287 public static final int WHEN_IN_FOCUSED_WINDOW = 2;
0288
0289 /**
0290 * Constant used by some of the APIs to mean that no condition is defined.
0291 */
0292 public static final int UNDEFINED_CONDITION = -1;
0293
0294 /**
0295 * The key used by <code>JComponent</code> to access keyboard bindings.
0296 */
0297 private static final String KEYBOARD_BINDINGS_KEY = "_KeyboardBindings";
0298
0299 /**
0300 * An array of <code>KeyStroke</code>s used for
0301 * <code>WHEN_IN_FOCUSED_WINDOW</code> are stashed
0302 * in the client properties under this string.
0303 */
0304 private static final String WHEN_IN_FOCUSED_WINDOW_BINDINGS = "_WhenInFocusedWindow";
0305
0306 /**
0307 * The comment to display when the cursor is over the component,
0308 * also known as a "value tip", "flyover help", or "flyover label".
0309 */
0310 public static final String TOOL_TIP_TEXT_KEY = "ToolTipText";
0311
0312 private static final String NEXT_FOCUS = "nextFocus";
0313
0314 /**
0315 * <code>JPopupMenu</code> assigned to this component
0316 * and all of its childrens
0317 */
0318 private JPopupMenu popupMenu;
0319
0320 /** Private flags **/
0321 private static final int IS_DOUBLE_BUFFERED = 0;
0322 private static final int ANCESTOR_USING_BUFFER = 1;
0323 private static final int IS_PAINTING_TILE = 2;
0324 private static final int IS_OPAQUE = 3;
0325 private static final int KEY_EVENTS_ENABLED = 4;
0326 private static final int FOCUS_INPUTMAP_CREATED = 5;
0327 private static final int ANCESTOR_INPUTMAP_CREATED = 6;
0328 private static final int WIF_INPUTMAP_CREATED = 7;
0329 private static final int ACTIONMAP_CREATED = 8;
0330 private static final int CREATED_DOUBLE_BUFFER = 9;
0331 // bit 10 is free
0332 private static final int IS_PRINTING = 11;
0333 private static final int IS_PRINTING_ALL = 12;
0334 private static final int IS_REPAINTING = 13;
0335 /** Bits 14-21 are used to handle nested writeObject calls. **/
0336 private static final int WRITE_OBJ_COUNTER_FIRST = 14;
0337 private static final int RESERVED_1 = 15;
0338 private static final int RESERVED_2 = 16;
0339 private static final int RESERVED_3 = 17;
0340 private static final int RESERVED_4 = 18;
0341 private static final int RESERVED_5 = 19;
0342 private static final int RESERVED_6 = 20;
0343 private static final int WRITE_OBJ_COUNTER_LAST = 21;
0344
0345 private static final int REQUEST_FOCUS_DISABLED = 22;
0346 private static final int INHERITS_POPUP_MENU = 23;
0347 private static final int OPAQUE_SET = 24;
0348 private static final int AUTOSCROLLS_SET = 25;
0349 private static final int FOCUS_TRAVERSAL_KEYS_FORWARD_SET = 26;
0350 private static final int FOCUS_TRAVERSAL_KEYS_BACKWARD_SET = 27;
0351 private static final int REVALIDATE_RUNNABLE_SCHEDULED = 28;
0352
0353 /**
0354 * Temporary rectangles.
0355 */
0356 private static java.util.List tempRectangles = new java.util.ArrayList(
0357 11);
0358
0359 /** Used for <code>WHEN_FOCUSED</code> bindings. */
0360 private InputMap focusInputMap;
0361 /** Used for <code>WHEN_ANCESTOR_OF_FOCUSED_COMPONENT</code> bindings. */
0362 private InputMap ancestorInputMap;
0363 /** Used for <code>WHEN_IN_FOCUSED_KEY</code> bindings. */
0364 private ComponentInputMap windowInputMap;
0365
0366 /** ActionMap. */
0367 private ActionMap actionMap;
0368
0369 /** Key used to store the default locale in an AppContext **/
0370 private static final String defaultLocale = "JComponent.defaultLocale";
0371
0372 private static Component componentObtainingGraphicsFrom;
0373 private static Object componentObtainingGraphicsFromLock = new StringBuilder(
0374 "componentObtainingGraphicsFrom");
0375
0376 /**
0377 * AA text hints.
0378 */
0379 transient private Object aaTextInfo;
0380
0381 static Graphics safelyGetGraphics(Component c) {
0382 return safelyGetGraphics(c, SwingUtilities.getRoot(c));
0383 }
0384
0385 static Graphics safelyGetGraphics(Component c, Component root) {
0386 synchronized (componentObtainingGraphicsFromLock) {
0387 componentObtainingGraphicsFrom = root;
0388 Graphics g = c.getGraphics();
0389 componentObtainingGraphicsFrom = null;
0390 return g;
0391 }
0392 }
0393
0394 static void getGraphicsInvoked(Component root) {
0395 if (!JComponent.isComponentObtainingGraphicsFrom(root)) {
0396 JRootPane rootPane = ((RootPaneContainer) root)
0397 .getRootPane();
0398 if (rootPane != null) {
0399 rootPane.disableTrueDoubleBuffering();
0400 }
0401 }
0402 }
0403
0404 /**
0405 * Returns true if {@code c} is the component the graphics is being
0406 * requested of. This is intended for use when getGraphics is invoked.
0407 */
0408 private static boolean isComponentObtainingGraphicsFrom(Component c) {
0409 synchronized (componentObtainingGraphicsFromLock) {
0410 return (componentObtainingGraphicsFrom == c);
0411 }
0412 }
0413
0414 /**
0415 * Returns the Set of <code>KeyStroke</code>s to use if the component
0416 * is managing focus for forward focus traversal.
0417 */
0418 static Set<KeyStroke> getManagingFocusForwardTraversalKeys() {
0419 synchronized (JComponent.class) {
0420 if (managingFocusForwardTraversalKeys == null) {
0421 managingFocusForwardTraversalKeys = new HashSet<KeyStroke>(
0422 1);
0423 managingFocusForwardTraversalKeys.add(KeyStroke
0424 .getKeyStroke(KeyEvent.VK_TAB,
0425 InputEvent.CTRL_MASK));
0426 }
0427 }
0428 return managingFocusForwardTraversalKeys;
0429 }
0430
0431 /**
0432 * Returns the Set of <code>KeyStroke</code>s to use if the component
0433 * is managing focus for backward focus traversal.
0434 */
0435 static Set<KeyStroke> getManagingFocusBackwardTraversalKeys() {
0436 synchronized (JComponent.class) {
0437 if (managingFocusBackwardTraversalKeys == null) {
0438 managingFocusBackwardTraversalKeys = new HashSet<KeyStroke>(
0439 1);
0440 managingFocusBackwardTraversalKeys.add(KeyStroke
0441 .getKeyStroke(KeyEvent.VK_TAB,
0442 InputEvent.SHIFT_MASK
0443 | InputEvent.CTRL_MASK));
0444 }
0445 }
0446 return managingFocusBackwardTraversalKeys;
0447 }
0448
0449 private static Rectangle fetchRectangle() {
0450 synchronized (tempRectangles) {
0451 Rectangle rect;
0452 int size = tempRectangles.size();
0453 if (size > 0) {
0454 rect = (Rectangle) tempRectangles.remove(size - 1);
0455 } else {
0456 rect = new Rectangle(0, 0, 0, 0);
0457 }
0458 return rect;
0459 }
0460 }
0461
0462 private static void recycleRectangle(Rectangle rect) {
0463 synchronized (tempRectangles) {
0464 tempRectangles.add(rect);
0465 }
0466 }
0467
0468 /**
0469 * Sets whether or not <code>getComponentPopupMenu</code> should delegate
0470 * to the parent if this component does not have a <code>JPopupMenu</code>
0471 * assigned to it.
0472 * <p>
0473 * The default value for this is false, but some <code>JComponent</code>
0474 * subclasses that are implemented as a number of <code>JComponent</code>s
0475 * may set this to true.
0476 * <p>
0477 * This is a bound property.
0478 *
0479 * @param value whether or not the JPopupMenu is inherited
0480 * @see #setComponentPopupMenu
0481 * @beaninfo
0482 * bound: true
0483 * description: Whether or not the JPopupMenu is inherited
0484 * @since 1.5
0485 */
0486 public void setInheritsPopupMenu(boolean value) {
0487 boolean oldValue = getFlag(INHERITS_POPUP_MENU);
0488 setFlag(INHERITS_POPUP_MENU, value);
0489 firePropertyChange("inheritsPopupMenu", oldValue, value);
0490 }
0491
0492 /**
0493 * Returns true if the JPopupMenu should be inherited from the parent.
0494 *
0495 * @see #setComponentPopupMenu
0496 * @since 1.5
0497 */
0498 public boolean getInheritsPopupMenu() {
0499 return getFlag(INHERITS_POPUP_MENU);
0500 }
0501
0502 /**
0503 * Sets the <code>JPopupMenu</code> for this <code>JComponent</code>.
0504 * The UI is responsible for registering bindings and adding the necessary
0505 * listeners such that the <code>JPopupMenu</code> will be shown at
0506 * the appropriate time. When the <code>JPopupMenu</code> is shown
0507 * depends upon the look and feel: some may show it on a mouse event,
0508 * some may enable a key binding.
0509 * <p>
0510 * If <code>popup</code> is null, and <code>getInheritsPopupMenu</code>
0511 * returns true, then <code>getComponentPopupMenu</code> will be delegated
0512 * to the parent. This provides for a way to make all child components
0513 * inherit the popupmenu of the parent.
0514 * <p>
0515 * This is a bound property.
0516 *
0517 * @param popup - the popup that will be assigned to this component
0518 * may be null
0519 * @see #getComponentPopupMenu
0520 * @beaninfo
0521 * bound: true
0522 * preferred: true
0523 * description: Popup to show
0524 * @since 1.5
0525 */
0526 public void setComponentPopupMenu(JPopupMenu popup) {
0527 if (popup != null) {
0528 enableEvents(AWTEvent.MOUSE_EVENT_MASK);
0529 }
0530 JPopupMenu oldPopup = this .popupMenu;
0531 this .popupMenu = popup;
0532 firePropertyChange("componentPopupMenu", oldPopup, popup);
0533 }
0534
0535 /**
0536 * Returns <code>JPopupMenu</code> that assigned for this component.
0537 * If this component does not have a <code>JPopupMenu</code> assigned
0538 * to it and <code>getInheritsPopupMenu</code> is true, this
0539 * will return <code>getParent().getComponentPopupMenu()</code> (assuming
0540 * the parent is valid.)
0541 *
0542 * @return <code>JPopupMenu</code> assigned for this component
0543 * or <code>null</code> if no popup assigned
0544 * @see #setComponentPopupMenu
0545 * @since 1.5
0546 */
0547 public JPopupMenu getComponentPopupMenu() {
0548
0549 if (!getInheritsPopupMenu()) {
0550 return popupMenu;
0551 }
0552
0553 if (popupMenu == null) {
0554 // Search parents for its popup
0555 Container parent = getParent();
0556 while (parent != null) {
0557 if (parent instanceof JComponent) {
0558 return ((JComponent) parent)
0559 .getComponentPopupMenu();
0560 }
0561 if (parent instanceof Window
0562 || parent instanceof Applet) {
0563 // Reached toplevel, break and return null
0564 break;
0565 }
0566 parent = parent.getParent();
0567 }
0568 return null;
0569 }
0570
0571 return popupMenu;
0572 }
0573
0574 /**
0575 * Default <code>JComponent</code> constructor. This constructor does
0576 * very little initialization beyond calling the <code>Container</code>
0577 * constructor. For example, the initial layout manager is
0578 * <code>null</code>. It does, however, set the component's locale
0579 * property to the value returned by
0580 * <code>JComponent.getDefaultLocale</code>.
0581 *
0582 * @see #getDefaultLocale
0583 */
0584 public JComponent() {
0585 super ();
0586 // We enable key events on all JComponents so that accessibility
0587 // bindings will work everywhere. This is a partial fix to BugID
0588 // 4282211.
0589 enableEvents(AWTEvent.KEY_EVENT_MASK);
0590 if (isManagingFocus()) {
0591 LookAndFeel.installProperty(this ,
0592 "focusTraversalKeysForward",
0593 getManagingFocusForwardTraversalKeys());
0594 LookAndFeel.installProperty(this ,
0595 "focusTraversalKeysBackward",
0596 getManagingFocusBackwardTraversalKeys());
0597 }
0598
0599 super .setLocale(JComponent.getDefaultLocale());
0600 }
0601
0602 /**
0603 * Resets the UI property to a value from the current look and feel.
0604 * <code>JComponent</code> subclasses must override this method
0605 * like this:
0606 * <pre>
0607 * public void updateUI() {
0608 * setUI((SliderUI)UIManager.getUI(this);
0609 * }
0610 * </pre>
0611 *
0612 * @see #setUI
0613 * @see UIManager#getLookAndFeel
0614 * @see UIManager#getUI
0615 */
0616 public void updateUI() {
0617 }
0618
0619 /**
0620 * Sets the look and feel delegate for this component.
0621 * <code>JComponent</code> subclasses generally override this method
0622 * to narrow the argument type. For example, in <code>JSlider</code>:
0623 * <pre>
0624 * public void setUI(SliderUI newUI) {
0625 * super.setUI(newUI);
0626 * }
0627 * </pre>
0628 * <p>
0629 * Additionally <code>JComponent</code> subclasses must provide a
0630 * <code>getUI</code> method that returns the correct type. For example:
0631 * <pre>
0632 * public SliderUI getUI() {
0633 * return (SliderUI)ui;
0634 * }
0635 * </pre>
0636 *
0637 * @param newUI the new UI delegate
0638 * @see #updateUI
0639 * @see UIManager#getLookAndFeel
0640 * @see UIManager#getUI
0641 * @beaninfo
0642 * bound: true
0643 * hidden: true
0644 * attribute: visualUpdate true
0645 * description: The component's look and feel delegate.
0646 */
0647 protected void setUI(ComponentUI newUI) {
0648 /* We do not check that the UI instance is different
0649 * before allowing the switch in order to enable the
0650 * same UI instance *with different default settings*
0651 * to be installed.
0652 */
0653
0654 uninstallUIAndProperties();
0655
0656 // aaText shouldn't persist between look and feels, reset it.
0657 aaTextInfo = UIManager.getDefaults().get(
0658 SwingUtilities2.AA_TEXT_PROPERTY_KEY);
0659 ComponentUI oldUI = ui;
0660 ui = newUI;
0661 if (ui != null) {
0662 ui.installUI(this );
0663 }
0664
0665 firePropertyChange("UI", oldUI, newUI);
0666 revalidate();
0667 repaint();
0668 }
0669
0670 /**
0671 * Uninstalls the UI, if any, and any client properties designated
0672 * as being specific to the installed UI - instances of
0673 * {@code UIClientPropertyKey}.
0674 */
0675 private void uninstallUIAndProperties() {
0676 if (ui != null) {
0677 ui.uninstallUI(this );
0678 //clean UIClientPropertyKeys from client properties
0679 if (clientProperties != null) {
0680 synchronized (clientProperties) {
0681 Object[] clientPropertyKeys = clientProperties
0682 .getKeys(null);
0683 if (clientPropertyKeys != null) {
0684 for (Object key : clientPropertyKeys) {
0685 if (key instanceof UIClientPropertyKey) {
0686 putClientProperty(key, null);
0687 }
0688 }
0689 }
0690 }
0691 }
0692 }
0693 }
0694
0695 /**
0696 * Returns the <code>UIDefaults</code> key used to
0697 * look up the name of the <code>swing.plaf.ComponentUI</code>
0698 * class that defines the look and feel
0699 * for this component. Most applications will never need to
0700 * call this method. Subclasses of <code>JComponent</code> that support
0701 * pluggable look and feel should override this method to
0702 * return a <code>UIDefaults</code> key that maps to the
0703 * <code>ComponentUI</code> subclass that defines their look and feel.
0704 *
0705 * @return the <code>UIDefaults</code> key for a
0706 * <code>ComponentUI</code> subclass
0707 * @see UIDefaults#getUI
0708 * @beaninfo
0709 * expert: true
0710 * description: UIClassID
0711 */
0712 public String getUIClassID() {
0713 return uiClassID;
0714 }
0715
0716 /**
0717 * Returns the graphics object used to paint this component.
0718 * If <code>DebugGraphics</code> is turned on we create a new
0719 * <code>DebugGraphics</code> object if necessary.
0720 * Otherwise we just configure the
0721 * specified graphics object's foreground and font.
0722 *
0723 * @param g the original <code>Graphics</code> object
0724 * @return a <code>Graphics</code> object configured for this component
0725 */
0726 protected Graphics getComponentGraphics(Graphics g) {
0727 Graphics componentGraphics = g;
0728 if (ui != null && DEBUG_GRAPHICS_LOADED) {
0729 if ((DebugGraphics.debugComponentCount() != 0)
0730 && (shouldDebugGraphics() != 0)
0731 && !(g instanceof DebugGraphics)) {
0732 componentGraphics = new DebugGraphics(g, this );
0733 }
0734 }
0735 componentGraphics.setColor(getForeground());
0736 componentGraphics.setFont(getFont());
0737
0738 return componentGraphics;
0739 }
0740
0741 /**
0742 * Calls the UI delegate's paint method, if the UI delegate
0743 * is non-<code>null</code>. We pass the delegate a copy of the
0744 * <code>Graphics</code> object to protect the rest of the
0745 * paint code from irrevocable changes
0746 * (for example, <code>Graphics.translate</code>).
0747 * <p>
0748 * If you override this in a subclass you should not make permanent
0749 * changes to the passed in <code>Graphics</code>. For example, you
0750 * should not alter the clip <code>Rectangle</code> or modify the
0751 * transform. If you need to do these operations you may find it
0752 * easier to create a new <code>Graphics</code> from the passed in
0753 * <code>Graphics</code> and manipulate it. Further, if you do not
0754 * invoker super's implementation you must honor the opaque property,
0755 * that is
0756 * if this component is opaque, you must completely fill in the background
0757 * in a non-opaque color. If you do not honor the opaque property you
0758 * will likely see visual artifacts.
0759 * <p>
0760 * The passed in <code>Graphics</code> object might
0761 * have a transform other than the identify transform
0762 * installed on it. In this case, you might get
0763 * unexpected results if you cumulatively apply
0764 * another transform.
0765 *
0766 * @param g the <code>Graphics</code> object to protect
0767 * @see #paint
0768 * @see ComponentUI
0769 */
0770 protected void paintComponent(Graphics g) {
0771 if (ui != null) {
0772 Graphics scratchGraphics = (g == null) ? null : g.create();
0773 try {
0774 ui.update(scratchGraphics, this );
0775 } finally {
0776 scratchGraphics.dispose();
0777 }
0778 }
0779 }
0780
0781 /**
0782 * Paints this component's children.
0783 * If <code>shouldUseBuffer</code> is true,
0784 * no component ancestor has a buffer and
0785 * the component children can use a buffer if they have one.
0786 * Otherwise, one ancestor has a buffer currently in use and children
0787 * should not use a buffer to paint.
0788 * @param g the <code>Graphics</code> context in which to paint
0789 * @see #paint
0790 * @see java.awt.Container#paint
0791 */
0792 protected void paintChildren(Graphics g) {
0793 boolean isJComponent;
0794 Graphics sg = g;
0795
0796 synchronized (getTreeLock()) {
0797 int i = getComponentCount() - 1;
0798 if (i < 0) {
0799 return;
0800 }
0801 // If we are only to paint to a specific child, determine
0802 // its index.
0803 if (paintingChild != null
0804 && (paintingChild instanceof JComponent)
0805 && ((JComponent) paintingChild).isOpaque()) {
0806 for (; i >= 0; i--) {
0807 if (getComponent(i) == paintingChild) {
0808 break;
0809 }
0810 }
0811 }
0812 Rectangle tmpRect = fetchRectangle();
0813 boolean checkSiblings = (!isOptimizedDrawingEnabled() && checkIfChildObscuredBySibling());
0814 Rectangle clipBounds = null;
0815 if (checkSiblings) {
0816 clipBounds = sg.getClipBounds();
0817 if (clipBounds == null) {
0818 clipBounds = new Rectangle(0, 0, getWidth(),
0819 getHeight());
0820 }
0821 }
0822 boolean printing = getFlag(IS_PRINTING);
0823 for (; i >= 0; i--) {
0824 Component comp = getComponent(i);
0825 isJComponent = (comp instanceof JComponent);
0826 if (comp != null
0827 && (isJComponent || isLightweightComponent(comp))
0828 && (comp.isVisible() == true)) {
0829 Rectangle cr;
0830
0831 cr = comp.getBounds(tmpRect);
0832
0833 boolean hitClip = g.hitClip(cr.x, cr.y, cr.width,
0834 cr.height);
0835
0836 if (hitClip) {
0837 if (checkSiblings && i > 0) {
0838 int x = cr.x;
0839 int y = cr.y;
0840 int width = cr.width;
0841 int height = cr.height;
0842 SwingUtilities.computeIntersection(
0843 clipBounds.x, clipBounds.y,
0844 clipBounds.width,
0845 clipBounds.height, cr);
0846
0847 if (getObscuredState(i, cr.x, cr.y,
0848 cr.width, cr.height) == COMPLETELY_OBSCURED) {
0849 continue;
0850 }
0851 cr.x = x;
0852 cr.y = y;
0853 cr.width = width;
0854 cr.height = height;
0855 }
0856 Graphics cg = sg.create(cr.x, cr.y, cr.width,
0857 cr.height);
0858 cg.setColor(comp.getForeground());
0859 cg.setFont(comp.getFont());
0860 boolean shouldSetFlagBack = false;
0861 try {
0862 if (isJComponent) {
0863 if (getFlag(ANCESTOR_USING_BUFFER)) {
0864 ((JComponent) comp)
0865 .setFlag(
0866 ANCESTOR_USING_BUFFER,
0867 true);
0868 shouldSetFlagBack = true;
0869 }
0870 if (getFlag(IS_PAINTING_TILE)) {
0871 ((JComponent) comp).setFlag(
0872 IS_PAINTING_TILE, true);
0873 shouldSetFlagBack = true;
0874 }
0875 if (!printing) {
0876 ((JComponent) comp).paint(cg);
0877 } else {
0878 if (!getFlag(IS_PRINTING_ALL)) {
0879 comp.print(cg);
0880 } else {
0881 comp.printAll(cg);
0882 }
0883 }
0884 } else {
0885 if (!printing) {
0886 comp.paint(cg);
0887 } else {
0888 if (!getFlag(IS_PRINTING_ALL)) {
0889 comp.print(cg);
0890 } else {
0891 comp.printAll(cg);
0892 }
0893 }
0894 }
0895 } finally {
0896 cg.dispose();
0897 if (shouldSetFlagBack) {
0898 ((JComponent) comp).setFlag(
0899 ANCESTOR_USING_BUFFER, false);
0900 ((JComponent) comp).setFlag(
0901 IS_PAINTING_TILE, false);
0902 }
0903 }
0904 }
0905 }
0906
0907 }
0908 recycleRectangle(tmpRect);
0909 }
0910 }
0911
0912 /**
0913 * Paints the component's border.
0914 * <p>
0915 * If you override this in a subclass you should not make permanent
0916 * changes to the passed in <code>Graphics</code>. For example, you
0917 * should not alter the clip <code>Rectangle</code> or modify the
0918 * transform. If you need to do these operations you may find it
0919 * easier to create a new <code>Graphics</code> from the passed in
0920 * <code>Graphics</code> and manipulate it.
0921 *
0922 * @param g the <code>Graphics</code> context in which to paint
0923 *
0924 * @see #paint
0925 * @see #setBorder
0926 */
0927 protected void paintBorder(Graphics g) {
0928 Border border = getBorder();
0929 if (border != null) {
0930 border.paintBorder(this , g, 0, 0, getWidth(), getHeight());
0931 }
0932 }
0933
0934 /**
0935 * Calls <code>paint</code>. Doesn't clear the background but see
0936 * <code>ComponentUI.update</code>, which is called by
0937 * <code>paintComponent</code>.
0938 *
0939 * @param g the <code>Graphics</code> context in which to paint
0940 * @see #paint
0941 * @see #paintComponent
0942 * @see javax.swing.plaf.ComponentUI
0943 */
0944 public void update(Graphics g) {
0945 paint(g);
0946 }
0947
0948 /**
0949 * Invoked by Swing to draw components.
0950 * Applications should not invoke <code>paint</code> directly,
0951 * but should instead use the <code>repaint</code> method to
0952 * schedule the component for redrawing.
0953 * <p>
0954 * This method actually delegates the work of painting to three
0955 * protected methods: <code>paintComponent</code>,
0956 * <code>paintBorder</code>,
0957 * and <code>paintChildren</code>. They're called in the order
0958 * listed to ensure that children appear on top of component itself.
0959 * Generally speaking, the component and its children should not
0960 * paint in the insets area allocated to the border. Subclasses can
0961 * just override this method, as always. A subclass that just
0962 * wants to specialize the UI (look and feel) delegate's
0963 * <code>paint</code> method should just override
0964 * <code>paintComponent</code>.
0965 *
0966 * @param g the <code>Graphics</code> context in which to paint
0967 * @see #paintComponent
0968 * @see #paintBorder
0969 * @see #paintChildren
0970 * @see #getComponentGraphics
0971 * @see #repaint
0972 */
0973 public void paint(Graphics g) {
0974 boolean shouldClearPaintFlags = false;
0975
0976 if ((getWidth() <= 0) || (getHeight() <= 0)) {
0977 return;
0978 }
0979
0980 Graphics componentGraphics = getComponentGraphics(g);
0981 Graphics co = componentGraphics.create();
0982 try {
0983 RepaintManager repaintManager = RepaintManager
0984 .currentManager(this );
0985 Rectangle clipRect = co.getClipBounds();
0986 int clipX;
0987 int clipY;
0988 int clipW;
0989 int clipH;
0990 if (clipRect == null) {
0991 clipX = clipY = 0;
0992 clipW = getWidth();
0993 clipH = getHeight();
0994 } else {
0995 clipX = clipRect.x;
0996 clipY = clipRect.y;
0997 clipW = clipRect.width;
0998 clipH = clipRect.height;
0999 }
1000
1001 if (clipW > getWidth()) {
1002 clipW = getWidth();
1003 }
1004 if (clipH > getHeight()) {
1005 clipH = getHeight();
1006 }
1007
1008 if (getParent() != null
1009 && !(getParent() instanceof JComponent)) {
1010 adjustPaintFlags();
1011 shouldClearPaintFlags = true;
1012 }
1013
1014 int bw, bh;
1015 boolean printing = getFlag(IS_PRINTING);
1016 if (!printing && repaintManager.isDoubleBufferingEnabled()
1017 && !getFlag(ANCESTOR_USING_BUFFER)
1018 && isDoubleBuffered()) {
1019 repaintManager.beginPaint();
1020 try {
1021 repaintManager.paint(this , this , co, clipX, clipY,
1022 clipW, clipH);
1023 } finally {
1024 repaintManager.endPaint();
1025 }
1026 } else {
1027 // Will ocassionaly happen in 1.2, especially when printing.
1028 if (clipRect == null) {
1029 co.setClip(clipX, clipY, clipW, clipH);
1030 }
1031
1032 if (!rectangleIsObscured(clipX, clipY, clipW, clipH)) {
1033 if (!printing) {
1034 paintComponent(co);
1035 paintBorder(co);
1036 } else {
1037 printComponent(co);
1038 printBorder(co);
1039 }
1040 }
1041 if (!printing) {
1042 paintChildren(co);
1043 } else {
1044 printChildren(co);
1045 }
1046 }
1047 } finally {
1048 co.dispose();
1049 if (shouldClearPaintFlags) {
1050 setFlag(ANCESTOR_USING_BUFFER, false);
1051 setFlag(IS_PAINTING_TILE, false);
1052 setFlag(IS_PRINTING, false);
1053 setFlag(IS_PRINTING_ALL, false);
1054 }
1055 }
1056 }
1057
1058 // paint forcing use of the double buffer. This is used for historical
1059 // reasons: JViewport, when scrolling, previously directly invoked paint
1060 // while turning off double buffering at the RepaintManager level, this
1061 // codes simulates that.
1062 void paintForceDoubleBuffered(Graphics g) {
1063 RepaintManager rm = RepaintManager.currentManager(this );
1064 Rectangle clip = g.getClipBounds();
1065 rm.beginPaint();
1066 setFlag(IS_REPAINTING, true);
1067 try {
1068 rm.paint(this , this , g, clip.x, clip.y, clip.width,
1069 clip.height);
1070 } finally {
1071 rm.endPaint();
1072 setFlag(IS_REPAINTING, false);
1073 }
1074 }
1075
1076 /**
1077 * Returns true if this component, or any of its ancestors, are in
1078 * the processing of painting.
1079 */
1080 boolean isPainting() {
1081 Container component = this ;
1082 while (component != null) {
1083 if (component instanceof JComponent
1084 && ((JComponent) component)
1085 .getFlag(ANCESTOR_USING_BUFFER)) {
1086 return true;
1087 }
1088 component = component.getParent();
1089 }
1090 return false;
1091 }
1092
1093 private void adjustPaintFlags() {
1094 JComponent jparent = null;
1095 Container parent;
1096 for (parent = getParent(); parent != null; parent = parent
1097 .getParent()) {
1098 if (parent instanceof JComponent) {
1099 jparent = (JComponent) parent;
1100 if (jparent.getFlag(ANCESTOR_USING_BUFFER))
1101 setFlag(ANCESTOR_USING_BUFFER, true);
1102 if (jparent.getFlag(IS_PAINTING_TILE))
1103 setFlag(IS_PAINTING_TILE, true);
1104 if (jparent.getFlag(IS_PRINTING))
1105 setFlag(IS_PRINTING, true);
1106 if (jparent.getFlag(IS_PRINTING_ALL))
1107 setFlag(IS_PRINTING_ALL, true);
1108 break;
1109 }
1110 }
1111 }
1112
1113 /**
1114 * Invoke this method to print the component. This method invokes
1115 * <code>print</code> on the component.
1116 *
1117 * @param g the <code>Graphics</code> context in which to paint
1118 * @see #print
1119 * @see #printComponent
1120 * @see #printBorder
1121 * @see #printChildren
1122 */
1123 public void printAll(Graphics g) {
1124 setFlag(IS_PRINTING_ALL, true);
1125 try {
1126 print(g);
1127 } finally {
1128 setFlag(IS_PRINTING_ALL, false);
1129 }
1130 }
1131
1132 /**
1133 * Invoke this method to print the component to the specified
1134 * <code>Graphics</code>. This method will result in invocations
1135 * of <code>printComponent</code>, <code>printBorder</code> and
1136 * <code>printChildren</code>. It is recommended that you override
1137 * one of the previously mentioned methods rather than this one if
1138 * your intention is to customize the way printing looks. However,
1139 * it can be useful to override this method should you want to prepare
1140 * state before invoking the superclass behavior. As an example,
1141 * if you wanted to change the component's background color before
1142 * printing, you could do the following:
1143 * <pre>
1144 * public void print(Graphics g) {
1145 * Color orig = getBackground();
1146 * setBackground(Color.WHITE);
1147 *
1148 * // wrap in try/finally so that we always restore the state
1149 * try {
1150 * super.print(g);
1151 * } finally {
1152 * setBackground(orig);
1153 * }
1154 * }
1155 * </pre>
1156 * <p>
1157 * Alternatively, or for components that delegate painting to other objects,
1158 * you can query during painting whether or not the component is in the
1159 * midst of a print operation. The <code>isPaintingForPrint</code> method provides
1160 * this ability and its return value will be changed by this method: to
1161 * <code>true</code> immediately before rendering and to <code>false</code>
1162 * immediately after. With each change a property change event is fired on
1163 * this component with the name <code>"paintingForPrint"</code>.
1164 * <p>
1165 * This method sets the component's state such that the double buffer
1166 * will not be used: painting will be done directly on the passed in
1167 * <code>Graphics</code>.
1168 *
1169 * @param g the <code>Graphics</code> context in which to paint
1170 * @see #printComponent
1171 * @see #printBorder
1172 * @see #printChildren
1173 * @see #isPaintingForPrint
1174 */
1175 public void print(Graphics g) {
1176 setFlag(IS_PRINTING, true);
1177 firePropertyChange("paintingForPrint", false, true);
1178 try {
1179 paint(g);
1180 } finally {
1181 setFlag(IS_PRINTING, false);
1182 firePropertyChange("paintingForPrint", true, false);
1183 }
1184 }
1185
1186 /**
1187 * This is invoked during a printing operation. This is implemented to
1188 * invoke <code>paintComponent</code> on the component. Override this
1189 * if you wish to add special painting behavior when printing.
1190 *
1191 * @param g the <code>Graphics</code> context in which to paint
1192 * @see #print
1193 * @since 1.3
1194 */
1195 protected void printComponent(Graphics g) {
1196 paintComponent(g);
1197 }
1198
1199 /**
1200 * Prints this component's children. This is implemented to invoke
1201 * <code>paintChildren</code> on the component. Override this if you
1202 * wish to print the children differently than painting.
1203 *
1204 * @param g the <code>Graphics</code> context in which to paint
1205 * @see #print
1206 * @since 1.3
1207 */
1208 protected void printChildren(Graphics g) {
1209 paintChildren(g);
1210 }
1211
1212 /**
1213 * Prints the component's border. This is implemented to invoke
1214 * <code>paintBorder</code> on the component. Override this if you
1215 * wish to print the border differently that it is painted.
1216 *
1217 * @param g the <code>Graphics</code> context in which to paint
1218 * @see #print
1219 * @since 1.3
1220 */
1221 protected void printBorder(Graphics g) {
1222 paintBorder(g);
1223 }
1224
1225 /**
1226 * Returns true if the component is currently painting a tile.
1227 * If this method returns true, paint will be called again for another
1228 * tile. This method returns false if you are not painting a tile or
1229 * if the last tile is painted.
1230 * Use this method to keep some state you might need between tiles.
1231 *
1232 * @return true if the component is currently painting a tile,
1233 * false otherwise
1234 */
1235 public boolean isPaintingTile() {
1236 return getFlag(IS_PAINTING_TILE);
1237 }
1238
1239 /**
1240 * Returns <code>true</code> if the current painting operation on this
1241 * component is part of a <code>print</code> operation. This method is
1242 * useful when you want to customize what you print versus what you show
1243 * on the screen.
1244 * <p>
1245 * You can detect changes in the value of this property by listening for
1246 * property change events on this component with name
1247 * <code>"paintingForPrint"</code>.
1248 * <p>
1249 * Note: This method provides complimentary functionality to that provided
1250 * by other high level Swing printing APIs. However, it deals strictly with
1251 * painting and should not be confused as providing information on higher
1252 * level print processes. For example, a {@link javax.swing.JTable#print()}
1253 * operation doesn't necessarily result in a continuous rendering of the
1254 * full component, and the return value of this method can change multiple
1255 * times during that operation. It is even possible for the component to be
1256 * painted to the screen while the printing process is ongoing. In such a
1257 * case, the return value of this method is <code>true</code> when, and only
1258 * when, the table is being painted as part of the printing process.
1259 *
1260 * @return true if the current painting operation on this component
1261 * is part of a print operation
1262 * @see #print
1263 * @since 1.6
1264 */
1265 public final boolean isPaintingForPrint() {
1266 return getFlag(IS_PRINTING);
1267 }
1268
1269 /**
1270 * In release 1.4, the focus subsystem was rearchitected.
1271 * For more information, see
1272 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
1273 * How to Use the Focus Subsystem</a>,
1274 * a section in <em>The Java Tutorial</em>.
1275 * <p>
1276 * Changes this <code>JComponent</code>'s focus traversal keys to
1277 * CTRL+TAB and CTRL+SHIFT+TAB. Also prevents
1278 * <code>SortingFocusTraversalPolicy</code> from considering descendants
1279 * of this JComponent when computing a focus traversal cycle.
1280 *
1281 * @see java.awt.Component#setFocusTraversalKeys
1282 * @see SortingFocusTraversalPolicy
1283 * @deprecated As of 1.4, replaced by
1284 * <code>Component.setFocusTraversalKeys(int, Set)</code> and
1285 * <code>Container.setFocusCycleRoot(boolean)</code>.
1286 */
1287 @Deprecated
1288 public boolean isManagingFocus() {
1289 return false;
1290 }
1291
1292 private void registerNextFocusableComponent() {
1293 registerNextFocusableComponent(getNextFocusableComponent());
1294 }
1295
1296 private void registerNextFocusableComponent(
1297 Component nextFocusableComponent) {
1298 if (nextFocusableComponent == null) {
1299 return;
1300 }
1301
1302 Container nearestRoot = (isFocusCycleRoot()) ? this
1303 : getFocusCycleRootAncestor();
1304 FocusTraversalPolicy policy = nearestRoot
1305 .getFocusTraversalPolicy();
1306 if (!(policy instanceof LegacyGlueFocusTraversalPolicy)) {
1307 policy = new LegacyGlueFocusTraversalPolicy(policy);
1308 nearestRoot.setFocusTraversalPolicy(policy);
1309 }
1310 ((LegacyGlueFocusTraversalPolicy) policy)
1311 .setNextFocusableComponent(this , nextFocusableComponent);
1312 }
1313
1314 private void deregisterNextFocusableComponent() {
1315 Component nextFocusableComponent = getNextFocusableComponent();
1316 if (nextFocusableComponent == null) {
1317 return;
1318 }
1319
1320 Container nearestRoot = (isFocusCycleRoot()) ? this
1321 : getFocusCycleRootAncestor();
1322 if (nearestRoot == null) {
1323 return;
1324 }
1325 FocusTraversalPolicy policy = nearestRoot
1326 .getFocusTraversalPolicy();
1327 if (policy instanceof LegacyGlueFocusTraversalPolicy) {
1328 ((LegacyGlueFocusTraversalPolicy) policy)
1329 .unsetNextFocusableComponent(this ,
1330 nextFocusableComponent);
1331 }
1332 }
1333
1334 /**
1335 * In release 1.4, the focus subsystem was rearchitected.
1336 * For more information, see
1337 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
1338 * How to Use the Focus Subsystem</a>,
1339 * a section in <em>The Java Tutorial</em>.
1340 * <p>
1341 * Overrides the default <code>FocusTraversalPolicy</code> for this
1342 * <code>JComponent</code>'s focus traversal cycle by unconditionally
1343 * setting the specified <code>Component</code> as the next
1344 * <code>Component</code> in the cycle, and this <code>JComponent</code>
1345 * as the specified <code>Component</code>'s previous
1346 * <code>Component</code> in the cycle.
1347 *
1348 * @param aComponent the <code>Component</code> that should follow this
1349 * <code>JComponent</code> in the focus traversal cycle
1350 *
1351 * @see #getNextFocusableComponent
1352 * @see java.awt.FocusTraversalPolicy
1353 * @deprecated As of 1.4, replaced by <code>FocusTraversalPolicy</code>
1354 */
1355 @Deprecated
1356 public void setNextFocusableComponent(Component aComponent) {
1357 boolean displayable = isDisplayable();
1358 if (displayable) {
1359 deregisterNextFocusableComponent();
1360 }
1361 putClientProperty(NEXT_FOCUS, aComponent);
1362 if (displayable) {
1363 registerNextFocusableComponent(aComponent);
1364 }
1365 }
1366
1367 /**
1368 * In release 1.4, the focus subsystem was rearchitected.
1369 * For more information, see
1370 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
1371 * How to Use the Focus Subsystem</a>,
1372 * a section in <em>The Java Tutorial</em>.
1373 * <p>
1374 * Returns the <code>Component</code> set by a prior call to
1375 * <code>setNextFocusableComponent(Component)</code> on this
1376 * <code>JComponent</code>.
1377 *
1378 * @return the <code>Component</code> that will follow this
1379 * <code>JComponent</code> in the focus traversal cycle, or
1380 * <code>null</code> if none has been explicitly specified
1381 *
1382 * @see #setNextFocusableComponent
1383 * @deprecated As of 1.4, replaced by <code>FocusTraversalPolicy</code>.
1384 */
1385 @Deprecated
1386 public Component getNextFocusableComponent() {
1387 return (Component) getClientProperty(NEXT_FOCUS);
1388 }
1389
1390 /**
1391 * Provides a hint as to whether or not this <code>JComponent</code>
1392 * should get focus. This is only a hint, and it is up to consumers that
1393 * are requesting focus to honor this property. This is typically honored
1394 * for mouse operations, but not keyboard operations. For example, look
1395 * and feels could verify this property is true before requesting focus
1396 * during a mouse operation. This would often times be used if you did
1397 * not want a mouse press on a <code>JComponent</code> to steal focus,
1398 * but did want the <code>JComponent</code> to be traversable via the
1399 * keyboard. If you do not want this <code>JComponent</code> focusable at
1400 * all, use the <code>setFocusable</code> method instead.
1401 * <p>
1402 * Please see
1403 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
1404 * How to Use the Focus Subsystem</a>,
1405 * a section in <em>The Java Tutorial</em>,
1406 * for more information.
1407 *
1408 * @param requestFocusEnabled indicates whether you want this
1409 * <code>JComponent</code> to be focusable or not
1410 * @see <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
1411 * @see java.awt.Component#setFocusable
1412 */
1413 public void setRequestFocusEnabled(boolean requestFocusEnabled) {
1414 setFlag(REQUEST_FOCUS_DISABLED, !requestFocusEnabled);
1415 }
1416
1417 /**
1418 * Returns <code>true</code> if this <code>JComponent</code> should
1419 * get focus; otherwise returns <code>false</code>.
1420 * <p>
1421 * Please see
1422 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
1423 * How to Use the Focus Subsystem</a>,
1424 * a section in <em>The Java Tutorial</em>,
1425 * for more information.
1426 *
1427 * @return <code>true</code> if this component should get focus,
1428 * otherwise returns <code>false</code>
1429 * @see #setRequestFocusEnabled
1430 * @see <a href="../../java/awt/doc-files/FocusSpec.html">Focus
1431 * Specification</a>
1432 * @see java.awt.Component#isFocusable
1433 */
1434 public boolean isRequestFocusEnabled() {
1435 return !getFlag(REQUEST_FOCUS_DISABLED);
1436 }
1437
1438 /**
1439 * Requests that this <code>Component</code> gets the input focus.
1440 * Refer to {@link java.awt.Component#requestFocus()
1441 * Component.requestFocus()} for a complete description of
1442 * this method.
1443 * <p>
1444 * Note that the use of this method is discouraged because
1445 * its behavior is platform dependent. Instead we recommend the
1446 * use of {@link #requestFocusInWindow() requestFocusInWindow()}.
1447 * If you would like more information on focus, see
1448 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
1449 * How to Use the Focus Subsystem</a>,
1450 * a section in <em>The Java Tutorial</em>.
1451 *
1452 * @see java.awt.Component#requestFocusInWindow()
1453 * @see java.awt.Component#requestFocusInWindow(boolean)
1454 * @since 1.4
1455 */
1456 public void requestFocus() {
1457 super .requestFocus();
1458 }
1459
1460 /**
1461 * Requests that this <code>Component</code> gets the input focus.
1462 * Refer to {@link java.awt.Component#requestFocus(boolean)
1463 * Component.requestFocus(boolean)} for a complete description of
1464 * this method.
1465 * <p>
1466 * Note that the use of this method is discouraged because
1467 * its behavior is platform dependent. Instead we recommend the
1468 * use of {@link #requestFocusInWindow(boolean)
1469 * requestFocusInWindow(boolean)}.
1470 * If you would like more information on focus, see
1471 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
1472 * How to Use the Focus Subsystem</a>,
1473 * a section in <em>The Java Tutorial</em>.
1474 *
1475 * @param temporary boolean indicating if the focus change is temporary
1476 * @return <code>false</code> if the focus change request is guaranteed to
1477 * fail; <code>true</code> if it is likely to succeed
1478 * @see java.awt.Component#requestFocusInWindow()
1479 * @see java.awt.Component#requestFocusInWindow(boolean)
1480 * @since 1.4
1481 */
1482 public boolean requestFocus(boolean temporary) {
1483 return super .requestFocus(temporary);
1484 }
1485
1486 /**
1487 * Requests that this <code>Component</code> gets the input focus.
1488 * Refer to {@link java.awt.Component#requestFocusInWindow()
1489 * Component.requestFocusInWindow()} for a complete description of
1490 * this method.
1491 * <p>
1492 * If you would like more information on focus, see
1493 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
1494 * How to Use the Focus Subsystem</a>,
1495 * a section in <em>The Java Tutorial</em>.
1496 *
1497 * @return <code>false</code> if the focus change request is guaranteed to
1498 * fail; <code>true</code> if it is likely to succeed
1499 * @see java.awt.Component#requestFocusInWindow()
1500 * @see java.awt.Component#requestFocusInWindow(boolean)
1501 * @since 1.4
1502 */
1503 public boolean requestFocusInWindow() {
1504 return super .requestFocusInWindow();
1505 }
1506
1507 /**
1508 * Requests that this <code>Component</code> gets the input focus.
1509 * Refer to {@link java.awt.Component#requestFocusInWindow(boolean)
1510 * Component.requestFocusInWindow(boolean)} for a complete description of
1511 * this method.
1512 * <p>
1513 * If you would like more information on focus, see
1514 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
1515 * How to Use the Focus Subsystem</a>,
1516 * a section in <em>The Java Tutorial</em>.
1517 *
1518 * @param temporary boolean indicating if the focus change is temporary
1519 * @return <code>false</code> if the focus change request is guaranteed to
1520 * fail; <code>true</code> if it is likely to succeed
1521 * @see java.awt.Component#requestFocusInWindow()
1522 * @see java.awt.Component#requestFocusInWindow(boolean)
1523 * @since 1.4
1524 */
1525 protected boolean requestFocusInWindow(boolean temporary) {
1526 return super .requestFocusInWindow(temporary);
1527 }
1528
1529 /**
1530 * Requests that this Component get the input focus, and that this
1531 * Component's top-level ancestor become the focused Window. This component
1532 * must be displayable, visible, and focusable for the request to be
1533 * granted.
1534 * <p>
1535 * This method is intended for use by focus implementations. Client code
1536 * should not use this method; instead, it should use
1537 * <code>requestFocusInWindow()</code>.
1538 *
1539 * @see #requestFocusInWindow()
1540 */
1541 public void grabFocus() {
1542 requestFocus();
1543 }
1544
1545 /**
1546 * Sets the value to indicate whether input verifier for the
1547 * current focus owner will be called before this component requests
1548 * focus. The default is true. Set to false on components such as a
1549 * Cancel button or a scrollbar, which should activate even if the
1550 * input in the current focus owner is not "passed" by the input
1551 * verifier for that component.
1552 *
1553 * @param verifyInputWhenFocusTarget value for the
1554 * <code>verifyInputWhenFocusTarget</code> property
1555 * @see InputVerifier
1556 * @see #setInputVerifier
1557 * @see #getInputVerifier
1558 * @see #getVerifyInputWhenFocusTarget
1559 *
1560 * @since 1.3
1561 * @beaninfo
1562 * bound: true
1563 * description: Whether the Component verifies input before accepting
1564 * focus.
1565 */
1566 public void setVerifyInputWhenFocusTarget(
1567 boolean verifyInputWhenFocusTarget) {
1568 boolean oldVerifyInputWhenFocusTarget = this .verifyInputWhenFocusTarget;
1569 this .verifyInputWhenFocusTarget = verifyInputWhenFocusTarget;
1570 firePropertyChange("verifyInputWhenFocusTarget",
1571 oldVerifyInputWhenFocusTarget,
1572 verifyInputWhenFocusTarget);
1573 }
1574
1575 /**
1576 * Returns the value that indicates whether the input verifier for the
1577 * current focus owner will be called before this component requests
1578 * focus.
1579 *
1580 * @return value of the <code>verifyInputWhenFocusTarget</code> property
1581 *
1582 * @see InputVerifier
1583 * @see #setInputVerifier
1584 * @see #getInputVerifier
1585 * @see #setVerifyInputWhenFocusTarget
1586 *
1587 * @since 1.3
1588 */
1589 public boolean getVerifyInputWhenFocusTarget() {
1590 return verifyInputWhenFocusTarget;
1591 }
1592
1593 /**
1594 * Gets the <code>FontMetrics</code> for the specified <code>Font</code>.
1595 *
1596 * @param font the font for which font metrics is to be
1597 * obtained
1598 * @return the font metrics for <code>font</code>
1599 * @throws NullPointerException if <code>font</code> is null
1600 * @since 1.5
1601 */
1602 public FontMetrics getFontMetrics(Font font) {
1603 return SwingUtilities2.getFontMetrics(this , font);
1604 }
1605
1606 /**
1607 * Sets the preferred size of this component.
1608 * If <code>preferredSize</code> is <code>null</code>, the UI will
1609 * be asked for the preferred size.
1610 * @beaninfo
1611 * preferred: true
1612 * bound: true
1613 * description: The preferred size of the component.
1614 */
1615 public void setPreferredSize(Dimension preferredSize) {
1616 super .setPreferredSize(preferredSize);
1617 }
1618
1619 /**
1620 * If the <code>preferredSize</code> has been set to a
1621 * non-<code>null</code> value just returns it.
1622 * If the UI delegate's <code>getPreferredSize</code>
1623 * method returns a non <code>null</code> value then return that;
1624 * otherwise defer to the component's layout manager.
1625 *
1626 * @return the value of the <code>preferredSize</code> property
1627 * @see #setPreferredSize
1628 * @see ComponentUI
1629 */
1630 public Dimension getPreferredSize() {
1631 if (isPreferredSizeSet()) {
1632 return super .getPreferredSize();
1633 }
1634 Dimension size = null;
1635 if (ui != null) {
1636 size = ui.getPreferredSize(this );
1637 }
1638 return (size != null) ? size : super .getPreferredSize();
1639 }
1640
1641 /**
1642 * Sets the maximum size of this component to a constant
1643 * value. Subsequent calls to <code>getMaximumSize</code> will always
1644 * return this value; the component's UI will not be asked
1645 * to compute it. Setting the maximum size to <code>null</code>
1646 * restores the default behavior.
1647 *
1648 * @param maximumSize a <code>Dimension</code> containing the
1649 * desired maximum allowable size
1650 * @see #getMaximumSize
1651 * @beaninfo
1652 * bound: true
1653 * description: The maximum size of the component.
1654 */
1655 public void setMaximumSize(Dimension maximumSize) {
1656 super .setMaximumSize(maximumSize);
1657 }
1658
1659 /**
1660 * If the maximum size has been set to a non-<code>null</code> value
1661 * just returns it. If the UI delegate's <code>getMaximumSize</code>
1662 * method returns a non-<code>null</code> value then return that;
1663 * otherwise defer to the component's layout manager.
1664 *
1665 * @return the value of the <code>maximumSize</code> property
1666 * @see #setMaximumSize
1667 * @see ComponentUI
1668 */
1669 public Dimension getMaximumSize() {
1670 if (isMaximumSizeSet()) {
1671 return super .getMaximumSize();
1672 }
1673 Dimension size = null;
1674 if (ui != null) {
1675 size = ui.getMaximumSize(this );
1676 }
1677 return (size != null) ? size : super .getMaximumSize();
1678 }
1679
1680 /**
1681 * Sets the minimum size of this component to a constant
1682 * value. Subsequent calls to <code>getMinimumSize</code> will always
1683 * return this value; the component's UI will not be asked
1684 * to compute it. Setting the minimum size to <code>null</code>
1685 * restores the default behavior.
1686 *
1687 * @param minimumSize the new minimum size of this component
1688 * @see #getMinimumSize
1689 * @beaninfo
1690 * bound: true
1691 * description: The minimum size of the component.
1692 */
1693 public void setMinimumSize(Dimension minimumSize) {
1694 super .setMinimumSize(minimumSize);
1695 }
1696
1697 /**
1698 * If the minimum size has been set to a non-<code>null</code> value
1699 * just returns it. If the UI delegate's <code>getMinimumSize</code>
1700 * method returns a non-<code>null</code> value then return that; otherwise
1701 * defer to the component's layout manager.
1702 *
1703 * @return the value of the <code>minimumSize</code> property
1704 * @see #setMinimumSize
1705 * @see ComponentUI
1706 */
1707 public Dimension getMinimumSize() {
1708 if (isMinimumSizeSet()) {
1709 return super .getMinimumSize();
1710 }
1711 Dimension size = null;
1712 if (ui != null) {
1713 size = ui.getMinimumSize(this );
1714 }
1715 return (size != null) ? size : super .getMinimumSize();
1716 }
1717
1718 /**
1719 * Gives the UI delegate an opportunity to define the precise
1720 * shape of this component for the sake of mouse processing.
1721 *
1722 * @return true if this component logically contains x,y
1723 * @see java.awt.Component#contains(int, int)
1724 * @see ComponentUI
1725 */
1726 public boolean contains(int x, int y) {
1727 return (ui != null) ? ui.contains(this , x, y) : super .contains(
1728 x, y);
1729 }
1730
1731 /**
1732 * Sets the border of this component. The <code>Border</code> object is
1733 * responsible for defining the insets for the component
1734 * (overriding any insets set directly on the component) and
1735 * for optionally rendering any border decorations within the
1736 * bounds of those insets. Borders should be used (rather
1737 * than insets) for creating both decorative and non-decorative
1738 * (such as margins and padding) regions for a swing component.
1739 * Compound borders can be used to nest multiple borders within a
1740 * single component.
1741 * <p>
1742 * Although technically you can set the border on any object
1743 * that inherits from <code>JComponent</code>, the look and
1744 * feel implementation of many standard Swing components
1745 * doesn't work well with user-set borders. In general,
1746 * when you want to set a border on a standard Swing
1747 * component other than <code>JPanel</code> or <code>JLabel</code>,
1748 * we recommend that you put the component in a <code>JPanel</code>
1749 * and set the border on the <code>JPanel</code>.
1750 * <p>
1751 * This is a bound property.
1752 *
1753 * @param border the border to be rendered for this component
1754 * @see Border
1755 * @see CompoundBorder
1756 * @beaninfo
1757 * bound: true
1758 * preferred: true
1759 * attribute: visualUpdate true
1760 * description: The component's border.
1761 */
1762 public void setBorder(Border border) {
1763 Border oldBorder = this .border;
1764
1765 this .border = border;
1766 firePropertyChange("border", oldBorder, border);
1767 if (border != oldBorder) {
1768 if (border == null
1769 || oldBorder == null
1770 || !(border.getBorderInsets(this ).equals(oldBorder
1771 .getBorderInsets(this )))) {
1772 revalidate();
1773 }
1774 repaint();
1775 }
1776 }
1777
1778 /**
1779 * Returns the border of this component or <code>null</code> if no
1780 * border is currently set.
1781 *
1782 * @return the border object for this component
1783 * @see #setBorder
1784 */
1785 public Border getBorder() {
1786 return border;
1787 }
1788
1789 /**
1790 * If a border has been set on this component, returns the
1791 * border's insets; otherwise calls <code>super.getInsets</code>.
1792 *
1793 * @return the value of the insets property
1794 * @see #setBorder
1795 */
1796 public Insets getInsets() {
1797 if (border != null) {
1798 return border.getBorderInsets(this );
1799 }
1800 return super .getInsets();
1801 }
1802
1803 /**
1804 * Returns an <code>Insets</code> object containing this component's inset
1805 * values. The passed-in <code>Insets</code> object will be reused
1806 * if possible.
1807 * Calling methods cannot assume that the same object will be returned,
1808 * however. All existing values within this object are overwritten.
1809 * If <code>insets</code> is null, this will allocate a new one.
1810 *
1811 * @param insets the <code>Insets</code> object, which can be reused
1812 * @return the <code>Insets</code> object
1813 * @see #getInsets
1814 * @beaninfo
1815 * expert: true
1816 */
1817 public Insets getInsets(Insets insets) {
1818 if (insets == null) {
1819 insets = new Insets(0, 0, 0, 0);
1820 }
1821 if (border != null) {
1822 if (border instanceof AbstractBorder) {
1823 return ((AbstractBorder) border).getBorderInsets(this ,
1824 insets);
1825 } else {
1826 // Can't reuse border insets because the Border interface
1827 // can't be enhanced.
1828 return border.getBorderInsets(this );
1829 }
1830 } else {
1831 // super.getInsets() always returns an Insets object with
1832 // all of its value zeroed. No need for a new object here.
1833 insets.left = insets.top = insets.right = insets.bottom = 0;
1834 return insets;
1835 }
1836 }
1837
1838 /**
1839 * Overrides <code>Container.getAlignmentY</code> to return
1840 * the horizontal alignment.
1841 *
1842 * @return the value of the <code>alignmentY</code> property
1843 * @see #setAlignmentY
1844 * @see java.awt.Component#getAlignmentY
1845 */
1846 public float getAlignmentY() {
1847 if (isAlignmentYSet) {
1848 return alignmentY;
1849 }
1850 return super .getAlignmentY();
1851 }
1852
1853 /**
1854 * Sets the the horizontal alignment.
1855 *
1856 * @param alignmentY the new horizontal alignment
1857 * @see #getAlignmentY
1858 * @beaninfo
1859 * description: The preferred vertical alignment of the component.
1860 */
1861 public void setAlignmentY(float alignmentY) {
1862 this .alignmentY = alignmentY > 1.0f ? 1.0f
1863 : alignmentY < 0.0f ? 0.0f : alignmentY;
1864 isAlignmentYSet = true;
1865 }
1866
1867 /**
1868 * Overrides <code>Container.getAlignmentX</code> to return
1869 * the vertical alignment.
1870 *
1871 * @return the value of the <code>alignmentX</code> property
1872 * @see #setAlignmentX
1873 * @see java.awt.Component#getAlignmentX
1874 */
1875 public float getAlignmentX() {
1876 if (isAlignmentXSet) {
1877 return alignmentX;
1878 }
1879 return super .getAlignmentX();
1880 }
1881
1882 /**
1883 * Sets the the vertical alignment.
1884 *
1885 * @param alignmentX the new vertical alignment
1886 * @see #getAlignmentX
1887 * @beaninfo
1888 * description: The preferred horizontal alignment of the component.
1889 */
1890 public void setAlignmentX(float alignmentX) {
1891 this .alignmentX = alignmentX > 1.0f ? 1.0f
1892 : alignmentX < 0.0f ? 0.0f : alignmentX;
1893 isAlignmentXSet = true;
1894 }
1895
1896 /**
1897 * Sets the input verifier for this component.
1898 *
1899 * @param inputVerifier the new input verifier
1900 * @since 1.3
1901 * @see InputVerifier
1902 * @beaninfo
1903 * bound: true
1904 * description: The component's input verifier.
1905 */
1906 public void setInputVerifier(InputVerifier inputVerifier) {
1907 InputVerifier oldInputVerifier = (InputVerifier) getClientProperty(JComponent_INPUT_VERIFIER);
1908 putClientProperty(JComponent_INPUT_VERIFIER, inputVerifier);
1909 firePropertyChange("inputVerifier", oldInputVerifier,
1910 inputVerifier);
1911 }
1912
1913 /**
1914 * Returns the input verifier for this component.
1915 *
1916 * @return the <code>inputVerifier</code> property
1917 * @since 1.3
1918 * @see InputVerifier
1919 */
1920 public InputVerifier getInputVerifier() {
1921 return (InputVerifier) getClientProperty(JComponent_INPUT_VERIFIER);
1922 }
1923
1924 /**
1925 * Returns this component's graphics context, which lets you draw
1926 * on a component. Use this method to get a <code>Graphics</code> object and
1927 * then invoke operations on that object to draw on the component.
1928 * @return this components graphics context
1929 */
1930 public Graphics getGraphics() {
1931 if (DEBUG_GRAPHICS_LOADED && shouldDebugGraphics() != 0) {
1932 DebugGraphics graphics = new DebugGraphics(super
1933 .getGraphics(), this );
1934 return graphics;
1935 }
1936 return super .getGraphics();
1937 }
1938
1939 /** Enables or disables diagnostic information about every graphics
1940 * operation performed within the component or one of its children.
1941 *
1942 * @param debugOptions determines how the component should display
1943 * the information; one of the following options:
1944 * <ul>
1945 * <li>DebugGraphics.LOG_OPTION - causes a text message to be printed.
1946 * <li>DebugGraphics.FLASH_OPTION - causes the drawing to flash several
1947 * times.
1948 * <li>DebugGraphics.BUFFERED_OPTION - creates an
1949 * <code>ExternalWindow</code> that displays the operations
1950 * performed on the View's offscreen buffer.
1951 * <li>DebugGraphics.NONE_OPTION disables debugging.
1952 * <li>A value of 0 causes no changes to the debugging options.
1953 * </ul>
1954 * <code>debugOptions</code> is bitwise OR'd into the current value
1955 *
1956 * @beaninfo
1957 * preferred: true
1958 * enum: NONE_OPTION DebugGraphics.NONE_OPTION
1959 * LOG_OPTION DebugGraphics.LOG_OPTION
1960 * FLASH_OPTION DebugGraphics.FLASH_OPTION
1961 * BUFFERED_OPTION DebugGraphics.BUFFERED_OPTION
1962 * description: Diagnostic options for graphics operations.
1963 */
1964 public void setDebugGraphicsOptions(int debugOptions) {
1965 DebugGraphics.setDebugOptions(this , debugOptions);
1966 }
1967
1968 /** Returns the state of graphics debugging.
1969 *
1970 * @return a bitwise OR'd flag of zero or more of the following options:
1971 * <ul>
1972 * <li>DebugGraphics.LOG_OPTION - causes a text message to be printed.
1973 * <li>DebugGraphics.FLASH_OPTION - causes the drawing to flash several
1974 * times.
1975 * <li>DebugGraphics.BUFFERED_OPTION - creates an
1976 * <code>ExternalWindow</code> that displays the operations
1977 * performed on the View's offscreen buffer.
1978 * <li>DebugGraphics.NONE_OPTION disables debugging.
1979 * <li>A value of 0 causes no changes to the debugging options.
1980 * </ul>
1981 * @see #setDebugGraphicsOptions
1982 */
1983 public int getDebugGraphicsOptions() {
1984 return DebugGraphics.getDebugOptions(this );
1985 }
1986
1987 /**
1988 * Returns true if debug information is enabled for this
1989 * <code>JComponent</code> or one of its parents.
1990 */
1991 int shouldDebugGraphics() {
1992 return DebugGraphics.shouldComponentDebug(this );
1993 }
1994
1995 /**
1996 * This method is now obsolete, please use a combination of
1997 * <code>getActionMap()</code> and <code>getInputMap()</code> for
1998 * similiar behavior. For example, to bind the <code>KeyStroke</code>
1999 * <code>aKeyStroke</code> to the <code>Action</code> <code>anAction</code>
2000 * now use:
2001 * <pre>
2002 * component.getInputMap().put(aKeyStroke, aCommand);
2003 * component.getActionMap().put(aCommmand, anAction);
2004 * </pre>
2005 * The above assumes you want the binding to be applicable for
2006 * <code>WHEN_FOCUSED</code>. To register bindings for other focus
2007 * states use the <code>getInputMap</code> method that takes an integer.
2008 * <p>
2009 * Register a new keyboard action.
2010 * <code>anAction</code> will be invoked if a key event matching
2011 * <code>aKeyStroke</code> occurs and <code>aCondition</code> is verified.
2012 * The <code>KeyStroke</code> object defines a
2013 * particular combination of a keyboard key and one or more modifiers
2014 * (alt, shift, ctrl, meta).
2015 * <p>
2016 * The <code>aCommand</code> will be set in the delivered event if
2017 * specified.
2018 * <p>
2019 * The <code>aCondition</code> can be one of:
2020 * <blockquote>
2021 * <DL>
2022 * <DT>WHEN_FOCUSED
2023 * <DD>The action will be invoked only when the keystroke occurs
2024 * while the component has the focus.
2025 * <DT>WHEN_IN_FOCUSED_WINDOW
2026 * <DD>The action will be invoked when the keystroke occurs while
2027 * the component has the focus or if the component is in the
2028 * window that has the focus. Note that the component need not
2029 * be an immediate descendent of the window -- it can be
2030 * anywhere in the window's containment hierarchy. In other
2031 * words, whenever <em>any</em> component in the window has the focus,
2032 * the action registered with this component is invoked.
2033 * <DT>WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
2034 * <DD>The action will be invoked when the keystroke occurs while the
2035 * component has the focus or if the component is an ancestor of
2036 * the component that has the focus.
2037 * </DL>
2038 * </blockquote>
2039 * <p>
2040 * The combination of keystrokes and conditions lets you define high
2041 * level (semantic) action events for a specified keystroke+modifier
2042 * combination (using the KeyStroke class) and direct to a parent or
2043 * child of a component that has the focus, or to the component itself.
2044 * In other words, in any hierarchical structure of components, an
2045 * arbitrary key-combination can be immediately directed to the
2046 * appropriate component in the hierarchy, and cause a specific method
2047 * to be invoked (usually by way of adapter objects).
2048 * <p>
2049 * If an action has already been registered for the receiving
2050 * container, with the same charCode and the same modifiers,
2051 * <code>anAction</code> will replace the action.
2052 *
2053 * @param anAction the <code>Action</code> to be registered
2054 * @param aCommand the command to be set in the delivered event
2055 * @param aKeyStroke the <code>KeyStroke</code> to bind to the action
2056 * @param aCondition the condition that needs to be met, see above
2057 * @see KeyStroke
2058 */
2059 public void registerKeyboardAction(ActionListener anAction,
2060 String aCommand, KeyStroke aKeyStroke, int aCondition) {
2061
2062 InputMap inputMap = getInputMap(aCondition, true);
2063
2064 if (inputMap != null) {
2065 ActionMap actionMap = getActionMap(true);
2066 ActionStandin action = new ActionStandin(anAction, aCommand);
2067 inputMap.put(aKeyStroke, action);
2068 if (actionMap != null) {
2069 actionMap.put(action, action);
2070 }
2071 }
2072 }
2073
2074 /**
2075 * Registers any bound <code>WHEN_IN_FOCUSED_WINDOW</code> actions with
2076 * the <code>KeyboardManager</code>. If <code>onlyIfNew</code>
2077 * is true only actions that haven't been registered are pushed
2078 * to the <code>KeyboardManager</code>;
2079 * otherwise all actions are pushed to the <code>KeyboardManager</code>.
2080 *
2081 * @param onlyIfNew if true, only actions that haven't been registered
2082 * are pushed to the <code>KeyboardManager</code>
2083 */
2084 private void registerWithKeyboardManager(boolean onlyIfNew) {
2085 InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW, false);
2086 KeyStroke[] strokes;
2087 Hashtable registered = (Hashtable) getClientProperty(WHEN_IN_FOCUSED_WINDOW_BINDINGS);
2088
2089 if (inputMap != null) {
2090 // Push any new KeyStrokes to the KeyboardManager.
2091 strokes = inputMap.allKeys();
2092 if (strokes != null) {
2093 for (int counter = strokes.length - 1; counter >= 0; counter--) {
2094 if (!onlyIfNew || registered == null
2095 || registered.get(strokes[counter]) == null) {
2096 registerWithKeyboardManager(strokes[counter]);
2097 }
2098 if (registered != null) {
2099 registered.remove(strokes[counter]);
2100 }
2101 }
2102 }
2103 } else {
2104 strokes = null;
2105 }
2106 // Remove any old ones.
2107 if (registered != null && registered.size() > 0) {
2108 Enumeration keys = registered.keys();
2109
2110 while (keys.hasMoreElements()) {
2111 KeyStroke ks = (KeyStroke) keys.nextElement();
2112 unregisterWithKeyboardManager(ks);
2113 }
2114 registered.clear();
2115 }
2116 // Updated the registered Hashtable.
2117 if (strokes != null && strokes.length > 0) {
2118 if (registered == null) {
2119 registered = new Hashtable(strokes.length);
2120 putClientProperty(WHEN_IN_FOCUSED_WINDOW_BINDINGS,
2121 registered);
2122 }
2123 for (int counter = strokes.length - 1; counter >= 0; counter--) {
2124 registered.put(strokes[counter], strokes[counter]);
2125 }
2126 } else {
2127 putClientProperty(WHEN_IN_FOCUSED_WINDOW_BINDINGS, null);
2128 }
2129 }
2130
2131 /**
2132 * Unregisters all the previously registered
2133 * <code>WHEN_IN_FOCUSED_WINDOW</code> <code>KeyStroke</code> bindings.
2134 */
2135 private void unregisterWithKeyboardManager() {
2136 Hashtable registered = (Hashtable) getClientProperty(WHEN_IN_FOCUSED_WINDOW_BINDINGS);
2137
2138 if (registered != null && registered.size() > 0) {
2139 Enumeration keys = registered.keys();
2140
2141 while (keys.hasMoreElements()) {
2142 KeyStroke ks = (KeyStroke) keys.nextElement();
2143 unregisterWithKeyboardManager(ks);
2144 }
2145 }
2146 putClientProperty(WHEN_IN_FOCUSED_WINDOW_BINDINGS, null);
2147 }
2148
2149 /**
2150 * Invoked from <code>ComponentInputMap</code> when its bindings change.
2151 * If <code>inputMap</code> is the current <code>windowInputMap</code>
2152 * (or a parent of the window <code>InputMap</code>)
2153 * the <code>KeyboardManager</code> is notified of the new bindings.
2154 *
2155 * @param inputMap the map containing the new bindings
2156 */
2157 void componentInputMapChanged(ComponentInputMap inputMap) {
2158 InputMap km = getInputMap(WHEN_IN_FOCUSED_WINDOW, false);
2159
2160 while (km != inputMap && km != null) {
2161 km = (ComponentInputMap) km.getParent();
2162 }
2163 if (km != null) {
2164 registerWithKeyboardManager(false);
2165 }
2166 }
2167
2168 private void registerWithKeyboardManager(KeyStroke aKeyStroke) {
2169 KeyboardManager.getCurrentManager().registerKeyStroke(
2170 aKeyStroke, this );
2171 }
2172
2173 private void unregisterWithKeyboardManager(KeyStroke aKeyStroke) {
2174 KeyboardManager.getCurrentManager().unregisterKeyStroke(
2175 aKeyStroke, this );
2176 }
2177
2178 /**
2179 * This method is now obsolete, please use a combination of
2180 * <code>getActionMap()</code> and <code>getInputMap()</code> for
2181 * similiar behavior.
2182 */
2183 public void registerKeyboardAction(ActionListener anAction,
2184 KeyStroke aKeyStroke, int aCondition) {
2185 registerKeyboardAction(anAction, null, aKeyStroke, aCondition);
2186 }
2187
2188 /**
2189 * This method is now obsolete. To unregister an existing binding
2190 * you can either remove the binding from the
2191 * <code>ActionMap/InputMap</code>, or place a dummy binding the
2192 * <code>InputMap</code>. Removing the binding from the
2193 * <code>InputMap</code> allows bindings in parent <code>InputMap</code>s
2194 * to be active, whereas putting a dummy binding in the
2195 * <code>InputMap</code> effectively disables
2196 * the binding from ever happening.
2197 * <p>
2198 * Unregisters a keyboard action.
2199 * This will remove the binding from the <code>ActionMap</code>
2200 * (if it exists) as well as the <code>InputMap</code>s.
2201 */
2202 public void unregisterKeyboardAction(KeyStroke aKeyStroke) {
2203 ActionMap am = getActionMap(false);
2204 for (int counter = 0; counter < 3; counter++) {
2205 InputMap km = getInputMap(counter, false);
2206 if (km != null) {
2207 Object actionID = km.get(aKeyStroke);
2208
2209 if (am != null && actionID != null) {
2210 am.remove(actionID);
2211 }
2212 km.remove(aKeyStroke);
2213 }
2214 }
2215 }
2216
2217 /**
2218 * Returns the <code>KeyStrokes</code> that will initiate
2219 * registered actions.
2220 *
2221 * @return an array of <code>KeyStroke</code> objects
2222 * @see #registerKeyboardAction
2223 */
2224 public KeyStroke[] getRegisteredKeyStrokes() {
2225 int[] counts = new int[3];
2226 KeyStroke[][] strokes = new KeyStroke[3][];
2227
2228 for (int counter = 0; counter < 3; counter++) {
2229 InputMap km = getInputMap(counter, false);
2230 strokes[counter] = (km != null) ? km.allKeys() : null;
2231 counts[counter] = (strokes[counter] != null) ? strokes[counter].length
2232 : 0;
2233 }
2234 KeyStroke[] retValue = new KeyStroke[counts[0] + counts[1]
2235 + counts[2]];
2236 for (int counter = 0, last = 0; counter < 3; counter++) {
2237 if (counts[counter] > 0) {
2238 System.arraycopy(strokes[counter], 0, retValue, last,
2239 counts[counter]);
2240 last += counts[counter];
2241 }
2242 }
2243 return retValue;
2244 }
2245
2246 /**
2247 * Returns the condition that determines whether a registered action
2248 * occurs in response to the specified keystroke.
2249 * <p>
2250 * For Java 2 platform v1.3, a <code>KeyStroke</code> can be associated
2251 * with more than one condition.
2252 * For example, 'a' could be bound for the two
2253 * conditions <code>WHEN_FOCUSED</code> and
2254 * <code>WHEN_IN_FOCUSED_WINDOW</code> condition.
2255 *
2256 * @return the action-keystroke condition
2257 */
2258 public int getConditionForKeyStroke(KeyStroke aKeyStroke) {
2259 for (int counter = 0; counter < 3; counter++) {
2260 InputMap inputMap = getInputMap(counter, false);
2261 if (inputMap != null && inputMap.get(aKeyStroke) != null) {
2262 return counter;
2263 }
2264 }
2265 return UNDEFINED_CONDITION;
2266 }
2267
2268 /**
2269 * Returns the object that will perform the action registered for a
2270 * given keystroke.
2271 *
2272 * @return the <code>ActionListener</code>
2273 * object invoked when the keystroke occurs
2274 */
2275 public ActionListener getActionForKeyStroke(KeyStroke aKeyStroke) {
2276 ActionMap am = getActionMap(false);
2277
2278 if (am == null) {
2279 return null;
2280 }
2281 for (int counter = 0; counter < 3; counter++) {
2282 InputMap inputMap = getInputMap(counter, false);
2283 if (inputMap != null) {
2284 Object actionBinding = inputMap.get(aKeyStroke);
2285
2286 if (actionBinding != null) {
2287 Action action = am.get(actionBinding);
2288 if (action instanceof ActionStandin) {
2289 return ((ActionStandin) action).actionListener;
2290 }
2291 return action;
2292 }
2293 }
2294 }
2295 return null;
2296 }
2297
2298 /**
2299 * Unregisters all the bindings in the first tier <code>InputMaps</code>
2300 * and <code>ActionMap</code>. This has the effect of removing any
2301 * local bindings, and allowing the bindings defined in parent
2302 * <code>InputMap/ActionMaps</code>
2303 * (the UI is usually defined in the second tier) to persist.
2304 */
2305 public void resetKeyboardActions() {
2306 // Keys
2307 for (int counter = 0; counter < 3; counter++) {
2308 InputMap inputMap = getInputMap(counter, false);
2309
2310 if (inputMap != null) {
2311 inputMap.clear();
2312 }
2313 }
2314
2315 // Actions
2316 ActionMap am = getActionMap(false);
2317
2318 if (am != null) {
2319 am.clear();
2320 }
2321 }
2322
2323 /**
2324 * Sets the <code>InputMap</code> to use under the condition
2325 * <code>condition</code> to
2326 * <code>map</code>. A <code>null</code> value implies you
2327 * do not want any bindings to be used, even from the UI. This will
2328 * not reinstall the UI <code>InputMap</code> (if there was one).
2329 * <code>condition</code> has one of the following values:
2330 * <ul>
2331 * <li><code>WHEN_IN_FOCUSED_WINDOW</code>
2332 * <li><code>WHEN_FOCUSED</code>
2333 * <li><code>WHEN_ANCESTOR_OF_FOCUSED_COMPONENT</code>
2334 * </ul>
2335 * If <code>condition</code> is <code>WHEN_IN_FOCUSED_WINDOW</code>
2336 * and <code>map</code> is not a <code>ComponentInputMap</code>, an
2337 * <code>IllegalArgumentException</code> will be thrown.
2338 * Similarly, if <code>condition</code> is not one of the values
2339 * listed, an <code>IllegalArgumentException</code> will be thrown.
2340 *
2341 * @param condition one of the values listed above
2342 * @param map the <code>InputMap</code> to use for the given condition
2343 * @exception IllegalArgumentException if <code>condition</code> is
2344 * <code>WHEN_IN_FOCUSED_WINDOW</code> and <code>map</code>
2345 * is not an instance of <code>ComponentInputMap</code>; or
2346 * if <code>condition</code> is not one of the legal values
2347 * specified above
2348 * @since 1.3
2349 */
2350 public final void setInputMap(int condition, InputMap map) {
2351 switch (condition) {
2352 case WHEN_IN_FOCUSED_WINDOW:
2353 if (map != null && !(map instanceof ComponentInputMap)) {
2354 throw new IllegalArgumentException(
2355 "WHEN_IN_FOCUSED_WINDOW InputMaps must be of type ComponentInputMap");
2356 }
2357 windowInputMap = (ComponentInputMap) map;
2358 setFlag(WIF_INPUTMAP_CREATED, true);
2359 registerWithKeyboardManager(false);
2360 break;
2361 case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT:
2362 ancestorInputMap = map;
2363 setFlag(ANCESTOR_INPUTMAP_CREATED, true);
2364 break;
2365 case WHEN_FOCUSED:
2366 focusInputMap = map;
2367 setFlag(FOCUS_INPUTMAP_CREATED, true);
2368 break;
2369 default:
2370 throw new IllegalArgumentException(
2371 "condition must be one of JComponent.WHEN_IN_FOCUSED_WINDOW, JComponent.WHEN_FOCUSED or JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT");
2372 }
2373 }
2374
2375 /**
2376 * Returns the <code>InputMap</code> that is used during
2377 * <code>condition</code>.
2378 *
2379 * @param condition one of WHEN_IN_FOCUSED_WINDOW, WHEN_FOCUSED,
2380 * WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
2381 * @return the <code>InputMap</code> for the specified
2382 * <code>condition</code>
2383 * @since 1.3
2384 */
2385 public final InputMap getInputMap(int condition) {
2386 return getInputMap(condition, true);
2387 }
2388
2389 /**
2390 * Returns the <code>InputMap</code> that is used when the
2391 * component has focus.
2392 * This is convenience method for <code>getInputMap(WHEN_FOCUSED)</code>.
2393 *
2394 * @return the <code>InputMap</code> used when the component has focus
2395 * @since 1.3
2396 */
2397 public final InputMap getInputMap() {
2398 return getInputMap(WHEN_FOCUSED, true);
2399 }
2400
2401 /**
2402 * Sets the <code>ActionMap</code> to <code>am</code>. This does not set
2403 * the parent of the <code>am</code> to be the <code>ActionMap</code>
2404 * from the UI (if there was one), it is up to the caller to have done this.
2405 *
2406 * @param am the new <code>ActionMap</code>
2407 * @since 1.3
2408 */
2409 public final void setActionMap(ActionMap am) {
2410 actionMap = am;
2411 setFlag(ACTIONMAP_CREATED, true);
2412 }
2413
2414 /**
2415 * Returns the <code>ActionMap</code> used to determine what
2416 * <code>Action</code> to fire for particular <code>KeyStroke</code>
2417 * binding. The returned <code>ActionMap</code>, unless otherwise
2418 * set, will have the <code>ActionMap</code> from the UI set as the parent.
2419 *
2420 * @return the <code>ActionMap</code> containing the key/action bindings
2421 * @since 1.3
2422 */
2423 public final ActionMap getActionMap() {
2424 return getActionMap(true);
2425 }
2426
2427 /**
2428 * Returns the <code>InputMap</code> to use for condition
2429 * <code>condition</code>. If the <code>InputMap</code> hasn't
2430 * been created, and <code>create</code> is
2431 * true, it will be created.
2432 *
2433 * @param condition one of the following values:
2434 * <ul>
2435 * <li>JComponent.FOCUS_INPUTMAP_CREATED
2436 * <li>JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
2437 * <li>JComponent.WHEN_IN_FOCUSED_WINDOW
2438 * </ul>
2439 * @param create if true, create the <code>InputMap</code> if it
2440 * is not already created
2441 * @return the <code>InputMap</code> for the given <code>condition</code>;
2442 * if <code>create</code> is false and the <code>InputMap</code>
2443 * hasn't been created, returns <code>null</code>
2444 * @exception IllegalArgumentException if <code>condition</code>
2445 * is not one of the legal values listed above
2446 */
2447 final InputMap getInputMap(int condition, boolean create) {
2448 switch (condition) {
2449 case WHEN_FOCUSED:
2450 if (getFlag(FOCUS_INPUTMAP_CREATED)) {
2451 return focusInputMap;
2452 }
2453 // Hasn't been created yet.
2454 if (create) {
2455 InputMap km = new InputMap();
2456 setInputMap(condition, km);
2457 return km;
2458 }
2459 break;
2460 case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT:
2461 if (getFlag(ANCESTOR_INPUTMAP_CREATED)) {
2462 return ancestorInputMap;
2463 }
2464 // Hasn't been created yet.
2465 if (create) {
2466 InputMap km = new InputMap();
2467 setInputMap(condition, km);
2468 return km;
2469 }
2470 break;
2471 case WHEN_IN_FOCUSED_WINDOW:
2472 if (getFlag(WIF_INPUTMAP_CREATED)) {
2473 return windowInputMap;
2474 }
2475 // Hasn't been created yet.
2476 if (create) {
2477 ComponentInputMap km = new ComponentInputMap(this );
2478 setInputMap(condition, km);
2479 return km;
2480 }
2481 break;
2482 default:
2483 throw new IllegalArgumentException(
2484 "condition must be one of JComponent.WHEN_IN_FOCUSED_WINDOW, JComponent.WHEN_FOCUSED or JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT");
2485 }
2486 return null;
2487 }
2488
2489 /**
2490 * Finds and returns the appropriate <code>ActionMap</code>.
2491 *
2492 * @param create if true, create the <code>ActionMap</code> if it
2493 * is not already created
2494 * @return the <code>ActionMap</code> for this component; if the
2495 * <code>create</code> flag is false and there is no
2496 * current <code>ActionMap</code>, returns <code>null</code>
2497 */
2498 final ActionMap getActionMap(boolean create) {
2499 if (getFlag(ACTIONMAP_CREATED)) {
2500 return actionMap;
2501 }
2502 // Hasn't been created.
2503 if (create) {
2504 ActionMap am = new ActionMap();
2505 setActionMap(am);
2506 return am;
2507 }
2508 return null;
2509 }
2510
2511 /**
2512 * Returns the baseline. The baseline is measured from the top of
2513 * the component. This method is primarily meant for
2514 * <code>LayoutManager</code>s to align components along their
2515 * baseline. A return value less than 0 indicates this component
2516 * does not have a reasonable baseline and that
2517 * <code>LayoutManager</code>s should not align this component on
2518 * its baseline.
2519 * <p>
2520 * This method calls into the <code>ComponentUI</code> method of the
2521 * same name. If this component does not have a <code>ComponentUI</code>
2522 * -1 will be returned. If a value >= 0 is
2523 * returned, then the component has a valid baseline for any
2524 * size >= the minimum size and <code>getBaselineResizeBehavior</code>
2525 * can be used to determine how the baseline changes with size.
2526 *
2527 * @throws IllegalArgumentException {@inheritDoc}
2528 * @see #getBaselineResizeBehavior
2529 * @see java.awt.FontMetrics
2530 * @since 1.6
2531 */
2532 public int getBaseline(int width, int height) {
2533 // check size.
2534 super .getBaseline(width, height);
2535 if (ui != null) {
2536 return ui.getBaseline(this , width, height);
2537 }
2538 return -1;
2539 }
2540
2541 /**
2542 * Returns an enum indicating how the baseline of the component
2543 * changes as the size changes. This method is primarily meant for
2544 * layout managers and GUI builders.
2545 * <p>
2546 * This method calls into the <code>ComponentUI</code> method of
2547 * the same name. If this component does not have a
2548 * <code>ComponentUI</code>
2549 * <code>BaselineResizeBehavior.OTHER</code> will be
2550 * returned. Subclasses should
2551 * never return <code>null</code>; if the baseline can not be
2552 * calculated return <code>BaselineResizeBehavior.OTHER</code>. Callers
2553 * should first ask for the baseline using
2554 * <code>getBaseline</code> and if a value >= 0 is returned use
2555 * this method. It is acceptable for this method to return a
2556 * value other than <code>BaselineResizeBehavior.OTHER</code> even if
2557 * <code>getBaseline</code> returns a value less than 0.
2558 *
2559 * @see #getBaseline(int, int)
2560 * @since 1.6
2561 */
2562 public BaselineResizeBehavior getBaselineResizeBehavior() {
2563 if (ui != null) {
2564 return ui.getBaselineResizeBehavior(this );
2565 }
2566 return BaselineResizeBehavior.OTHER;
2567 }
2568
2569 /**
2570 * In release 1.4, the focus subsystem was rearchitected.
2571 * For more information, see
2572 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
2573 * How to Use the Focus Subsystem</a>,
2574 * a section in <em>The Java Tutorial</em>.
2575 * <p>
2576 * Requests focus on this <code>JComponent</code>'s
2577 * <code>FocusTraversalPolicy</code>'s default <code>Component</code>.
2578 * If this <code>JComponent</code> is a focus cycle root, then its
2579 * <code>FocusTraversalPolicy</code> is used. Otherwise, the
2580 * <code>FocusTraversalPolicy</code> of this <code>JComponent</code>'s
2581 * focus-cycle-root ancestor is used.
2582 *
2583 * @see java.awt.FocusTraversalPolicy#getDefaultComponent
2584 * @deprecated As of 1.4, replaced by
2585 * <code>FocusTraversalPolicy.getDefaultComponent(Container).requestFocus()</code>
2586 */
2587 @Deprecated
2588 public boolean requestDefaultFocus() {
2589 Container nearestRoot = (isFocusCycleRoot()) ? this
2590 : getFocusCycleRootAncestor();
2591 if (nearestRoot == null) {
2592 return false;
2593 }
2594 Component comp = nearestRoot.getFocusTraversalPolicy()
2595 .getDefaultComponent(nearestRoot);
2596 if (comp != null) {
2597 comp.requestFocus();
2598 return true;
2599 } else {
2600 return false;
2601 }
2602 }
2603
2604 /**
2605 * Makes the component visible or invisible.
2606 * Overrides <code>Component.setVisible</code>.
2607 *
2608 * @param aFlag true to make the component visible; false to
2609 * make it invisible
2610 *
2611 * @beaninfo
2612 * attribute: visualUpdate true
2613 */
2614 public void setVisible(boolean aFlag) {
2615 if (aFlag != isVisible()) {
2616 super .setVisible(aFlag);
2617 Container parent = getParent();
2618 if (parent != null) {
2619 Rectangle r = getBounds();
2620 parent.repaint(r.x, r.y, r.width, r.height);
2621 }
2622 // Some (all should) LayoutManagers do not consider components
2623 // that are not visible. As such we need to revalidate when the
2624 // visible bit changes.
2625 revalidate();
2626 }
2627 }
2628
2629 /**
2630 * Sets whether or not this component is enabled.
2631 * A component that is enabled may respond to user input,
2632 * while a component that is not enabled cannot respond to
2633 * user input. Some components may alter their visual
2634 * representation when they are disabled in order to
2635 * provide feedback to the user that they cannot take input.
2636 * <p>Note: Disabling a component does not disable its children.
2637 *
2638 * <p>Note: Disabling a lightweight component does not prevent it from
2639 * receiving MouseEvents.
2640 *
2641 * @param enabled true if this component should be enabled, false otherwise
2642 * @see java.awt.Component#isEnabled
2643 * @see java.awt.Component#isLightweight
2644 *
2645 * @beaninfo
2646 * preferred: true
2647 * bound: true
2648 * attribute: visualUpdate true
2649 * description: The enabled state of the component.
2650 */
2651 public void setEnabled(boolean enabled) {
2652 boolean oldEnabled = isEnabled();
2653 super .setEnabled(enabled);
2654 firePropertyChange("enabled", oldEnabled, enabled);
2655 if (enabled != oldEnabled) {
2656 repaint();
2657 }
2658 }
2659
2660 /**
2661 * Sets the foreground color of this component. It is up to the
2662 * look and feel to honor this property, some may choose to ignore
2663 * it.
2664 *
2665 * @param fg the desired foreground <code>Color</code>
2666 * @see java.awt.Component#getForeground
2667 *
2668 * @beaninfo
2669 * preferred: true
2670 * bound: true
2671 * attribute: visualUpdate true
2672 * description: The foreground color of the component.
2673 */
2674 public void setForeground(Color fg) {
2675 Color oldFg = getForeground();
2676 super .setForeground(fg);
2677 if ((oldFg != null) ? !oldFg.equals(fg) : ((fg != null) && !fg
2678 .equals(oldFg))) {
2679 // foreground already bound in AWT1.2
2680 repaint();
2681 }
2682 }
2683
2684 /**
2685 * Sets the background color of this component. The background
2686 * color is used only if the component is opaque, and only
2687 * by subclasses of <code>JComponent</code> or
2688 * <code>ComponentUI</code> implementations. Direct subclasses of
2689 * <code>JComponent</code> must override
2690 * <code>paintComponent</code> to honor this property.
2691 * <p>
2692 * It is up to the look and feel to honor this property, some may
2693 * choose to ignore it.
2694 *
2695 * @param bg the desired background <code>Color</code>
2696 * @see java.awt.Component#getBackground
2697 * @see #setOpaque
2698 *
2699 * @beaninfo
2700 * preferred: true
2701 * bound: true
2702 * attribute: visualUpdate true
2703 * description: The background color of the component.
2704 */
2705 public void setBackground(Color bg) {
2706 Color oldBg = getBackground();
2707 super .setBackground(bg);
2708 if ((oldBg != null) ? !oldBg.equals(bg) : ((bg != null) && !bg
2709 .equals(oldBg))) {
2710 // background already bound in AWT1.2
2711 repaint();
2712 }
2713 }
2714
2715 /**
2716 * Sets the font for this component.
2717 *
2718 * @param font the desired <code>Font</code> for this component
2719 * @see java.awt.Component#getFont
2720 *
2721 * @beaninfo
2722 * preferred: true
2723 * bound: true
2724 * attribute: visualUpdate true
2725 * description: The font for the component.
2726 */
2727 public void setFont(Font font) {
2728 Font oldFont = getFont();
2729 super .setFont(font);
2730 // font already bound in AWT1.2
2731 if (font != oldFont) {
2732 revalidate();
2733 repaint();
2734 }
2735 }
2736
2737 /**
2738 * Returns the default locale used to initialize each JComponent's
2739 * locale property upon creation.
2740 *
2741 * The default locale has "AppContext" scope so that applets (and
2742 * potentially multiple lightweight applications running in a single VM)
2743 * can have their own setting. An applet can safely alter its default
2744 * locale because it will have no affect on other applets (or the browser).
2745 *
2746 * @return the default <code>Locale</code>.
2747 * @see #setDefaultLocale
2748 * @see java.awt.Component#getLocale
2749 * @see #setLocale
2750 * @since 1.4
2751 */
2752 static public Locale getDefaultLocale() {
2753 Locale l = (Locale) SwingUtilities.appContextGet(defaultLocale);
2754 if (l == null) {
2755 //REMIND(bcb) choosing the default value is more complicated
2756 //than this.
2757 l = Locale.getDefault();
2758 JComponent.setDefaultLocale(l);
2759 }
2760 return l;
2761 }
2762
2763 /**
2764 * Sets the default locale used to initialize each JComponent's locale
2765 * property upon creation. The initial value is the VM's default locale.
2766 *
2767 * The default locale has "AppContext" scope so that applets (and
2768 * potentially multiple lightweight applications running in a single VM)
2769 * can have their own setting. An applet can safely alter its default
2770 * locale because it will have no affect on other applets (or the browser).
2771 *
2772 * @param l the desired default <code>Locale</code> for new components.
2773 * @see #getDefaultLocale
2774 * @see java.awt.Component#getLocale
2775 * @see #setLocale
2776 * @since 1.4
2777 */
2778 static public void setDefaultLocale(Locale l) {
2779 SwingUtilities.appContextPut(defaultLocale, l);
2780 }
2781
2782 /**
2783 * Processes any key events that the component itself
2784 * recognizes. This is called after the focus
2785 * manager and any interested listeners have been
2786 * given a chance to steal away the event. This
2787 * method is called only if the event has not
2788 * yet been consumed. This method is called prior
2789 * to the keyboard UI logic.
2790 * <p>
2791 * This method is implemented to do nothing. Subclasses would
2792 * normally override this method if they process some
2793 * key events themselves. If the event is processed,
2794 * it should be consumed.
2795 */
2796 protected void processComponentKeyEvent(KeyEvent e) {
2797 }
2798
2799 /** Overrides <code>processKeyEvent</code> to process events. **/
2800 protected void processKeyEvent(KeyEvent e) {
2801 boolean result;
2802 boolean shouldProcessKey;
2803
2804 // This gives the key event listeners a crack at the event
2805 super .processKeyEvent(e);
2806
2807 // give the component itself a crack at the event
2808 if (!e.isConsumed()) {
2809 processComponentKeyEvent(e);
2810 }
2811
2812 shouldProcessKey = KeyboardState.shouldProcess(e);
2813
2814 if (e.isConsumed()) {
2815 return;
2816 }
2817
2818 if (shouldProcessKey
2819 && processKeyBindings(e,
2820 e.getID() == KeyEvent.KEY_PRESSED)) {
2821 e.consume();
2822 }
2823 }
2824
2825 /**
2826 * Invoked to process the key bindings for <code>ks</code> as the result
2827 * of the <code>KeyEvent</code> <code>e</code>. This obtains
2828 * the appropriate <code>InputMap</code>,
2829 * gets the binding, gets the action from the <code>ActionMap</code>,
2830 * and then (if the action is found and the component
2831 * is enabled) invokes <code>notifyAction</code> to notify the action.
2832 *
2833 * @param ks the <code>KeyStroke</code> queried
2834 * @param e the <code>KeyEvent</code>
2835 * @param condition one of the following values:
2836 * <ul>
2837 * <li>JComponent.WHEN_FOCUSED
2838 * <li>JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
2839 * <li>JComponent.WHEN_IN_FOCUSED_WINDOW
2840 * </ul>
2841 * @param pressed true if the key is pressed
2842 * @return true if there was a binding to an action, and the action
2843 * was enabled
2844 *
2845 * @since 1.3
2846 */
2847 protected boolean processKeyBinding(KeyStroke ks, KeyEvent e,
2848 int condition, boolean pressed) {
2849 InputMap map = getInputMap(condition, false);
2850 ActionMap am = getActionMap(false);
2851
2852 if (map != null && am != null && isEnabled()) {
2853 Object binding = map.get(ks);
2854 Action action = (binding == null) ? null : am.get(binding);
2855 if (action != null) {
2856 return SwingUtilities.notifyAction(action, ks, e, this ,
2857 e.getModifiers());
2858 }
2859 }
2860 return false;
2861 }
2862
2863 /**
2864 * This is invoked as the result of a <code>KeyEvent</code>
2865 * that was not consumed by the <code>FocusManager</code>,
2866 * <code>KeyListeners</code>, or the component. It will first try
2867 * <code>WHEN_FOCUSED</code> bindings,
2868 * then <code>WHEN_ANCESTOR_OF_FOCUSED_COMPONENT</code> bindings,
2869 * and finally <code>WHEN_IN_FOCUSED_WINDOW</code> bindings.
2870 *
2871 * @param e the unconsumed <code>KeyEvent</code>
2872 * @param pressed true if the key is pressed
2873 * @return true if there is a key binding for <code>e</code>
2874 */
2875 boolean processKeyBindings(KeyEvent e, boolean pressed) {
2876 if (!SwingUtilities.isValidKeyEventForKeyBindings(e)) {
2877 return false;
2878 }
2879 // Get the KeyStroke
2880 KeyStroke ks;
2881
2882 if (e.getID() == KeyEvent.KEY_TYPED) {
2883 ks = KeyStroke.getKeyStroke(e.getKeyChar());
2884 } else {
2885 ks = KeyStroke.getKeyStroke(e.getKeyCode(), e
2886 .getModifiers(), (pressed ? false : true));
2887 }
2888
2889 /* Do we have a key binding for e? */
2890 if (processKeyBinding(ks, e, WHEN_FOCUSED, pressed))
2891 return true;
2892
2893 /* We have no key binding. Let's try the path from our parent to the
2894 * window excluded. We store the path components so we can avoid
2895 * asking the same component twice.
2896 */
2897 Container parent = this ;
2898 while (parent != null && !(parent instanceof Window)
2899 && !(parent instanceof Applet)) {
2900 if (parent instanceof JComponent) {
2901 if (((JComponent) parent).processKeyBinding(ks, e,
2902 WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, pressed))
2903 return true;
2904 }
2905 // This is done so that the children of a JInternalFrame are
2906 // given precedence for WHEN_IN_FOCUSED_WINDOW bindings before
2907 // other components WHEN_IN_FOCUSED_WINDOW bindings. This also gives
2908 // more precedence to the WHEN_IN_FOCUSED_WINDOW bindings of the
2909 // JInternalFrame's children vs the
2910 // WHEN_ANCESTOR_OF_FOCUSED_COMPONENT bindings of the parents.
2911 // maybe generalize from JInternalFrame (like isFocusCycleRoot).
2912 if ((parent instanceof JInternalFrame)
2913 && JComponent.processKeyBindingsForAllComponents(e,
2914 parent, pressed)) {
2915 return true;
2916 }
2917 parent = parent.getParent();
2918 }
2919
2920 /* No components between the focused component and the window is
2921 * actually interested by the key event. Let's try the other
2922 * JComponent in this window.
2923 */
2924 if (parent != null) {
2925 return JComponent.processKeyBindingsForAllComponents(e,
2926 parent, pressed);
2927 }
2928 return false;
2929 }
2930
2931 static boolean processKeyBindingsForAllComponents(KeyEvent e,
2932 Container container, boolean pressed) {
2933 while (true) {
2934 if (KeyboardManager.getCurrentManager().fireKeyboardAction(
2935 e, pressed, container)) {
2936 return true;
2937 }
2938 if (container instanceof Popup.HeavyWeightWindow) {
2939 container = ((Window) container).getOwner();
2940 } else {
2941 return false;
2942 }
2943 }
2944 }
2945
2946 /**
2947 * Registers the text to display in a tool tip.
2948 * The text displays when the cursor lingers over the component.
2949 * <p>
2950 * See <a href="http://java.sun.com/docs/books/tutorial/uiswing/components/tooltip.html">How to Use Tool Tips</a>
2951 * in <em>The Java Tutorial</em>
2952 * for further documentation.
2953 *
2954 * @param text the string to display; if the text is <code>null</code>,
2955 * the tool tip is turned off for this component
2956 * @see #TOOL_TIP_TEXT_KEY
2957 * @beaninfo
2958 * preferred: true
2959 * description: The text to display in a tool tip.
2960 */
2961 public void setToolTipText(String text) {
2962 String oldText = getToolTipText();
2963 putClientProperty(TOOL_TIP_TEXT_KEY, text);
2964 ToolTipManager toolTipManager = ToolTipManager.sharedInstance();
2965 if (text != null) {
2966 if (oldText == null) {
2967 toolTipManager.registerComponent(this );
2968 }
2969 } else {
2970 toolTipManager.unregisterComponent(this );
2971 }
2972 }
2973
2974 /**
2975 * Returns the tooltip string that has been set with
2976 * <code>setToolTipText</code>.
2977 *
2978 * @return the text of the tool tip
2979 * @see #TOOL_TIP_TEXT_KEY
2980 */
2981 public String getToolTipText() {
2982 return (String) getClientProperty(TOOL_TIP_TEXT_KEY);
2983 }
2984
2985 /**
2986 * Returns the string to be used as the tooltip for <i>event</i>.
2987 * By default this returns any string set using
2988 * <code>setToolTipText</code>. If a component provides
2989 * more extensive API to support differing tooltips at different locations,
2990 * this method should be overridden.
2991 */
2992 public String getToolTipText(MouseEvent event) {
2993 return getToolTipText();
2994 }
2995
2996 /**
2997 * Returns the tooltip location in this component's coordinate system.
2998 * If <code>null</code> is returned, Swing will choose a location.
2999 * The default implementation returns <code>null</code>.
3000 *
3001 * @param event the <code>MouseEvent</code> that caused the
3002 * <code>ToolTipManager</code> to show the tooltip
3003 * @return always returns <code>null</code>
3004 */
3005 public Point getToolTipLocation(MouseEvent event) {
3006 return null;
3007 }
3008
3009 /**
3010 * Returns the preferred location to display the popup menu in this
3011 * component's coordinate system. It is up to the look and feel to
3012 * honor this property, some may choose to ignore it.
3013 * If {@code null}, the look and feel will choose a suitable location.
3014 *
3015 * @param event the {@code MouseEvent} that triggered the popup to be
3016 * shown, or {@code null} if the popup is not being shown as the
3017 * result of a mouse event
3018 * @return location to display the {@code JPopupMenu}, or {@code null}
3019 * @since 1.5
3020 */
3021 public Point getPopupLocation(MouseEvent event) {
3022 return null;
3023 }
3024
3025 /**
3026 * Returns the instance of <code>JToolTip</code> that should be used
3027 * to display the tooltip.
3028 * Components typically would not override this method,
3029 * but it can be used to
3030 * cause different tooltips to be displayed differently.
3031 *
3032 * @return the <code>JToolTip</code> used to display this toolTip
3033 */
3034 public JToolTip createToolTip() {
3035 JToolTip tip = new JToolTip();
3036 tip.setComponent(this );
3037 return tip;
3038 }
3039
3040 /**
3041 * Forwards the <code>scrollRectToVisible()</code> message to the
3042 * <code>JComponent</code>'s parent. Components that can service
3043 * the request, such as <code>JViewport</code>,
3044 * override this method and perform the scrolling.
3045 *
3046 * @param aRect the visible <code>Rectangle</code>
3047 * @see JViewport
3048 */
3049 public void scrollRectToVisible(Rectangle aRect) {
3050 Container parent;
3051 int dx = getX(), dy = getY();
3052
3053 for (parent = getParent(); !(parent == null)
3054 && !(parent instanceof JComponent)
3055 && !(parent instanceof CellRendererPane); parent = parent
3056 .getParent()) {
3057 Rectangle bounds = parent.getBounds();
3058
3059 dx += bounds.x;
3060 dy += bounds.y;
3061 }
3062
3063 if (!(parent == null) && !(parent instanceof CellRendererPane)) {
3064 aRect.x += dx;
3065 aRect.y += dy;
3066
3067 ((JComponent) parent).scrollRectToVisible(aRect);
3068 aRect.x -= dx;
3069 aRect.y -= dy;
3070 }
3071 }
3072
3073 /**
3074 * Sets the <code>autoscrolls</code> property.
3075 * If <code>true</code> mouse dragged events will be
3076 * synthetically generated when the mouse is dragged
3077 * outside of the component's bounds and mouse motion
3078 * has paused (while the button continues to be held
3079 * down). The synthetic events make it appear that the
3080 * drag gesture has resumed in the direction established when
3081 * the component's boundary was crossed. Components that
3082 * support autoscrolling must handle <code>mouseDragged</code>
3083 * events by calling <code>scrollRectToVisible</code> with a
3084 * rectangle that contains the mouse event's location. All of
3085 * the Swing components that support item selection and are
3086 * typically displayed in a <code>JScrollPane</code>
3087 * (<code>JTable</code>, <code>JList</code>, <code>JTree</code>,
3088 * <code>JTextArea</code>, and <code>JEditorPane</code>)
3089 * already handle mouse dragged events in this way. To enable
3090 * autoscrolling in any other component, add a mouse motion
3091 * listener that calls <code>scrollRectToVisible</code>.
3092 * For example, given a <code>JPanel</code>, <code>myPanel</code>:
3093 * <pre>
3094 * MouseMotionListener doScrollRectToVisible = new MouseMotionAdapter() {
3095 * public void mouseDragged(MouseEvent e) {
3096 * Rectangle r = new Rectangle(e.getX(), e.getY(), 1, 1);
3097 * ((JPanel)e.getSource()).scrollRectToVisible(r);
3098 * }
3099 * };
3100 * myPanel.addMouseMotionListener(doScrollRectToVisible);
3101 * </pre>
3102 * The default value of the <code>autoScrolls</code>
3103 * property is <code>false</code>.
3104 *
3105 * @param autoscrolls if true, synthetic mouse dragged events
3106 * are generated when the mouse is dragged outside of a component's
3107 * bounds and the mouse button continues to be held down; otherwise
3108 * false
3109 * @see #getAutoscrolls
3110 * @see JViewport
3111 * @see JScrollPane
3112 *
3113 * @beaninfo
3114 * expert: true
3115 * description: Determines if this component automatically scrolls its contents when dragged.
3116 */
3117 public void setAutoscrolls(boolean autoscrolls) {
3118 setFlag(AUTOSCROLLS_SET, true);
3119 if (this .autoscrolls != autoscrolls) {
3120 this .autoscrolls = autoscrolls;
3121 if (autoscrolls) {
3122 enableEvents(AWTEvent.MOUSE_EVENT_MASK);
3123 enableEvents(AWTEvent.MOUSE_MOTION_EVENT_MASK);
3124 } else {
3125 Autoscroller.stop(this );
3126 }
3127 }
3128 }
3129
3130 /**
3131 * Gets the <code>autoscrolls</code> property.
3132 *
3133 * @return the value of the <code>autoscrolls</code> property
3134 * @see JViewport
3135 * @see #setAutoscrolls
3136 */
3137 public boolean getAutoscrolls() {
3138 return autoscrolls;
3139 }
3140
3141 /**
3142 * Sets the {@code TransferHandler}, which provides support for transfer
3143 * of data into and out of this component via cut/copy/paste and drag
3144 * and drop. This may be {@code null} if the component does not support
3145 * data transfer operations.
3146 * <p>
3147 * If the new {@code TransferHandler} is not {@code null}, this method
3148 * also installs a <b>new</b> {@code DropTarget} on the component to
3149 * activate drop handling through the {@code TransferHandler} and activate
3150 * any built-in support (such as calculating and displaying potential drop
3151 * locations). If you do not wish for this component to respond in any way
3152 * to drops, you can disable drop support entirely either by removing the
3153 * drop target ({@code setDropTarget(null)}) or by de-activating it
3154 * ({@code getDropTaget().setActive(false)}).
3155 * <p>
3156 * If the new {@code TransferHandler} is {@code null}, this method removes
3157 * the drop target.
3158 * <p>
3159 * Under two circumstances, this method does not modify the drop target:
3160 * First, if the existing drop target on this component was explicitly
3161 * set by the developer to a {@code non-null} value. Second, if the
3162 * system property {@code suppressSwingDropSupport} is {@code true}. The
3163 * default value for the system property is {@code false}.
3164 * <p>
3165 * Please see
3166 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/dnd.html">
3167 * How to Use Drag and Drop and Data Transfer</a>,
3168 * a section in <em>The Java Tutorial</em>, for more information.
3169 *
3170 * @param newHandler the new {@code TransferHandler}
3171 *
3172 * @see TransferHandler
3173 * @see #getTransferHandler
3174 * @since 1.4
3175 * @beaninfo
3176 * bound: true
3177 * hidden: true
3178 * description: Mechanism for transfer of data to and from the component
3179 */
3180 public void setTransferHandler(TransferHandler newHandler) {
3181 TransferHandler oldHandler = (TransferHandler) getClientProperty(JComponent_TRANSFER_HANDLER);
3182 putClientProperty(JComponent_TRANSFER_HANDLER, newHandler);
3183
3184 SwingUtilities.installSwingDropTargetAsNecessary(this ,
3185 newHandler);
3186 firePropertyChange("transferHandler", oldHandler, newHandler);
3187 }
3188
3189 /**
3190 * Gets the <code>transferHandler</code> property.
3191 *
3192 * @return the value of the <code>transferHandler</code> property
3193 *
3194 * @see TransferHandler
3195 * @see #setTransferHandler
3196 * @since 1.4
3197 */
3198 public TransferHandler getTransferHandler() {
3199 return (TransferHandler) getClientProperty(JComponent_TRANSFER_HANDLER);
3200 }
3201
3202 /**
3203 * Calculates a custom drop location for this type of component,
3204 * representing where a drop at the given point should insert data.
3205 * <code>null</code> is returned if this component doesn't calculate
3206 * custom drop locations. In this case, <code>TransferHandler</code>
3207 * will provide a default <code>DropLocation</code> containing just
3208 * the point.
3209 *
3210 * @param p the point to calculate a drop location for
3211 * @return the drop location, or <code>null</code>
3212 */
3213 TransferHandler.DropLocation dropLocationForPoint(Point p) {
3214 return null;
3215 }
3216
3217 /**
3218 * Called to set or clear the drop location during a DnD operation.
3219 * In some cases, the component may need to use its internal selection
3220 * temporarily to indicate the drop location. To help facilitate this,
3221 * this method returns and accepts as a parameter a state object.
3222 * This state object can be used to store, and later restore, the selection
3223 * state. Whatever this method returns will be passed back to it in
3224 * future calls, as the state parameter. If it wants the DnD system to
3225 * continue storing the same state, it must pass it back every time.
3226 * Here's how this is used:
3227 * <p>
3228 * Let's say that on the first call to this method the component decides
3229 * to save some state (because it is about to use the selection to show
3230 * a drop index). It can return a state object to the caller encapsulating
3231 * any saved selection state. On a second call, let's say the drop location
3232 * is being changed to something else. The component doesn't need to
3233 * restore anything yet, so it simply passes back the same state object
3234 * to have the DnD system continue storing it. Finally, let's say this
3235 * method is messaged with <code>null</code>. This means DnD
3236 * is finished with this component for now, meaning it should restore
3237 * state. At this point, it can use the state parameter to restore
3238 * said state, and of course return <code>null</code> since there's
3239 * no longer anything to store.
3240 *
3241 * @param location the drop location (as calculated by
3242 * <code>dropLocationForPoint</code>) or <code>null</code>
3243 * if there's no longer a valid drop location
3244 * @param state the state object saved earlier for this component,
3245 * or <code>null</code>
3246 * @param forDrop whether or not the method is being called because an
3247 * actual drop occurred
3248 * @return any saved state for this component, or <code>null</code> if none
3249 */
3250 Object setDropLocation(TransferHandler.DropLocation location,
3251 Object state, boolean forDrop) {
3252
3253 return null;
3254 }
3255
3256 /**
3257 * Called to indicate to this component that DnD is done.
3258 * Needed by <code>JTree</code>.
3259 */
3260 void dndDone() {
3261 }
3262
3263 /**
3264 * Processes mouse events occurring on this component by
3265 * dispatching them to any registered
3266 * <code>MouseListener</code> objects, refer to
3267 * {@link java.awt.Component#processMouseEvent(MouseEvent)}
3268 * for a complete description of this method.
3269 *
3270 * @param e the mouse event
3271 * @see java.awt.Component#processMouseEvent
3272 * @since 1.5
3273 */
3274 protected void processMouseEvent(MouseEvent e) {
3275 if (autoscrolls && e.getID() == MouseEvent.MOUSE_RELEASED) {
3276 Autoscroller.stop(this );
3277 }
3278 super .processMouseEvent(e);
3279 }
3280
3281 /**
3282 * Processes mouse motion events, such as MouseEvent.MOUSE_DRAGGED.
3283 *
3284 * @param e the <code>MouseEvent</code>
3285 * @see MouseEvent
3286 */
3287 protected void processMouseMotionEvent(MouseEvent e) {
3288 boolean dispatch = true;
3289 if (autoscrolls && e.getID() == MouseEvent.MOUSE_DRAGGED) {
3290 // We don't want to do the drags when the mouse moves if we're
3291 // autoscrolling. It makes it feel spastic.
3292 dispatch = !Autoscroller.isRunning(this );
3293 Autoscroller.processMouseDragged(e);
3294 }
3295 if (dispatch) {
3296 super .processMouseMotionEvent(e);
3297 }
3298 }
3299
3300 // Inner classes can't get at this method from a super class
3301 void super ProcessMouseMotionEvent(MouseEvent e) {
3302 super .processMouseMotionEvent(e);
3303 }
3304
3305 /**
3306 * This is invoked by the <code>RepaintManager</code> if
3307 * <code>createImage</code> is called on the component.
3308 *
3309 * @param newValue true if the double buffer image was created from this component
3310 */
3311 void setCreatedDoubleBuffer(boolean newValue) {
3312 setFlag(CREATED_DOUBLE_BUFFER, newValue);
3313 }
3314
3315 /**
3316 * Returns true if the <code>RepaintManager</code>
3317 * created the double buffer image from the component.
3318 *
3319 * @return true if this component had a double buffer image, false otherwise
3320 */
3321 boolean getCreatedDoubleBuffer() {
3322 return getFlag(CREATED_DOUBLE_BUFFER);
3323 }
3324
3325 /**
3326 * <code>ActionStandin</code> is used as a standin for
3327 * <code>ActionListeners</code> that are
3328 * added via <code>registerKeyboardAction</code>.
3329 */
3330 final class ActionStandin implements Action {
3331 private final ActionListener actionListener;
3332 private final String command;
3333 // This will be non-null if actionListener is an Action.
3334 private final Action action;
3335
3336 ActionStandin(ActionListener actionListener, String command) {
3337 this .actionListener = actionListener;
3338 if (actionListener instanceof Action) {
3339 this .action = (Action) actionListener;
3340 } else {
3341 this .action = null;
3342 }
3343 this .command = command;
3344 }
3345
3346 public Object getValue(String key) {
3347 if (key != null) {
3348 if (key.equals(Action.ACTION_COMMAND_KEY)) {
3349 return command;
3350 }
3351 if (action != null) {
3352 return action.getValue(key);
3353 }
3354 if (key.equals(NAME)) {
3355 return "ActionStandin";
3356 }
3357 }
3358 return null;
3359 }
3360
3361 public boolean isEnabled() {
3362 if (actionListener == null) {
3363 // This keeps the old semantics where
3364 // registerKeyboardAction(null) would essentialy remove
3365 // the binding. We don't remove the binding from the
3366 // InputMap as that would still allow parent InputMaps
3367 // bindings to be accessed.
3368 return false;
3369 }
3370 if (action == null) {
3371 return true;
3372 }
3373 return action.isEnabled();
3374 }
3375
3376 public void actionPerformed(ActionEvent ae) {
3377 if (actionListener != null) {
3378 actionListener.actionPerformed(ae);
3379 }
3380 }
3381
3382 // We don't allow any values to be added.
3383 public void putValue(String key, Object value) {
3384 }
3385
3386 // Does nothing, our enabledness is determiend from our asociated
3387 // action.
3388 public void setEnabled(boolean b) {
3389 }
3390
3391 public void addPropertyChangeListener(
3392 PropertyChangeListener listener) {
3393 }
3394
3395 public void removePropertyChangeListener(
3396 PropertyChangeListener listener) {
3397 }
3398 }
3399
3400 // This class is used by the KeyboardState class to provide a single
3401 // instance that can be stored in the AppContext.
3402 static final class IntVector {
3403 int array[] = null;
3404 int count = 0;
3405 int capacity = 0;
3406
3407 int size() {
3408 return count;
3409 }
3410
3411 int elementAt(int index) {
3412 return array[index];
3413 }
3414
3415 void addElement(int value) {
3416 if (count == capacity) {
3417 capacity = (capacity + 2) * 2;
3418 int[] newarray = new int[capacity];
3419 if (count > 0) {
3420 System.arraycopy(array, 0, newarray, 0, count);
3421 }
3422 array = newarray;
3423 }
3424 array[count++] = value;
3425 }
3426
3427 void setElementAt(int value, int index) {
3428 array[index] = value;
3429 }
3430 }
3431
3432 static class KeyboardState implements Serializable {
3433 private static final Object keyCodesKey = JComponent.KeyboardState.class;
3434
3435 // Get the array of key codes from the AppContext.
3436 static IntVector getKeyCodeArray() {
3437 IntVector iv = (IntVector) SwingUtilities
3438 .appContextGet(keyCodesKey);
3439 if (iv == null) {
3440 iv = new IntVector();
3441 SwingUtilities.appContextPut(keyCodesKey, iv);
3442 }
3443 return iv;
3444 }
3445
3446 static void registerKeyPressed(int keyCode) {
3447 IntVector kca = getKeyCodeArray();
3448 int count = kca.size();
3449 int i;
3450 for (i = 0; i < count; i++) {
3451 if (kca.elementAt(i) == -1) {
3452 kca.setElementAt(keyCode, i);
3453 return;
3454 }
3455 }
3456 kca.addElement(keyCode);
3457 }
3458
3459 static void registerKeyReleased(int keyCode) {
3460 IntVector kca = getKeyCodeArray();
3461 int count = kca.size();
3462 int i;
3463 for (i = 0; i < count; i++) {
3464 if (kca.elementAt(i) == keyCode) {
3465 kca.setElementAt(-1, i);
3466 return;
3467 }
3468 }
3469 }
3470
3471 static boolean keyIsPressed(int keyCode) {
3472 IntVector kca = getKeyCodeArray();
3473 int count = kca.size();
3474 int i;
3475 for (i = 0; i < count; i++) {
3476 if (kca.elementAt(i) == keyCode) {
3477 return true;
3478 }
3479 }
3480 return false;
3481 }
3482
3483 /**
3484 * Updates internal state of the KeyboardState and returns true
3485 * if the event should be processed further.
3486 */
3487 static boolean shouldProcess(KeyEvent e) {
3488 switch (e.getID()) {
3489 case KeyEvent.KEY_PRESSED:
3490 if (!keyIsPressed(e.getKeyCode())) {
3491 registerKeyPressed(e.getKeyCode());
3492 }
3493 return true;
3494 case KeyEvent.KEY_RELEASED:
3495 // We are forced to process VK_PRINTSCREEN separately because
3496 // the Windows doesn't generate the key pressed event for
3497 // printscreen and it block the processing of key release
3498 // event for printscreen.
3499 if (keyIsPressed(e.getKeyCode())
3500 || e.getKeyCode() == KeyEvent.VK_PRINTSCREEN) {
3501 registerKeyReleased(e.getKeyCode());
3502 return true;
3503 }
3504 return false;
3505 case KeyEvent.KEY_TYPED:
3506 return true;
3507 default:
3508 // Not a known KeyEvent type, bail.
3509 return false;
3510 }
3511 }
3512 }
3513
3514 static final sun.awt.RequestFocusController focusController = new sun.awt.RequestFocusController() {
3515 public boolean acceptRequestFocus(Component from, Component to,
3516 boolean temporary, boolean focusedWindowChangeAllowed,
3517 sun.awt.CausedFocusEvent.Cause cause) {
3518 if ((to == null) || !(to instanceof JComponent)) {
3519 return true;
3520 }
3521
3522 if ((from == null) || !(from instanceof JComponent)) {
3523 return true;
3524 }
3525
3526 JComponent target = (JComponent) to;
3527 if (!target.getVerifyInputWhenFocusTarget()) {
3528 return true;
3529 }
3530
3531 JComponent jFocusOwner = (JComponent) from;
3532 InputVerifier iv = jFocusOwner.getInputVerifier();
3533
3534 if (iv == null) {
3535 return true;
3536 } else {
3537 Object currentSource = SwingUtilities
3538 .appContextGet(INPUT_VERIFIER_SOURCE_KEY);
3539 if (currentSource == jFocusOwner) {
3540 // We're currently calling into the InputVerifier
3541 // for this component, so allow the focus change.
3542 return true;
3543 }
3544 SwingUtilities.appContextPut(INPUT_VERIFIER_SOURCE_KEY,
3545 jFocusOwner);
3546 try {
3547 return iv.shouldYieldFocus(jFocusOwner);
3548 } finally {
3549 if (currentSource != null) {
3550 // We're already in the InputVerifier for
3551 // currentSource. By resetting the currentSource
3552 // we ensure that if the InputVerifier for
3553 // currentSource does a requestFocus, we don't
3554 // try and run the InputVerifier again.
3555 SwingUtilities.appContextPut(
3556 INPUT_VERIFIER_SOURCE_KEY,
3557 currentSource);
3558 } else {
3559 SwingUtilities
3560 .appContextRemove(INPUT_VERIFIER_SOURCE_KEY);
3561 }
3562 }
3563 }
3564 }
3565 };
3566
3567 /*
3568 * --- Accessibility Support ---
3569 */
3570
3571 /**
3572 * @deprecated As of JDK version 1.1,
3573 * replaced by <code>java.awt.Component.setEnabled(boolean)</code>.
3574 */
3575 @Deprecated
3576 public void enable() {
3577 if (isEnabled() != true) {
3578 super .enable();
3579 if (accessibleContext != null) {
3580 accessibleContext.firePropertyChange(
3581 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
3582 null, AccessibleState.ENABLED);
3583 }
3584 }
3585 }
3586
3587 /**
3588 * @deprecated As of JDK version 1.1,
3589 * replaced by <code>java.awt.Component.setEnabled(boolean)</code>.
3590 */
3591 @Deprecated
3592 public void disable() {
3593 if (isEnabled() != false) {
3594 super .disable();
3595 if (accessibleContext != null) {
3596 accessibleContext.firePropertyChange(
3597 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
3598 AccessibleState.ENABLED, null);
3599 }
3600 }
3601 }
3602
3603 /**
3604 * The <code>AccessibleContext</code> associated with this
3605 * <code>JComponent</code>.
3606 */
3607 protected AccessibleContext accessibleContext = null;
3608
3609 /**
3610 * Returns the <code>AccessibleContext</code> associated with this
3611 * <code>JComponent</code>. The method implemented by this base
3612 * class returns null. Classes that extend <code>JComponent</code>
3613 * should implement this method to return the
3614 * <code>AccessibleContext</code> associated with the subclass.
3615 *
3616 * @return the <code>AccessibleContext</code> of this
3617 * <code>JComponent</code>
3618 */
3619 public AccessibleContext getAccessibleContext() {
3620 return accessibleContext;
3621 }
3622
3623 /**
3624 * Inner class of JComponent used to provide default support for
3625 * accessibility. This class is not meant to be used directly by
3626 * application developers, but is instead meant only to be
3627 * subclassed by component developers.
3628 * <p>
3629 * <strong>Warning:</strong>
3630 * Serialized objects of this class will not be compatible with
3631 * future Swing releases. The current serialization support is
3632 * appropriate for short term storage or RMI between applications running
3633 * the same version of Swing. As of 1.4, support for long term storage
3634 * of all JavaBeans<sup><font size="-2">TM</font></sup>
3635 * has been added to the <code>java.beans</code> package.
3636 * Please see {@link java.beans.XMLEncoder}.
3637 */
3638 public abstract class AccessibleJComponent extends
3639 AccessibleAWTContainer implements
3640 AccessibleExtendedComponent {
3641 /**
3642 * Though the class is abstract, this should be called by
3643 * all sub-classes.
3644 */
3645 protected AccessibleJComponent() {
3646 super ();
3647 }
3648
3649 protected ContainerListener accessibleContainerHandler = null;
3650 protected FocusListener accessibleFocusHandler = null;
3651
3652 /**
3653 * Fire PropertyChange listener, if one is registered,
3654 * when children added/removed.
3655 */
3656 protected class AccessibleContainerHandler implements
3657 ContainerListener {
3658 public void componentAdded(ContainerEvent e) {
3659 Component c = e.getChild();
3660 if (c != null && c instanceof Accessible) {
3661 AccessibleJComponent.this
3662 .firePropertyChange(
3663 AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
3664 null, ((Accessible) c)
3665 .getAccessibleContext());
3666 }
3667 }
3668
3669 public void componentRemoved(ContainerEvent e) {
3670 Component c = e.getChild();
3671 if (c != null && c instanceof Accessible) {
3672 AccessibleJComponent.this
3673 .firePropertyChange(
3674 AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
3675 ((Accessible) c)
3676 .getAccessibleContext(),
3677 null);
3678 }
3679 }
3680 }
3681
3682 /**
3683 * Fire PropertyChange listener, if one is registered,
3684 * when focus events happen
3685 * @since 1.3
3686 */
3687 protected class AccessibleFocusHandler implements FocusListener {
3688 public void focusGained(FocusEvent event) {
3689 if (accessibleContext != null) {
3690 accessibleContext
3691 .firePropertyChange(
3692 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
3693 null, AccessibleState.FOCUSED);
3694 }
3695 }
3696
3697 public void focusLost(FocusEvent event) {
3698 if (accessibleContext != null) {
3699 accessibleContext
3700 .firePropertyChange(
3701 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
3702 AccessibleState.FOCUSED, null);
3703 }
3704 }
3705 } // inner class AccessibleFocusHandler
3706
3707 /**
3708 * Adds a PropertyChangeListener to the listener list.
3709 *
3710 * @param listener the PropertyChangeListener to be added
3711 */
3712 public void addPropertyChangeListener(
3713 PropertyChangeListener listener) {
3714 if (accessibleFocusHandler == null) {
3715 accessibleFocusHandler = new AccessibleFocusHandler();
3716 JComponent.this
3717 .addFocusListener(accessibleFocusHandler);
3718 }
3719 if (accessibleContainerHandler == null) {
3720 accessibleContainerHandler = new AccessibleContainerHandler();
3721 JComponent.this
3722 .addContainerListener(accessibleContainerHandler);
3723 }
3724 super .addPropertyChangeListener(listener);
3725 }
3726
3727 /**
3728 * Removes a PropertyChangeListener from the listener list.
3729 * This removes a PropertyChangeListener that was registered
3730 * for all properties.
3731 *
3732 * @param listener the PropertyChangeListener to be removed
3733 */
3734 public void removePropertyChangeListener(
3735 PropertyChangeListener listener) {
3736 if (accessibleFocusHandler != null) {
3737 JComponent.this
3738 .removeFocusListener(accessibleFocusHandler);
3739 accessibleFocusHandler = null;
3740 }
3741 super .removePropertyChangeListener(listener);
3742 }
3743
3744 /**
3745 * Recursively search through the border hierarchy (if it exists)
3746 * for a TitledBorder with a non-null title. This does a depth
3747 * first search on first the inside borders then the outside borders.
3748 * The assumption is that titles make really pretty inside borders
3749 * but not very pretty outside borders in compound border situations.
3750 * It's rather arbitrary, but hopefully decent UI programmers will
3751 * not create multiple titled borders for the same component.
3752 */
3753 protected String getBorderTitle(Border b) {
3754 String s;
3755 if (b instanceof TitledBorder) {
3756 return ((TitledBorder) b).getTitle();
3757 } else if (b instanceof CompoundBorder) {
3758 s = getBorderTitle(((CompoundBorder) b)
3759 .getInsideBorder());
3760 if (s == null) {
3761 s = getBorderTitle(((CompoundBorder) b)
3762 .getOutsideBorder());
3763 }
3764 return s;
3765 } else {
3766 return null;
3767 }
3768 }
3769
3770 // AccessibleContext methods
3771 //
3772 /**
3773 * Gets the accessible name of this object. This should almost never
3774 * return java.awt.Component.getName(), as that generally isn't
3775 * a localized name, and doesn't have meaning for the user. If the
3776 * object is fundamentally a text object (such as a menu item), the
3777 * accessible name should be the text of the object (for example,
3778 * "save").
3779 * If the object has a tooltip, the tooltip text may also be an
3780 * appropriate String to return.
3781 *
3782 * @return the localized name of the object -- can be null if this
3783 * object does not have a name
3784 * @see AccessibleContext#setAccessibleName
3785 */
3786 public String getAccessibleName() {
3787 String name = accessibleName;
3788
3789 // fallback to the client name property
3790 //
3791 if (name == null) {
3792 name = (String) getClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY);
3793 }
3794
3795 // fallback to the titled border if it exists
3796 //
3797 if (name == null) {
3798 name = getBorderTitle(getBorder());
3799 }
3800
3801 // fallback to the label labeling us if it exists
3802 //
3803 if (name == null) {
3804 Object o = getClientProperty(JLabel.LABELED_BY_PROPERTY);
3805 if (o instanceof Accessible) {
3806 AccessibleContext ac = ((Accessible) o)
3807 .getAccessibleContext();
3808 if (ac != null) {
3809 name = ac.getAccessibleName();
3810 }
3811 }
3812 }
3813 return name;
3814 }
3815
3816 /**
3817 * Gets the accessible description of this object. This should be
3818 * a concise, localized description of what this object is - what
3819 * is its meaning to the user. If the object has a tooltip, the
3820 * tooltip text may be an appropriate string to return, assuming
3821 * it contains a concise description of the object (instead of just
3822 * the name of the object - for example a "Save" icon on a toolbar that
3823 * had "save" as the tooltip text shouldn't return the tooltip
3824 * text as the description, but something like "Saves the current
3825 * text document" instead).
3826 *
3827 * @return the localized description of the object -- can be null if
3828 * this object does not have a description
3829 * @see AccessibleContext#setAccessibleDescription
3830 */
3831 public String getAccessibleDescription() {
3832 String description = accessibleDescription;
3833
3834 // fallback to the client description property
3835 //
3836 if (description == null) {
3837 description = (String) getClientProperty(AccessibleContext.ACCESSIBLE_DESCRIPTION_PROPERTY);
3838 }
3839
3840 // fallback to the tool tip text if it exists
3841 //
3842 if (description == null) {
3843 try {
3844 description = getToolTipText();
3845 } catch (Exception e) {
3846 // Just in case the subclass overrode the
3847 // getToolTipText method and actually
3848 // requires a MouseEvent.
3849 // [[[FIXME: WDW - we probably should require this
3850 // method to take a MouseEvent and just pass it on
3851 // to getToolTipText. The swing-feedback traffic
3852 // leads me to believe getToolTipText might change,
3853 // though, so I was hesitant to make this change at
3854 // this time.]]]
3855 }
3856 }
3857
3858 // fallback to the label labeling us if it exists
3859 //
3860 if (description == null) {
3861 Object o = getClientProperty(JLabel.LABELED_BY_PROPERTY);
3862 if (o instanceof Accessible) {
3863 AccessibleContext ac = ((Accessible) o)
3864 .getAccessibleContext();
3865 if (ac != null) {
3866 description = ac.getAccessibleDescription();
3867 }
3868 }
3869 }
3870
3871 return description;
3872 }
3873
3874 /**
3875 * Gets the role of this object.
3876 *
3877 * @return an instance of AccessibleRole describing the role of the
3878 * object
3879 * @see AccessibleRole
3880 */
3881 public AccessibleRole getAccessibleRole() {
3882 return AccessibleRole.SWING_COMPONENT;
3883 }
3884
3885 /**
3886 * Gets the state of this object.
3887 *
3888 * @return an instance of AccessibleStateSet containing the current
3889 * state set of the object
3890 * @see AccessibleState
3891 */
3892 public AccessibleStateSet getAccessibleStateSet() {
3893 AccessibleStateSet states = super .getAccessibleStateSet();
3894 if (JComponent.this .isOpaque()) {
3895 states.add(AccessibleState.OPAQUE);
3896 }
3897 return states;
3898 }
3899
3900 /**
3901 * Returns the number of accessible children in the object. If all
3902 * of the children of this object implement Accessible, than this
3903 * method should return the number of children of this object.
3904 *
3905 * @return the number of accessible children in the object.
3906 */
3907 public int getAccessibleChildrenCount() {
3908 return super .getAccessibleChildrenCount();
3909 }
3910
3911 /**
3912 * Returns the nth Accessible child of the object.
3913 *
3914 * @param i zero-based index of child
3915 * @return the nth Accessible child of the object
3916 */
3917 public Accessible getAccessibleChild(int i) {
3918 return super .getAccessibleChild(i);
3919 }
3920
3921 // ----- AccessibleExtendedComponent
3922
3923 /**
3924 * Returns the AccessibleExtendedComponent
3925 *
3926 * @return the AccessibleExtendedComponent
3927 */
3928 AccessibleExtendedComponent getAccessibleExtendedComponent() {
3929 return this ;
3930 }
3931
3932 /**
3933 * Returns the tool tip text
3934 *
3935 * @return the tool tip text, if supported, of the object;
3936 * otherwise, null
3937 * @since 1.4
3938 */
3939 public String getToolTipText() {
3940 return JComponent.this .getToolTipText();
3941 }
3942
3943 /**
3944 * Returns the titled border text
3945 *
3946 * @return the titled border text, if supported, of the object;
3947 * otherwise, null
3948 * @since 1.4
3949 */
3950 public String getTitledBorderText() {
3951 Border border = JComponent.this .getBorder();
3952 if (border instanceof TitledBorder) {
3953 return ((TitledBorder) border).getTitle();
3954 } else {
3955 return null;
3956 }
3957 }
3958
3959 /**
3960 * Returns key bindings associated with this object
3961 *
3962 * @return the key bindings, if supported, of the object;
3963 * otherwise, null
3964 * @see AccessibleKeyBinding
3965 * @since 1.4
3966 */
3967 public AccessibleKeyBinding getAccessibleKeyBinding() {
3968 return null;
3969 }
3970 } // inner class AccessibleJComponent
3971
3972 /**
3973 * Returns an <code>ArrayTable</code> used for
3974 * key/value "client properties" for this component. If the
3975 * <code>clientProperties</code> table doesn't exist, an empty one
3976 * will be created.
3977 *
3978 * @return an ArrayTable
3979 * @see #putClientProperty
3980 * @see #getClientProperty
3981 */
3982 private ArrayTable getClientProperties() {
3983 if (clientProperties == null) {
3984 clientProperties = new ArrayTable();
3985 }
3986 return clientProperties;
3987 }
3988
3989 /**
3990 * Returns the value of the property with the specified key. Only
3991 * properties added with <code>putClientProperty</code> will return
3992 * a non-<code>null</code> value.
3993 *
3994 * @param key the being queried
3995 * @return the value of this property or <code>null</code>
3996 * @see #putClientProperty
3997 */
3998 public final Object getClientProperty(Object key) {
3999 if (key == SwingUtilities2.AA_TEXT_PROPERTY_KEY) {
4000 return aaTextInfo;
4001 } else if (key == SwingUtilities2.COMPONENT_UI_PROPERTY_KEY) {
4002 return ui;
4003 }
4004 if (clientProperties == null) {
4005 return null;
4006 } else {
4007 synchronized (clientProperties) {
4008 return clientProperties.get(key);
4009 }
4010 }
4011 }
4012
4013 /**
4014 * Adds an arbitrary key/value "client property" to this component.
4015 * <p>
4016 * The <code>get/putClientProperty</code> methods provide access to
4017 * a small per-instance hashtable. Callers can use get/putClientProperty
4018 * to annotate components that were created by another module.
4019 * For example, a
4020 * layout manager might store per child constraints this way. For example:
4021 * <pre>
4022 * componentA.putClientProperty("to the left of", componentB);
4023 * </pre>
4024 * If value is <code>null</code> this method will remove the property.
4025 * Changes to client properties are reported with
4026 * <code>PropertyChange</code> events.
4027 * The name of the property (for the sake of PropertyChange
4028 * events) is <code>key.toString()</code>.
4029 * <p>
4030 * The <code>clientProperty</code> dictionary is not intended to
4031 * support large
4032 * scale extensions to JComponent nor should be it considered an
4033 * alternative to subclassing when designing a new component.
4034 *
4035 * @param key the new client property key
4036 * @param value the new client property value; if <code>null</code>
4037 * this method will remove the property
4038 * @see #getClientProperty
4039 * @see #addPropertyChangeListener
4040 */
4041 public final void putClientProperty(Object key, Object value) {
4042 if (key == SwingUtilities2.AA_TEXT_PROPERTY_KEY) {
4043 aaTextInfo = value;
4044 return;
4045 }
4046 if (value == null && clientProperties == null) {
4047 // Both the value and ArrayTable are null, implying we don't
4048 // have to do anything.
4049 return;
4050 }
4051 ArrayTable clientProperties = getClientProperties();
4052 Object oldValue;
4053 synchronized (clientProperties) {
4054 oldValue = clientProperties.get(key);
4055 if (value != null) {
4056 clientProperties.put(key, value);
4057 } else if (oldValue != null) {
4058 clientProperties.remove(key);
4059 } else {
4060 // old == new == null
4061 return;
4062 }
4063 }
4064 clientPropertyChanged(key, oldValue, value);
4065 firePropertyChange(key.toString(), oldValue, value);
4066 }
4067
4068 // Invoked from putClientProperty. This is provided for subclasses
4069 // in Swing.
4070 void clientPropertyChanged(Object key, Object oldValue,
4071 Object newValue) {
4072 }
4073
4074 /*
4075 * Sets the property with the specified name to the specified value if
4076 * the property has not already been set by the client program.
4077 * This method is used primarily to set UI defaults for properties
4078 * with primitive types, where the values cannot be marked with
4079 * UIResource.
4080 * @see LookAndFeel#installProperty
4081 * @param propertyName String containing the name of the property
4082 * @param value Object containing the property value
4083 */
4084 void setUIProperty(String propertyName, Object value) {
4085 if (propertyName == "opaque") {
4086 if (!getFlag(OPAQUE_SET)) {
4087 setOpaque(((Boolean) value).booleanValue());
4088 setFlag(OPAQUE_SET, false);
4089 }
4090 } else if (propertyName == "autoscrolls") {
4091 if (!getFlag(AUTOSCROLLS_SET)) {
4092 setAutoscrolls(((Boolean) value).booleanValue());
4093 setFlag(AUTOSCROLLS_SET, false);
4094 }
4095 } else if (propertyName == "focusTraversalKeysForward") {
4096 if (!getFlag(FOCUS_TRAVERSAL_KEYS_FORWARD_SET)) {
4097 super .setFocusTraversalKeys(
4098 KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
4099 (Set) value);
4100 }
4101 } else if (propertyName == "focusTraversalKeysBackward") {
4102 if (!getFlag(FOCUS_TRAVERSAL_KEYS_BACKWARD_SET)) {
4103 super .setFocusTraversalKeys(
4104 KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
4105 (Set) value);
4106 }
4107 } else {
4108 throw new IllegalArgumentException("property \""
4109 + propertyName
4110 + "\" cannot be set using this method");
4111 }
4112 }
4113
4114 /**
4115 * Sets the focus traversal keys for a given traversal operation for this
4116 * Component.
4117 * Refer to
4118 * {@link java.awt.Component#setFocusTraversalKeys}
4119 * for a complete description of this method.
4120 *
4121 * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
4122 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, or
4123 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS
4124 * @param keystrokes the Set of AWTKeyStroke for the specified operation
4125 * @see java.awt.KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
4126 * @see java.awt.KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
4127 * @see java.awt.KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
4128 * @throws IllegalArgumentException if id is not one of
4129 * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
4130 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, or
4131 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or if keystrokes
4132 * contains null, or if any Object in keystrokes is not an
4133 * AWTKeyStroke, or if any keystroke represents a KEY_TYPED event,
4134 * or if any keystroke already maps to another focus traversal
4135 * operation for this Component
4136 * @since 1.5
4137 * @beaninfo
4138 * bound: true
4139 */
4140 public void setFocusTraversalKeys(int id,
4141 Set<? extends AWTKeyStroke> keystrokes) {
4142 if (id == KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS) {
4143 setFlag(FOCUS_TRAVERSAL_KEYS_FORWARD_SET, true);
4144 } else if (id == KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS) {
4145 setFlag(FOCUS_TRAVERSAL_KEYS_BACKWARD_SET, true);
4146 }
4147 super .setFocusTraversalKeys(id, keystrokes);
4148 }
4149
4150 /* --- Transitional java.awt.Component Support ---
4151 * The methods and fields in this section will migrate to
4152 * java.awt.Component in the next JDK release.
4153 */
4154
4155 /**
4156 * Returns true if this component is lightweight, that is, if it doesn't
4157 * have a native window system peer.
4158 *
4159 * @return true if this component is lightweight
4160 */
4161 public static boolean isLightweightComponent(Component c) {
4162 return c.getPeer() instanceof LightweightPeer;
4163 }
4164
4165 /**
4166 * @deprecated As of JDK 5,
4167 * replaced by <code>Component.setBounds(int, int, int, int)</code>.
4168 * <p>
4169 * Moves and resizes this component.
4170 *
4171 * @param x the new horizontal location
4172 * @param y the new vertical location
4173 * @param w the new width
4174 * @param h the new height
4175 * @see java.awt.Component#setBounds
4176 */
4177 @Deprecated
4178 public void reshape(int x, int y, int w, int h) {
4179 super .reshape(x, y, w, h);
4180 }
4181
4182 /**
4183 * Stores the bounds of this component into "return value"
4184 * <code>rv</code> and returns <code>rv</code>.
4185 * If <code>rv</code> is <code>null</code> a new <code>Rectangle</code>
4186 * is allocated. This version of <code>getBounds</code> is useful
4187 * if the caller wants to avoid allocating a new <code>Rectangle</code>
4188 * object on the heap.
4189 *
4190 * @param rv the return value, modified to the component's bounds
4191 * @return <code>rv</code>; if <code>rv</code> is <code>null</code>
4192 * return a newly created <code>Rectangle</code> with this
4193 * component's bounds
4194 */
4195 public Rectangle getBounds(Rectangle rv) {
4196 if (rv == null) {
4197 return new Rectangle(getX(), getY(), getWidth(),
4198 getHeight());
4199 } else {
4200 rv.setBounds(getX(), getY(), getWidth(), getHeight());
4201 return rv;
4202 }
4203 }
4204
4205 /**
4206 * Stores the width/height of this component into "return value"
4207 * <code>rv</code> and returns <code>rv</code>.
4208 * If <code>rv</code> is <code>null</code> a new <code>Dimension</code>
4209 * object is allocated. This version of <code>getSize</code>
4210 * is useful if the caller wants to avoid allocating a new
4211 * <code>Dimension</code> object on the heap.
4212 *
4213 * @param rv the return value, modified to the component's size
4214 * @return <code>rv</code>
4215 */
4216 public Dimension getSize(Dimension rv) {
4217 if (rv == null) {
4218 return new Dimension(getWidth(), getHeight());
4219 } else {
4220 rv.setSize(getWidth(), getHeight());
4221 return rv;
4222 }
4223 }
4224
4225 /**
4226 * Stores the x,y origin of this component into "return value"
4227 * <code>rv</code> and returns <code>rv</code>.
4228 * If <code>rv</code> is <code>null</code> a new <code>Point</code>
4229 * is allocated. This version of <code>getLocation</code> is useful
4230 * if the caller wants to avoid allocating a new <code>Point</code>
4231 * object on the heap.
4232 *
4233 * @param rv the return value, modified to the component's location
4234 * @return <code>rv</code>
4235 */
4236 public Point getLocation(Point rv) {
4237 if (rv == null) {
4238 return new Point(getX(), getY());
4239 } else {
4240 rv.setLocation(getX(), getY());
4241 return rv;
4242 }
4243 }
4244
4245 /**
4246 * Returns the current x coordinate of the component's origin.
4247 * This method is preferable to writing
4248 * <code>component.getBounds().x</code>, or
4249 * <code>component.getLocation().x</code> because it doesn't cause any
4250 * heap allocations.
4251 *
4252 * @return the current x coordinate of the component's origin
4253 */
4254 public int getX() {
4255 return super .getX();
4256 }
4257
4258 /**
4259 * Returns the current y coordinate of the component's origin.
4260 * This method is preferable to writing
4261 * <code>component.getBounds().y</code>, or
4262 * <code>component.getLocation().y</code> because it doesn't cause any
4263 * heap allocations.
4264 *
4265 * @return the current y coordinate of the component's origin
4266 */
4267 public int getY() {
4268 return super .getY();
4269 }
4270
4271 /**
4272 * Returns the current width of this component.
4273 * This method is preferable to writing
4274 * <code>component.getBounds().width</code>, or
4275 * <code>component.getSize().width</code> because it doesn't cause any
4276 * heap allocations.
4277 *
4278 * @return the current width of this component
4279 */
4280 public int getWidth() {
4281 return super .getWidth();
4282 }
4283
4284 /**
4285 * Returns the current height of this component.
4286 * This method is preferable to writing
4287 * <code>component.getBounds().height</code>, or
4288 * <code>component.getSize().height</code> because it doesn't cause any
4289 * heap allocations.
4290 *
4291 * @return the current height of this component
4292 */
4293 public int getHeight() {
4294 return super .getHeight();
4295 }
4296
4297 /**
4298 * Returns true if this component is completely opaque.
4299 * <p>
4300 * An opaque component paints every pixel within its
4301 * rectangular bounds. A non-opaque component paints only a subset of
4302 * its pixels or none at all, allowing the pixels underneath it to
4303 * "show through". Therefore, a component that does not fully paint
4304 * its pixels provides a degree of transparency.
4305 * <p>
4306 * Subclasses that guarantee to always completely paint their contents
4307 * should override this method and return true.
4308 *
4309 * @return true if this component is completely opaque
4310 * @see #setOpaque
4311 */
4312 public boolean isOpaque() {
4313 return getFlag(IS_OPAQUE);
4314 }
4315
4316 /**
4317 * If true the component paints every pixel within its bounds.
4318 * Otherwise, the component may not paint some or all of its
4319 * pixels, allowing the underlying pixels to show through.
4320 * <p>
4321 * The default value of this property is false for <code>JComponent</code>.
4322 * However, the default value for this property on most standard
4323 * <code>JComponent</code> subclasses (such as <code>JButton</code> and
4324 * <code>JTree</code>) is look-and-feel dependent.
4325 *
4326 * @param isOpaque true if this component should be opaque
4327 * @see #isOpaque
4328 * @beaninfo
4329 * bound: true
4330 * expert: true
4331 * description: The component's opacity
4332 */
4333 public void setOpaque(boolean isOpaque) {
4334 boolean oldValue = getFlag(IS_OPAQUE);
4335 setFlag(IS_OPAQUE, isOpaque);
4336 setFlag(OPAQUE_SET, true);
4337 firePropertyChange("opaque", oldValue, isOpaque);
4338 }
4339
4340 /**
4341 * If the specified rectangle is completely obscured by any of this
4342 * component's opaque children then returns true. Only direct children
4343 * are considered, more distant descendants are ignored. A
4344 * <code>JComponent</code> is opaque if
4345 * <code>JComponent.isOpaque()</code> returns true, other lightweight
4346 * components are always considered transparent, and heavyweight components
4347 * are always considered opaque.
4348 *
4349 * @param x x value of specified rectangle
4350 * @param y y value of specified rectangle
4351 * @param width width of specified rectangle
4352 * @param height height of specified rectangle
4353 * @return true if the specified rectangle is obscured by an opaque child
4354 */
4355 boolean rectangleIsObscured(int x, int y, int width, int height) {
4356 int numChildren = getComponentCount();
4357
4358 for (int i = 0; i < numChildren; i++) {
4359 Component child = getComponent(i);
4360 int cx, cy, cw, ch;
4361
4362 cx = child.getX();
4363 cy = child.getY();
4364 cw = child.getWidth();
4365 ch = child.getHeight();
4366
4367 if (x >= cx && (x + width) <= (cx + cw) && y >= cy
4368 && (y + height) <= (cy + ch) && child.isVisible()) {
4369
4370 if (child instanceof JComponent) {
4371 // System.out.println("A) checking opaque: " + ((JComponent)child).isOpaque() + " " + child);
4372 // System.out.print("B) ");
4373 // Thread.dumpStack();
4374 return ((JComponent) child).isOpaque();
4375 } else {
4376 /** Sometimes a heavy weight can have a bound larger than its peer size
4377 * so we should always draw under heavy weights
4378 */
4379 return false;
4380 }
4381 }
4382 }
4383
4384 return false;
4385 }
4386
4387 /**
4388 * Returns the <code>Component</code>'s "visible rect rectangle" - the
4389 * intersection of the visible rectangles for the component <code>c</code>
4390 * and all of its ancestors. The return value is stored in
4391 * <code>visibleRect</code>.
4392 *
4393 * @param c the component
4394 * @param visibleRect a <code>Rectangle</code> computed as the
4395 * intersection of all visible rectangles for the component
4396 * <code>c</code> and all of its ancestors -- this is the
4397 * return value for this method
4398 * @see #getVisibleRect
4399 */
4400 static final void computeVisibleRect(Component c,
4401 Rectangle visibleRect) {
4402 Container p = c.getParent();
4403 Rectangle bounds = c.getBounds();
4404
4405 if (p == null || p instanceof Window || p instanceof Applet) {
4406 visibleRect.setBounds(0, 0, bounds.width, bounds.height);
4407 } else {
4408 computeVisibleRect(p, visibleRect);
4409 visibleRect.x -= bounds.x;
4410 visibleRect.y -= bounds.y;
4411 SwingUtilities.computeIntersection(0, 0, bounds.width,
4412 bounds.height, visibleRect);
4413 }
4414 }
4415
4416 /**
4417 * Returns the <code>Component</code>'s "visible rect rectangle" - the
4418 * intersection of the visible rectangles for this component
4419 * and all of its ancestors. The return value is stored in
4420 * <code>visibleRect</code>.
4421 *
4422 * @param visibleRect a <code>Rectangle</code> computed as the
4423 * intersection of all visible rectangles for this
4424 * component and all of its ancestors -- this is the return
4425 * value for this method
4426 * @see #getVisibleRect
4427 */
4428 public void computeVisibleRect(Rectangle visibleRect) {
4429 computeVisibleRect(this , visibleRect);
4430 }
4431
4432 /**
4433 * Returns the <code>Component</code>'s "visible rectangle" - the
4434 * intersection of this component's visible rectangle,
4435 * <code>new Rectangle(0, 0, getWidth(), getHeight())</code>,
4436 * and all of its ancestors' visible rectangles.
4437 *
4438 * @return the visible rectangle
4439 */
4440 public Rectangle getVisibleRect() {
4441 Rectangle visibleRect = new Rectangle();
4442
4443 computeVisibleRect(visibleRect);
4444 return visibleRect;
4445 }
4446
4447 /**
4448 * Support for reporting bound property changes for boolean properties.
4449 * This method can be called when a bound property has changed and it will
4450 * send the appropriate PropertyChangeEvent to any registered
4451 * PropertyChangeListeners.
4452 *
4453 * @param propertyName the property whose value has changed
4454 * @param oldValue the property's previous value
4455 * @param newValue the property's new value
4456 */
4457 public void firePropertyChange(String propertyName,
4458 boolean oldValue, boolean newValue) {
4459 super .firePropertyChange(propertyName, oldValue, newValue);
4460 }
4461
4462 /**
4463 * Support for reporting bound property changes for integer properties.
4464 * This method can be called when a bound property has changed and it will
4465 * send the appropriate PropertyChangeEvent to any registered
4466 * PropertyChangeListeners.
4467 *
4468 * @param propertyName the property whose value has changed
4469 * @param oldValue the property's previous value
4470 * @param newValue the property's new value
4471 */
4472 public void firePropertyChange(String propertyName, int oldValue,
4473 int newValue) {
4474 super .firePropertyChange(propertyName, oldValue, newValue);
4475 }
4476
4477 // XXX This method is implemented as a workaround to a JLS issue with ambiguous
4478 // methods. This should be removed once 4758654 is resolved.
4479 public void firePropertyChange(String propertyName, char oldValue,
4480 char newValue) {
4481 super .firePropertyChange(propertyName, oldValue, newValue);
4482 }
4483
4484 /**
4485 * Supports reporting constrained property changes.
4486 * This method can be called when a constrained property has changed
4487 * and it will send the appropriate <code>PropertyChangeEvent</code>
4488 * to any registered <code>VetoableChangeListeners</code>.
4489 *
4490 * @param propertyName the name of the property that was listened on
4491 * @param oldValue the old value of the property
4492 * @param newValue the new value of the property
4493 * @exception PropertyVetoException when the attempt to set the
4494 * property is vetoed by the component
4495 */
4496 protected void fireVetoableChange(String propertyName,
4497 Object oldValue, Object newValue)
4498 throws java.beans.PropertyVetoException {
4499 if (vetoableChangeSupport == null) {
4500 return;
4501 }
4502 vetoableChangeSupport.fireVetoableChange(propertyName,
4503 oldValue, newValue);
4504 }
4505
4506 /**
4507 * Adds a <code>VetoableChangeListener</code> to the listener list.
4508 * The listener is registered for all properties.
4509 *
4510 * @param listener the <code>VetoableChangeListener</code> to be added
4511 */
4512 public synchronized void addVetoableChangeListener(
4513 VetoableChangeListener listener) {
4514 if (vetoableChangeSupport == null) {
4515 vetoableChangeSupport = new java.beans.VetoableChangeSupport(
4516 this );
4517 }
4518 vetoableChangeSupport.addVetoableChangeListener(listener);
4519 }
4520
4521 /**
4522 * Removes a <code>VetoableChangeListener</code> from the listener list.
4523 * This removes a <code>VetoableChangeListener</code> that was registered
4524 * for all properties.
4525 *
4526 * @param listener the <code>VetoableChangeListener</code> to be removed
4527 */
4528 public synchronized void removeVetoableChangeListener(
4529 VetoableChangeListener listener) {
4530 if (vetoableChangeSupport == null) {
4531 return;
4532 }
4533 vetoableChangeSupport.removeVetoableChangeListener(listener);
4534 }
4535
4536 /**
4537 * Returns an array of all the vetoable change listeners
4538 * registered on this component.
4539 *
4540 * @return all of the component's <code>VetoableChangeListener</code>s
4541 * or an empty
4542 * array if no vetoable change listeners are currently registered
4543 *
4544 * @see #addVetoableChangeListener
4545 * @see #removeVetoableChangeListener
4546 *
4547 * @since 1.4
4548 */
4549 public synchronized VetoableChangeListener[] getVetoableChangeListeners() {
4550 if (vetoableChangeSupport == null) {
4551 return new VetoableChangeListener[0];
4552 }
4553 return vetoableChangeSupport.getVetoableChangeListeners();
4554 }
4555
4556 /**
4557 * Returns the top-level ancestor of this component (either the
4558 * containing <code>Window</code> or <code>Applet</code>),
4559 * or <code>null</code> if this component has not
4560 * been added to any container.
4561 *
4562 * @return the top-level <code>Container</code> that this component is in,
4563 * or <code>null</code> if not in any container
4564 */
4565 public Container getTopLevelAncestor() {
4566 for (Container p = this ; p != null; p = p.getParent()) {
4567 if (p instanceof Window || p instanceof Applet) {
4568 return p;
4569 }
4570 }
4571 return null;
4572 }
4573
4574 private AncestorNotifier getAncestorNotifier() {
4575 return (AncestorNotifier) getClientProperty(JComponent_ANCESTOR_NOTIFIER);
4576 }
4577
4578 /**
4579 * Registers <code>listener</code> so that it will receive
4580 * <code>AncestorEvents</code> when it or any of its ancestors
4581 * move or are made visible or invisible.
4582 * Events are also sent when the component or its ancestors are added
4583 * or removed from the containment hierarchy.
4584 *
4585 * @param listener the <code>AncestorListener</code> to register
4586 * @see AncestorEvent
4587 */
4588 public void addAncestorListener(AncestorListener listener) {
4589 AncestorNotifier ancestorNotifier = getAncestorNotifier();
4590 if (ancestorNotifier == null) {
4591 ancestorNotifier = new AncestorNotifier(this );
4592 putClientProperty(JComponent_ANCESTOR_NOTIFIER,
4593 ancestorNotifier);
4594 }
4595 ancestorNotifier.addAncestorListener(listener);
4596 }
4597
4598 /**
4599 * Unregisters <code>listener</code> so that it will no longer receive
4600 * <code>AncestorEvents</code>.
4601 *
4602 * @param listener the <code>AncestorListener</code> to be removed
4603 * @see #addAncestorListener
4604 */
4605 public void removeAncestorListener(AncestorListener listener) {
4606 AncestorNotifier ancestorNotifier = getAncestorNotifier();
4607 if (ancestorNotifier == null) {
4608 return;
4609 }
4610 ancestorNotifier.removeAncestorListener(listener);
4611 if (ancestorNotifier.listenerList.getListenerList().length == 0) {
4612 ancestorNotifier.removeAllListeners();
4613 putClientProperty(JComponent_ANCESTOR_NOTIFIER, null);
4614 }
4615 }
4616
4617 /**
4618 * Returns an array of all the ancestor listeners
4619 * registered on this component.
4620 *
4621 * @return all of the component's <code>AncestorListener</code>s
4622 * or an empty
4623 * array if no ancestor listeners are currently registered
4624 *
4625 * @see #addAncestorListener
4626 * @see #removeAncestorListener
4627 *
4628 * @since 1.4
4629 */
4630 public AncestorListener[] getAncestorListeners() {
4631 AncestorNotifier ancestorNotifier = getAncestorNotifier();
4632 if (ancestorNotifier == null) {
4633 return new AncestorListener[0];
4634 }
4635 return ancestorNotifier.getAncestorListeners();
4636 }
4637
4638 /**
4639 * Returns an array of all the objects currently registered
4640 * as <code><em>Foo</em>Listener</code>s
4641 * upon this <code>JComponent</code>.
4642 * <code><em>Foo</em>Listener</code>s are registered using the
4643 * <code>add<em>Foo</em>Listener</code> method.
4644 *
4645 * <p>
4646 *
4647 * You can specify the <code>listenerType</code> argument
4648 * with a class literal,
4649 * such as
4650 * <code><em>Foo</em>Listener.class</code>.
4651 * For example, you can query a
4652 * <code>JComponent</code> <code>c</code>
4653 * for its mouse listeners with the following code:
4654 * <pre>MouseListener[] mls = (MouseListener[])(c.getListeners(MouseListener.class));</pre>
4655 * If no such listeners exist, this method returns an empty array.
4656 *
4657 * @param listenerType the type of listeners requested; this parameter
4658 * should specify an interface that descends from
4659 * <code>java.util.EventListener</code>
4660 * @return an array of all objects registered as
4661 * <code><em>Foo</em>Listener</code>s on this component,
4662 * or an empty array if no such
4663 * listeners have been added
4664 * @exception ClassCastException if <code>listenerType</code>
4665 * doesn't specify a class or interface that implements
4666 * <code>java.util.EventListener</code>
4667 *
4668 * @since 1.3
4669 *
4670 * @see #getVetoableChangeListeners
4671 * @see #getAncestorListeners
4672 */
4673 public <T extends EventListener> T[] getListeners(
4674 Class<T> listenerType) {
4675 T[] result;
4676 if (listenerType == AncestorListener.class) {
4677 // AncestorListeners are handled by the AncestorNotifier
4678 result = (T[]) getAncestorListeners();
4679 } else if (listenerType == VetoableChangeListener.class) {
4680 // VetoableChangeListeners are handled by VetoableChangeSupport
4681 result = (T[]) getVetoableChangeListeners();
4682 } else if (listenerType == PropertyChangeListener.class) {
4683 // PropertyChangeListeners are handled by PropertyChangeSupport
4684 result = (T[]) getPropertyChangeListeners();
4685 } else {
4686 result = (T[]) listenerList.getListeners(listenerType);
4687 }
4688
4689 if (result.length == 0) {
4690 return super .getListeners(listenerType);
4691 }
4692 return result;
4693 }
4694
4695 /**
4696 * Notifies this component that it now has a parent component.
4697 * When this method is invoked, the chain of parent components is
4698 * set up with <code>KeyboardAction</code> event listeners.
4699 *
4700 * @see #registerKeyboardAction
4701 */
4702 public void addNotify() {
4703 super .addNotify();
4704 firePropertyChange("ancestor", null, getParent());
4705
4706 registerWithKeyboardManager(false);
4707 registerNextFocusableComponent();
4708 }
4709
4710 /**
4711 * Notifies this component that it no longer has a parent component.
4712 * When this method is invoked, any <code>KeyboardAction</code>s
4713 * set up in the the chain of parent components are removed.
4714 *
4715 * @see #registerKeyboardAction
4716 */
4717 public void removeNotify() {
4718 super .removeNotify();
4719 // This isn't strictly correct. The event shouldn't be
4720 // fired until *after* the parent is set to null. But
4721 // we only get notified before that happens
4722 firePropertyChange("ancestor", getParent(), null);
4723
4724 unregisterWithKeyboardManager();
4725 deregisterNextFocusableComponent();
4726
4727 if (getCreatedDoubleBuffer()) {
4728 RepaintManager.currentManager(this ).resetDoubleBuffer();
4729 setCreatedDoubleBuffer(false);
4730 }
4731 if (autoscrolls) {
4732 Autoscroller.stop(this );
4733 }
4734 }
4735
4736 /**
4737 * Adds the specified region to the dirty region list if the component
4738 * is showing. The component will be repainted after all of the
4739 * currently pending events have been dispatched.
4740 *
4741 * @param tm this parameter is not used
4742 * @param x the x value of the dirty region
4743 * @param y the y value of the dirty region
4744 * @param width the width of the dirty region
4745 * @param height the height of the dirty region
4746 * @see java.awt.Component#isShowing
4747 * @see RepaintManager#addDirtyRegion
4748 */
4749 public void repaint(long tm, int x, int y, int width, int height) {
4750 RepaintManager.currentManager(this ).addDirtyRegion(this , x, y,
4751 width, height);
4752 }
4753
4754 /**
4755 * Adds the specified region to the dirty region list if the component
4756 * is showing. The component will be repainted after all of the
4757 * currently pending events have been dispatched.
4758 *
4759 * @param r a <code>Rectangle</code> containing the dirty region
4760 * @see java.awt.Component#isShowing
4761 * @see RepaintManager#addDirtyRegion
4762 */
4763 public void repaint(Rectangle r) {
4764 repaint(0, r.x, r.y, r.width, r.height);
4765 }
4766
4767 /**
4768 * Supports deferred automatic layout.
4769 * <p>
4770 * Calls <code>invalidate</code> and then adds this component's
4771 * <code>validateRoot</code> to a list of components that need to be
4772 * validated. Validation will occur after all currently pending
4773 * events have been dispatched. In other words after this method
4774 * is called, the first validateRoot (if any) found when walking
4775 * up the containment hierarchy of this component will be validated.
4776 * By default, <code>JRootPane</code>, <code>JScrollPane</code>,
4777 * and <code>JTextField</code> return true
4778 * from <code>isValidateRoot</code>.
4779 * <p>
4780 * This method will automatically be called on this component
4781 * when a property value changes such that size, location, or
4782 * internal layout of this component has been affected. This automatic
4783 * updating differs from the AWT because programs generally no
4784 * longer need to invoke <code>validate</code> to get the contents of the
4785 * GUI to update.
4786 * <p>
4787 *
4788 * @see java.awt.Component#invalidate
4789 * @see java.awt.Container#validate
4790 * @see #isValidateRoot
4791 * @see RepaintManager#addInvalidComponent
4792 */
4793 public void revalidate() {
4794 if (getParent() == null) {
4795 // Note: We don't bother invalidating here as once added
4796 // to a valid parent invalidate will be invoked (addImpl
4797 // invokes addNotify which will invoke invalidate on the
4798 // new Component). Also, if we do add a check to isValid
4799 // here it can potentially be called before the constructor
4800 // which was causing some people grief.
4801 return;
4802 }
4803 if (SwingUtilities.isEventDispatchThread()) {
4804 invalidate();
4805 RepaintManager.currentManager(this ).addInvalidComponent(
4806 this );
4807 } else {
4808 // To avoid a flood of Runnables when constructing GUIs off
4809 // the EDT, a flag is maintained as to whether or not
4810 // a Runnable has been scheduled.
4811 synchronized (this ) {
4812 if (getFlag(REVALIDATE_RUNNABLE_SCHEDULED)) {
4813 return;
4814 }
4815 setFlag(REVALIDATE_RUNNABLE_SCHEDULED, true);
4816 }
4817 Runnable callRevalidate = new Runnable() {
4818 public void run() {
4819 synchronized (JComponent.this ) {
4820 setFlag(REVALIDATE_RUNNABLE_SCHEDULED, false);
4821 }
4822 revalidate();
4823 }
4824 };
4825 SwingUtilities.invokeLater(callRevalidate);
4826 }
4827 }
4828
4829 /**
4830 * If this method returns true, <code>revalidate</code> calls by
4831 * descendants of this component will cause the entire tree
4832 * beginning with this root to be validated.
4833 * Returns false by default. <code>JScrollPane</code> overrides
4834 * this method and returns true.
4835 *
4836 * @return always returns false
4837 * @see #revalidate
4838 * @see java.awt.Component#invalidate
4839 * @see java.awt.Container#validate
4840 */
4841 public boolean isValidateRoot() {
4842 return false;
4843 }
4844
4845 /**
4846 * Returns true if this component tiles its children -- that is, if
4847 * it can guarantee that the children will not overlap. The
4848 * repainting system is substantially more efficient in this
4849 * common case. <code>JComponent</code> subclasses that can't make this
4850 * guarantee, such as <code>JLayeredPane</code>,
4851 * should override this method to return false.
4852 *
4853 * @return always returns true
4854 */
4855 public boolean isOptimizedDrawingEnabled() {
4856 return true;
4857 }
4858
4859 /**
4860 * Returns true if a paint triggered on a child component should cause
4861 * painting to originate from this Component, or one of its ancestors.
4862 *
4863 * @return true if painting should originate from this Component or
4864 * one of its ancestors.
4865 */
4866 boolean isPaintingOrigin() {
4867 return false;
4868 }
4869
4870 /**
4871 * Paints the specified region in this component and all of its
4872 * descendants that overlap the region, immediately.
4873 * <p>
4874 * It's rarely necessary to call this method. In most cases it's
4875 * more efficient to call repaint, which defers the actual painting
4876 * and can collapse redundant requests into a single paint call.
4877 * This method is useful if one needs to update the display while
4878 * the current event is being dispatched.
4879 *
4880 * @param x the x value of the region to be painted
4881 * @param y the y value of the region to be painted
4882 * @param w the width of the region to be painted
4883 * @param h the height of the region to be painted
4884 * @see #repaint
4885 */
4886 public void paintImmediately(int x, int y, int w, int h) {
4887 Component c = this ;
4888 Component parent;
4889
4890 if (!isShowing()) {
4891 return;
4892 }
4893 while (!((JComponent) c).isOpaque()) {
4894 parent = c.getParent();
4895 if (parent != null) {
4896 x += c.getX();
4897 y += c.getY();
4898 c = parent;
4899 } else {
4900 break;
4901 }
4902
4903 if (!(c instanceof JComponent)) {
4904 break;
4905 }
4906 }
4907 if (c instanceof JComponent) {
4908 ((JComponent) c)._paintImmediately(x, y, w, h);
4909 } else {
4910 c.repaint(x, y, w, h);
4911 }
4912 }
4913
4914 /**
4915 * Paints the specified region now.
4916 *
4917 * @param r a <code>Rectangle</code> containing the region to be painted
4918 */
4919 public void paintImmediately(Rectangle r) {
4920 paintImmediately(r.x, r.y, r.width, r.height);
4921 }
4922
4923 /**
4924 * Returns whether this component should be guaranteed to be on top.
4925 * For example, it would make no sense for <code>Menu</code>s to pop up
4926 * under another component, so they would always return true.
4927 * Most components will want to return false, hence that is the default.
4928 *
4929 * @return always returns false
4930 */
4931 // package private
4932 boolean alwaysOnTop() {
4933 return false;
4934 }
4935
4936 void setPaintingChild(Component paintingChild) {
4937 this .paintingChild = paintingChild;
4938 }
4939
4940 void _paintImmediately(int x, int y, int w, int h) {
4941 Graphics g;
4942 Container c;
4943 Rectangle b;
4944
4945 int tmpX, tmpY, tmpWidth, tmpHeight;
4946 int offsetX = 0, offsetY = 0;
4947
4948 boolean hasBuffer = false;
4949
4950 JComponent bufferedComponent = null;
4951 JComponent paintingComponent = this ;
4952
4953 RepaintManager repaintManager = RepaintManager
4954 .currentManager(this );
4955 // parent Container's up to Window or Applet. First container is
4956 // the direct parent. Note that in testing it was faster to
4957 // alloc a new Vector vs keeping a stack of them around, and gc
4958 // seemed to have a minimal effect on this.
4959 java.util.List<Component> path = new java.util.ArrayList<Component>(
4960 7);
4961 int pIndex = -1;
4962 int pCount = 0;
4963
4964 tmpX = tmpY = tmpWidth = tmpHeight = 0;
4965
4966 Rectangle paintImmediatelyClip = fetchRectangle();
4967 paintImmediatelyClip.x = x;
4968 paintImmediatelyClip.y = y;
4969 paintImmediatelyClip.width = w;
4970 paintImmediatelyClip.height = h;
4971
4972 // System.out.println("1) ************* in _paintImmediately for " + this);
4973
4974 boolean ontop = alwaysOnTop() && isOpaque();
4975 if (ontop) {
4976 SwingUtilities.computeIntersection(0, 0, getWidth(),
4977 getHeight(), paintImmediatelyClip);
4978 if (paintImmediatelyClip.width == 0) {
4979 recycleRectangle(paintImmediatelyClip);
4980 return;
4981 }
4982 }
4983 Component child;
4984 for (c = this , child = null; c != null
4985 && !(c instanceof Window) && !(c instanceof Applet); child = c, c = c
4986 .getParent()) {
4987 JComponent jc = (c instanceof JComponent) ? (JComponent) c
4988 : null;
4989 path.add(c);
4990 if (!ontop && jc != null && !jc.isOptimizedDrawingEnabled()) {
4991 boolean resetPC;
4992
4993 // Children of c may overlap, three possible cases for the
4994 // painting region:
4995 // . Completely obscured by an opaque sibling, in which
4996 // case there is no need to paint.
4997 // . Partially obscured by a sibling: need to start
4998 // painting from c.
4999 // . Otherwise we aren't obscured and thus don't need to
5000 // start painting from parent.
5001 if (c != this ) {
5002 if (jc.isPaintingOrigin()) {
5003 resetPC = true;
5004 } else {
5005 Component[] children = c.getComponents();
5006 int i = 0;
5007 for (; i < children.length; i++) {
5008 if (children[i] == child)
5009 break;
5010 }
5011 switch (jc.getObscuredState(i,
5012 paintImmediatelyClip.x,
5013 paintImmediatelyClip.y,
5014 paintImmediatelyClip.width,
5015 paintImmediatelyClip.height)) {
5016 case NOT_OBSCURED:
5017 resetPC = false;
5018 break;
5019 case COMPLETELY_OBSCURED:
5020 recycleRectangle(paintImmediatelyClip);
5021 return;
5022 default:
5023 resetPC = true;
5024 break;
5025 }
5026 }
5027 } else {
5028 resetPC = false;
5029 }
5030
5031 if (resetPC) {
5032 // Get rid of any buffer since we draw from here and
5033 // we might draw something larger
5034 paintingComponent = jc;
5035 pIndex = pCount;
5036 offsetX = offsetY = 0;
5037 hasBuffer = false;
5038 }
5039 }
5040 pCount++;
5041
5042 // look to see if the parent (and therefor this component)
5043 // is double buffered
5044 if (repaintManager.isDoubleBufferingEnabled() && jc != null
5045 && jc.isDoubleBuffered()) {
5046 hasBuffer = true;
5047 bufferedComponent = jc;
5048 }
5049
5050 // if we aren't on top, include the parent's clip
5051 if (!ontop) {
5052 int bx = c.getX();
5053 int by = c.getY();
5054 tmpWidth = c.getWidth();
5055 tmpHeight = c.getHeight();
5056 SwingUtilities.computeIntersection(tmpX, tmpY,
5057 tmpWidth, tmpHeight, paintImmediatelyClip);
5058 paintImmediatelyClip.x += bx;
5059 paintImmediatelyClip.y += by;
5060 offsetX += bx;
5061 offsetY += by;
5062 }
5063 }
5064
5065 // If the clip width or height is negative, don't bother painting
5066 if (c == null || c.getPeer() == null
5067 || paintImmediatelyClip.width <= 0
5068 || paintImmediatelyClip.height <= 0) {
5069 recycleRectangle(paintImmediatelyClip);
5070 return;
5071 }
5072
5073 paintingComponent.setFlag(IS_REPAINTING, true);
5074
5075 paintImmediatelyClip.x -= offsetX;
5076 paintImmediatelyClip.y -= offsetY;
5077
5078 // Notify the Components that are going to be painted of the
5079 // child component to paint to.
5080 if (paintingComponent != this ) {
5081 Component comp;
5082 int i = pIndex;
5083 for (; i > 0; i--) {
5084 comp = path.get(i);
5085 if (comp instanceof JComponent) {
5086 ((JComponent) comp).setPaintingChild(path
5087 .get(i - 1));
5088 }
5089 }
5090 }
5091
5092 try {
5093 g = safelyGetGraphics(paintingComponent, c);
5094 try {
5095 if (hasBuffer) {
5096 RepaintManager rm = RepaintManager
5097 .currentManager(bufferedComponent);
5098 rm.beginPaint();
5099 try {
5100 rm.paint(paintingComponent, bufferedComponent,
5101 g, paintImmediatelyClip.x,
5102 paintImmediatelyClip.y,
5103 paintImmediatelyClip.width,
5104 paintImmediatelyClip.height);
5105 } finally {
5106 rm.endPaint();
5107 }
5108 } else {
5109 g.setClip(paintImmediatelyClip.x,
5110 paintImmediatelyClip.y,
5111 paintImmediatelyClip.width,
5112 paintImmediatelyClip.height);
5113 paintingComponent.paint(g);
5114 }
5115 } finally {
5116 g.dispose();
5117 }
5118 } finally {
5119 // Reset the painting child for the parent components.
5120 if (paintingComponent != this ) {
5121 Component comp;
5122 int i = pIndex;
5123 for (; i > 0; i--) {
5124 comp = path.get(i);
5125 if (comp instanceof JComponent) {
5126 ((JComponent) comp).setPaintingChild(null);
5127 }
5128 }
5129 }
5130 paintingComponent.setFlag(IS_REPAINTING, false);
5131 }
5132 recycleRectangle(paintImmediatelyClip);
5133 }
5134
5135 /**
5136 * Paints to the specified graphics. This does not set the clip and it
5137 * does not adjust the Graphics in anyway, callers must do that first.
5138 * This method is package-private for RepaintManager.PaintManager and
5139 * its subclasses to call, it is NOT intended for general use outside
5140 * of that.
5141 */
5142 void paintToOffscreen(Graphics g, int x, int y, int w, int h,
5143 int maxX, int maxY) {
5144 try {
5145 setFlag(ANCESTOR_USING_BUFFER, true);
5146 if ((y + h) < maxY || (x + w) < maxX) {
5147 setFlag(IS_PAINTING_TILE, true);
5148 }
5149 if (getFlag(IS_REPAINTING)) {
5150 // Called from paintImmediately (RepaintManager) to fill
5151 // repaint request
5152 paint(g);
5153 } else {
5154 // Called from paint() (AWT) to repair damage
5155 if (!rectangleIsObscured(x, y, w, h)) {
5156 paintComponent(g);
5157 paintBorder(g);
5158 }
5159 paintChildren(g);
5160 }
5161 } finally {
5162 setFlag(ANCESTOR_USING_BUFFER, false);
5163 setFlag(IS_PAINTING_TILE, false);
5164 }
5165 }
5166
5167 /**
5168 * Returns whether or not the region of the specified component is
5169 * obscured by a sibling.
5170 *
5171 * @return NOT_OBSCURED if non of the siblings above the Component obscure
5172 * it, COMPLETELY_OBSCURED if one of the siblings completely
5173 * obscures the Component or PARTIALLY_OBSCURED if the Comonent is
5174 * only partially obscured.
5175 */
5176 private int getObscuredState(int compIndex, int x, int y,
5177 int width, int height) {
5178 int retValue = NOT_OBSCURED;
5179 Rectangle tmpRect = fetchRectangle();
5180
5181 for (int i = compIndex - 1; i >= 0; i--) {
5182 Component sibling = getComponent(i);
5183 if (!sibling.isVisible()) {
5184 continue;
5185 }
5186 Rectangle siblingRect;
5187 boolean opaque;
5188 if (sibling instanceof JComponent) {
5189 opaque = ((JComponent) sibling).isOpaque();
5190 if (!opaque) {
5191 if (retValue == PARTIALLY_OBSCURED) {
5192 continue;
5193 }
5194 }
5195 } else {
5196 opaque = true;
5197 }
5198 siblingRect = sibling.getBounds(tmpRect);
5199 if (opaque
5200 && x >= siblingRect.x
5201 && (x + width) <= (siblingRect.x + siblingRect.width)
5202 && y >= siblingRect.y
5203 && (y + height) <= (siblingRect.y + siblingRect.height)) {
5204 recycleRectangle(tmpRect);
5205 return COMPLETELY_OBSCURED;
5206 } else if (retValue == NOT_OBSCURED
5207 && !((x + width <= siblingRect.x)
5208 || (y + height <= siblingRect.y)
5209 || (x >= siblingRect.x + siblingRect.width) || (y >= siblingRect.y
5210 + siblingRect.height))) {
5211 retValue = PARTIALLY_OBSCURED;
5212 }
5213 }
5214 recycleRectangle(tmpRect);
5215 return retValue;
5216 }
5217
5218 /**
5219 * Returns true, which implies that before checking if a child should
5220 * be painted it is first check that the child is not obscured by another
5221 * sibling. This is only checked if <code>isOptimizedDrawingEnabled</code>
5222 * returns false.
5223 *
5224 * @return always returns true
5225 */
5226 boolean checkIfChildObscuredBySibling() {
5227 return true;
5228 }
5229
5230 private void setFlag(int aFlag, boolean aValue) {
5231 if (aValue) {
5232 flags |= (1 << aFlag);
5233 } else {
5234 flags &= ~(1 << aFlag);
5235 }
5236 }
5237
5238 private boolean getFlag(int aFlag) {
5239 int mask = (1 << aFlag);
5240 return ((flags & mask) == mask);
5241 }
5242
5243 // These functions must be static so that they can be called from
5244 // subclasses inside the package, but whose inheritance hierarhcy includes
5245 // classes outside of the package below JComponent (e.g., JTextArea).
5246 static void setWriteObjCounter(JComponent comp, byte count) {
5247 comp.flags = (comp.flags & ~(0xFF << WRITE_OBJ_COUNTER_FIRST))
5248 | (count << WRITE_OBJ_COUNTER_FIRST);
5249 }
5250
5251 static byte getWriteObjCounter(JComponent comp) {
5252 return (byte) ((comp.flags >> WRITE_OBJ_COUNTER_FIRST) & 0xFF);
5253 }
5254
5255 /** Buffering **/
5256
5257 /**
5258 * Sets whether this component should use a buffer to paint.
5259 * If set to true, all the drawing from this component will be done
5260 * in an offscreen painting buffer. The offscreen painting buffer will
5261 * the be copied onto the screen.
5262 * If a <code>Component</code> is buffered and one of its ancestor
5263 * is also buffered, the ancestor buffer will be used.
5264 *
5265 * @param aFlag if true, set this component to be double buffered
5266 */
5267 public void setDoubleBuffered(boolean aFlag) {
5268 setFlag(IS_DOUBLE_BUFFERED, aFlag);
5269 }
5270
5271 /**
5272 * Returns whether this component should use a buffer to paint.
5273 *
5274 * @return true if this component is double buffered, otherwise false
5275 */
5276 public boolean isDoubleBuffered() {
5277 return getFlag(IS_DOUBLE_BUFFERED);
5278 }
5279
5280 /**
5281 * Returns the <code>JRootPane</code> ancestor for this component.
5282 *
5283 * @return the <code>JRootPane</code> that contains this component,
5284 * or <code>null</code> if no <code>JRootPane</code> is found
5285 */
5286 public JRootPane getRootPane() {
5287 return SwingUtilities.getRootPane(this );
5288 }
5289
5290 /** Serialization **/
5291
5292 /**
5293 * This is called from Component by way of reflection. Do NOT change
5294 * the name unless you change the code in Component as well.
5295 */
5296 void compWriteObjectNotify() {
5297 byte count = JComponent.getWriteObjCounter(this );
5298 JComponent.setWriteObjCounter(this , (byte) (count + 1));
5299 if (count != 0) {
5300 return;
5301 }
5302
5303 uninstallUIAndProperties();
5304
5305 /* JTableHeader is in a separate package, which prevents it from
5306 * being able to override this package-private method the way the
5307 * other components can. We don't want to make this method protected
5308 * because it would introduce public-api for a less-than-desirable
5309 * serialization scheme, so we compromise with this 'instanceof' hack
5310 * for now.
5311 */
5312 if (getToolTipText() != null
5313 || this instanceof javax.swing.table.JTableHeader) {
5314 ToolTipManager.sharedInstance().unregisterComponent(
5315 JComponent.this );
5316 }
5317 }
5318
5319 /**
5320 * This object is the <code>ObjectInputStream</code> callback
5321 * that's called after a complete graph of objects (including at least
5322 * one <code>JComponent</code>) has been read.
5323 * It sets the UI property of each Swing component
5324 * that was read to the current default with <code>updateUI</code>.
5325 * <p>
5326 * As each component is read in we keep track of the current set of
5327 * root components here, in the roots vector. Note that there's only one
5328 * <code>ReadObjectCallback</code> per <code>ObjectInputStream</code>,
5329 * they're stored in the static <code>readObjectCallbacks</code>
5330 * hashtable.
5331 *
5332 * @see java.io.ObjectInputStream#registerValidation
5333 * @see SwingUtilities#updateComponentTreeUI
5334 */
5335 private class ReadObjectCallback implements ObjectInputValidation {
5336 private final Vector roots = new Vector(1);
5337 private final ObjectInputStream inputStream;
5338
5339 ReadObjectCallback(ObjectInputStream s) throws Exception {
5340 inputStream = s;
5341 s.registerValidation(this , 0);
5342 }
5343
5344 /**
5345 * This is the method that's called after the entire graph
5346 * of objects has been read in. It initializes
5347 * the UI property of all of the copmonents with
5348 * <code>SwingUtilities.updateComponentTreeUI</code>.
5349 */
5350 public void validateObject() throws InvalidObjectException {
5351 try {
5352 for (int i = 0; i < roots.size(); i++) {
5353 JComponent root = (JComponent) (roots.elementAt(i));
5354 SwingUtilities.updateComponentTreeUI(root);
5355 }
5356 } finally {
5357 readObjectCallbacks.remove(inputStream);
5358 }
5359 }
5360
5361 /**
5362 * If <code>c</code> isn't a descendant of a component we've already
5363 * seen, then add it to the roots <code>Vector</code>.
5364 *
5365 * @param c the <code>JComponent</code> to add
5366 */
5367 private void registerComponent(JComponent c) {
5368 /* If the Component c is a descendant of one of the
5369 * existing roots (or it IS an existing root), we're done.
5370 */
5371 for (int i = 0; i < roots.size(); i++) {
5372 JComponent root = (JComponent) roots.elementAt(i);
5373 for (Component p = c; p != null; p = p.getParent()) {
5374 if (p == root) {
5375 return;
5376 }
5377 }
5378 }
5379
5380 /* Otherwise: if Component c is an ancestor of any of the
5381 * existing roots then remove them and add c (the "new root")
5382 * to the roots vector.
5383 */
5384 for (int i = 0; i < roots.size(); i++) {
5385 JComponent root = (JComponent) roots.elementAt(i);
5386 for (Component p = root.getParent(); p != null; p = p
5387 .getParent()) {
5388 if (p == c) {
5389 roots.removeElementAt(i--); // !!
5390 break;
5391 }
5392 }
5393 }
5394
5395 roots.addElement(c);
5396 }
5397 }
5398
5399 /**
5400 * We use the <code>ObjectInputStream</code> "registerValidation"
5401 * callback to update the UI for the entire tree of components
5402 * after they've all been read in.
5403 *
5404 * @param s the <code>ObjectInputStream</code> from which to read
5405 */
5406 private void readObject(ObjectInputStream s) throws IOException,
5407 ClassNotFoundException {
5408 s.defaultReadObject();
5409
5410 /* If there's no ReadObjectCallback for this stream yet, that is, if
5411 * this is the first call to JComponent.readObject() for this
5412 * graph of objects, then create a callback and stash it
5413 * in the readObjectCallbacks table. Note that the ReadObjectCallback
5414 * constructor takes care of calling s.registerValidation().
5415 */
5416 ReadObjectCallback cb = (ReadObjectCallback) (readObjectCallbacks
5417 .get(s));
5418 if (cb == null) {
5419 try {
5420 readObjectCallbacks.put(s, cb = new ReadObjectCallback(
5421 s));
5422 } catch (Exception e) {
5423 throw new IOException(e.toString());
5424 }
5425 }
5426 cb.registerComponent(this );
5427
5428 // Read back the client properties.
5429 int cpCount = s.readInt();
5430 if (cpCount > 0) {
5431 clientProperties = new ArrayTable();
5432 for (int counter = 0; counter < cpCount; counter++) {
5433 clientProperties.put(s.readObject(), s.readObject());
5434 }
5435 }
5436 if (getToolTipText() != null) {
5437 ToolTipManager.sharedInstance().registerComponent(this );
5438 }
5439 setWriteObjCounter(this , (byte) 0);
5440 }
5441
5442 /**
5443 * Before writing a <code>JComponent</code> to an
5444 * <code>ObjectOutputStream</code> we temporarily uninstall its UI.
5445 * This is tricky to do because we want to uninstall
5446 * the UI before any of the <code>JComponent</code>'s children
5447 * (or its <code>LayoutManager</code> etc.) are written,
5448 * and we don't want to restore the UI until the most derived
5449 * <code>JComponent</code> subclass has been been stored.
5450 *
5451 * @param s the <code>ObjectOutputStream</code> in which to write
5452 */
5453 private void writeObject(ObjectOutputStream s) throws IOException {
5454 s.defaultWriteObject();
5455 if (getUIClassID().equals(uiClassID)) {
5456 byte count = JComponent.getWriteObjCounter(this );
5457 JComponent.setWriteObjCounter(this , --count);
5458 if (count == 0 && ui != null) {
5459 ui.installUI(this );
5460 }
5461 }
5462 ArrayTable.writeArrayTable(s, clientProperties);
5463 }
5464
5465 /**
5466 * Returns a string representation of this <code>JComponent</code>.
5467 * This method
5468 * is intended to be used only for debugging purposes, and the
5469 * content and format of the returned string may vary between
5470 * implementations. The returned string may be empty but may not
5471 * be <code>null</code>.
5472 *
5473 * @return a string representation of this <code>JComponent</code>
5474 */
5475 protected String paramString() {
5476 String preferredSizeString = (isPreferredSizeSet() ? getPreferredSize()
5477 .toString()
5478 : "");
5479 String minimumSizeString = (isMinimumSizeSet() ? getMinimumSize()
5480 .toString()
5481 : "");
5482 String maximumSizeString = (isMaximumSizeSet() ? getMaximumSize()
5483 .toString()
5484 : "");
5485 String borderString = (border == null ? ""
5486 : (border == this ? "this" : border.toString()));
5487
5488 return super .paramString() + ",alignmentX=" + alignmentX
5489 + ",alignmentY=" + alignmentY + ",border="
5490 + borderString + ",flags="
5491 + flags
5492 + // should beef this up a bit
5493 ",maximumSize=" + maximumSizeString + ",minimumSize="
5494 + minimumSizeString + ",preferredSize="
5495 + preferredSizeString;
5496 }
5497
5498 }
|