1 /* 2 * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package javax.swing; 26 27 28 import java.util.HashSet; 29 import java.util.Hashtable; 30 import java.util.Enumeration; 31 import java.util.Locale; 32 import java.util.Vector; 33 import java.util.EventListener; 34 import java.util.Set; 35 36 import java.awt.*; 37 import java.awt.event.*; 38 import java.awt.peer.LightweightPeer; 39 import java.beans.PropertyChangeListener; 40 import java.beans.VetoableChangeListener; 41 import java.beans.VetoableChangeSupport; 42 import java.beans.Transient; 43 44 import java.applet.Applet; 45 46 import java.io.Serializable; 47 import java.io.ObjectOutputStream; 48 import java.io.ObjectInputStream; 49 import java.io.IOException; 50 import java.io.ObjectInputValidation; 51 import java.io.InvalidObjectException; 52 import java.util.concurrent.atomic.AtomicBoolean; 53 54 import javax.swing.border.*; 55 import javax.swing.event.*; 56 import javax.swing.plaf.*; 57 import static javax.swing.ClientPropertyKey.*; 58 import javax.accessibility.*; 59 60 import sun.awt.SunToolkit; 61 import sun.swing.SwingUtilities2; 62 import sun.swing.UIClientPropertyKey; 63 64 /** 65 * The base class for all Swing components except top-level containers. 66 * To use a component that inherits from <code>JComponent</code>, 67 * you must place the component in a containment hierarchy 68 * whose root is a top-level Swing container. 69 * Top-level Swing containers -- 70 * such as <code>JFrame</code>, <code>JDialog</code>, 71 * and <code>JApplet</code> -- 72 * are specialized components 73 * that provide a place for other Swing components to paint themselves. 74 * For an explanation of containment hierarchies, see 75 * <a 76 href="http://docs.oracle.com/javase/tutorial/uiswing/components/toplevel.html">Swing Components and the Containment Hierarchy</a>, 77 * a section in <em>The Java Tutorial</em>. 78 * 79 * <p> 80 * The <code>JComponent</code> class provides: 81 * <ul> 82 * <li>The base class for both standard and custom components 83 * that use the Swing architecture. 84 * <li>A "pluggable look and feel" (L&F) that can be specified by the 85 * programmer or (optionally) selected by the user at runtime. 86 * The look and feel for each component is provided by a 87 * <em>UI delegate</em> -- an object that descends from 88 * {@link javax.swing.plaf.ComponentUI}. 89 * See <a 90 * href="http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html">How 91 * to Set the Look and Feel</a> 92 * in <em>The Java Tutorial</em> 93 * for more information. 94 * <li>Comprehensive keystroke handling. 95 * See the document <a 96 * href="http://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html">How to Use Key Bindings</a>, 97 * an article in <em>The Java Tutorial</em>, 98 * for more information. 99 * <li>Support for tool tips -- 100 * short descriptions that pop up when the cursor lingers 101 * over a component. 102 * See <a 103 * href="http://docs.oracle.com/javase/tutorial/uiswing/components/tooltip.html">How 104 * to Use Tool Tips</a> 105 * in <em>The Java Tutorial</em> 106 * for more information. 107 * <li>Support for accessibility. 108 * <code>JComponent</code> contains all of the methods in the 109 * <code>Accessible</code> interface, 110 * but it doesn't actually implement the interface. That is the 111 * responsibility of the individual classes 112 * that extend <code>JComponent</code>. 113 * <li>Support for component-specific properties. 114 * With the {@link #putClientProperty} 115 * and {@link #getClientProperty} methods, 116 * you can associate name-object pairs 117 * with any object that descends from <code>JComponent</code>. 118 * <li>An infrastructure for painting 119 * that includes double buffering and support for borders. 120 * For more information see <a 121 * href="http://www.oracle.com/technetwork/java/painting-140037.html#swing">Painting</a> and 122 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/border.html">How 123 * to Use Borders</a>, 124 * both of which are sections in <em>The Java Tutorial</em>. 125 * </ul> 126 * For more information on these subjects, see the 127 * <a href="package-summary.html#package_description">Swing package description</a> 128 * and <em>The Java Tutorial</em> section 129 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/jcomponent.html">The JComponent Class</a>. 130 * <p> 131 * <code>JComponent</code> and its subclasses document default values 132 * for certain properties. For example, <code>JTable</code> documents the 133 * default row height as 16. Each <code>JComponent</code> subclass 134 * that has a <code>ComponentUI</code> will create the 135 * <code>ComponentUI</code> as part of its constructor. In order 136 * to provide a particular look and feel each 137 * <code>ComponentUI</code> may set properties back on the 138 * <code>JComponent</code> that created it. For example, a custom 139 * look and feel may require <code>JTable</code>s to have a row 140 * height of 24. The documented defaults are the value of a property 141 * BEFORE the <code>ComponentUI</code> has been installed. If you 142 * need a specific value for a particular property you should 143 * explicitly set it. 144 * <p> 145 * In release 1.4, the focus subsystem was rearchitected. 146 * For more information, see 147 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html"> 148 * How to Use the Focus Subsystem</a>, 149 * a section in <em>The Java Tutorial</em>. 150 * <p> 151 * <strong>Warning:</strong> Swing is not thread safe. For more 152 * information see <a 153 * href="package-summary.html#threading">Swing's Threading 154 * Policy</a>. 155 * <p> 156 * <strong>Warning:</strong> 157 * Serialized objects of this class will not be compatible with 158 * future Swing releases. The current serialization support is 159 * appropriate for short term storage or RMI between applications running 160 * the same version of Swing. As of 1.4, support for long term storage 161 * of all JavaBeans™ 162 * has been added to the <code>java.beans</code> package. 163 * Please see {@link java.beans.XMLEncoder}. 164 * 165 * @see KeyStroke 166 * @see Action 167 * @see #setBorder 168 * @see #registerKeyboardAction 169 * @see JOptionPane 170 * @see #setDebugGraphicsOptions 171 * @see #setToolTipText 172 * @see #setAutoscrolls 173 * 174 * @author Hans Muller 175 * @author Arnaud Weber 176 * @since 1.2 177 */ 178 @SuppressWarnings("serial") // Same-version serialization only 179 public abstract class JComponent extends Container implements Serializable, 180 TransferHandler.HasGetTransferHandler 181 { 182 /** 183 * @see #getUIClassID 184 * @see #writeObject 185 */ 186 private static final String uiClassID = "ComponentUI"; 187 188 /** 189 * @see #readObject 190 */ 191 private static final Hashtable<ObjectInputStream, ReadObjectCallback> readObjectCallbacks = 192 new Hashtable<ObjectInputStream, ReadObjectCallback>(1); 193 194 /** 195 * Keys to use for forward focus traversal when the JComponent is 196 * managing focus. 197 */ 198 private static Set<KeyStroke> managingFocusForwardTraversalKeys; 199 200 /** 201 * Keys to use for backward focus traversal when the JComponent is 202 * managing focus. 203 */ 204 private static Set<KeyStroke> managingFocusBackwardTraversalKeys; 205 206 // Following are the possible return values from getObscuredState. 207 private static final int NOT_OBSCURED = 0; 208 private static final int PARTIALLY_OBSCURED = 1; 209 private static final int COMPLETELY_OBSCURED = 2; 210 211 /** 212 * Set to true when DebugGraphics has been loaded. 213 */ 214 static boolean DEBUG_GRAPHICS_LOADED; 215 216 /** 217 * Key used to look up a value from the AppContext to determine the 218 * JComponent the InputVerifier is running for. That is, if 219 * AppContext.get(INPUT_VERIFIER_SOURCE_KEY) returns non-null, it 220 * indicates the EDT is calling into the InputVerifier from the 221 * returned component. 222 */ 223 private static final Object INPUT_VERIFIER_SOURCE_KEY = 224 new StringBuilder("InputVerifierSourceKey"); 225 226 /* The following fields support set methods for the corresponding 227 * java.awt.Component properties. 228 */ 229 private boolean isAlignmentXSet; 230 private float alignmentX; 231 private boolean isAlignmentYSet; 232 private float alignmentY; 233 234 /** 235 * Backing store for JComponent properties and listeners 236 */ 237 238 /** The look and feel delegate for this component. */ 239 protected transient ComponentUI ui; 240 /** A list of event listeners for this component. */ 241 protected EventListenerList listenerList = new EventListenerList(); 242 243 private transient ArrayTable clientProperties; 244 private VetoableChangeSupport vetoableChangeSupport; 245 /** 246 * Whether or not autoscroll has been enabled. 247 */ 248 private boolean autoscrolls; 249 private Border border; 250 private int flags; 251 252 /* Input verifier for this component */ 253 private InputVerifier inputVerifier = null; 254 255 private boolean verifyInputWhenFocusTarget = true; 256 257 /** 258 * Set in <code>_paintImmediately</code>. 259 * Will indicate the child that initiated the painting operation. 260 * If <code>paintingChild</code> is opaque, no need to paint 261 * any child components after <code>paintingChild</code>. 262 * Test used in <code>paintChildren</code>. 263 */ 264 transient Component paintingChild; 265 266 /** 267 * Constant used for <code>registerKeyboardAction</code> that 268 * means that the command should be invoked when 269 * the component has the focus. 270 */ 271 public static final int WHEN_FOCUSED = 0; 272 273 /** 274 * Constant used for <code>registerKeyboardAction</code> that 275 * means that the command should be invoked when the receiving 276 * component is an ancestor of the focused component or is 277 * itself the focused component. 278 */ 279 public static final int WHEN_ANCESTOR_OF_FOCUSED_COMPONENT = 1; 280 281 /** 282 * Constant used for <code>registerKeyboardAction</code> that 283 * means that the command should be invoked when 284 * the receiving component is in the window that has the focus 285 * or is itself the focused component. 286 */ 287 public static final int WHEN_IN_FOCUSED_WINDOW = 2; 288 289 /** 290 * Constant used by some of the APIs to mean that no condition is defined. 291 */ 292 public static final int UNDEFINED_CONDITION = -1; 293 294 /** 295 * The key used by <code>JComponent</code> to access keyboard bindings. 296 */ 297 private static final String KEYBOARD_BINDINGS_KEY = "_KeyboardBindings"; 298 299 /** 300 * An array of <code>KeyStroke</code>s used for 301 * <code>WHEN_IN_FOCUSED_WINDOW</code> are stashed 302 * in the client properties under this string. 303 */ 304 private static final String WHEN_IN_FOCUSED_WINDOW_BINDINGS = "_WhenInFocusedWindow"; 305 306 /** 307 * The comment to display when the cursor is over the component, 308 * also known as a "value tip", "flyover help", or "flyover label". 309 */ 310 public static final String TOOL_TIP_TEXT_KEY = "ToolTipText"; 311 312 private static final String NEXT_FOCUS = "nextFocus"; 313 314 /** 315 * <code>JPopupMenu</code> assigned to this component 316 * and all of its children 317 */ 318 private JPopupMenu popupMenu; 319 320 /** Private flags **/ 321 private static final int IS_DOUBLE_BUFFERED = 0; 322 private static final int ANCESTOR_USING_BUFFER = 1; 323 private static final int IS_PAINTING_TILE = 2; 324 private static final int IS_OPAQUE = 3; 325 private static final int KEY_EVENTS_ENABLED = 4; 326 private static final int FOCUS_INPUTMAP_CREATED = 5; 327 private static final int ANCESTOR_INPUTMAP_CREATED = 6; 328 private static final int WIF_INPUTMAP_CREATED = 7; 329 private static final int ACTIONMAP_CREATED = 8; 330 private static final int CREATED_DOUBLE_BUFFER = 9; 331 // bit 10 is free 332 private static final int IS_PRINTING = 11; 333 private static final int IS_PRINTING_ALL = 12; 334 private static final int IS_REPAINTING = 13; 335 /** Bits 14-21 are used to handle nested writeObject calls. **/ 336 private static final int WRITE_OBJ_COUNTER_FIRST = 14; 337 private static final int RESERVED_1 = 15; 338 private static final int RESERVED_2 = 16; 339 private static final int RESERVED_3 = 17; 340 private static final int RESERVED_4 = 18; 341 private static final int RESERVED_5 = 19; 342 private static final int RESERVED_6 = 20; 343 private static final int WRITE_OBJ_COUNTER_LAST = 21; 344 345 private static final int REQUEST_FOCUS_DISABLED = 22; 346 private static final int INHERITS_POPUP_MENU = 23; 347 private static final int OPAQUE_SET = 24; 348 private static final int AUTOSCROLLS_SET = 25; 349 private static final int FOCUS_TRAVERSAL_KEYS_FORWARD_SET = 26; 350 private static final int FOCUS_TRAVERSAL_KEYS_BACKWARD_SET = 27; 351 352 private transient AtomicBoolean revalidateRunnableScheduled = new AtomicBoolean(false); 353 354 /** 355 * Temporary rectangles. 356 */ 357 private static java.util.List<Rectangle> tempRectangles = new java.util.ArrayList<Rectangle>(11); 358 359 /** Used for <code>WHEN_FOCUSED</code> bindings. */ 360 private InputMap focusInputMap; 361 /** Used for <code>WHEN_ANCESTOR_OF_FOCUSED_COMPONENT</code> bindings. */ 362 private InputMap ancestorInputMap; 363 /** Used for <code>WHEN_IN_FOCUSED_KEY</code> bindings. */ 364 private ComponentInputMap windowInputMap; 365 366 /** ActionMap. */ 367 private ActionMap actionMap; 368 369 /** Key used to store the default locale in an AppContext **/ 370 private static final String defaultLocale = "JComponent.defaultLocale"; 371 372 private static Component componentObtainingGraphicsFrom; 373 private static Object componentObtainingGraphicsFromLock = new 374 StringBuilder("componentObtainingGraphicsFrom"); 375 376 /** 377 * AA text hints. 378 */ 379 transient private Object aaTextInfo; 380 381 static Graphics safelyGetGraphics(Component c) { 382 return safelyGetGraphics(c, SwingUtilities.getRoot(c)); 383 } 384 385 static Graphics safelyGetGraphics(Component c, Component root) { 386 synchronized(componentObtainingGraphicsFromLock) { 387 componentObtainingGraphicsFrom = root; 388 Graphics g = c.getGraphics(); 389 componentObtainingGraphicsFrom = null; 390 return g; 391 } 392 } 393 394 static void getGraphicsInvoked(Component root) { 395 if (!JComponent.isComponentObtainingGraphicsFrom(root)) { 396 JRootPane rootPane = ((RootPaneContainer)root).getRootPane(); 397 if (rootPane != null) { 398 rootPane.disableTrueDoubleBuffering(); 399 } 400 } 401 } 402 403 404 /** 405 * Returns true if {@code c} is the component the graphics is being 406 * requested of. This is intended for use when getGraphics is invoked. 407 */ 408 private static boolean isComponentObtainingGraphicsFrom(Component c) { 409 synchronized(componentObtainingGraphicsFromLock) { 410 return (componentObtainingGraphicsFrom == c); 411 } 412 } 413 414 /** 415 * Returns the Set of <code>KeyStroke</code>s to use if the component 416 * is managing focus for forward focus traversal. 417 */ 418 static Set<KeyStroke> getManagingFocusForwardTraversalKeys() { 419 synchronized(JComponent.class) { 420 if (managingFocusForwardTraversalKeys == null) { 421 managingFocusForwardTraversalKeys = new HashSet<KeyStroke>(1); 422 managingFocusForwardTraversalKeys.add( 423 KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 424 InputEvent.CTRL_MASK)); 425 } 426 } 427 return managingFocusForwardTraversalKeys; 428 } 429 430 /** 431 * Returns the Set of <code>KeyStroke</code>s to use if the component 432 * is managing focus for backward focus traversal. 433 */ 434 static Set<KeyStroke> getManagingFocusBackwardTraversalKeys() { 435 synchronized(JComponent.class) { 436 if (managingFocusBackwardTraversalKeys == null) { 437 managingFocusBackwardTraversalKeys = new HashSet<KeyStroke>(1); 438 managingFocusBackwardTraversalKeys.add( 439 KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 440 InputEvent.SHIFT_MASK | 441 InputEvent.CTRL_MASK)); 442 } 443 } 444 return managingFocusBackwardTraversalKeys; 445 } 446 447 private static Rectangle fetchRectangle() { 448 synchronized(tempRectangles) { 449 Rectangle rect; 450 int size = tempRectangles.size(); 451 if (size > 0) { 452 rect = tempRectangles.remove(size - 1); 453 } 454 else { 455 rect = new Rectangle(0, 0, 0, 0); 456 } 457 return rect; 458 } 459 } 460 461 private static void recycleRectangle(Rectangle rect) { 462 synchronized(tempRectangles) { 463 tempRectangles.add(rect); 464 } 465 } 466 467 /** 468 * Sets whether or not <code>getComponentPopupMenu</code> should delegate 469 * to the parent if this component does not have a <code>JPopupMenu</code> 470 * assigned to it. 471 * <p> 472 * The default value for this is false, but some <code>JComponent</code> 473 * subclasses that are implemented as a number of <code>JComponent</code>s 474 * may set this to true. 475 * <p> 476 * This is a bound property. 477 * 478 * @param value whether or not the JPopupMenu is inherited 479 * @see #setComponentPopupMenu 480 * @beaninfo 481 * bound: true 482 * description: Whether or not the JPopupMenu is inherited 483 * @since 1.5 484 */ 485 public void setInheritsPopupMenu(boolean value) { 486 boolean oldValue = getFlag(INHERITS_POPUP_MENU); 487 setFlag(INHERITS_POPUP_MENU, value); 488 firePropertyChange("inheritsPopupMenu", oldValue, value); 489 } 490 491 /** 492 * Returns true if the JPopupMenu should be inherited from the parent. 493 * 494 * @return true if the JPopupMenu should be inherited from the parent 495 * @see #setComponentPopupMenu 496 * @since 1.5 497 */ 498 public boolean getInheritsPopupMenu() { 499 return getFlag(INHERITS_POPUP_MENU); 500 } 501 502 /** 503 * Sets the <code>JPopupMenu</code> for this <code>JComponent</code>. 504 * The UI is responsible for registering bindings and adding the necessary 505 * listeners such that the <code>JPopupMenu</code> will be shown at 506 * the appropriate time. When the <code>JPopupMenu</code> is shown 507 * depends upon the look and feel: some may show it on a mouse event, 508 * some may enable a key binding. 509 * <p> 510 * If <code>popup</code> is null, and <code>getInheritsPopupMenu</code> 511 * returns true, then <code>getComponentPopupMenu</code> will be delegated 512 * to the parent. This provides for a way to make all child components 513 * inherit the popupmenu of the parent. 514 * <p> 515 * This is a bound property. 516 * 517 * @param popup - the popup that will be assigned to this component 518 * may be null 519 * @see #getComponentPopupMenu 520 * @beaninfo 521 * bound: true 522 * preferred: true 523 * description: Popup to show 524 * @since 1.5 525 */ 526 public void setComponentPopupMenu(JPopupMenu popup) { 527 if(popup != null) { 528 enableEvents(AWTEvent.MOUSE_EVENT_MASK); 529 } 530 JPopupMenu oldPopup = this.popupMenu; 531 this.popupMenu = popup; 532 firePropertyChange("componentPopupMenu", oldPopup, popup); 533 } 534 535 /** 536 * Returns <code>JPopupMenu</code> that assigned for this component. 537 * If this component does not have a <code>JPopupMenu</code> assigned 538 * to it and <code>getInheritsPopupMenu</code> is true, this 539 * will return <code>getParent().getComponentPopupMenu()</code> (assuming 540 * the parent is valid.) 541 * 542 * @return <code>JPopupMenu</code> assigned for this component 543 * or <code>null</code> if no popup assigned 544 * @see #setComponentPopupMenu 545 * @since 1.5 546 */ 547 public JPopupMenu getComponentPopupMenu() { 548 549 if(!getInheritsPopupMenu()) { 550 return popupMenu; 551 } 552 553 if(popupMenu == null) { 554 // Search parents for its popup 555 Container parent = getParent(); 556 while (parent != null) { 557 if(parent instanceof JComponent) { 558 return ((JComponent)parent).getComponentPopupMenu(); 559 } 560 if(parent instanceof Window || 561 parent instanceof Applet) { 562 // Reached toplevel, break and return null 563 break; 564 } 565 parent = parent.getParent(); 566 } 567 return null; 568 } 569 570 return popupMenu; 571 } 572 573 /** 574 * Default <code>JComponent</code> constructor. This constructor does 575 * very little initialization beyond calling the <code>Container</code> 576 * constructor. For example, the initial layout manager is 577 * <code>null</code>. It does, however, set the component's locale 578 * property to the value returned by 579 * <code>JComponent.getDefaultLocale</code>. 580 * 581 * @see #getDefaultLocale 582 */ 583 public JComponent() { 584 super(); 585 // We enable key events on all JComponents so that accessibility 586 // bindings will work everywhere. This is a partial fix to BugID 587 // 4282211. 588 enableEvents(AWTEvent.KEY_EVENT_MASK); 589 if (isManagingFocus()) { 590 LookAndFeel.installProperty(this, 591 "focusTraversalKeysForward", 592 getManagingFocusForwardTraversalKeys()); 593 LookAndFeel.installProperty(this, 594 "focusTraversalKeysBackward", 595 getManagingFocusBackwardTraversalKeys()); 596 } 597 598 super.setLocale( JComponent.getDefaultLocale() ); 599 } 600 601 602 /** 603 * Resets the UI property to a value from the current look and feel. 604 * <code>JComponent</code> subclasses must override this method 605 * like this: 606 * <pre> 607 * public void updateUI() { 608 * setUI((SliderUI)UIManager.getUI(this); 609 * } 610 * </pre> 611 * 612 * @see #setUI 613 * @see UIManager#getLookAndFeel 614 * @see UIManager#getUI 615 */ 616 public void updateUI() {} 617 618 619 /** 620 * Sets the look and feel delegate for this component. 621 * <code>JComponent</code> subclasses generally override this method 622 * to narrow the argument type. For example, in <code>JSlider</code>: 623 * <pre> 624 * public void setUI(SliderUI newUI) { 625 * super.setUI(newUI); 626 * } 627 * </pre> 628 * <p> 629 * Additionally <code>JComponent</code> subclasses must provide a 630 * <code>getUI</code> method that returns the correct type. For example: 631 * <pre> 632 * public SliderUI getUI() { 633 * return (SliderUI)ui; 634 * } 635 * </pre> 636 * 637 * @param newUI the new UI delegate 638 * @see #updateUI 639 * @see UIManager#getLookAndFeel 640 * @see UIManager#getUI 641 * @beaninfo 642 * bound: true 643 * hidden: true 644 * attribute: visualUpdate true 645 * description: The component's look and feel delegate. 646 */ 647 protected void setUI(ComponentUI newUI) { 648 /* We do not check that the UI instance is different 649 * before allowing the switch in order to enable the 650 * same UI instance *with different default settings* 651 * to be installed. 652 */ 653 654 uninstallUIAndProperties(); 655 656 // aaText shouldn't persist between look and feels, reset it. 657 aaTextInfo = 658 UIManager.getDefaults().get(SwingUtilities2.AA_TEXT_PROPERTY_KEY); 659 ComponentUI oldUI = ui; 660 ui = newUI; 661 if (ui != null) { 662 ui.installUI(this); 663 } 664 665 firePropertyChange("UI", oldUI, newUI); 666 revalidate(); 667 repaint(); 668 } 669 670 /** 671 * Uninstalls the UI, if any, and any client properties designated 672 * as being specific to the installed UI - instances of 673 * {@code UIClientPropertyKey}. 674 */ 675 private void uninstallUIAndProperties() { 676 if (ui != null) { 677 ui.uninstallUI(this); 678 //clean UIClientPropertyKeys from client properties 679 if (clientProperties != null) { 680 synchronized(clientProperties) { 681 Object[] clientPropertyKeys = 682 clientProperties.getKeys(null); 683 if (clientPropertyKeys != null) { 684 for (Object key : clientPropertyKeys) { 685 if (key instanceof UIClientPropertyKey) { 686 putClientProperty(key, null); 687 } 688 } 689 } 690 } 691 } 692 } 693 } 694 695 /** 696 * Returns the <code>UIDefaults</code> key used to 697 * look up the name of the <code>swing.plaf.ComponentUI</code> 698 * class that defines the look and feel 699 * for this component. Most applications will never need to 700 * call this method. Subclasses of <code>JComponent</code> that support 701 * pluggable look and feel should override this method to 702 * return a <code>UIDefaults</code> key that maps to the 703 * <code>ComponentUI</code> subclass that defines their look and feel. 704 * 705 * @return the <code>UIDefaults</code> key for a 706 * <code>ComponentUI</code> subclass 707 * @see UIDefaults#getUI 708 * @beaninfo 709 * expert: true 710 * description: UIClassID 711 */ 712 public String getUIClassID() { 713 return uiClassID; 714 } 715 716 717 /** 718 * Returns the graphics object used to paint this component. 719 * If <code>DebugGraphics</code> is turned on we create a new 720 * <code>DebugGraphics</code> object if necessary. 721 * Otherwise we just configure the 722 * specified graphics object's foreground and font. 723 * 724 * @param g the original <code>Graphics</code> object 725 * @return a <code>Graphics</code> object configured for this component 726 */ 727 protected Graphics getComponentGraphics(Graphics g) { 728 Graphics componentGraphics = g; 729 if (ui != null && DEBUG_GRAPHICS_LOADED) { 730 if ((DebugGraphics.debugComponentCount() != 0) && 731 (shouldDebugGraphics() != 0) && 732 !(g instanceof DebugGraphics)) { 733 componentGraphics = new DebugGraphics(g,this); 734 } 735 } 736 componentGraphics.setColor(getForeground()); 737 componentGraphics.setFont(getFont()); 738 739 return componentGraphics; 740 } 741 742 743 /** 744 * Calls the UI delegate's paint method, if the UI delegate 745 * is non-<code>null</code>. We pass the delegate a copy of the 746 * <code>Graphics</code> object to protect the rest of the 747 * paint code from irrevocable changes 748 * (for example, <code>Graphics.translate</code>). 749 * <p> 750 * If you override this in a subclass you should not make permanent 751 * changes to the passed in <code>Graphics</code>. For example, you 752 * should not alter the clip <code>Rectangle</code> or modify the 753 * transform. If you need to do these operations you may find it 754 * easier to create a new <code>Graphics</code> from the passed in 755 * <code>Graphics</code> and manipulate it. Further, if you do not 756 * invoker super's implementation you must honor the opaque property, 757 * that is 758 * if this component is opaque, you must completely fill in the background 759 * in a non-opaque color. If you do not honor the opaque property you 760 * will likely see visual artifacts. 761 * <p> 762 * The passed in <code>Graphics</code> object might 763 * have a transform other than the identify transform 764 * installed on it. In this case, you might get 765 * unexpected results if you cumulatively apply 766 * another transform. 767 * 768 * @param g the <code>Graphics</code> object to protect 769 * @see #paint 770 * @see ComponentUI 771 */ 772 protected void paintComponent(Graphics g) { 773 if (ui != null) { 774 Graphics scratchGraphics = (g == null) ? null : g.create(); 775 try { 776 ui.update(scratchGraphics, this); 777 } 778 finally { 779 scratchGraphics.dispose(); 780 } 781 } 782 } 783 784 /** 785 * Paints this component's children. 786 * If <code>shouldUseBuffer</code> is true, 787 * no component ancestor has a buffer and 788 * the component children can use a buffer if they have one. 789 * Otherwise, one ancestor has a buffer currently in use and children 790 * should not use a buffer to paint. 791 * @param g the <code>Graphics</code> context in which to paint 792 * @see #paint 793 * @see java.awt.Container#paint 794 */ 795 protected void paintChildren(Graphics g) { 796 Graphics sg = g; 797 798 synchronized(getTreeLock()) { 799 int i = getComponentCount() - 1; 800 if (i < 0) { 801 return; 802 } 803 // If we are only to paint to a specific child, determine 804 // its index. 805 if (paintingChild != null && 806 (paintingChild instanceof JComponent) && 807 paintingChild.isOpaque()) { 808 for (; i >= 0; i--) { 809 if (getComponent(i) == paintingChild){ 810 break; 811 } 812 } 813 } 814 Rectangle tmpRect = fetchRectangle(); 815 boolean checkSiblings = (!isOptimizedDrawingEnabled() && 816 checkIfChildObscuredBySibling()); 817 Rectangle clipBounds = null; 818 if (checkSiblings) { 819 clipBounds = sg.getClipBounds(); 820 if (clipBounds == null) { 821 clipBounds = new Rectangle(0, 0, getWidth(), 822 getHeight()); 823 } 824 } 825 boolean printing = getFlag(IS_PRINTING); 826 final Window window = SwingUtilities.getWindowAncestor(this); 827 final boolean isWindowOpaque = window == null || window.isOpaque(); 828 for (; i >= 0 ; i--) { 829 Component comp = getComponent(i); 830 if (comp == null) { 831 continue; 832 } 833 834 final boolean isJComponent = comp instanceof JComponent; 835 836 // Enable painting of heavyweights in non-opaque windows. 837 // See 6884960 838 if ((!isWindowOpaque || isJComponent || 839 isLightweightComponent(comp)) && comp.isVisible()) 840 { 841 Rectangle cr; 842 843 cr = comp.getBounds(tmpRect); 844 845 boolean hitClip = g.hitClip(cr.x, cr.y, cr.width, 846 cr.height); 847 848 if (hitClip) { 849 if (checkSiblings && i > 0) { 850 int x = cr.x; 851 int y = cr.y; 852 int width = cr.width; 853 int height = cr.height; 854 SwingUtilities.computeIntersection 855 (clipBounds.x, clipBounds.y, 856 clipBounds.width, clipBounds.height, cr); 857 858 if(getObscuredState(i, cr.x, cr.y, cr.width, 859 cr.height) == COMPLETELY_OBSCURED) { 860 continue; 861 } 862 cr.x = x; 863 cr.y = y; 864 cr.width = width; 865 cr.height = height; 866 } 867 Graphics cg = sg.create(cr.x, cr.y, cr.width, 868 cr.height); 869 cg.setColor(comp.getForeground()); 870 cg.setFont(comp.getFont()); 871 boolean shouldSetFlagBack = false; 872 try { 873 if(isJComponent) { 874 if(getFlag(ANCESTOR_USING_BUFFER)) { 875 ((JComponent)comp).setFlag( 876 ANCESTOR_USING_BUFFER,true); 877 shouldSetFlagBack = true; 878 } 879 if(getFlag(IS_PAINTING_TILE)) { 880 ((JComponent)comp).setFlag( 881 IS_PAINTING_TILE,true); 882 shouldSetFlagBack = true; 883 } 884 if(!printing) { 885 comp.paint(cg); 886 } 887 else { 888 if (!getFlag(IS_PRINTING_ALL)) { 889 comp.print(cg); 890 } 891 else { 892 comp.printAll(cg); 893 } 894 } 895 } else { 896 // The component is either lightweight, or 897 // heavyweight in a non-opaque window 898 if (!printing) { 899 comp.paint(cg); 900 } 901 else { 902 if (!getFlag(IS_PRINTING_ALL)) { 903 comp.print(cg); 904 } 905 else { 906 comp.printAll(cg); 907 } 908 } 909 } 910 } finally { 911 cg.dispose(); 912 if(shouldSetFlagBack) { 913 ((JComponent)comp).setFlag( 914 ANCESTOR_USING_BUFFER,false); 915 ((JComponent)comp).setFlag( 916 IS_PAINTING_TILE,false); 917 } 918 } 919 } 920 } 921 922 } 923 recycleRectangle(tmpRect); 924 } 925 } 926 927 /** 928 * Paints the component's border. 929 * <p> 930 * If you override this in a subclass you should not make permanent 931 * changes to the passed in <code>Graphics</code>. For example, you 932 * should not alter the clip <code>Rectangle</code> or modify the 933 * transform. If you need to do these operations you may find it 934 * easier to create a new <code>Graphics</code> from the passed in 935 * <code>Graphics</code> and manipulate it. 936 * 937 * @param g the <code>Graphics</code> context in which to paint 938 * 939 * @see #paint 940 * @see #setBorder 941 */ 942 protected void paintBorder(Graphics g) { 943 Border border = getBorder(); 944 if (border != null) { 945 border.paintBorder(this, g, 0, 0, getWidth(), getHeight()); 946 } 947 } 948 949 950 /** 951 * Calls <code>paint</code>. Doesn't clear the background but see 952 * <code>ComponentUI.update</code>, which is called by 953 * <code>paintComponent</code>. 954 * 955 * @param g the <code>Graphics</code> context in which to paint 956 * @see #paint 957 * @see #paintComponent 958 * @see javax.swing.plaf.ComponentUI 959 */ 960 public void update(Graphics g) { 961 paint(g); 962 } 963 964 965 /** 966 * Invoked by Swing to draw components. 967 * Applications should not invoke <code>paint</code> directly, 968 * but should instead use the <code>repaint</code> method to 969 * schedule the component for redrawing. 970 * <p> 971 * This method actually delegates the work of painting to three 972 * protected methods: <code>paintComponent</code>, 973 * <code>paintBorder</code>, 974 * and <code>paintChildren</code>. They're called in the order 975 * listed to ensure that children appear on top of component itself. 976 * Generally speaking, the component and its children should not 977 * paint in the insets area allocated to the border. Subclasses can 978 * just override this method, as always. A subclass that just 979 * wants to specialize the UI (look and feel) delegate's 980 * <code>paint</code> method should just override 981 * <code>paintComponent</code>. 982 * 983 * @param g the <code>Graphics</code> context in which to paint 984 * @see #paintComponent 985 * @see #paintBorder 986 * @see #paintChildren 987 * @see #getComponentGraphics 988 * @see #repaint 989 */ 990 public void paint(Graphics g) { 991 boolean shouldClearPaintFlags = false; 992 993 if ((getWidth() <= 0) || (getHeight() <= 0)) { 994 return; 995 } 996 997 Graphics componentGraphics = getComponentGraphics(g); 998 Graphics co = componentGraphics.create(); 999 try { 1000 RepaintManager repaintManager = RepaintManager.currentManager(this); 1001 Rectangle clipRect = co.getClipBounds(); 1002 int clipX; 1003 int clipY; 1004 int clipW; 1005 int clipH; 1006 if (clipRect == null) { 1007 clipX = clipY = 0; 1008 clipW = getWidth(); 1009 clipH = getHeight(); 1010 } 1011 else { 1012 clipX = clipRect.x; 1013 clipY = clipRect.y; 1014 clipW = clipRect.width; 1015 clipH = clipRect.height; 1016 } 1017 1018 if(clipW > getWidth()) { 1019 clipW = getWidth(); 1020 } 1021 if(clipH > getHeight()) { 1022 clipH = getHeight(); 1023 } 1024 1025 if(getParent() != null && !(getParent() instanceof JComponent)) { 1026 adjustPaintFlags(); 1027 shouldClearPaintFlags = true; 1028 } 1029 1030 int bw,bh; 1031 boolean printing = getFlag(IS_PRINTING); 1032 if (!printing && repaintManager.isDoubleBufferingEnabled() && 1033 !getFlag(ANCESTOR_USING_BUFFER) && isDoubleBuffered() && 1034 (getFlag(IS_REPAINTING) || repaintManager.isPainting())) 1035 { 1036 repaintManager.beginPaint(); 1037 try { 1038 repaintManager.paint(this, this, co, clipX, clipY, clipW, 1039 clipH); 1040 } finally { 1041 repaintManager.endPaint(); 1042 } 1043 } 1044 else { 1045 // Will ocassionaly happen in 1.2, especially when printing. 1046 if (clipRect == null) { 1047 co.setClip(clipX, clipY, clipW, clipH); 1048 } 1049 1050 if (!rectangleIsObscured(clipX,clipY,clipW,clipH)) { 1051 if (!printing) { 1052 paintComponent(co); 1053 paintBorder(co); 1054 } 1055 else { 1056 printComponent(co); 1057 printBorder(co); 1058 } 1059 } 1060 if (!printing) { 1061 paintChildren(co); 1062 } 1063 else { 1064 printChildren(co); 1065 } 1066 } 1067 } finally { 1068 co.dispose(); 1069 if(shouldClearPaintFlags) { 1070 setFlag(ANCESTOR_USING_BUFFER,false); 1071 setFlag(IS_PAINTING_TILE,false); 1072 setFlag(IS_PRINTING,false); 1073 setFlag(IS_PRINTING_ALL,false); 1074 } 1075 } 1076 } 1077 1078 // paint forcing use of the double buffer. This is used for historical 1079 // reasons: JViewport, when scrolling, previously directly invoked paint 1080 // while turning off double buffering at the RepaintManager level, this 1081 // codes simulates that. 1082 void paintForceDoubleBuffered(Graphics g) { 1083 RepaintManager rm = RepaintManager.currentManager(this); 1084 Rectangle clip = g.getClipBounds(); 1085 rm.beginPaint(); 1086 setFlag(IS_REPAINTING, true); 1087 try { 1088 rm.paint(this, this, g, clip.x, clip.y, clip.width, clip.height); 1089 } finally { 1090 rm.endPaint(); 1091 setFlag(IS_REPAINTING, false); 1092 } 1093 } 1094 1095 /** 1096 * Returns true if this component, or any of its ancestors, are in 1097 * the processing of painting. 1098 */ 1099 boolean isPainting() { 1100 Container component = this; 1101 while (component != null) { 1102 if (component instanceof JComponent && 1103 ((JComponent)component).getFlag(ANCESTOR_USING_BUFFER)) { 1104 return true; 1105 } 1106 component = component.getParent(); 1107 } 1108 return false; 1109 } 1110 1111 private void adjustPaintFlags() { 1112 JComponent jparent; 1113 Container parent; 1114 for(parent = getParent() ; parent != null ; parent = 1115 parent.getParent()) { 1116 if(parent instanceof JComponent) { 1117 jparent = (JComponent) parent; 1118 if(jparent.getFlag(ANCESTOR_USING_BUFFER)) 1119 setFlag(ANCESTOR_USING_BUFFER, true); 1120 if(jparent.getFlag(IS_PAINTING_TILE)) 1121 setFlag(IS_PAINTING_TILE, true); 1122 if(jparent.getFlag(IS_PRINTING)) 1123 setFlag(IS_PRINTING, true); 1124 if(jparent.getFlag(IS_PRINTING_ALL)) 1125 setFlag(IS_PRINTING_ALL, true); 1126 break; 1127 } 1128 } 1129 } 1130 1131 /** 1132 * Invoke this method to print the component. This method invokes 1133 * <code>print</code> on the component. 1134 * 1135 * @param g the <code>Graphics</code> context in which to paint 1136 * @see #print 1137 * @see #printComponent 1138 * @see #printBorder 1139 * @see #printChildren 1140 */ 1141 public void printAll(Graphics g) { 1142 setFlag(IS_PRINTING_ALL, true); 1143 try { 1144 print(g); 1145 } 1146 finally { 1147 setFlag(IS_PRINTING_ALL, false); 1148 } 1149 } 1150 1151 /** 1152 * Invoke this method to print the component to the specified 1153 * <code>Graphics</code>. This method will result in invocations 1154 * of <code>printComponent</code>, <code>printBorder</code> and 1155 * <code>printChildren</code>. It is recommended that you override 1156 * one of the previously mentioned methods rather than this one if 1157 * your intention is to customize the way printing looks. However, 1158 * it can be useful to override this method should you want to prepare 1159 * state before invoking the superclass behavior. As an example, 1160 * if you wanted to change the component's background color before 1161 * printing, you could do the following: 1162 * <pre> 1163 * public void print(Graphics g) { 1164 * Color orig = getBackground(); 1165 * setBackground(Color.WHITE); 1166 * 1167 * // wrap in try/finally so that we always restore the state 1168 * try { 1169 * super.print(g); 1170 * } finally { 1171 * setBackground(orig); 1172 * } 1173 * } 1174 * </pre> 1175 * <p> 1176 * Alternatively, or for components that delegate painting to other objects, 1177 * you can query during painting whether or not the component is in the 1178 * midst of a print operation. The <code>isPaintingForPrint</code> method provides 1179 * this ability and its return value will be changed by this method: to 1180 * <code>true</code> immediately before rendering and to <code>false</code> 1181 * immediately after. With each change a property change event is fired on 1182 * this component with the name <code>"paintingForPrint"</code>. 1183 * <p> 1184 * This method sets the component's state such that the double buffer 1185 * will not be used: painting will be done directly on the passed in 1186 * <code>Graphics</code>. 1187 * 1188 * @param g the <code>Graphics</code> context in which to paint 1189 * @see #printComponent 1190 * @see #printBorder 1191 * @see #printChildren 1192 * @see #isPaintingForPrint 1193 */ 1194 public void print(Graphics g) { 1195 setFlag(IS_PRINTING, true); 1196 firePropertyChange("paintingForPrint", false, true); 1197 try { 1198 paint(g); 1199 } 1200 finally { 1201 setFlag(IS_PRINTING, false); 1202 firePropertyChange("paintingForPrint", true, false); 1203 } 1204 } 1205 1206 /** 1207 * This is invoked during a printing operation. This is implemented to 1208 * invoke <code>paintComponent</code> on the component. Override this 1209 * if you wish to add special painting behavior when printing. 1210 * 1211 * @param g the <code>Graphics</code> context in which to paint 1212 * @see #print 1213 * @since 1.3 1214 */ 1215 protected void printComponent(Graphics g) { 1216 paintComponent(g); 1217 } 1218 1219 /** 1220 * Prints this component's children. This is implemented to invoke 1221 * <code>paintChildren</code> on the component. Override this if you 1222 * wish to print the children differently than painting. 1223 * 1224 * @param g the <code>Graphics</code> context in which to paint 1225 * @see #print 1226 * @since 1.3 1227 */ 1228 protected void printChildren(Graphics g) { 1229 paintChildren(g); 1230 } 1231 1232 /** 1233 * Prints the component's border. This is implemented to invoke 1234 * <code>paintBorder</code> on the component. Override this if you 1235 * wish to print the border differently that it is painted. 1236 * 1237 * @param g the <code>Graphics</code> context in which to paint 1238 * @see #print 1239 * @since 1.3 1240 */ 1241 protected void printBorder(Graphics g) { 1242 paintBorder(g); 1243 } 1244 1245 /** 1246 * Returns true if the component is currently painting a tile. 1247 * If this method returns true, paint will be called again for another 1248 * tile. This method returns false if you are not painting a tile or 1249 * if the last tile is painted. 1250 * Use this method to keep some state you might need between tiles. 1251 * 1252 * @return true if the component is currently painting a tile, 1253 * false otherwise 1254 */ 1255 public boolean isPaintingTile() { 1256 return getFlag(IS_PAINTING_TILE); 1257 } 1258 1259 /** 1260 * Returns <code>true</code> if the current painting operation on this 1261 * component is part of a <code>print</code> operation. This method is 1262 * useful when you want to customize what you print versus what you show 1263 * on the screen. 1264 * <p> 1265 * You can detect changes in the value of this property by listening for 1266 * property change events on this component with name 1267 * <code>"paintingForPrint"</code>. 1268 * <p> 1269 * Note: This method provides complimentary functionality to that provided 1270 * by other high level Swing printing APIs. However, it deals strictly with 1271 * painting and should not be confused as providing information on higher 1272 * level print processes. For example, a {@link javax.swing.JTable#print()} 1273 * operation doesn't necessarily result in a continuous rendering of the 1274 * full component, and the return value of this method can change multiple 1275 * times during that operation. It is even possible for the component to be 1276 * painted to the screen while the printing process is ongoing. In such a 1277 * case, the return value of this method is <code>true</code> when, and only 1278 * when, the table is being painted as part of the printing process. 1279 * 1280 * @return true if the current painting operation on this component 1281 * is part of a print operation 1282 * @see #print 1283 * @since 1.6 1284 */ 1285 public final boolean isPaintingForPrint() { 1286 return getFlag(IS_PRINTING); 1287 } 1288 1289 /** 1290 * In release 1.4, the focus subsystem was rearchitected. 1291 * For more information, see 1292 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html"> 1293 * How to Use the Focus Subsystem</a>, 1294 * a section in <em>The Java Tutorial</em>. 1295 * <p> 1296 * Changes this <code>JComponent</code>'s focus traversal keys to 1297 * CTRL+TAB and CTRL+SHIFT+TAB. Also prevents 1298 * <code>SortingFocusTraversalPolicy</code> from considering descendants 1299 * of this JComponent when computing a focus traversal cycle. 1300 * 1301 * @return false 1302 * @see java.awt.Component#setFocusTraversalKeys 1303 * @see SortingFocusTraversalPolicy 1304 * @deprecated As of 1.4, replaced by 1305 * <code>Component.setFocusTraversalKeys(int, Set)</code> and 1306 * <code>Container.setFocusCycleRoot(boolean)</code>. 1307 */ 1308 @Deprecated 1309 public boolean isManagingFocus() { 1310 return false; 1311 } 1312 1313 private void registerNextFocusableComponent() { 1314 registerNextFocusableComponent(getNextFocusableComponent()); 1315 } 1316 1317 private void registerNextFocusableComponent(Component 1318 nextFocusableComponent) { 1319 if (nextFocusableComponent == null) { 1320 return; 1321 } 1322 1323 Container nearestRoot = 1324 (isFocusCycleRoot()) ? this : getFocusCycleRootAncestor(); 1325 FocusTraversalPolicy policy = nearestRoot.getFocusTraversalPolicy(); 1326 if (!(policy instanceof LegacyGlueFocusTraversalPolicy)) { 1327 policy = new LegacyGlueFocusTraversalPolicy(policy); 1328 nearestRoot.setFocusTraversalPolicy(policy); 1329 } 1330 ((LegacyGlueFocusTraversalPolicy)policy). 1331 setNextFocusableComponent(this, nextFocusableComponent); 1332 } 1333 1334 private void deregisterNextFocusableComponent() { 1335 Component nextFocusableComponent = getNextFocusableComponent(); 1336 if (nextFocusableComponent == null) { 1337 return; 1338 } 1339 1340 Container nearestRoot = 1341 (isFocusCycleRoot()) ? this : getFocusCycleRootAncestor(); 1342 if (nearestRoot == null) { 1343 return; 1344 } 1345 FocusTraversalPolicy policy = nearestRoot.getFocusTraversalPolicy(); 1346 if (policy instanceof LegacyGlueFocusTraversalPolicy) { 1347 ((LegacyGlueFocusTraversalPolicy)policy). 1348 unsetNextFocusableComponent(this, nextFocusableComponent); 1349 } 1350 } 1351 1352 /** 1353 * In release 1.4, the focus subsystem was rearchitected. 1354 * For more information, see 1355 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html"> 1356 * How to Use the Focus Subsystem</a>, 1357 * a section in <em>The Java Tutorial</em>. 1358 * <p> 1359 * Overrides the default <code>FocusTraversalPolicy</code> for this 1360 * <code>JComponent</code>'s focus traversal cycle by unconditionally 1361 * setting the specified <code>Component</code> as the next 1362 * <code>Component</code> in the cycle, and this <code>JComponent</code> 1363 * as the specified <code>Component</code>'s previous 1364 * <code>Component</code> in the cycle. 1365 * 1366 * @param aComponent the <code>Component</code> that should follow this 1367 * <code>JComponent</code> in the focus traversal cycle 1368 * 1369 * @see #getNextFocusableComponent 1370 * @see java.awt.FocusTraversalPolicy 1371 * @deprecated As of 1.4, replaced by <code>FocusTraversalPolicy</code> 1372 */ 1373 @Deprecated 1374 public void setNextFocusableComponent(Component aComponent) { 1375 boolean displayable = isDisplayable(); 1376 if (displayable) { 1377 deregisterNextFocusableComponent(); 1378 } 1379 putClientProperty(NEXT_FOCUS, aComponent); 1380 if (displayable) { 1381 registerNextFocusableComponent(aComponent); 1382 } 1383 } 1384 1385 /** 1386 * In release 1.4, the focus subsystem was rearchitected. 1387 * For more information, see 1388 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html"> 1389 * How to Use the Focus Subsystem</a>, 1390 * a section in <em>The Java Tutorial</em>. 1391 * <p> 1392 * Returns the <code>Component</code> set by a prior call to 1393 * <code>setNextFocusableComponent(Component)</code> on this 1394 * <code>JComponent</code>. 1395 * 1396 * @return the <code>Component</code> that will follow this 1397 * <code>JComponent</code> in the focus traversal cycle, or 1398 * <code>null</code> if none has been explicitly specified 1399 * 1400 * @see #setNextFocusableComponent 1401 * @deprecated As of 1.4, replaced by <code>FocusTraversalPolicy</code>. 1402 */ 1403 @Deprecated 1404 public Component getNextFocusableComponent() { 1405 return (Component)getClientProperty(NEXT_FOCUS); 1406 } 1407 1408 /** 1409 * Provides a hint as to whether or not this <code>JComponent</code> 1410 * should get focus. This is only a hint, and it is up to consumers that 1411 * are requesting focus to honor this property. This is typically honored 1412 * for mouse operations, but not keyboard operations. For example, look 1413 * and feels could verify this property is true before requesting focus 1414 * during a mouse operation. This would often times be used if you did 1415 * not want a mouse press on a <code>JComponent</code> to steal focus, 1416 * but did want the <code>JComponent</code> to be traversable via the 1417 * keyboard. If you do not want this <code>JComponent</code> focusable at 1418 * all, use the <code>setFocusable</code> method instead. 1419 * <p> 1420 * Please see 1421 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html"> 1422 * How to Use the Focus Subsystem</a>, 1423 * a section in <em>The Java Tutorial</em>, 1424 * for more information. 1425 * 1426 * @param requestFocusEnabled indicates whether you want this 1427 * <code>JComponent</code> to be focusable or not 1428 * @see <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a> 1429 * @see java.awt.Component#setFocusable 1430 */ 1431 public void setRequestFocusEnabled(boolean requestFocusEnabled) { 1432 setFlag(REQUEST_FOCUS_DISABLED, !requestFocusEnabled); 1433 } 1434 1435 /** 1436 * Returns <code>true</code> if this <code>JComponent</code> should 1437 * get focus; otherwise returns <code>false</code>. 1438 * <p> 1439 * Please see 1440 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html"> 1441 * How to Use the Focus Subsystem</a>, 1442 * a section in <em>The Java Tutorial</em>, 1443 * for more information. 1444 * 1445 * @return <code>true</code> if this component should get focus, 1446 * otherwise returns <code>false</code> 1447 * @see #setRequestFocusEnabled 1448 * @see <a href="../../java/awt/doc-files/FocusSpec.html">Focus 1449 * Specification</a> 1450 * @see java.awt.Component#isFocusable 1451 */ 1452 public boolean isRequestFocusEnabled() { 1453 return !getFlag(REQUEST_FOCUS_DISABLED); 1454 } 1455 1456 /** 1457 * Requests that this <code>Component</code> gets the input focus. 1458 * Refer to {@link java.awt.Component#requestFocus() 1459 * Component.requestFocus()} for a complete description of 1460 * this method. 1461 * <p> 1462 * Note that the use of this method is discouraged because 1463 * its behavior is platform dependent. Instead we recommend the 1464 * use of {@link #requestFocusInWindow() requestFocusInWindow()}. 1465 * If you would like more information on focus, see 1466 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html"> 1467 * How to Use the Focus Subsystem</a>, 1468 * a section in <em>The Java Tutorial</em>. 1469 * 1470 * @see java.awt.Component#requestFocusInWindow() 1471 * @see java.awt.Component#requestFocusInWindow(boolean) 1472 * @since 1.4 1473 */ 1474 public void requestFocus() { 1475 super.requestFocus(); 1476 } 1477 1478 /** 1479 * Requests that this <code>Component</code> gets the input focus. 1480 * Refer to {@link java.awt.Component#requestFocus(boolean) 1481 * Component.requestFocus(boolean)} for a complete description of 1482 * this method. 1483 * <p> 1484 * Note that the use of this method is discouraged because 1485 * its behavior is platform dependent. Instead we recommend the 1486 * use of {@link #requestFocusInWindow(boolean) 1487 * requestFocusInWindow(boolean)}. 1488 * If you would like more information on focus, see 1489 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html"> 1490 * How to Use the Focus Subsystem</a>, 1491 * a section in <em>The Java Tutorial</em>. 1492 * 1493 * @param temporary boolean indicating if the focus change is temporary 1494 * @return <code>false</code> if the focus change request is guaranteed to 1495 * fail; <code>true</code> if it is likely to succeed 1496 * @see java.awt.Component#requestFocusInWindow() 1497 * @see java.awt.Component#requestFocusInWindow(boolean) 1498 * @since 1.4 1499 */ 1500 public boolean requestFocus(boolean temporary) { 1501 return super.requestFocus(temporary); 1502 } 1503 1504 /** 1505 * Requests that this <code>Component</code> gets the input focus. 1506 * Refer to {@link java.awt.Component#requestFocusInWindow() 1507 * Component.requestFocusInWindow()} for a complete description of 1508 * this method. 1509 * <p> 1510 * If you would like more information on focus, see 1511 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html"> 1512 * How to Use the Focus Subsystem</a>, 1513 * a section in <em>The Java Tutorial</em>. 1514 * 1515 * @return <code>false</code> if the focus change request is guaranteed to 1516 * fail; <code>true</code> if it is likely to succeed 1517 * @see java.awt.Component#requestFocusInWindow() 1518 * @see java.awt.Component#requestFocusInWindow(boolean) 1519 * @since 1.4 1520 */ 1521 public boolean requestFocusInWindow() { 1522 return super.requestFocusInWindow(); 1523 } 1524 1525 /** 1526 * Requests that this <code>Component</code> gets the input focus. 1527 * Refer to {@link java.awt.Component#requestFocusInWindow(boolean) 1528 * Component.requestFocusInWindow(boolean)} for a complete description of 1529 * this method. 1530 * <p> 1531 * If you would like more information on focus, see 1532 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html"> 1533 * How to Use the Focus Subsystem</a>, 1534 * a section in <em>The Java Tutorial</em>. 1535 * 1536 * @param temporary boolean indicating if the focus change is temporary 1537 * @return <code>false</code> if the focus change request is guaranteed to 1538 * fail; <code>true</code> if it is likely to succeed 1539 * @see java.awt.Component#requestFocusInWindow() 1540 * @see java.awt.Component#requestFocusInWindow(boolean) 1541 * @since 1.4 1542 */ 1543 protected boolean requestFocusInWindow(boolean temporary) { 1544 return super.requestFocusInWindow(temporary); 1545 } 1546 1547 /** 1548 * Requests that this Component get the input focus, and that this 1549 * Component's top-level ancestor become the focused Window. This component 1550 * must be displayable, visible, and focusable for the request to be 1551 * granted. 1552 * <p> 1553 * This method is intended for use by focus implementations. Client code 1554 * should not use this method; instead, it should use 1555 * <code>requestFocusInWindow()</code>. 1556 * 1557 * @see #requestFocusInWindow() 1558 */ 1559 public void grabFocus() { 1560 requestFocus(); 1561 } 1562 1563 /** 1564 * Sets the value to indicate whether input verifier for the 1565 * current focus owner will be called before this component requests 1566 * focus. The default is true. Set to false on components such as a 1567 * Cancel button or a scrollbar, which should activate even if the 1568 * input in the current focus owner is not "passed" by the input 1569 * verifier for that component. 1570 * 1571 * @param verifyInputWhenFocusTarget value for the 1572 * <code>verifyInputWhenFocusTarget</code> property 1573 * @see InputVerifier 1574 * @see #setInputVerifier 1575 * @see #getInputVerifier 1576 * @see #getVerifyInputWhenFocusTarget 1577 * 1578 * @since 1.3 1579 * @beaninfo 1580 * bound: true 1581 * description: Whether the Component verifies input before accepting 1582 * focus. 1583 */ 1584 public void setVerifyInputWhenFocusTarget(boolean 1585 verifyInputWhenFocusTarget) { 1586 boolean oldVerifyInputWhenFocusTarget = 1587 this.verifyInputWhenFocusTarget; 1588 this.verifyInputWhenFocusTarget = verifyInputWhenFocusTarget; 1589 firePropertyChange("verifyInputWhenFocusTarget", 1590 oldVerifyInputWhenFocusTarget, 1591 verifyInputWhenFocusTarget); 1592 } 1593 1594 /** 1595 * Returns the value that indicates whether the input verifier for the 1596 * current focus owner will be called before this component requests 1597 * focus. 1598 * 1599 * @return value of the <code>verifyInputWhenFocusTarget</code> property 1600 * 1601 * @see InputVerifier 1602 * @see #setInputVerifier 1603 * @see #getInputVerifier 1604 * @see #setVerifyInputWhenFocusTarget 1605 * 1606 * @since 1.3 1607 */ 1608 public boolean getVerifyInputWhenFocusTarget() { 1609 return verifyInputWhenFocusTarget; 1610 } 1611 1612 1613 /** 1614 * Gets the <code>FontMetrics</code> for the specified <code>Font</code>. 1615 * 1616 * @param font the font for which font metrics is to be 1617 * obtained 1618 * @return the font metrics for <code>font</code> 1619 * @throws NullPointerException if <code>font</code> is null 1620 * @since 1.5 1621 */ 1622 public FontMetrics getFontMetrics(Font font) { 1623 return SwingUtilities2.getFontMetrics(this, font); 1624 } 1625 1626 1627 /** 1628 * Sets the preferred size of this component. 1629 * If <code>preferredSize</code> is <code>null</code>, the UI will 1630 * be asked for the preferred size. 1631 * @beaninfo 1632 * preferred: true 1633 * bound: true 1634 * description: The preferred size of the component. 1635 */ 1636 public void setPreferredSize(Dimension preferredSize) { 1637 super.setPreferredSize(preferredSize); 1638 } 1639 1640 1641 /** 1642 * If the <code>preferredSize</code> has been set to a 1643 * non-<code>null</code> value just returns it. 1644 * If the UI delegate's <code>getPreferredSize</code> 1645 * method returns a non <code>null</code> value then return that; 1646 * otherwise defer to the component's layout manager. 1647 * 1648 * @return the value of the <code>preferredSize</code> property 1649 * @see #setPreferredSize 1650 * @see ComponentUI 1651 */ 1652 @Transient 1653 public Dimension getPreferredSize() { 1654 if (isPreferredSizeSet()) { 1655 return super.getPreferredSize(); 1656 } 1657 Dimension size = null; 1658 if (ui != null) { 1659 size = ui.getPreferredSize(this); 1660 } 1661 return (size != null) ? size : super.getPreferredSize(); 1662 } 1663 1664 1665 /** 1666 * Sets the maximum size of this component to a constant 1667 * value. Subsequent calls to <code>getMaximumSize</code> will always 1668 * return this value; the component's UI will not be asked 1669 * to compute it. Setting the maximum size to <code>null</code> 1670 * restores the default behavior. 1671 * 1672 * @param maximumSize a <code>Dimension</code> containing the 1673 * desired maximum allowable size 1674 * @see #getMaximumSize 1675 * @beaninfo 1676 * bound: true 1677 * description: The maximum size of the component. 1678 */ 1679 public void setMaximumSize(Dimension maximumSize) { 1680 super.setMaximumSize(maximumSize); 1681 } 1682 1683 1684 /** 1685 * If the maximum size has been set to a non-<code>null</code> value 1686 * just returns it. If the UI delegate's <code>getMaximumSize</code> 1687 * method returns a non-<code>null</code> value then return that; 1688 * otherwise defer to the component's layout manager. 1689 * 1690 * @return the value of the <code>maximumSize</code> property 1691 * @see #setMaximumSize 1692 * @see ComponentUI 1693 */ 1694 @Transient 1695 public Dimension getMaximumSize() { 1696 if (isMaximumSizeSet()) { 1697 return super.getMaximumSize(); 1698 } 1699 Dimension size = null; 1700 if (ui != null) { 1701 size = ui.getMaximumSize(this); 1702 } 1703 return (size != null) ? size : super.getMaximumSize(); 1704 } 1705 1706 1707 /** 1708 * Sets the minimum size of this component to a constant 1709 * value. Subsequent calls to <code>getMinimumSize</code> will always 1710 * return this value; the component's UI will not be asked 1711 * to compute it. Setting the minimum size to <code>null</code> 1712 * restores the default behavior. 1713 * 1714 * @param minimumSize the new minimum size of this component 1715 * @see #getMinimumSize 1716 * @beaninfo 1717 * bound: true 1718 * description: The minimum size of the component. 1719 */ 1720 public void setMinimumSize(Dimension minimumSize) { 1721 super.setMinimumSize(minimumSize); 1722 } 1723 1724 /** 1725 * If the minimum size has been set to a non-<code>null</code> value 1726 * just returns it. If the UI delegate's <code>getMinimumSize</code> 1727 * method returns a non-<code>null</code> value then return that; otherwise 1728 * defer to the component's layout manager. 1729 * 1730 * @return the value of the <code>minimumSize</code> property 1731 * @see #setMinimumSize 1732 * @see ComponentUI 1733 */ 1734 @Transient 1735 public Dimension getMinimumSize() { 1736 if (isMinimumSizeSet()) { 1737 return super.getMinimumSize(); 1738 } 1739 Dimension size = null; 1740 if (ui != null) { 1741 size = ui.getMinimumSize(this); 1742 } 1743 return (size != null) ? size : super.getMinimumSize(); 1744 } 1745 1746 /** 1747 * Gives the UI delegate an opportunity to define the precise 1748 * shape of this component for the sake of mouse processing. 1749 * 1750 * @return true if this component logically contains x,y 1751 * @see java.awt.Component#contains(int, int) 1752 * @see ComponentUI 1753 */ 1754 public boolean contains(int x, int y) { 1755 return (ui != null) ? ui.contains(this, x, y) : super.contains(x, y); 1756 } 1757 1758 /** 1759 * Sets the border of this component. The <code>Border</code> object is 1760 * responsible for defining the insets for the component 1761 * (overriding any insets set directly on the component) and 1762 * for optionally rendering any border decorations within the 1763 * bounds of those insets. Borders should be used (rather 1764 * than insets) for creating both decorative and non-decorative 1765 * (such as margins and padding) regions for a swing component. 1766 * Compound borders can be used to nest multiple borders within a 1767 * single component. 1768 * <p> 1769 * Although technically you can set the border on any object 1770 * that inherits from <code>JComponent</code>, the look and 1771 * feel implementation of many standard Swing components 1772 * doesn't work well with user-set borders. In general, 1773 * when you want to set a border on a standard Swing 1774 * component other than <code>JPanel</code> or <code>JLabel</code>, 1775 * we recommend that you put the component in a <code>JPanel</code> 1776 * and set the border on the <code>JPanel</code>. 1777 * <p> 1778 * This is a bound property. 1779 * 1780 * @param border the border to be rendered for this component 1781 * @see Border 1782 * @see CompoundBorder 1783 * @beaninfo 1784 * bound: true 1785 * preferred: true 1786 * attribute: visualUpdate true 1787 * description: The component's border. 1788 */ 1789 public void setBorder(Border border) { 1790 Border oldBorder = this.border; 1791 1792 this.border = border; 1793 firePropertyChange("border", oldBorder, border); 1794 if (border != oldBorder) { 1795 if (border == null || oldBorder == null || 1796 !(border.getBorderInsets(this).equals(oldBorder.getBorderInsets(this)))) { 1797 revalidate(); 1798 } 1799 repaint(); 1800 } 1801 } 1802 1803 /** 1804 * Returns the border of this component or <code>null</code> if no 1805 * border is currently set. 1806 * 1807 * @return the border object for this component 1808 * @see #setBorder 1809 */ 1810 public Border getBorder() { 1811 return border; 1812 } 1813 1814 /** 1815 * If a border has been set on this component, returns the 1816 * border's insets; otherwise calls <code>super.getInsets</code>. 1817 * 1818 * @return the value of the insets property 1819 * @see #setBorder 1820 */ 1821 public Insets getInsets() { 1822 if (border != null) { 1823 return border.getBorderInsets(this); 1824 } 1825 return super.getInsets(); 1826 } 1827 1828 /** 1829 * Returns an <code>Insets</code> object containing this component's inset 1830 * values. The passed-in <code>Insets</code> object will be reused 1831 * if possible. 1832 * Calling methods cannot assume that the same object will be returned, 1833 * however. All existing values within this object are overwritten. 1834 * If <code>insets</code> is null, this will allocate a new one. 1835 * 1836 * @param insets the <code>Insets</code> object, which can be reused 1837 * @return the <code>Insets</code> object 1838 * @see #getInsets 1839 * @beaninfo 1840 * expert: true 1841 */ 1842 public Insets getInsets(Insets insets) { 1843 if (insets == null) { 1844 insets = new Insets(0, 0, 0, 0); 1845 } 1846 if (border != null) { 1847 if (border instanceof AbstractBorder) { 1848 return ((AbstractBorder)border).getBorderInsets(this, insets); 1849 } else { 1850 // Can't reuse border insets because the Border interface 1851 // can't be enhanced. 1852 return border.getBorderInsets(this); 1853 } 1854 } else { 1855 // super.getInsets() always returns an Insets object with 1856 // all of its value zeroed. No need for a new object here. 1857 insets.left = insets.top = insets.right = insets.bottom = 0; 1858 return insets; 1859 } 1860 } 1861 1862 /** 1863 * Overrides <code>Container.getAlignmentY</code> to return 1864 * the vertical alignment. 1865 * 1866 * @return the value of the <code>alignmentY</code> property 1867 * @see #setAlignmentY 1868 * @see java.awt.Component#getAlignmentY 1869 */ 1870 public float getAlignmentY() { 1871 if (isAlignmentYSet) { 1872 return alignmentY; 1873 } 1874 return super.getAlignmentY(); 1875 } 1876 1877 /** 1878 * Sets the vertical alignment. 1879 * 1880 * @param alignmentY the new vertical alignment 1881 * @see #getAlignmentY 1882 * @beaninfo 1883 * description: The preferred vertical alignment of the component. 1884 */ 1885 public void setAlignmentY(float alignmentY) { 1886 this.alignmentY = validateAlignment(alignmentY); 1887 isAlignmentYSet = true; 1888 } 1889 1890 1891 /** 1892 * Overrides <code>Container.getAlignmentX</code> to return 1893 * the horizontal alignment. 1894 * 1895 * @return the value of the <code>alignmentX</code> property 1896 * @see #setAlignmentX 1897 * @see java.awt.Component#getAlignmentX 1898 */ 1899 public float getAlignmentX() { 1900 if (isAlignmentXSet) { 1901 return alignmentX; 1902 } 1903 return super.getAlignmentX(); 1904 } 1905 1906 /** 1907 * Sets the horizontal alignment. 1908 * 1909 * @param alignmentX the new horizontal alignment 1910 * @see #getAlignmentX 1911 * @beaninfo 1912 * description: The preferred horizontal alignment of the component. 1913 */ 1914 public void setAlignmentX(float alignmentX) { 1915 this.alignmentX = validateAlignment(alignmentX); 1916 isAlignmentXSet = true; 1917 } 1918 1919 private float validateAlignment(float alignment) { 1920 return alignment > 1.0f ? 1.0f : alignment < 0.0f ? 0.0f : alignment; 1921 } 1922 1923 /** 1924 * Sets the input verifier for this component. 1925 * 1926 * @param inputVerifier the new input verifier 1927 * @since 1.3 1928 * @see InputVerifier 1929 * @beaninfo 1930 * bound: true 1931 * description: The component's input verifier. 1932 */ 1933 public void setInputVerifier(InputVerifier inputVerifier) { 1934 InputVerifier oldInputVerifier = (InputVerifier)getClientProperty( 1935 JComponent_INPUT_VERIFIER); 1936 putClientProperty(JComponent_INPUT_VERIFIER, inputVerifier); 1937 firePropertyChange("inputVerifier", oldInputVerifier, inputVerifier); 1938 } 1939 1940 /** 1941 * Returns the input verifier for this component. 1942 * 1943 * @return the <code>inputVerifier</code> property 1944 * @since 1.3 1945 * @see InputVerifier 1946 */ 1947 public InputVerifier getInputVerifier() { 1948 return (InputVerifier)getClientProperty(JComponent_INPUT_VERIFIER); 1949 } 1950 1951 /** 1952 * Returns this component's graphics context, which lets you draw 1953 * on a component. Use this method to get a <code>Graphics</code> object and 1954 * then invoke operations on that object to draw on the component. 1955 * @return this components graphics context 1956 */ 1957 public Graphics getGraphics() { 1958 if (DEBUG_GRAPHICS_LOADED && shouldDebugGraphics() != 0) { 1959 DebugGraphics graphics = new DebugGraphics(super.getGraphics(), 1960 this); 1961 return graphics; 1962 } 1963 return super.getGraphics(); 1964 } 1965 1966 1967 /** Enables or disables diagnostic information about every graphics 1968 * operation performed within the component or one of its children. 1969 * 1970 * @param debugOptions determines how the component should display 1971 * the information; one of the following options: 1972 * <ul> 1973 * <li>DebugGraphics.LOG_OPTION - causes a text message to be printed. 1974 * <li>DebugGraphics.FLASH_OPTION - causes the drawing to flash several 1975 * times. 1976 * <li>DebugGraphics.BUFFERED_OPTION - creates an 1977 * <code>ExternalWindow</code> that displays the operations 1978 * performed on the View's offscreen buffer. 1979 * <li>DebugGraphics.NONE_OPTION disables debugging. 1980 * <li>A value of 0 causes no changes to the debugging options. 1981 * </ul> 1982 * <code>debugOptions</code> is bitwise OR'd into the current value 1983 * 1984 * @beaninfo 1985 * preferred: true 1986 * enum: NONE_OPTION DebugGraphics.NONE_OPTION 1987 * LOG_OPTION DebugGraphics.LOG_OPTION 1988 * FLASH_OPTION DebugGraphics.FLASH_OPTION 1989 * BUFFERED_OPTION DebugGraphics.BUFFERED_OPTION 1990 * description: Diagnostic options for graphics operations. 1991 */ 1992 public void setDebugGraphicsOptions(int debugOptions) { 1993 DebugGraphics.setDebugOptions(this, debugOptions); 1994 } 1995 1996 /** Returns the state of graphics debugging. 1997 * 1998 * @return a bitwise OR'd flag of zero or more of the following options: 1999 * <ul> 2000 * <li>DebugGraphics.LOG_OPTION - causes a text message to be printed. 2001 * <li>DebugGraphics.FLASH_OPTION - causes the drawing to flash several 2002 * times. 2003 * <li>DebugGraphics.BUFFERED_OPTION - creates an 2004 * <code>ExternalWindow</code> that displays the operations 2005 * performed on the View's offscreen buffer. 2006 * <li>DebugGraphics.NONE_OPTION disables debugging. 2007 * <li>A value of 0 causes no changes to the debugging options. 2008 * </ul> 2009 * @see #setDebugGraphicsOptions 2010 */ 2011 public int getDebugGraphicsOptions() { 2012 return DebugGraphics.getDebugOptions(this); 2013 } 2014 2015 2016 /** 2017 * Returns true if debug information is enabled for this 2018 * <code>JComponent</code> or one of its parents. 2019 */ 2020 int shouldDebugGraphics() { 2021 return DebugGraphics.shouldComponentDebug(this); 2022 } 2023 2024 /** 2025 * This method is now obsolete, please use a combination of 2026 * <code>getActionMap()</code> and <code>getInputMap()</code> for 2027 * similar behavior. For example, to bind the <code>KeyStroke</code> 2028 * <code>aKeyStroke</code> to the <code>Action</code> <code>anAction</code> 2029 * now use: 2030 * <pre> 2031 * component.getInputMap().put(aKeyStroke, aCommand); 2032 * component.getActionMap().put(aCommmand, anAction); 2033 * </pre> 2034 * The above assumes you want the binding to be applicable for 2035 * <code>WHEN_FOCUSED</code>. To register bindings for other focus 2036 * states use the <code>getInputMap</code> method that takes an integer. 2037 * <p> 2038 * Register a new keyboard action. 2039 * <code>anAction</code> will be invoked if a key event matching 2040 * <code>aKeyStroke</code> occurs and <code>aCondition</code> is verified. 2041 * The <code>KeyStroke</code> object defines a 2042 * particular combination of a keyboard key and one or more modifiers 2043 * (alt, shift, ctrl, meta). 2044 * <p> 2045 * The <code>aCommand</code> will be set in the delivered event if 2046 * specified. 2047 * <p> 2048 * The <code>aCondition</code> can be one of: 2049 * <blockquote> 2050 * <DL> 2051 * <DT>WHEN_FOCUSED 2052 * <DD>The action will be invoked only when the keystroke occurs 2053 * while the component has the focus. 2054 * <DT>WHEN_IN_FOCUSED_WINDOW 2055 * <DD>The action will be invoked when the keystroke occurs while 2056 * the component has the focus or if the component is in the 2057 * window that has the focus. Note that the component need not 2058 * be an immediate descendent of the window -- it can be 2059 * anywhere in the window's containment hierarchy. In other 2060 * words, whenever <em>any</em> component in the window has the focus, 2061 * the action registered with this component is invoked. 2062 * <DT>WHEN_ANCESTOR_OF_FOCUSED_COMPONENT 2063 * <DD>The action will be invoked when the keystroke occurs while the 2064 * component has the focus or if the component is an ancestor of 2065 * the component that has the focus. 2066 * </DL> 2067 * </blockquote> 2068 * <p> 2069 * The combination of keystrokes and conditions lets you define high 2070 * level (semantic) action events for a specified keystroke+modifier 2071 * combination (using the KeyStroke class) and direct to a parent or 2072 * child of a component that has the focus, or to the component itself. 2073 * In other words, in any hierarchical structure of components, an 2074 * arbitrary key-combination can be immediately directed to the 2075 * appropriate component in the hierarchy, and cause a specific method 2076 * to be invoked (usually by way of adapter objects). 2077 * <p> 2078 * If an action has already been registered for the receiving 2079 * container, with the same charCode and the same modifiers, 2080 * <code>anAction</code> will replace the action. 2081 * 2082 * @param anAction the <code>Action</code> to be registered 2083 * @param aCommand the command to be set in the delivered event 2084 * @param aKeyStroke the <code>KeyStroke</code> to bind to the action 2085 * @param aCondition the condition that needs to be met, see above 2086 * @see KeyStroke 2087 */ 2088 public void registerKeyboardAction(ActionListener anAction,String aCommand,KeyStroke aKeyStroke,int aCondition) { 2089 2090 InputMap inputMap = getInputMap(aCondition, true); 2091 2092 if (inputMap != null) { 2093 ActionMap actionMap = getActionMap(true); 2094 ActionStandin action = new ActionStandin(anAction, aCommand); 2095 inputMap.put(aKeyStroke, action); 2096 if (actionMap != null) { 2097 actionMap.put(action, action); 2098 } 2099 } 2100 } 2101 2102 /** 2103 * Registers any bound <code>WHEN_IN_FOCUSED_WINDOW</code> actions with 2104 * the <code>KeyboardManager</code>. If <code>onlyIfNew</code> 2105 * is true only actions that haven't been registered are pushed 2106 * to the <code>KeyboardManager</code>; 2107 * otherwise all actions are pushed to the <code>KeyboardManager</code>. 2108 * 2109 * @param onlyIfNew if true, only actions that haven't been registered 2110 * are pushed to the <code>KeyboardManager</code> 2111 */ 2112 private void registerWithKeyboardManager(boolean onlyIfNew) { 2113 InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW, false); 2114 KeyStroke[] strokes; 2115 @SuppressWarnings("unchecked") 2116 Hashtable<KeyStroke, KeyStroke> registered = 2117 (Hashtable<KeyStroke, KeyStroke>)getClientProperty 2118 (WHEN_IN_FOCUSED_WINDOW_BINDINGS); 2119 2120 if (inputMap != null) { 2121 // Push any new KeyStrokes to the KeyboardManager. 2122 strokes = inputMap.allKeys(); 2123 if (strokes != null) { 2124 for (int counter = strokes.length - 1; counter >= 0; 2125 counter--) { 2126 if (!onlyIfNew || registered == null || 2127 registered.get(strokes[counter]) == null) { 2128 registerWithKeyboardManager(strokes[counter]); 2129 } 2130 if (registered != null) { 2131 registered.remove(strokes[counter]); 2132 } 2133 } 2134 } 2135 } 2136 else { 2137 strokes = null; 2138 } 2139 // Remove any old ones. 2140 if (registered != null && registered.size() > 0) { 2141 Enumeration<KeyStroke> keys = registered.keys(); 2142 2143 while (keys.hasMoreElements()) { 2144 KeyStroke ks = keys.nextElement(); 2145 unregisterWithKeyboardManager(ks); 2146 } 2147 registered.clear(); 2148 } 2149 // Updated the registered Hashtable. 2150 if (strokes != null && strokes.length > 0) { 2151 if (registered == null) { 2152 registered = new Hashtable<KeyStroke, KeyStroke>(strokes.length); 2153 putClientProperty(WHEN_IN_FOCUSED_WINDOW_BINDINGS, registered); 2154 } 2155 for (int counter = strokes.length - 1; counter >= 0; counter--) { 2156 registered.put(strokes[counter], strokes[counter]); 2157 } 2158 } 2159 else { 2160 putClientProperty(WHEN_IN_FOCUSED_WINDOW_BINDINGS, null); 2161 } 2162 } 2163 2164 /** 2165 * Unregisters all the previously registered 2166 * <code>WHEN_IN_FOCUSED_WINDOW</code> <code>KeyStroke</code> bindings. 2167 */ 2168 private void unregisterWithKeyboardManager() { 2169 @SuppressWarnings("unchecked") 2170 Hashtable<KeyStroke, KeyStroke> registered = 2171 (Hashtable<KeyStroke, KeyStroke>)getClientProperty 2172 (WHEN_IN_FOCUSED_WINDOW_BINDINGS); 2173 2174 if (registered != null && registered.size() > 0) { 2175 Enumeration<KeyStroke> keys = registered.keys(); 2176 2177 while (keys.hasMoreElements()) { 2178 KeyStroke ks = keys.nextElement(); 2179 unregisterWithKeyboardManager(ks); 2180 } 2181 } 2182 putClientProperty(WHEN_IN_FOCUSED_WINDOW_BINDINGS, null); 2183 } 2184 2185 /** 2186 * Invoked from <code>ComponentInputMap</code> when its bindings change. 2187 * If <code>inputMap</code> is the current <code>windowInputMap</code> 2188 * (or a parent of the window <code>InputMap</code>) 2189 * the <code>KeyboardManager</code> is notified of the new bindings. 2190 * 2191 * @param inputMap the map containing the new bindings 2192 */ 2193 void componentInputMapChanged(ComponentInputMap inputMap) { 2194 InputMap km = getInputMap(WHEN_IN_FOCUSED_WINDOW, false); 2195 2196 while (km != inputMap && km != null) { 2197 km = km.getParent(); 2198 } 2199 if (km != null) { 2200 registerWithKeyboardManager(false); 2201 } 2202 } 2203 2204 private void registerWithKeyboardManager(KeyStroke aKeyStroke) { 2205 KeyboardManager.getCurrentManager().registerKeyStroke(aKeyStroke,this); 2206 } 2207 2208 private void unregisterWithKeyboardManager(KeyStroke aKeyStroke) { 2209 KeyboardManager.getCurrentManager().unregisterKeyStroke(aKeyStroke, 2210 this); 2211 } 2212 2213 /** 2214 * This method is now obsolete, please use a combination of 2215 * <code>getActionMap()</code> and <code>getInputMap()</code> for 2216 * similar behavior. 2217 * 2218 * @param anAction action to be registered to given keystroke and condition 2219 * @param aKeyStroke a {@code KeyStroke} 2220 * @param aCondition the condition to be associated with given keystroke 2221 * and action 2222 * @see #getActionMap 2223 * @see #getInputMap(int) 2224 */ 2225 public void registerKeyboardAction(ActionListener anAction,KeyStroke aKeyStroke,int aCondition) { 2226 registerKeyboardAction(anAction,null,aKeyStroke,aCondition); 2227 } 2228 2229 /** 2230 * This method is now obsolete. To unregister an existing binding 2231 * you can either remove the binding from the 2232 * <code>ActionMap/InputMap</code>, or place a dummy binding the 2233 * <code>InputMap</code>. Removing the binding from the 2234 * <code>InputMap</code> allows bindings in parent <code>InputMap</code>s 2235 * to be active, whereas putting a dummy binding in the 2236 * <code>InputMap</code> effectively disables 2237 * the binding from ever happening. 2238 * <p> 2239 * Unregisters a keyboard action. 2240 * This will remove the binding from the <code>ActionMap</code> 2241 * (if it exists) as well as the <code>InputMap</code>s. 2242 * 2243 * @param aKeyStroke the keystroke for which to unregister its 2244 * keyboard action 2245 */ 2246 public void unregisterKeyboardAction(KeyStroke aKeyStroke) { 2247 ActionMap am = getActionMap(false); 2248 for (int counter = 0; counter < 3; counter++) { 2249 InputMap km = getInputMap(counter, false); 2250 if (km != null) { 2251 Object actionID = km.get(aKeyStroke); 2252 2253 if (am != null && actionID != null) { 2254 am.remove(actionID); 2255 } 2256 km.remove(aKeyStroke); 2257 } 2258 } 2259 } 2260 2261 /** 2262 * Returns the <code>KeyStrokes</code> that will initiate 2263 * registered actions. 2264 * 2265 * @return an array of <code>KeyStroke</code> objects 2266 * @see #registerKeyboardAction 2267 */ 2268 public KeyStroke[] getRegisteredKeyStrokes() { 2269 int[] counts = new int[3]; 2270 KeyStroke[][] strokes = new KeyStroke[3][]; 2271 2272 for (int counter = 0; counter < 3; counter++) { 2273 InputMap km = getInputMap(counter, false); 2274 strokes[counter] = (km != null) ? km.allKeys() : null; 2275 counts[counter] = (strokes[counter] != null) ? 2276 strokes[counter].length : 0; 2277 } 2278 KeyStroke[] retValue = new KeyStroke[counts[0] + counts[1] + 2279 counts[2]]; 2280 for (int counter = 0, last = 0; counter < 3; counter++) { 2281 if (counts[counter] > 0) { 2282 System.arraycopy(strokes[counter], 0, retValue, last, 2283 counts[counter]); 2284 last += counts[counter]; 2285 } 2286 } 2287 return retValue; 2288 } 2289 2290 /** 2291 * Returns the condition that determines whether a registered action 2292 * occurs in response to the specified keystroke. 2293 * <p> 2294 * For Java 2 platform v1.3, a <code>KeyStroke</code> can be associated 2295 * with more than one condition. 2296 * For example, 'a' could be bound for the two 2297 * conditions <code>WHEN_FOCUSED</code> and 2298 * <code>WHEN_IN_FOCUSED_WINDOW</code> condition. 2299 * 2300 * @param aKeyStroke the keystroke for which to request an 2301 * action-keystroke condition 2302 * @return the action-keystroke condition 2303 */ 2304 public int getConditionForKeyStroke(KeyStroke aKeyStroke) { 2305 for (int counter = 0; counter < 3; counter++) { 2306 InputMap inputMap = getInputMap(counter, false); 2307 if (inputMap != null && inputMap.get(aKeyStroke) != null) { 2308 return counter; 2309 } 2310 } 2311 return UNDEFINED_CONDITION; 2312 } 2313 2314 /** 2315 * Returns the object that will perform the action registered for a 2316 * given keystroke. 2317 * 2318 * @param aKeyStroke the keystroke for which to return a listener 2319 * @return the <code>ActionListener</code> 2320 * object invoked when the keystroke occurs 2321 */ 2322 public ActionListener getActionForKeyStroke(KeyStroke aKeyStroke) { 2323 ActionMap am = getActionMap(false); 2324 2325 if (am == null) { 2326 return null; 2327 } 2328 for (int counter = 0; counter < 3; counter++) { 2329 InputMap inputMap = getInputMap(counter, false); 2330 if (inputMap != null) { 2331 Object actionBinding = inputMap.get(aKeyStroke); 2332 2333 if (actionBinding != null) { 2334 Action action = am.get(actionBinding); 2335 if (action instanceof ActionStandin) { 2336 return ((ActionStandin)action).actionListener; 2337 } 2338 return action; 2339 } 2340 } 2341 } 2342 return null; 2343 } 2344 2345 /** 2346 * Unregisters all the bindings in the first tier <code>InputMaps</code> 2347 * and <code>ActionMap</code>. This has the effect of removing any 2348 * local bindings, and allowing the bindings defined in parent 2349 * <code>InputMap/ActionMaps</code> 2350 * (the UI is usually defined in the second tier) to persist. 2351 */ 2352 public void resetKeyboardActions() { 2353 // Keys 2354 for (int counter = 0; counter < 3; counter++) { 2355 InputMap inputMap = getInputMap(counter, false); 2356 2357 if (inputMap != null) { 2358 inputMap.clear(); 2359 } 2360 } 2361 2362 // Actions 2363 ActionMap am = getActionMap(false); 2364 2365 if (am != null) { 2366 am.clear(); 2367 } 2368 } 2369 2370 /** 2371 * Sets the <code>InputMap</code> to use under the condition 2372 * <code>condition</code> to 2373 * <code>map</code>. A <code>null</code> value implies you 2374 * do not want any bindings to be used, even from the UI. This will 2375 * not reinstall the UI <code>InputMap</code> (if there was one). 2376 * <code>condition</code> has one of the following values: 2377 * <ul> 2378 * <li><code>WHEN_IN_FOCUSED_WINDOW</code> 2379 * <li><code>WHEN_FOCUSED</code> 2380 * <li><code>WHEN_ANCESTOR_OF_FOCUSED_COMPONENT</code> 2381 * </ul> 2382 * If <code>condition</code> is <code>WHEN_IN_FOCUSED_WINDOW</code> 2383 * and <code>map</code> is not a <code>ComponentInputMap</code>, an 2384 * <code>IllegalArgumentException</code> will be thrown. 2385 * Similarly, if <code>condition</code> is not one of the values 2386 * listed, an <code>IllegalArgumentException</code> will be thrown. 2387 * 2388 * @param condition one of the values listed above 2389 * @param map the <code>InputMap</code> to use for the given condition 2390 * @exception IllegalArgumentException if <code>condition</code> is 2391 * <code>WHEN_IN_FOCUSED_WINDOW</code> and <code>map</code> 2392 * is not an instance of <code>ComponentInputMap</code>; or 2393 * if <code>condition</code> is not one of the legal values 2394 * specified above 2395 * @since 1.3 2396 */ 2397 public final void setInputMap(int condition, InputMap map) { 2398 switch (condition) { 2399 case WHEN_IN_FOCUSED_WINDOW: 2400 if (map != null && !(map instanceof ComponentInputMap)) { 2401 throw new IllegalArgumentException("WHEN_IN_FOCUSED_WINDOW InputMaps must be of type ComponentInputMap"); 2402 } 2403 windowInputMap = (ComponentInputMap)map; 2404 setFlag(WIF_INPUTMAP_CREATED, true); 2405 registerWithKeyboardManager(false); 2406 break; 2407 case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT: 2408 ancestorInputMap = map; 2409 setFlag(ANCESTOR_INPUTMAP_CREATED, true); 2410 break; 2411 case WHEN_FOCUSED: 2412 focusInputMap = map; 2413 setFlag(FOCUS_INPUTMAP_CREATED, true); 2414 break; 2415 default: 2416 throw new IllegalArgumentException("condition must be one of JComponent.WHEN_IN_FOCUSED_WINDOW, JComponent.WHEN_FOCUSED or JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT"); 2417 } 2418 } 2419 2420 /** 2421 * Returns the <code>InputMap</code> that is used during 2422 * <code>condition</code>. 2423 * 2424 * @param condition one of WHEN_IN_FOCUSED_WINDOW, WHEN_FOCUSED, 2425 * WHEN_ANCESTOR_OF_FOCUSED_COMPONENT 2426 * @return the <code>InputMap</code> for the specified 2427 * <code>condition</code> 2428 * @since 1.3 2429 */ 2430 public final InputMap getInputMap(int condition) { 2431 return getInputMap(condition, true); 2432 } 2433 2434 /** 2435 * Returns the <code>InputMap</code> that is used when the 2436 * component has focus. 2437 * This is convenience method for <code>getInputMap(WHEN_FOCUSED)</code>. 2438 * 2439 * @return the <code>InputMap</code> used when the component has focus 2440 * @since 1.3 2441 */ 2442 public final InputMap getInputMap() { 2443 return getInputMap(WHEN_FOCUSED, true); 2444 } 2445 2446 /** 2447 * Sets the <code>ActionMap</code> to <code>am</code>. This does not set 2448 * the parent of the <code>am</code> to be the <code>ActionMap</code> 2449 * from the UI (if there was one), it is up to the caller to have done this. 2450 * 2451 * @param am the new <code>ActionMap</code> 2452 * @since 1.3 2453 */ 2454 public final void setActionMap(ActionMap am) { 2455 actionMap = am; 2456 setFlag(ACTIONMAP_CREATED, true); 2457 } 2458 2459 /** 2460 * Returns the <code>ActionMap</code> used to determine what 2461 * <code>Action</code> to fire for particular <code>KeyStroke</code> 2462 * binding. The returned <code>ActionMap</code>, unless otherwise 2463 * set, will have the <code>ActionMap</code> from the UI set as the parent. 2464 * 2465 * @return the <code>ActionMap</code> containing the key/action bindings 2466 * @since 1.3 2467 */ 2468 public final ActionMap getActionMap() { 2469 return getActionMap(true); 2470 } 2471 2472 /** 2473 * Returns the <code>InputMap</code> to use for condition 2474 * <code>condition</code>. If the <code>InputMap</code> hasn't 2475 * been created, and <code>create</code> is 2476 * true, it will be created. 2477 * 2478 * @param condition one of the following values: 2479 * <ul> 2480 * <li>JComponent.FOCUS_INPUTMAP_CREATED 2481 * <li>JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT 2482 * <li>JComponent.WHEN_IN_FOCUSED_WINDOW 2483 * </ul> 2484 * @param create if true, create the <code>InputMap</code> if it 2485 * is not already created 2486 * @return the <code>InputMap</code> for the given <code>condition</code>; 2487 * if <code>create</code> is false and the <code>InputMap</code> 2488 * hasn't been created, returns <code>null</code> 2489 * @exception IllegalArgumentException if <code>condition</code> 2490 * is not one of the legal values listed above 2491 */ 2492 final InputMap getInputMap(int condition, boolean create) { 2493 switch (condition) { 2494 case WHEN_FOCUSED: 2495 if (getFlag(FOCUS_INPUTMAP_CREATED)) { 2496 return focusInputMap; 2497 } 2498 // Hasn't been created yet. 2499 if (create) { 2500 InputMap km = new InputMap(); 2501 setInputMap(condition, km); 2502 return km; 2503 } 2504 break; 2505 case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT: 2506 if (getFlag(ANCESTOR_INPUTMAP_CREATED)) { 2507 return ancestorInputMap; 2508 } 2509 // Hasn't been created yet. 2510 if (create) { 2511 InputMap km = new InputMap(); 2512 setInputMap(condition, km); 2513 return km; 2514 } 2515 break; 2516 case WHEN_IN_FOCUSED_WINDOW: 2517 if (getFlag(WIF_INPUTMAP_CREATED)) { 2518 return windowInputMap; 2519 } 2520 // Hasn't been created yet. 2521 if (create) { 2522 ComponentInputMap km = new ComponentInputMap(this); 2523 setInputMap(condition, km); 2524 return km; 2525 } 2526 break; 2527 default: 2528 throw new IllegalArgumentException("condition must be one of JComponent.WHEN_IN_FOCUSED_WINDOW, JComponent.WHEN_FOCUSED or JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT"); 2529 } 2530 return null; 2531 } 2532 2533 /** 2534 * Finds and returns the appropriate <code>ActionMap</code>. 2535 * 2536 * @param create if true, create the <code>ActionMap</code> if it 2537 * is not already created 2538 * @return the <code>ActionMap</code> for this component; if the 2539 * <code>create</code> flag is false and there is no 2540 * current <code>ActionMap</code>, returns <code>null</code> 2541 */ 2542 final ActionMap getActionMap(boolean create) { 2543 if (getFlag(ACTIONMAP_CREATED)) { 2544 return actionMap; 2545 } 2546 // Hasn't been created. 2547 if (create) { 2548 ActionMap am = new ActionMap(); 2549 setActionMap(am); 2550 return am; 2551 } 2552 return null; 2553 } 2554 2555 /** 2556 * Returns the baseline. The baseline is measured from the top of 2557 * the component. This method is primarily meant for 2558 * <code>LayoutManager</code>s to align components along their 2559 * baseline. A return value less than 0 indicates this component 2560 * does not have a reasonable baseline and that 2561 * <code>LayoutManager</code>s should not align this component on 2562 * its baseline. 2563 * <p> 2564 * This method calls into the <code>ComponentUI</code> method of the 2565 * same name. If this component does not have a <code>ComponentUI</code> 2566 * -1 will be returned. If a value >= 0 is 2567 * returned, then the component has a valid baseline for any 2568 * size >= the minimum size and <code>getBaselineResizeBehavior</code> 2569 * can be used to determine how the baseline changes with size. 2570 * 2571 * @throws IllegalArgumentException {@inheritDoc} 2572 * @see #getBaselineResizeBehavior 2573 * @see java.awt.FontMetrics 2574 * @since 1.6 2575 */ 2576 public int getBaseline(int width, int height) { 2577 // check size. 2578 super.getBaseline(width, height); 2579 if (ui != null) { 2580 return ui.getBaseline(this, width, height); 2581 } 2582 return -1; 2583 } 2584 2585 /** 2586 * Returns an enum indicating how the baseline of the component 2587 * changes as the size changes. This method is primarily meant for 2588 * layout managers and GUI builders. 2589 * <p> 2590 * This method calls into the <code>ComponentUI</code> method of 2591 * the same name. If this component does not have a 2592 * <code>ComponentUI</code> 2593 * <code>BaselineResizeBehavior.OTHER</code> will be 2594 * returned. Subclasses should 2595 * never return <code>null</code>; if the baseline can not be 2596 * calculated return <code>BaselineResizeBehavior.OTHER</code>. Callers 2597 * should first ask for the baseline using 2598 * <code>getBaseline</code> and if a value >= 0 is returned use 2599 * this method. It is acceptable for this method to return a 2600 * value other than <code>BaselineResizeBehavior.OTHER</code> even if 2601 * <code>getBaseline</code> returns a value less than 0. 2602 * 2603 * @see #getBaseline(int, int) 2604 * @since 1.6 2605 */ 2606 public BaselineResizeBehavior getBaselineResizeBehavior() { 2607 if (ui != null) { 2608 return ui.getBaselineResizeBehavior(this); 2609 } 2610 return BaselineResizeBehavior.OTHER; 2611 } 2612 2613 /** 2614 * In release 1.4, the focus subsystem was rearchitected. 2615 * For more information, see 2616 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html"> 2617 * How to Use the Focus Subsystem</a>, 2618 * a section in <em>The Java Tutorial</em>. 2619 * <p> 2620 * Requests focus on this <code>JComponent</code>'s 2621 * <code>FocusTraversalPolicy</code>'s default <code>Component</code>. 2622 * If this <code>JComponent</code> is a focus cycle root, then its 2623 * <code>FocusTraversalPolicy</code> is used. Otherwise, the 2624 * <code>FocusTraversalPolicy</code> of this <code>JComponent</code>'s 2625 * focus-cycle-root ancestor is used. 2626 * 2627 * @return true if this component can request to get the input focus, 2628 * false if it can not 2629 * @see java.awt.FocusTraversalPolicy#getDefaultComponent 2630 * @deprecated As of 1.4, replaced by 2631 * <code>FocusTraversalPolicy.getDefaultComponent(Container).requestFocus()</code> 2632 */ 2633 @Deprecated 2634 public boolean requestDefaultFocus() { 2635 Container nearestRoot = 2636 (isFocusCycleRoot()) ? this : getFocusCycleRootAncestor(); 2637 if (nearestRoot == null) { 2638 return false; 2639 } 2640 Component comp = nearestRoot.getFocusTraversalPolicy(). 2641 getDefaultComponent(nearestRoot); 2642 if (comp != null) { 2643 comp.requestFocus(); 2644 return true; 2645 } else { 2646 return false; 2647 } 2648 } 2649 2650 /** 2651 * Makes the component visible or invisible. 2652 * Overrides <code>Component.setVisible</code>. 2653 * 2654 * @param aFlag true to make the component visible; false to 2655 * make it invisible 2656 * 2657 * @beaninfo 2658 * attribute: visualUpdate true 2659 */ 2660 public void setVisible(boolean aFlag) { 2661 if (aFlag != isVisible()) { 2662 super.setVisible(aFlag); 2663 if (aFlag) { 2664 Container parent = getParent(); 2665 if (parent != null) { 2666 Rectangle r = getBounds(); 2667 parent.repaint(r.x, r.y, r.width, r.height); 2668 } 2669 revalidate(); 2670 } 2671 } 2672 } 2673 2674 /** 2675 * Sets whether or not this component is enabled. 2676 * A component that is enabled may respond to user input, 2677 * while a component that is not enabled cannot respond to 2678 * user input. Some components may alter their visual 2679 * representation when they are disabled in order to 2680 * provide feedback to the user that they cannot take input. 2681 * <p>Note: Disabling a component does not disable its children. 2682 * 2683 * <p>Note: Disabling a lightweight component does not prevent it from 2684 * receiving MouseEvents. 2685 * 2686 * @param enabled true if this component should be enabled, false otherwise 2687 * @see java.awt.Component#isEnabled 2688 * @see java.awt.Component#isLightweight 2689 * 2690 * @beaninfo 2691 * preferred: true 2692 * bound: true 2693 * attribute: visualUpdate true 2694 * description: The enabled state of the component. 2695 */ 2696 public void setEnabled(boolean enabled) { 2697 boolean oldEnabled = isEnabled(); 2698 super.setEnabled(enabled); 2699 firePropertyChange("enabled", oldEnabled, enabled); 2700 if (enabled != oldEnabled) { 2701 repaint(); 2702 } 2703 } 2704 2705 /** 2706 * Sets the foreground color of this component. It is up to the 2707 * look and feel to honor this property, some may choose to ignore 2708 * it. 2709 * 2710 * @param fg the desired foreground <code>Color</code> 2711 * @see java.awt.Component#getForeground 2712 * 2713 * @beaninfo 2714 * preferred: true 2715 * bound: true 2716 * attribute: visualUpdate true 2717 * description: The foreground color of the component. 2718 */ 2719 public void setForeground(Color fg) { 2720 Color oldFg = getForeground(); 2721 super.setForeground(fg); 2722 if ((oldFg != null) ? !oldFg.equals(fg) : ((fg != null) && !fg.equals(oldFg))) { 2723 // foreground already bound in AWT1.2 2724 repaint(); 2725 } 2726 } 2727 2728 /** 2729 * Sets the background color of this component. The background 2730 * color is used only if the component is opaque, and only 2731 * by subclasses of <code>JComponent</code> or 2732 * <code>ComponentUI</code> implementations. Direct subclasses of 2733 * <code>JComponent</code> must override 2734 * <code>paintComponent</code> to honor this property. 2735 * <p> 2736 * It is up to the look and feel to honor this property, some may 2737 * choose to ignore it. 2738 * 2739 * @param bg the desired background <code>Color</code> 2740 * @see java.awt.Component#getBackground 2741 * @see #setOpaque 2742 * 2743 * @beaninfo 2744 * preferred: true 2745 * bound: true 2746 * attribute: visualUpdate true 2747 * description: The background color of the component. 2748 */ 2749 public void setBackground(Color bg) { 2750 Color oldBg = getBackground(); 2751 super.setBackground(bg); 2752 if ((oldBg != null) ? !oldBg.equals(bg) : ((bg != null) && !bg.equals(oldBg))) { 2753 // background already bound in AWT1.2 2754 repaint(); 2755 } 2756 } 2757 2758 /** 2759 * Sets the font for this component. 2760 * 2761 * @param font the desired <code>Font</code> for this component 2762 * @see java.awt.Component#getFont 2763 * 2764 * @beaninfo 2765 * preferred: true 2766 * bound: true 2767 * attribute: visualUpdate true 2768 * description: The font for the component. 2769 */ 2770 public void setFont(Font font) { 2771 Font oldFont = getFont(); 2772 super.setFont(font); 2773 // font already bound in AWT1.2 2774 if (font != oldFont) { 2775 revalidate(); 2776 repaint(); 2777 } 2778 } 2779 2780 /** 2781 * Returns the default locale used to initialize each JComponent's 2782 * locale property upon creation. 2783 * 2784 * The default locale has "AppContext" scope so that applets (and 2785 * potentially multiple lightweight applications running in a single VM) 2786 * can have their own setting. An applet can safely alter its default 2787 * locale because it will have no affect on other applets (or the browser). 2788 * 2789 * @return the default <code>Locale</code>. 2790 * @see #setDefaultLocale 2791 * @see java.awt.Component#getLocale 2792 * @see #setLocale 2793 * @since 1.4 2794 */ 2795 static public Locale getDefaultLocale() { 2796 Locale l = (Locale) SwingUtilities.appContextGet(defaultLocale); 2797 if( l == null ) { 2798 //REMIND(bcb) choosing the default value is more complicated 2799 //than this. 2800 l = Locale.getDefault(); 2801 JComponent.setDefaultLocale( l ); 2802 } 2803 return l; 2804 } 2805 2806 2807 /** 2808 * Sets the default locale used to initialize each JComponent's locale 2809 * property upon creation. The initial value is the VM's default locale. 2810 * 2811 * The default locale has "AppContext" scope so that applets (and 2812 * potentially multiple lightweight applications running in a single VM) 2813 * can have their own setting. An applet can safely alter its default 2814 * locale because it will have no affect on other applets (or the browser). 2815 * 2816 * @param l the desired default <code>Locale</code> for new components. 2817 * @see #getDefaultLocale 2818 * @see java.awt.Component#getLocale 2819 * @see #setLocale 2820 * @since 1.4 2821 */ 2822 static public void setDefaultLocale( Locale l ) { 2823 SwingUtilities.appContextPut(defaultLocale, l); 2824 } 2825 2826 2827 /** 2828 * Processes any key events that the component itself 2829 * recognizes. This is called after the focus 2830 * manager and any interested listeners have been 2831 * given a chance to steal away the event. This 2832 * method is called only if the event has not 2833 * yet been consumed. This method is called prior 2834 * to the keyboard UI logic. 2835 * <p> 2836 * This method is implemented to do nothing. Subclasses would 2837 * normally override this method if they process some 2838 * key events themselves. If the event is processed, 2839 * it should be consumed. 2840 * 2841 * @param e the event to be processed 2842 */ 2843 protected void processComponentKeyEvent(KeyEvent e) { 2844 } 2845 2846 /** Overrides <code>processKeyEvent</code> to process events. **/ 2847 protected void processKeyEvent(KeyEvent e) { 2848 boolean result; 2849 boolean shouldProcessKey; 2850 2851 // This gives the key event listeners a crack at the event 2852 super.processKeyEvent(e); 2853 2854 // give the component itself a crack at the event 2855 if (! e.isConsumed()) { 2856 processComponentKeyEvent(e); 2857 } 2858 2859 shouldProcessKey = KeyboardState.shouldProcess(e); 2860 2861 if(e.isConsumed()) { 2862 return; 2863 } 2864 2865 if (shouldProcessKey && processKeyBindings(e, e.getID() == 2866 KeyEvent.KEY_PRESSED)) { 2867 e.consume(); 2868 } 2869 } 2870 2871 /** 2872 * Invoked to process the key bindings for <code>ks</code> as the result 2873 * of the <code>KeyEvent</code> <code>e</code>. This obtains 2874 * the appropriate <code>InputMap</code>, 2875 * gets the binding, gets the action from the <code>ActionMap</code>, 2876 * and then (if the action is found and the component 2877 * is enabled) invokes <code>notifyAction</code> to notify the action. 2878 * 2879 * @param ks the <code>KeyStroke</code> queried 2880 * @param e the <code>KeyEvent</code> 2881 * @param condition one of the following values: 2882 * <ul> 2883 * <li>JComponent.WHEN_FOCUSED 2884 * <li>JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT 2885 * <li>JComponent.WHEN_IN_FOCUSED_WINDOW 2886 * </ul> 2887 * @param pressed true if the key is pressed 2888 * @return true if there was a binding to an action, and the action 2889 * was enabled 2890 * 2891 * @since 1.3 2892 */ 2893 protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, 2894 int condition, boolean pressed) { 2895 InputMap map = getInputMap(condition, false); 2896 ActionMap am = getActionMap(false); 2897 2898 if(map != null && am != null && isEnabled()) { 2899 Object binding = map.get(ks); 2900 Action action = (binding == null) ? null : am.get(binding); 2901 if (action != null) { 2902 return SwingUtilities.notifyAction(action, ks, e, this, 2903 e.getModifiers()); 2904 } 2905 } 2906 return false; 2907 } 2908 2909 /** 2910 * This is invoked as the result of a <code>KeyEvent</code> 2911 * that was not consumed by the <code>FocusManager</code>, 2912 * <code>KeyListeners</code>, or the component. It will first try 2913 * <code>WHEN_FOCUSED</code> bindings, 2914 * then <code>WHEN_ANCESTOR_OF_FOCUSED_COMPONENT</code> bindings, 2915 * and finally <code>WHEN_IN_FOCUSED_WINDOW</code> bindings. 2916 * 2917 * @param e the unconsumed <code>KeyEvent</code> 2918 * @param pressed true if the key is pressed 2919 * @return true if there is a key binding for <code>e</code> 2920 */ 2921 boolean processKeyBindings(KeyEvent e, boolean pressed) { 2922 if (!SwingUtilities.isValidKeyEventForKeyBindings(e)) { 2923 return false; 2924 } 2925 // Get the KeyStroke 2926 // There may be two keystrokes associated with a low-level key event; 2927 // in this case a keystroke made of an extended key code has a priority. 2928 KeyStroke ks; 2929 KeyStroke ksE = null; 2930 2931 if (e.getID() == KeyEvent.KEY_TYPED) { 2932 ks = KeyStroke.getKeyStroke(e.getKeyChar()); 2933 } 2934 else { 2935 ks = KeyStroke.getKeyStroke(e.getKeyCode(),e.getModifiers(), 2936 (pressed ? false:true)); 2937 if (e.getKeyCode() != e.getExtendedKeyCode()) { 2938 ksE = KeyStroke.getKeyStroke(e.getExtendedKeyCode(),e.getModifiers(), 2939 (pressed ? false:true)); 2940 } 2941 } 2942 2943 // Do we have a key binding for e? 2944 // If we have a binding by an extended code, use it. 2945 // If not, check for regular code binding. 2946 if(ksE != null && processKeyBinding(ksE, e, WHEN_FOCUSED, pressed)) { 2947 return true; 2948 } 2949 if(processKeyBinding(ks, e, WHEN_FOCUSED, pressed)) 2950 return true; 2951 2952 /* We have no key binding. Let's try the path from our parent to the 2953 * window excluded. We store the path components so we can avoid 2954 * asking the same component twice. 2955 */ 2956 Container parent = this; 2957 while (parent != null && !(parent instanceof Window) && 2958 !(parent instanceof Applet)) { 2959 if(parent instanceof JComponent) { 2960 if(ksE != null && ((JComponent)parent).processKeyBinding(ksE, e, 2961 WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, pressed)) 2962 return true; 2963 if(((JComponent)parent).processKeyBinding(ks, e, 2964 WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, pressed)) 2965 return true; 2966 } 2967 // This is done so that the children of a JInternalFrame are 2968 // given precedence for WHEN_IN_FOCUSED_WINDOW bindings before 2969 // other components WHEN_IN_FOCUSED_WINDOW bindings. This also gives 2970 // more precedence to the WHEN_IN_FOCUSED_WINDOW bindings of the 2971 // JInternalFrame's children vs the 2972 // WHEN_ANCESTOR_OF_FOCUSED_COMPONENT bindings of the parents. 2973 // maybe generalize from JInternalFrame (like isFocusCycleRoot). 2974 if ((parent instanceof JInternalFrame) && 2975 JComponent.processKeyBindingsForAllComponents(e,parent,pressed)){ 2976 return true; 2977 } 2978 parent = parent.getParent(); 2979 } 2980 2981 /* No components between the focused component and the window is 2982 * actually interested by the key event. Let's try the other 2983 * JComponent in this window. 2984 */ 2985 if(parent != null) { 2986 return JComponent.processKeyBindingsForAllComponents(e,parent,pressed); 2987 } 2988 return false; 2989 } 2990 2991 static boolean processKeyBindingsForAllComponents(KeyEvent e, 2992 Container container, boolean pressed) { 2993 while (true) { 2994 if (KeyboardManager.getCurrentManager().fireKeyboardAction( 2995 e, pressed, container)) { 2996 return true; 2997 } 2998 if (container instanceof Popup.HeavyWeightWindow) { 2999 container = ((Window)container).getOwner(); 3000 } 3001 else { 3002 return false; 3003 } 3004 } 3005 } 3006 3007 /** 3008 * Registers the text to display in a tool tip. 3009 * The text displays when the cursor lingers over the component. 3010 * <p> 3011 * See <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/tooltip.html">How to Use Tool Tips</a> 3012 * in <em>The Java Tutorial</em> 3013 * for further documentation. 3014 * 3015 * @param text the string to display; if the text is <code>null</code>, 3016 * the tool tip is turned off for this component 3017 * @see #TOOL_TIP_TEXT_KEY 3018 * @beaninfo 3019 * preferred: true 3020 * description: The text to display in a tool tip. 3021 */ 3022 public void setToolTipText(String text) { 3023 String oldText = getToolTipText(); 3024 putClientProperty(TOOL_TIP_TEXT_KEY, text); 3025 ToolTipManager toolTipManager = ToolTipManager.sharedInstance(); 3026 if (text != null) { 3027 if (oldText == null) { 3028 toolTipManager.registerComponent(this); 3029 } 3030 } else { 3031 toolTipManager.unregisterComponent(this); 3032 } 3033 } 3034 3035 /** 3036 * Returns the tooltip string that has been set with 3037 * <code>setToolTipText</code>. 3038 * 3039 * @return the text of the tool tip 3040 * @see #TOOL_TIP_TEXT_KEY 3041 */ 3042 public String getToolTipText() { 3043 return (String)getClientProperty(TOOL_TIP_TEXT_KEY); 3044 } 3045 3046 3047 /** 3048 * Returns the string to be used as the tooltip for <i>event</i>. 3049 * By default this returns any string set using 3050 * <code>setToolTipText</code>. If a component provides 3051 * more extensive API to support differing tooltips at different locations, 3052 * this method should be overridden. 3053 * 3054 * @param event the {@code MouseEvent} that initiated the 3055 * {@code ToolTip} display 3056 * @return a string containing the tooltip 3057 */ 3058 public String getToolTipText(MouseEvent event) { 3059 return getToolTipText(); 3060 } 3061 3062 /** 3063 * Returns the tooltip location in this component's coordinate system. 3064 * If <code>null</code> is returned, Swing will choose a location. 3065 * The default implementation returns <code>null</code>. 3066 * 3067 * @param event the <code>MouseEvent</code> that caused the 3068 * <code>ToolTipManager</code> to show the tooltip 3069 * @return always returns <code>null</code> 3070 */ 3071 public Point getToolTipLocation(MouseEvent event) { 3072 return null; 3073 } 3074 3075 /** 3076 * Returns the preferred location to display the popup menu in this 3077 * component's coordinate system. It is up to the look and feel to 3078 * honor this property, some may choose to ignore it. 3079 * If {@code null}, the look and feel will choose a suitable location. 3080 * 3081 * @param event the {@code MouseEvent} that triggered the popup to be 3082 * shown, or {@code null} if the popup is not being shown as the 3083 * result of a mouse event 3084 * @return location to display the {@code JPopupMenu}, or {@code null} 3085 * @since 1.5 3086 */ 3087 public Point getPopupLocation(MouseEvent event) { 3088 return null; 3089 } 3090 3091 3092 /** 3093 * Returns the instance of <code>JToolTip</code> that should be used 3094 * to display the tooltip. 3095 * Components typically would not override this method, 3096 * but it can be used to 3097 * cause different tooltips to be displayed differently. 3098 * 3099 * @return the <code>JToolTip</code> used to display this toolTip 3100 */ 3101 public JToolTip createToolTip() { 3102 JToolTip tip = new JToolTip(); 3103 tip.setComponent(this); 3104 return tip; 3105 } 3106 3107 /** 3108 * Forwards the <code>scrollRectToVisible()</code> message to the 3109 * <code>JComponent</code>'s parent. Components that can service 3110 * the request, such as <code>JViewport</code>, 3111 * override this method and perform the scrolling. 3112 * 3113 * @param aRect the visible <code>Rectangle</code> 3114 * @see JViewport 3115 */ 3116 public void scrollRectToVisible(Rectangle aRect) { 3117 Container parent; 3118 int dx = getX(), dy = getY(); 3119 3120 for (parent = getParent(); 3121 !(parent == null) && 3122 !(parent instanceof JComponent) && 3123 !(parent instanceof CellRendererPane); 3124 parent = parent.getParent()) { 3125 Rectangle bounds = parent.getBounds(); 3126 3127 dx += bounds.x; 3128 dy += bounds.y; 3129 } 3130 3131 if (!(parent == null) && !(parent instanceof CellRendererPane)) { 3132 aRect.x += dx; 3133 aRect.y += dy; 3134 3135 ((JComponent)parent).scrollRectToVisible(aRect); 3136 aRect.x -= dx; 3137 aRect.y -= dy; 3138 } 3139 } 3140 3141 /** 3142 * Sets the <code>autoscrolls</code> property. 3143 * If <code>true</code> mouse dragged events will be 3144 * synthetically generated when the mouse is dragged 3145 * outside of the component's bounds and mouse motion 3146 * has paused (while the button continues to be held 3147 * down). The synthetic events make it appear that the 3148 * drag gesture has resumed in the direction established when 3149 * the component's boundary was crossed. Components that 3150 * support autoscrolling must handle <code>mouseDragged</code> 3151 * events by calling <code>scrollRectToVisible</code> with a 3152 * rectangle that contains the mouse event's location. All of 3153 * the Swing components that support item selection and are 3154 * typically displayed in a <code>JScrollPane</code> 3155 * (<code>JTable</code>, <code>JList</code>, <code>JTree</code>, 3156 * <code>JTextArea</code>, and <code>JEditorPane</code>) 3157 * already handle mouse dragged events in this way. To enable 3158 * autoscrolling in any other component, add a mouse motion 3159 * listener that calls <code>scrollRectToVisible</code>. 3160 * For example, given a <code>JPanel</code>, <code>myPanel</code>: 3161 * <pre> 3162 * MouseMotionListener doScrollRectToVisible = new MouseMotionAdapter() { 3163 * public void mouseDragged(MouseEvent e) { 3164 * Rectangle r = new Rectangle(e.getX(), e.getY(), 1, 1); 3165 * ((JPanel)e.getSource()).scrollRectToVisible(r); 3166 * } 3167 * }; 3168 * myPanel.addMouseMotionListener(doScrollRectToVisible); 3169 * </pre> 3170 * The default value of the <code>autoScrolls</code> 3171 * property is <code>false</code>. 3172 * 3173 * @param autoscrolls if true, synthetic mouse dragged events 3174 * are generated when the mouse is dragged outside of a component's 3175 * bounds and the mouse button continues to be held down; otherwise 3176 * false 3177 * @see #getAutoscrolls 3178 * @see JViewport 3179 * @see JScrollPane 3180 * 3181 * @beaninfo 3182 * expert: true 3183 * description: Determines if this component automatically scrolls its contents when dragged. 3184 */ 3185 public void setAutoscrolls(boolean autoscrolls) { 3186 setFlag(AUTOSCROLLS_SET, true); 3187 if (this.autoscrolls != autoscrolls) { 3188 this.autoscrolls = autoscrolls; 3189 if (autoscrolls) { 3190 enableEvents(AWTEvent.MOUSE_EVENT_MASK); 3191 enableEvents(AWTEvent.MOUSE_MOTION_EVENT_MASK); 3192 } 3193 else { 3194 Autoscroller.stop(this); 3195 } 3196 } 3197 } 3198 3199 /** 3200 * Gets the <code>autoscrolls</code> property. 3201 * 3202 * @return the value of the <code>autoscrolls</code> property 3203 * @see JViewport 3204 * @see #setAutoscrolls 3205 */ 3206 public boolean getAutoscrolls() { 3207 return autoscrolls; 3208 } 3209 3210 /** 3211 * Sets the {@code TransferHandler}, which provides support for transfer 3212 * of data into and out of this component via cut/copy/paste and drag 3213 * and drop. This may be {@code null} if the component does not support 3214 * data transfer operations. 3215 * <p> 3216 * If the new {@code TransferHandler} is not {@code null}, this method 3217 * also installs a <b>new</b> {@code DropTarget} on the component to 3218 * activate drop handling through the {@code TransferHandler} and activate 3219 * any built-in support (such as calculating and displaying potential drop 3220 * locations). If you do not wish for this component to respond in any way 3221 * to drops, you can disable drop support entirely either by removing the 3222 * drop target ({@code setDropTarget(null)}) or by de-activating it 3223 * ({@code getDropTaget().setActive(false)}). 3224 * <p> 3225 * If the new {@code TransferHandler} is {@code null}, this method removes 3226 * the drop target. 3227 * <p> 3228 * Under two circumstances, this method does not modify the drop target: 3229 * First, if the existing drop target on this component was explicitly 3230 * set by the developer to a {@code non-null} value. Second, if the 3231 * system property {@code suppressSwingDropSupport} is {@code true}. The 3232 * default value for the system property is {@code false}. 3233 * <p> 3234 * Please see 3235 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/dnd/index.html"> 3236 * How to Use Drag and Drop and Data Transfer</a>, 3237 * a section in <em>The Java Tutorial</em>, for more information. 3238 * 3239 * @param newHandler the new {@code TransferHandler} 3240 * 3241 * @see TransferHandler 3242 * @see #getTransferHandler 3243 * @since 1.4 3244 * @beaninfo 3245 * bound: true 3246 * hidden: true 3247 * description: Mechanism for transfer of data to and from the component 3248 */ 3249 public void setTransferHandler(TransferHandler newHandler) { 3250 TransferHandler oldHandler = (TransferHandler)getClientProperty( 3251 JComponent_TRANSFER_HANDLER); 3252 putClientProperty(JComponent_TRANSFER_HANDLER, newHandler); 3253 3254 SwingUtilities.installSwingDropTargetAsNecessary(this, newHandler); 3255 firePropertyChange("transferHandler", oldHandler, newHandler); 3256 } 3257 3258 /** 3259 * Gets the <code>transferHandler</code> property. 3260 * 3261 * @return the value of the <code>transferHandler</code> property 3262 * 3263 * @see TransferHandler 3264 * @see #setTransferHandler 3265 * @since 1.4 3266 */ 3267 public TransferHandler getTransferHandler() { 3268 return (TransferHandler)getClientProperty(JComponent_TRANSFER_HANDLER); 3269 } 3270 3271 /** 3272 * Calculates a custom drop location for this type of component, 3273 * representing where a drop at the given point should insert data. 3274 * <code>null</code> is returned if this component doesn't calculate 3275 * custom drop locations. In this case, <code>TransferHandler</code> 3276 * will provide a default <code>DropLocation</code> containing just 3277 * the point. 3278 * 3279 * @param p the point to calculate a drop location for 3280 * @return the drop location, or <code>null</code> 3281 */ 3282 TransferHandler.DropLocation dropLocationForPoint(Point p) { 3283 return null; 3284 } 3285 3286 /** 3287 * Called to set or clear the drop location during a DnD operation. 3288 * In some cases, the component may need to use its internal selection 3289 * temporarily to indicate the drop location. To help facilitate this, 3290 * this method returns and accepts as a parameter a state object. 3291 * This state object can be used to store, and later restore, the selection 3292 * state. Whatever this method returns will be passed back to it in 3293 * future calls, as the state parameter. If it wants the DnD system to 3294 * continue storing the same state, it must pass it back every time. 3295 * Here's how this is used: 3296 * <p> 3297 * Let's say that on the first call to this method the component decides 3298 * to save some state (because it is about to use the selection to show 3299 * a drop index). It can return a state object to the caller encapsulating 3300 * any saved selection state. On a second call, let's say the drop location 3301 * is being changed to something else. The component doesn't need to 3302 * restore anything yet, so it simply passes back the same state object 3303 * to have the DnD system continue storing it. Finally, let's say this 3304 * method is messaged with <code>null</code>. This means DnD 3305 * is finished with this component for now, meaning it should restore 3306 * state. At this point, it can use the state parameter to restore 3307 * said state, and of course return <code>null</code> since there's 3308 * no longer anything to store. 3309 * 3310 * @param location the drop location (as calculated by 3311 * <code>dropLocationForPoint</code>) or <code>null</code> 3312 * if there's no longer a valid drop location 3313 * @param state the state object saved earlier for this component, 3314 * or <code>null</code> 3315 * @param forDrop whether or not the method is being called because an 3316 * actual drop occurred 3317 * @return any saved state for this component, or <code>null</code> if none 3318 */ 3319 Object setDropLocation(TransferHandler.DropLocation location, 3320 Object state, 3321 boolean forDrop) { 3322 3323 return null; 3324 } 3325 3326 /** 3327 * Called to indicate to this component that DnD is done. 3328 * Needed by <code>JTree</code>. 3329 */ 3330 void dndDone() { 3331 } 3332 3333 /** 3334 * Processes mouse events occurring on this component by 3335 * dispatching them to any registered 3336 * <code>MouseListener</code> objects, refer to 3337 * {@link java.awt.Component#processMouseEvent(MouseEvent)} 3338 * for a complete description of this method. 3339 * 3340 * @param e the mouse event 3341 * @see java.awt.Component#processMouseEvent 3342 * @since 1.5 3343 */ 3344 protected void processMouseEvent(MouseEvent e) { 3345 if (autoscrolls && e.getID() == MouseEvent.MOUSE_RELEASED) { 3346 Autoscroller.stop(this); 3347 } 3348 super.processMouseEvent(e); 3349 } 3350 3351 /** 3352 * Processes mouse motion events, such as MouseEvent.MOUSE_DRAGGED. 3353 * 3354 * @param e the <code>MouseEvent</code> 3355 * @see MouseEvent 3356 */ 3357 protected void processMouseMotionEvent(MouseEvent e) { 3358 boolean dispatch = true; 3359 if (autoscrolls && e.getID() == MouseEvent.MOUSE_DRAGGED) { 3360 // We don't want to do the drags when the mouse moves if we're 3361 // autoscrolling. It makes it feel spastic. 3362 dispatch = !Autoscroller.isRunning(this); 3363 Autoscroller.processMouseDragged(e); 3364 } 3365 if (dispatch) { 3366 super.processMouseMotionEvent(e); 3367 } 3368 } 3369 3370 // Inner classes can't get at this method from a super class 3371 void superProcessMouseMotionEvent(MouseEvent e) { 3372 super.processMouseMotionEvent(e); 3373 } 3374 3375 /** 3376 * This is invoked by the <code>RepaintManager</code> if 3377 * <code>createImage</code> is called on the component. 3378 * 3379 * @param newValue true if the double buffer image was created from this component 3380 */ 3381 void setCreatedDoubleBuffer(boolean newValue) { 3382 setFlag(CREATED_DOUBLE_BUFFER, newValue); 3383 } 3384 3385 /** 3386 * Returns true if the <code>RepaintManager</code> 3387 * created the double buffer image from the component. 3388 * 3389 * @return true if this component had a double buffer image, false otherwise 3390 */ 3391 boolean getCreatedDoubleBuffer() { 3392 return getFlag(CREATED_DOUBLE_BUFFER); 3393 } 3394 3395 /** 3396 * <code>ActionStandin</code> is used as a standin for 3397 * <code>ActionListeners</code> that are 3398 * added via <code>registerKeyboardAction</code>. 3399 */ 3400 final class ActionStandin implements Action { 3401 private final ActionListener actionListener; 3402 private final String command; 3403 // This will be non-null if actionListener is an Action. 3404 private final Action action; 3405 3406 ActionStandin(ActionListener actionListener, String command) { 3407 this.actionListener = actionListener; 3408 if (actionListener instanceof Action) { 3409 this.action = (Action)actionListener; 3410 } 3411 else { 3412 this.action = null; 3413 } 3414 this.command = command; 3415 } 3416 3417 public Object getValue(String key) { 3418 if (key != null) { 3419 if (key.equals(Action.ACTION_COMMAND_KEY)) { 3420 return command; 3421 } 3422 if (action != null) { 3423 return action.getValue(key); 3424 } 3425 if (key.equals(NAME)) { 3426 return "ActionStandin"; 3427 } 3428 } 3429 return null; 3430 } 3431 3432 public boolean isEnabled() { 3433 if (actionListener == null) { 3434 // This keeps the old semantics where 3435 // registerKeyboardAction(null) would essentialy remove 3436 // the binding. We don't remove the binding from the 3437 // InputMap as that would still allow parent InputMaps 3438 // bindings to be accessed. 3439 return false; 3440 } 3441 if (action == null) { 3442 return true; 3443 } 3444 return action.isEnabled(); 3445 } 3446 3447 public void actionPerformed(ActionEvent ae) { 3448 if (actionListener != null) { 3449 actionListener.actionPerformed(ae); 3450 } 3451 } 3452 3453 // We don't allow any values to be added. 3454 public void putValue(String key, Object value) {} 3455 3456 // Does nothing, our enabledness is determiend from our asociated 3457 // action. 3458 public void setEnabled(boolean b) { } 3459 3460 public void addPropertyChangeListener 3461 (PropertyChangeListener listener) {} 3462 public void removePropertyChangeListener 3463 (PropertyChangeListener listener) {} 3464 } 3465 3466 3467 // This class is used by the KeyboardState class to provide a single 3468 // instance that can be stored in the AppContext. 3469 static final class IntVector { 3470 int array[] = null; 3471 int count = 0; 3472 int capacity = 0; 3473 3474 int size() { 3475 return count; 3476 } 3477 3478 int elementAt(int index) { 3479 return array[index]; 3480 } 3481 3482 void addElement(int value) { 3483 if (count == capacity) { 3484 capacity = (capacity + 2) * 2; 3485 int[] newarray = new int[capacity]; 3486 if (count > 0) { 3487 System.arraycopy(array, 0, newarray, 0, count); 3488 } 3489 array = newarray; 3490 } 3491 array[count++] = value; 3492 } 3493 3494 void setElementAt(int value, int index) { 3495 array[index] = value; 3496 } 3497 } 3498 3499 @SuppressWarnings("serial") 3500 static class KeyboardState implements Serializable { 3501 private static final Object keyCodesKey = 3502 JComponent.KeyboardState.class; 3503 3504 // Get the array of key codes from the AppContext. 3505 static IntVector getKeyCodeArray() { 3506 IntVector iv = 3507 (IntVector)SwingUtilities.appContextGet(keyCodesKey); 3508 if (iv == null) { 3509 iv = new IntVector(); 3510 SwingUtilities.appContextPut(keyCodesKey, iv); 3511 } 3512 return iv; 3513 } 3514 3515 static void registerKeyPressed(int keyCode) { 3516 IntVector kca = getKeyCodeArray(); 3517 int count = kca.size(); 3518 int i; 3519 for(i=0;i<count;i++) { 3520 if(kca.elementAt(i) == -1){ 3521 kca.setElementAt(keyCode, i); 3522 return; 3523 } 3524 } 3525 kca.addElement(keyCode); 3526 } 3527 3528 static void registerKeyReleased(int keyCode) { 3529 IntVector kca = getKeyCodeArray(); 3530 int count = kca.size(); 3531 int i; 3532 for(i=0;i<count;i++) { 3533 if(kca.elementAt(i) == keyCode) { 3534 kca.setElementAt(-1, i); 3535 return; 3536 } 3537 } 3538 } 3539 3540 static boolean keyIsPressed(int keyCode) { 3541 IntVector kca = getKeyCodeArray(); 3542 int count = kca.size(); 3543 int i; 3544 for(i=0;i<count;i++) { 3545 if(kca.elementAt(i) == keyCode) { 3546 return true; 3547 } 3548 } 3549 return false; 3550 } 3551 3552 /** 3553 * Updates internal state of the KeyboardState and returns true 3554 * if the event should be processed further. 3555 */ 3556 static boolean shouldProcess(KeyEvent e) { 3557 switch (e.getID()) { 3558 case KeyEvent.KEY_PRESSED: 3559 if (!keyIsPressed(e.getKeyCode())) { 3560 registerKeyPressed(e.getKeyCode()); 3561 } 3562 return true; 3563 case KeyEvent.KEY_RELEASED: 3564 // We are forced to process VK_PRINTSCREEN separately because 3565 // the Windows doesn't generate the key pressed event for 3566 // printscreen and it block the processing of key release 3567 // event for printscreen. 3568 if (keyIsPressed(e.getKeyCode()) || e.getKeyCode()==KeyEvent.VK_PRINTSCREEN) { 3569 registerKeyReleased(e.getKeyCode()); 3570 return true; 3571 } 3572 return false; 3573 case KeyEvent.KEY_TYPED: 3574 return true; 3575 default: 3576 // Not a known KeyEvent type, bail. 3577 return false; 3578 } 3579 } 3580 } 3581 3582 static final sun.awt.RequestFocusController focusController = 3583 new sun.awt.RequestFocusController() { 3584 public boolean acceptRequestFocus(Component from, Component to, 3585 boolean temporary, boolean focusedWindowChangeAllowed, 3586 sun.awt.CausedFocusEvent.Cause cause) 3587 { 3588 if ((to == null) || !(to instanceof JComponent)) { 3589 return true; 3590 } 3591 3592 if ((from == null) || !(from instanceof JComponent)) { 3593 return true; 3594 } 3595 3596 JComponent target = (JComponent) to; 3597 if (!target.getVerifyInputWhenFocusTarget()) { 3598 return true; 3599 } 3600 3601 JComponent jFocusOwner = (JComponent)from; 3602 InputVerifier iv = jFocusOwner.getInputVerifier(); 3603 3604 if (iv == null) { 3605 return true; 3606 } else { 3607 Object currentSource = SwingUtilities.appContextGet( 3608 INPUT_VERIFIER_SOURCE_KEY); 3609 if (currentSource == jFocusOwner) { 3610 // We're currently calling into the InputVerifier 3611 // for this component, so allow the focus change. 3612 return true; 3613 } 3614 SwingUtilities.appContextPut(INPUT_VERIFIER_SOURCE_KEY, 3615 jFocusOwner); 3616 try { 3617 return iv.shouldYieldFocus(jFocusOwner); 3618 } finally { 3619 if (currentSource != null) { 3620 // We're already in the InputVerifier for 3621 // currentSource. By resetting the currentSource 3622 // we ensure that if the InputVerifier for 3623 // currentSource does a requestFocus, we don't 3624 // try and run the InputVerifier again. 3625 SwingUtilities.appContextPut( 3626 INPUT_VERIFIER_SOURCE_KEY, currentSource); 3627 } else { 3628 SwingUtilities.appContextRemove( 3629 INPUT_VERIFIER_SOURCE_KEY); 3630 } 3631 } 3632 } 3633 } 3634 }; 3635 3636 /* 3637 * --- Accessibility Support --- 3638 */ 3639 3640 /** 3641 * @deprecated As of JDK version 1.1, 3642 * replaced by <code>java.awt.Component.setEnabled(boolean)</code>. 3643 */ 3644 @Deprecated 3645 public void enable() { 3646 if (isEnabled() != true) { 3647 super.enable(); 3648 if (accessibleContext != null) { 3649 accessibleContext.firePropertyChange( 3650 AccessibleContext.ACCESSIBLE_STATE_PROPERTY, 3651 null, AccessibleState.ENABLED); 3652 } 3653 } 3654 } 3655 3656 /** 3657 * @deprecated As of JDK version 1.1, 3658 * replaced by <code>java.awt.Component.setEnabled(boolean)</code>. 3659 */ 3660 @Deprecated 3661 public void disable() { 3662 if (isEnabled() != false) { 3663 super.disable(); 3664 if (accessibleContext != null) { 3665 accessibleContext.firePropertyChange( 3666 AccessibleContext.ACCESSIBLE_STATE_PROPERTY, 3667 AccessibleState.ENABLED, null); 3668 } 3669 } 3670 } 3671 3672 /** 3673 * Inner class of JComponent used to provide default support for 3674 * accessibility. This class is not meant to be used directly by 3675 * application developers, but is instead meant only to be 3676 * subclassed by component developers. 3677 * <p> 3678 * <strong>Warning:</strong> 3679 * Serialized objects of this class will not be compatible with 3680 * future Swing releases. The current serialization support is 3681 * appropriate for short term storage or RMI between applications running 3682 * the same version of Swing. As of 1.4, support for long term storage 3683 * of all JavaBeans™ 3684 * has been added to the <code>java.beans</code> package. 3685 * Please see {@link java.beans.XMLEncoder}. 3686 */ 3687 @SuppressWarnings("serial") // Same-version serialization only 3688 public abstract class AccessibleJComponent extends AccessibleAWTContainer 3689 implements AccessibleExtendedComponent 3690 { 3691 /** 3692 * Though the class is abstract, this should be called by 3693 * all sub-classes. 3694 */ 3695 protected AccessibleJComponent() { 3696 super(); 3697 } 3698 3699 /** 3700 * Number of PropertyChangeListener objects registered. It's used 3701 * to add/remove ContainerListener and FocusListener to track 3702 * target JComponent's state 3703 */ 3704 private volatile transient int propertyListenersCount = 0; 3705 3706 /** 3707 * This field duplicates the function of the accessibleAWTFocusHandler field 3708 * in java.awt.Component.AccessibleAWTComponent, so it has been deprecated. 3709 */ 3710 @Deprecated 3711 protected FocusListener accessibleFocusHandler = null; 3712 3713 /** 3714 * Fire PropertyChange listener, if one is registered, 3715 * when children added/removed. 3716 */ 3717 protected class AccessibleContainerHandler 3718 implements ContainerListener { 3719 public void componentAdded(ContainerEvent e) { 3720 Component c = e.getChild(); 3721 if (c != null && c instanceof Accessible) { 3722 AccessibleJComponent.this.firePropertyChange( 3723 AccessibleContext.ACCESSIBLE_CHILD_PROPERTY, 3724 null, c.getAccessibleContext()); 3725 } 3726 } 3727 public void componentRemoved(ContainerEvent e) { 3728 Component c = e.getChild(); 3729 if (c != null && c instanceof Accessible) { 3730 AccessibleJComponent.this.firePropertyChange( 3731 AccessibleContext.ACCESSIBLE_CHILD_PROPERTY, 3732 c.getAccessibleContext(), null); 3733 } 3734 } 3735 } 3736 3737 /** 3738 * Fire PropertyChange listener, if one is registered, 3739 * when focus events happen 3740 * @since 1.3 3741 */ 3742 protected class AccessibleFocusHandler implements FocusListener { 3743 public void focusGained(FocusEvent event) { 3744 if (accessibleContext != null) { 3745 accessibleContext.firePropertyChange( 3746 AccessibleContext.ACCESSIBLE_STATE_PROPERTY, 3747 null, AccessibleState.FOCUSED); 3748 } 3749 } 3750 public void focusLost(FocusEvent event) { 3751 if (accessibleContext != null) { 3752 accessibleContext.firePropertyChange( 3753 AccessibleContext.ACCESSIBLE_STATE_PROPERTY, 3754 AccessibleState.FOCUSED, null); 3755 } 3756 } 3757 } // inner class AccessibleFocusHandler 3758 3759 3760 /** 3761 * Adds a PropertyChangeListener to the listener list. 3762 * 3763 * @param listener the PropertyChangeListener to be added 3764 */ 3765 public void addPropertyChangeListener(PropertyChangeListener listener) { 3766 super.addPropertyChangeListener(listener); 3767 } 3768 3769 /** 3770 * Removes a PropertyChangeListener from the listener list. 3771 * This removes a PropertyChangeListener that was registered 3772 * for all properties. 3773 * 3774 * @param listener the PropertyChangeListener to be removed 3775 */ 3776 public void removePropertyChangeListener(PropertyChangeListener listener) { 3777 super.removePropertyChangeListener(listener); 3778 } 3779 3780 3781 3782 /** 3783 * Recursively search through the border hierarchy (if it exists) 3784 * for a TitledBorder with a non-null title. This does a depth 3785 * first search on first the inside borders then the outside borders. 3786 * The assumption is that titles make really pretty inside borders 3787 * but not very pretty outside borders in compound border situations. 3788 * It's rather arbitrary, but hopefully decent UI programmers will 3789 * not create multiple titled borders for the same component. 3790 * 3791 * @param b the {@code Border} for which to retrieve its title 3792 * @return the border's title as a {@code String}, null if it has 3793 * no title 3794 */ 3795 protected String getBorderTitle(Border b) { 3796 String s; 3797 if (b instanceof TitledBorder) { 3798 return ((TitledBorder) b).getTitle(); 3799 } else if (b instanceof CompoundBorder) { 3800 s = getBorderTitle(((CompoundBorder) b).getInsideBorder()); 3801 if (s == null) { 3802 s = getBorderTitle(((CompoundBorder) b).getOutsideBorder()); 3803 } 3804 return s; 3805 } else { 3806 return null; 3807 } 3808 } 3809 3810 // AccessibleContext methods 3811 // 3812 /** 3813 * Gets the accessible name of this object. This should almost never 3814 * return java.awt.Component.getName(), as that generally isn't 3815 * a localized name, and doesn't have meaning for the user. If the 3816 * object is fundamentally a text object (such as a menu item), the 3817 * accessible name should be the text of the object (for example, 3818 * "save"). 3819 * If the object has a tooltip, the tooltip text may also be an 3820 * appropriate String to return. 3821 * 3822 * @return the localized name of the object -- can be null if this 3823 * object does not have a name 3824 * @see AccessibleContext#setAccessibleName 3825 */ 3826 public String getAccessibleName() { 3827 String name = accessibleName; 3828 3829 // fallback to the client name property 3830 // 3831 if (name == null) { 3832 name = (String)getClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY); 3833 } 3834 3835 // fallback to the titled border if it exists 3836 // 3837 if (name == null) { 3838 name = getBorderTitle(getBorder()); 3839 } 3840 3841 // fallback to the label labeling us if it exists 3842 // 3843 if (name == null) { 3844 Object o = getClientProperty(JLabel.LABELED_BY_PROPERTY); 3845 if (o instanceof Accessible) { 3846 AccessibleContext ac = ((Accessible) o).getAccessibleContext(); 3847 if (ac != null) { 3848 name = ac.getAccessibleName(); 3849 } 3850 } 3851 } 3852 return name; 3853 } 3854 3855 /** 3856 * Gets the accessible description of this object. This should be 3857 * a concise, localized description of what this object is - what 3858 * is its meaning to the user. If the object has a tooltip, the 3859 * tooltip text may be an appropriate string to return, assuming 3860 * it contains a concise description of the object (instead of just 3861 * the name of the object - for example a "Save" icon on a toolbar that 3862 * had "save" as the tooltip text shouldn't return the tooltip 3863 * text as the description, but something like "Saves the current 3864 * text document" instead). 3865 * 3866 * @return the localized description of the object -- can be null if 3867 * this object does not have a description 3868 * @see AccessibleContext#setAccessibleDescription 3869 */ 3870 public String getAccessibleDescription() { 3871 String description = accessibleDescription; 3872 3873 // fallback to the client description property 3874 // 3875 if (description == null) { 3876 description = (String)getClientProperty(AccessibleContext.ACCESSIBLE_DESCRIPTION_PROPERTY); 3877 } 3878 3879 // fallback to the tool tip text if it exists 3880 // 3881 if (description == null) { 3882 try { 3883 description = getToolTipText(); 3884 } catch (Exception e) { 3885 // Just in case the subclass overrode the 3886 // getToolTipText method and actually 3887 // requires a MouseEvent. 3888 // [[[FIXME: WDW - we probably should require this 3889 // method to take a MouseEvent and just pass it on 3890 // to getToolTipText. The swing-feedback traffic 3891 // leads me to believe getToolTipText might change, 3892 // though, so I was hesitant to make this change at 3893 // this time.]]] 3894 } 3895 } 3896 3897 // fallback to the label labeling us if it exists 3898 // 3899 if (description == null) { 3900 Object o = getClientProperty(JLabel.LABELED_BY_PROPERTY); 3901 if (o instanceof Accessible) { 3902 AccessibleContext ac = ((Accessible) o).getAccessibleContext(); 3903 if (ac != null) { 3904 description = ac.getAccessibleDescription(); 3905 } 3906 } 3907 } 3908 3909 return description; 3910 } 3911 3912 /** 3913 * Gets the role of this object. 3914 * 3915 * @return an instance of AccessibleRole describing the role of the 3916 * object 3917 * @see AccessibleRole 3918 */ 3919 public AccessibleRole getAccessibleRole() { 3920 return AccessibleRole.SWING_COMPONENT; 3921 } 3922 3923 /** 3924 * Gets the state of this object. 3925 * 3926 * @return an instance of AccessibleStateSet containing the current 3927 * state set of the object 3928 * @see AccessibleState 3929 */ 3930 public AccessibleStateSet getAccessibleStateSet() { 3931 AccessibleStateSet states = super.getAccessibleStateSet(); 3932 if (JComponent.this.isOpaque()) { 3933 states.add(AccessibleState.OPAQUE); 3934 } 3935 return states; 3936 } 3937 3938 /** 3939 * Returns the number of accessible children in the object. If all 3940 * of the children of this object implement Accessible, than this 3941 * method should return the number of children of this object. 3942 * 3943 * @return the number of accessible children in the object. 3944 */ 3945 public int getAccessibleChildrenCount() { 3946 return super.getAccessibleChildrenCount(); 3947 } 3948 3949 /** 3950 * Returns the nth Accessible child of the object. 3951 * 3952 * @param i zero-based index of child 3953 * @return the nth Accessible child of the object 3954 */ 3955 public Accessible getAccessibleChild(int i) { 3956 return super.getAccessibleChild(i); 3957 } 3958 3959 // ----- AccessibleExtendedComponent 3960 3961 /** 3962 * Returns the AccessibleExtendedComponent 3963 * 3964 * @return the AccessibleExtendedComponent 3965 */ 3966 AccessibleExtendedComponent getAccessibleExtendedComponent() { 3967 return this; 3968 } 3969 3970 /** 3971 * Returns the tool tip text 3972 * 3973 * @return the tool tip text, if supported, of the object; 3974 * otherwise, null 3975 * @since 1.4 3976 */ 3977 public String getToolTipText() { 3978 return JComponent.this.getToolTipText(); 3979 } 3980 3981 /** 3982 * Returns the titled border text 3983 * 3984 * @return the titled border text, if supported, of the object; 3985 * otherwise, null 3986 * @since 1.4 3987 */ 3988 public String getTitledBorderText() { 3989 Border border = JComponent.this.getBorder(); 3990 if (border instanceof TitledBorder) { 3991 return ((TitledBorder)border).getTitle(); 3992 } else { 3993 return null; 3994 } 3995 } 3996 3997 /** 3998 * Returns key bindings associated with this object 3999 * 4000 * @return the key bindings, if supported, of the object; 4001 * otherwise, null 4002 * @see AccessibleKeyBinding 4003 * @since 1.4 4004 */ 4005 public AccessibleKeyBinding getAccessibleKeyBinding(){ 4006 // Try to get the linked label's mnemonic if it exists 4007 Object o = getClientProperty(JLabel.LABELED_BY_PROPERTY); 4008 if (o instanceof Accessible){ 4009 AccessibleContext ac = ((Accessible) o).getAccessibleContext(); 4010 if (ac != null){ 4011 AccessibleComponent comp = ac.getAccessibleComponent(); 4012 if (! (comp instanceof AccessibleExtendedComponent)) 4013 return null; 4014 return ((AccessibleExtendedComponent)comp).getAccessibleKeyBinding(); 4015 } 4016 } 4017 return null; 4018 } 4019 } // inner class AccessibleJComponent 4020 4021 4022 /** 4023 * Returns an <code>ArrayTable</code> used for 4024 * key/value "client properties" for this component. If the 4025 * <code>clientProperties</code> table doesn't exist, an empty one 4026 * will be created. 4027 * 4028 * @return an ArrayTable 4029 * @see #putClientProperty 4030 * @see #getClientProperty 4031 */ 4032 private ArrayTable getClientProperties() { 4033 if (clientProperties == null) { 4034 clientProperties = new ArrayTable(); 4035 } 4036 return clientProperties; 4037 } 4038 4039 4040 /** 4041 * Returns the value of the property with the specified key. Only 4042 * properties added with <code>putClientProperty</code> will return 4043 * a non-<code>null</code> value. 4044 * 4045 * @param key the being queried 4046 * @return the value of this property or <code>null</code> 4047 * @see #putClientProperty 4048 */ 4049 public final Object getClientProperty(Object key) { 4050 if (key == SwingUtilities2.AA_TEXT_PROPERTY_KEY) { 4051 return aaTextInfo; 4052 } else if (key == SwingUtilities2.COMPONENT_UI_PROPERTY_KEY) { 4053 return ui; 4054 } 4055 if(clientProperties == null) { 4056 return null; 4057 } else { 4058 synchronized(clientProperties) { 4059 return clientProperties.get(key); 4060 } 4061 } 4062 } 4063 4064 /** 4065 * Adds an arbitrary key/value "client property" to this component. 4066 * <p> 4067 * The <code>get/putClientProperty</code> methods provide access to 4068 * a small per-instance hashtable. Callers can use get/putClientProperty 4069 * to annotate components that were created by another module. 4070 * For example, a 4071 * layout manager might store per child constraints this way. For example: 4072 * <pre> 4073 * componentA.putClientProperty("to the left of", componentB); 4074 * </pre> 4075 * If value is <code>null</code> this method will remove the property. 4076 * Changes to client properties are reported with 4077 * <code>PropertyChange</code> events. 4078 * The name of the property (for the sake of PropertyChange 4079 * events) is <code>key.toString()</code>. 4080 * <p> 4081 * The <code>clientProperty</code> dictionary is not intended to 4082 * support large 4083 * scale extensions to JComponent nor should be it considered an 4084 * alternative to subclassing when designing a new component. 4085 * 4086 * @param key the new client property key 4087 * @param value the new client property value; if <code>null</code> 4088 * this method will remove the property 4089 * @see #getClientProperty 4090 * @see #addPropertyChangeListener 4091 */ 4092 public final void putClientProperty(Object key, Object value) { 4093 if (key == SwingUtilities2.AA_TEXT_PROPERTY_KEY) { 4094 aaTextInfo = value; 4095 return; 4096 } 4097 if (value == null && clientProperties == null) { 4098 // Both the value and ArrayTable are null, implying we don't 4099 // have to do anything. 4100 return; 4101 } 4102 ArrayTable clientProperties = getClientProperties(); 4103 Object oldValue; 4104 synchronized(clientProperties) { 4105 oldValue = clientProperties.get(key); 4106 if (value != null) { 4107 clientProperties.put(key, value); 4108 } else if (oldValue != null) { 4109 clientProperties.remove(key); 4110 } else { 4111 // old == new == null 4112 return; 4113 } 4114 } 4115 clientPropertyChanged(key, oldValue, value); 4116 firePropertyChange(key.toString(), oldValue, value); 4117 } 4118 4119 // Invoked from putClientProperty. This is provided for subclasses 4120 // in Swing. 4121 void clientPropertyChanged(Object key, Object oldValue, 4122 Object newValue) { 4123 } 4124 4125 4126 /* 4127 * Sets the property with the specified name to the specified value if 4128 * the property has not already been set by the client program. 4129 * This method is used primarily to set UI defaults for properties 4130 * with primitive types, where the values cannot be marked with 4131 * UIResource. 4132 * @see LookAndFeel#installProperty 4133 * @param propertyName String containing the name of the property 4134 * @param value Object containing the property value 4135 */ 4136 void setUIProperty(String propertyName, Object value) { 4137 if (propertyName == "opaque") { 4138 if (!getFlag(OPAQUE_SET)) { 4139 setOpaque(((Boolean)value).booleanValue()); 4140 setFlag(OPAQUE_SET, false); 4141 } 4142 } else if (propertyName == "autoscrolls") { 4143 if (!getFlag(AUTOSCROLLS_SET)) { 4144 setAutoscrolls(((Boolean)value).booleanValue()); 4145 setFlag(AUTOSCROLLS_SET, false); 4146 } 4147 } else if (propertyName == "focusTraversalKeysForward") { 4148 @SuppressWarnings("unchecked") 4149 Set<AWTKeyStroke> strokeSet = (Set<AWTKeyStroke>) value; 4150 if (!getFlag(FOCUS_TRAVERSAL_KEYS_FORWARD_SET)) { 4151 super.setFocusTraversalKeys(KeyboardFocusManager. 4152 FORWARD_TRAVERSAL_KEYS, 4153 strokeSet); 4154 } 4155 } else if (propertyName == "focusTraversalKeysBackward") { 4156 @SuppressWarnings("unchecked") 4157 Set<AWTKeyStroke> strokeSet = (Set<AWTKeyStroke>) value; 4158 if (!getFlag(FOCUS_TRAVERSAL_KEYS_BACKWARD_SET)) { 4159 super.setFocusTraversalKeys(KeyboardFocusManager. 4160 BACKWARD_TRAVERSAL_KEYS, 4161 strokeSet); 4162 } 4163 } else { 4164 throw new IllegalArgumentException("property \""+ 4165 propertyName+ "\" cannot be set using this method"); 4166 } 4167 } 4168 4169 4170 /** 4171 * Sets the focus traversal keys for a given traversal operation for this 4172 * Component. 4173 * Refer to 4174 * {@link java.awt.Component#setFocusTraversalKeys} 4175 * for a complete description of this method. 4176 * <p> 4177 * This method may throw a {@code ClassCastException} if any {@code Object} 4178 * in {@code keystrokes} is not an {@code AWTKeyStroke}. 4179 * 4180 * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, 4181 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, or 4182 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS 4183 * @param keystrokes the Set of AWTKeyStroke for the specified operation 4184 * @see java.awt.KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS 4185 * @see java.awt.KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS 4186 * @see java.awt.KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS 4187 * @throws IllegalArgumentException if id is not one of 4188 * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, 4189 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, or 4190 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or if keystrokes 4191 * contains null, or if any keystroke represents a KEY_TYPED event, 4192 * or if any keystroke already maps to another focus traversal 4193 * operation for this Component 4194 * @since 1.5 4195 * @beaninfo 4196 * bound: true 4197 */ 4198 public void 4199 setFocusTraversalKeys(int id, Set<? extends AWTKeyStroke> keystrokes) 4200 { 4201 if (id == KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS) { 4202 setFlag(FOCUS_TRAVERSAL_KEYS_FORWARD_SET,true); 4203 } else if (id == KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS) { 4204 setFlag(FOCUS_TRAVERSAL_KEYS_BACKWARD_SET,true); 4205 } 4206 super.setFocusTraversalKeys(id,keystrokes); 4207 } 4208 4209 /* --- Transitional java.awt.Component Support --- 4210 * The methods and fields in this section will migrate to 4211 * java.awt.Component in the next JDK release. 4212 */ 4213 4214 /** 4215 * Returns true if this component is lightweight, that is, if it doesn't 4216 * have a native window system peer. 4217 * 4218 * @param c the {@code Component} to be checked 4219 * @return true if this component is lightweight 4220 */ 4221 @SuppressWarnings("deprecation") 4222 public static boolean isLightweightComponent(Component c) { 4223 return c.getPeer() instanceof LightweightPeer; 4224 } 4225 4226 4227 /** 4228 * @deprecated As of JDK 5, 4229 * replaced by <code>Component.setBounds(int, int, int, int)</code>. 4230 * <p> 4231 * Moves and resizes this component. 4232 * 4233 * @param x the new horizontal location 4234 * @param y the new vertical location 4235 * @param w the new width 4236 * @param h the new height 4237 * @see java.awt.Component#setBounds 4238 */ 4239 @Deprecated 4240 public void reshape(int x, int y, int w, int h) { 4241 super.reshape(x, y, w, h); 4242 } 4243 4244 4245 /** 4246 * Stores the bounds of this component into "return value" 4247 * <code>rv</code> and returns <code>rv</code>. 4248 * If <code>rv</code> is <code>null</code> a new <code>Rectangle</code> 4249 * is allocated. This version of <code>getBounds</code> is useful 4250 * if the caller wants to avoid allocating a new <code>Rectangle</code> 4251 * object on the heap. 4252 * 4253 * @param rv the return value, modified to the component's bounds 4254 * @return <code>rv</code>; if <code>rv</code> is <code>null</code> 4255 * return a newly created <code>Rectangle</code> with this 4256 * component's bounds 4257 */ 4258 public Rectangle getBounds(Rectangle rv) { 4259 if (rv == null) { 4260 return new Rectangle(getX(), getY(), getWidth(), getHeight()); 4261 } 4262 else { 4263 rv.setBounds(getX(), getY(), getWidth(), getHeight()); 4264 return rv; 4265 } 4266 } 4267 4268 4269 /** 4270 * Stores the width/height of this component into "return value" 4271 * <code>rv</code> and returns <code>rv</code>. 4272 * If <code>rv</code> is <code>null</code> a new <code>Dimension</code> 4273 * object is allocated. This version of <code>getSize</code> 4274 * is useful if the caller wants to avoid allocating a new 4275 * <code>Dimension</code> object on the heap. 4276 * 4277 * @param rv the return value, modified to the component's size 4278 * @return <code>rv</code> 4279 */ 4280 public Dimension getSize(Dimension rv) { 4281 if (rv == null) { 4282 return new Dimension(getWidth(), getHeight()); 4283 } 4284 else { 4285 rv.setSize(getWidth(), getHeight()); 4286 return rv; 4287 } 4288 } 4289 4290 4291 /** 4292 * Stores the x,y origin of this component into "return value" 4293 * <code>rv</code> and returns <code>rv</code>. 4294 * If <code>rv</code> is <code>null</code> a new <code>Point</code> 4295 * is allocated. This version of <code>getLocation</code> is useful 4296 * if the caller wants to avoid allocating a new <code>Point</code> 4297 * object on the heap. 4298 * 4299 * @param rv the return value, modified to the component's location 4300 * @return <code>rv</code> 4301 */ 4302 public Point getLocation(Point rv) { 4303 if (rv == null) { 4304 return new Point(getX(), getY()); 4305 } 4306 else { 4307 rv.setLocation(getX(), getY()); 4308 return rv; 4309 } 4310 } 4311 4312 4313 /** 4314 * Returns the current x coordinate of the component's origin. 4315 * This method is preferable to writing 4316 * <code>component.getBounds().x</code>, or 4317 * <code>component.getLocation().x</code> because it doesn't cause any 4318 * heap allocations. 4319 * 4320 * @return the current x coordinate of the component's origin 4321 */ 4322 public int getX() { return super.getX(); } 4323 4324 4325 /** 4326 * Returns the current y coordinate of the component's origin. 4327 * This method is preferable to writing 4328 * <code>component.getBounds().y</code>, or 4329 * <code>component.getLocation().y</code> because it doesn't cause any 4330 * heap allocations. 4331 * 4332 * @return the current y coordinate of the component's origin 4333 */ 4334 public int getY() { return super.getY(); } 4335 4336 4337 /** 4338 * Returns the current width of this component. 4339 * This method is preferable to writing 4340 * <code>component.getBounds().width</code>, or 4341 * <code>component.getSize().width</code> because it doesn't cause any 4342 * heap allocations. 4343 * 4344 * @return the current width of this component 4345 */ 4346 public int getWidth() { return super.getWidth(); } 4347 4348 4349 /** 4350 * Returns the current height of this component. 4351 * This method is preferable to writing 4352 * <code>component.getBounds().height</code>, or 4353 * <code>component.getSize().height</code> because it doesn't cause any 4354 * heap allocations. 4355 * 4356 * @return the current height of this component 4357 */ 4358 public int getHeight() { return super.getHeight(); } 4359 4360 /** 4361 * Returns true if this component is completely opaque. 4362 * <p> 4363 * An opaque component paints every pixel within its 4364 * rectangular bounds. A non-opaque component paints only a subset of 4365 * its pixels or none at all, allowing the pixels underneath it to 4366 * "show through". Therefore, a component that does not fully paint 4367 * its pixels provides a degree of transparency. 4368 * <p> 4369 * Subclasses that guarantee to always completely paint their contents 4370 * should override this method and return true. 4371 * 4372 * @return true if this component is completely opaque 4373 * @see #setOpaque 4374 */ 4375 public boolean isOpaque() { 4376 return getFlag(IS_OPAQUE); 4377 } 4378 4379 /** 4380 * If true the component paints every pixel within its bounds. 4381 * Otherwise, the component may not paint some or all of its 4382 * pixels, allowing the underlying pixels to show through. 4383 * <p> 4384 * The default value of this property is false for <code>JComponent</code>. 4385 * However, the default value for this property on most standard 4386 * <code>JComponent</code> subclasses (such as <code>JButton</code> and 4387 * <code>JTree</code>) is look-and-feel dependent. 4388 * 4389 * @param isOpaque true if this component should be opaque 4390 * @see #isOpaque 4391 * @beaninfo 4392 * bound: true 4393 * expert: true 4394 * description: The component's opacity 4395 */ 4396 public void setOpaque(boolean isOpaque) { 4397 boolean oldValue = getFlag(IS_OPAQUE); 4398 setFlag(IS_OPAQUE, isOpaque); 4399 setFlag(OPAQUE_SET, true); 4400 firePropertyChange("opaque", oldValue, isOpaque); 4401 } 4402 4403 4404 /** 4405 * If the specified rectangle is completely obscured by any of this 4406 * component's opaque children then returns true. Only direct children 4407 * are considered, more distant descendants are ignored. A 4408 * <code>JComponent</code> is opaque if 4409 * <code>JComponent.isOpaque()</code> returns true, other lightweight 4410 * components are always considered transparent, and heavyweight components 4411 * are always considered opaque. 4412 * 4413 * @param x x value of specified rectangle 4414 * @param y y value of specified rectangle 4415 * @param width width of specified rectangle 4416 * @param height height of specified rectangle 4417 * @return true if the specified rectangle is obscured by an opaque child 4418 */ 4419 boolean rectangleIsObscured(int x,int y,int width,int height) 4420 { 4421 int numChildren = getComponentCount(); 4422 4423 for(int i = 0; i < numChildren; i++) { 4424 Component child = getComponent(i); 4425 int cx, cy, cw, ch; 4426 4427 cx = child.getX(); 4428 cy = child.getY(); 4429 cw = child.getWidth(); 4430 ch = child.getHeight(); 4431 4432 if (x >= cx && (x + width) <= (cx + cw) && 4433 y >= cy && (y + height) <= (cy + ch) && child.isVisible()) { 4434 4435 if(child instanceof JComponent) { 4436 // System.out.println("A) checking opaque: " + ((JComponent)child).isOpaque() + " " + child); 4437 // System.out.print("B) "); 4438 // Thread.dumpStack(); 4439 return child.isOpaque(); 4440 } else { 4441 /** Sometimes a heavy weight can have a bound larger than its peer size 4442 * so we should always draw under heavy weights 4443 */ 4444 return false; 4445 } 4446 } 4447 } 4448 4449 return false; 4450 } 4451 4452 4453 /** 4454 * Returns the <code>Component</code>'s "visible rect rectangle" - the 4455 * intersection of the visible rectangles for the component <code>c</code> 4456 * and all of its ancestors. The return value is stored in 4457 * <code>visibleRect</code>. 4458 * 4459 * @param c the component 4460 * @param visibleRect a <code>Rectangle</code> computed as the 4461 * intersection of all visible rectangles for the component 4462 * <code>c</code> and all of its ancestors -- this is the 4463 * return value for this method 4464 * @see #getVisibleRect 4465 */ 4466 static final void computeVisibleRect(Component c, Rectangle visibleRect) { 4467 Container p = c.getParent(); 4468 Rectangle bounds = c.getBounds(); 4469 4470 if (p == null || p instanceof Window || p instanceof Applet) { 4471 visibleRect.setBounds(0, 0, bounds.width, bounds.height); 4472 } else { 4473 computeVisibleRect(p, visibleRect); 4474 visibleRect.x -= bounds.x; 4475 visibleRect.y -= bounds.y; 4476 SwingUtilities.computeIntersection(0,0,bounds.width,bounds.height,visibleRect); 4477 } 4478 } 4479 4480 4481 /** 4482 * Returns the <code>Component</code>'s "visible rect rectangle" - the 4483 * intersection of the visible rectangles for this component 4484 * and all of its ancestors. The return value is stored in 4485 * <code>visibleRect</code>. 4486 * 4487 * @param visibleRect a <code>Rectangle</code> computed as the 4488 * intersection of all visible rectangles for this 4489 * component and all of its ancestors -- this is the return 4490 * value for this method 4491 * @see #getVisibleRect 4492 */ 4493 public void computeVisibleRect(Rectangle visibleRect) { 4494 computeVisibleRect(this, visibleRect); 4495 } 4496 4497 4498 /** 4499 * Returns the <code>Component</code>'s "visible rectangle" - the 4500 * intersection of this component's visible rectangle, 4501 * <code>new Rectangle(0, 0, getWidth(), getHeight())</code>, 4502 * and all of its ancestors' visible rectangles. 4503 * 4504 * @return the visible rectangle 4505 */ 4506 public Rectangle getVisibleRect() { 4507 Rectangle visibleRect = new Rectangle(); 4508 4509 computeVisibleRect(visibleRect); 4510 return visibleRect; 4511 } 4512 4513 /** 4514 * Support for reporting bound property changes for boolean properties. 4515 * This method can be called when a bound property has changed and it will 4516 * send the appropriate PropertyChangeEvent to any registered 4517 * PropertyChangeListeners. 4518 * 4519 * @param propertyName the property whose value has changed 4520 * @param oldValue the property's previous value 4521 * @param newValue the property's new value 4522 */ 4523 public void firePropertyChange(String propertyName, 4524 boolean oldValue, boolean newValue) { 4525 super.firePropertyChange(propertyName, oldValue, newValue); 4526 } 4527 4528 4529 /** 4530 * Support for reporting bound property changes for integer properties. 4531 * This method can be called when a bound property has changed and it will 4532 * send the appropriate PropertyChangeEvent to any registered 4533 * PropertyChangeListeners. 4534 * 4535 * @param propertyName the property whose value has changed 4536 * @param oldValue the property's previous value 4537 * @param newValue the property's new value 4538 */ 4539 public void firePropertyChange(String propertyName, 4540 int oldValue, int newValue) { 4541 super.firePropertyChange(propertyName, oldValue, newValue); 4542 } 4543 4544 // XXX This method is implemented as a workaround to a JLS issue with ambiguous 4545 // methods. This should be removed once 4758654 is resolved. 4546 public void firePropertyChange(String propertyName, char oldValue, char newValue) { 4547 super.firePropertyChange(propertyName, oldValue, newValue); 4548 } 4549 4550 /** 4551 * Supports reporting constrained property changes. 4552 * This method can be called when a constrained property has changed 4553 * and it will send the appropriate <code>PropertyChangeEvent</code> 4554 * to any registered <code>VetoableChangeListeners</code>. 4555 * 4556 * @param propertyName the name of the property that was listened on 4557 * @param oldValue the old value of the property 4558 * @param newValue the new value of the property 4559 * @exception java.beans.PropertyVetoException when the attempt to set the 4560 * property is vetoed by the component 4561 */ 4562 protected void fireVetoableChange(String propertyName, Object oldValue, Object newValue) 4563 throws java.beans.PropertyVetoException 4564 { 4565 if (vetoableChangeSupport == null) { 4566 return; 4567 } 4568 vetoableChangeSupport.fireVetoableChange(propertyName, oldValue, newValue); 4569 } 4570 4571 4572 /** 4573 * Adds a <code>VetoableChangeListener</code> to the listener list. 4574 * The listener is registered for all properties. 4575 * 4576 * @param listener the <code>VetoableChangeListener</code> to be added 4577 */ 4578 public synchronized void addVetoableChangeListener(VetoableChangeListener listener) { 4579 if (vetoableChangeSupport == null) { 4580 vetoableChangeSupport = new java.beans.VetoableChangeSupport(this); 4581 } 4582 vetoableChangeSupport.addVetoableChangeListener(listener); 4583 } 4584 4585 4586 /** 4587 * Removes a <code>VetoableChangeListener</code> from the listener list. 4588 * This removes a <code>VetoableChangeListener</code> that was registered 4589 * for all properties. 4590 * 4591 * @param listener the <code>VetoableChangeListener</code> to be removed 4592 */ 4593 public synchronized void removeVetoableChangeListener(VetoableChangeListener listener) { 4594 if (vetoableChangeSupport == null) { 4595 return; 4596 } 4597 vetoableChangeSupport.removeVetoableChangeListener(listener); 4598 } 4599 4600 4601 /** 4602 * Returns an array of all the vetoable change listeners 4603 * registered on this component. 4604 * 4605 * @return all of the component's <code>VetoableChangeListener</code>s 4606 * or an empty 4607 * array if no vetoable change listeners are currently registered 4608 * 4609 * @see #addVetoableChangeListener 4610 * @see #removeVetoableChangeListener 4611 * 4612 * @since 1.4 4613 */ 4614 public synchronized VetoableChangeListener[] getVetoableChangeListeners() { 4615 if (vetoableChangeSupport == null) { 4616 return new VetoableChangeListener[0]; 4617 } 4618 return vetoableChangeSupport.getVetoableChangeListeners(); 4619 } 4620 4621 4622 /** 4623 * Returns the top-level ancestor of this component (either the 4624 * containing <code>Window</code> or <code>Applet</code>), 4625 * or <code>null</code> if this component has not 4626 * been added to any container. 4627 * 4628 * @return the top-level <code>Container</code> that this component is in, 4629 * or <code>null</code> if not in any container 4630 */ 4631 public Container getTopLevelAncestor() { 4632 for(Container p = this; p != null; p = p.getParent()) { 4633 if(p instanceof Window || p instanceof Applet) { 4634 return p; 4635 } 4636 } 4637 return null; 4638 } 4639 4640 private AncestorNotifier getAncestorNotifier() { 4641 return (AncestorNotifier) 4642 getClientProperty(JComponent_ANCESTOR_NOTIFIER); 4643 } 4644 4645 /** 4646 * Registers <code>listener</code> so that it will receive 4647 * <code>AncestorEvents</code> when it or any of its ancestors 4648 * move or are made visible or invisible. 4649 * Events are also sent when the component or its ancestors are added 4650 * or removed from the containment hierarchy. 4651 * 4652 * @param listener the <code>AncestorListener</code> to register 4653 * @see AncestorEvent 4654 */ 4655 public void addAncestorListener(AncestorListener listener) { 4656 AncestorNotifier ancestorNotifier = getAncestorNotifier(); 4657 if (ancestorNotifier == null) { 4658 ancestorNotifier = new AncestorNotifier(this); 4659 putClientProperty(JComponent_ANCESTOR_NOTIFIER, 4660 ancestorNotifier); 4661 } 4662 ancestorNotifier.addAncestorListener(listener); 4663 } 4664 4665 /** 4666 * Unregisters <code>listener</code> so that it will no longer receive 4667 * <code>AncestorEvents</code>. 4668 * 4669 * @param listener the <code>AncestorListener</code> to be removed 4670 * @see #addAncestorListener 4671 */ 4672 public void removeAncestorListener(AncestorListener listener) { 4673 AncestorNotifier ancestorNotifier = getAncestorNotifier(); 4674 if (ancestorNotifier == null) { 4675 return; 4676 } 4677 ancestorNotifier.removeAncestorListener(listener); 4678 if (ancestorNotifier.listenerList.getListenerList().length == 0) { 4679 ancestorNotifier.removeAllListeners(); 4680 putClientProperty(JComponent_ANCESTOR_NOTIFIER, null); 4681 } 4682 } 4683 4684 /** 4685 * Returns an array of all the ancestor listeners 4686 * registered on this component. 4687 * 4688 * @return all of the component's <code>AncestorListener</code>s 4689 * or an empty 4690 * array if no ancestor listeners are currently registered 4691 * 4692 * @see #addAncestorListener 4693 * @see #removeAncestorListener 4694 * 4695 * @since 1.4 4696 */ 4697 public AncestorListener[] getAncestorListeners() { 4698 AncestorNotifier ancestorNotifier = getAncestorNotifier(); 4699 if (ancestorNotifier == null) { 4700 return new AncestorListener[0]; 4701 } 4702 return ancestorNotifier.getAncestorListeners(); 4703 } 4704 4705 /** 4706 * Returns an array of all the objects currently registered 4707 * as <code><em>Foo</em>Listener</code>s 4708 * upon this <code>JComponent</code>. 4709 * <code><em>Foo</em>Listener</code>s are registered using the 4710 * <code>add<em>Foo</em>Listener</code> method. 4711 * 4712 * <p> 4713 * 4714 * You can specify the <code>listenerType</code> argument 4715 * with a class literal, 4716 * such as 4717 * <code><em>Foo</em>Listener.class</code>. 4718 * For example, you can query a 4719 * <code>JComponent</code> <code>c</code> 4720 * for its mouse listeners with the following code: 4721 * <pre>MouseListener[] mls = (MouseListener[])(c.getListeners(MouseListener.class));</pre> 4722 * If no such listeners exist, this method returns an empty array. 4723 * 4724 * @param listenerType the type of listeners requested; this parameter 4725 * should specify an interface that descends from 4726 * <code>java.util.EventListener</code> 4727 * @return an array of all objects registered as 4728 * <code><em>Foo</em>Listener</code>s on this component, 4729 * or an empty array if no such 4730 * listeners have been added 4731 * @exception ClassCastException if <code>listenerType</code> 4732 * doesn't specify a class or interface that implements 4733 * <code>java.util.EventListener</code> 4734 * 4735 * @since 1.3 4736 * 4737 * @see #getVetoableChangeListeners 4738 * @see #getAncestorListeners 4739 */ 4740 @SuppressWarnings("unchecked") // Casts to (T[]) 4741 public <T extends EventListener> T[] getListeners(Class<T> listenerType) { 4742 T[] result; 4743 if (listenerType == AncestorListener.class) { 4744 // AncestorListeners are handled by the AncestorNotifier 4745 result = (T[])getAncestorListeners(); 4746 } 4747 else if (listenerType == VetoableChangeListener.class) { 4748 // VetoableChangeListeners are handled by VetoableChangeSupport 4749 result = (T[])getVetoableChangeListeners(); 4750 } 4751 else if (listenerType == PropertyChangeListener.class) { 4752 // PropertyChangeListeners are handled by PropertyChangeSupport 4753 result = (T[])getPropertyChangeListeners(); 4754 } 4755 else { 4756 result = listenerList.getListeners(listenerType); 4757 } 4758 4759 if (result.length == 0) { 4760 return super.getListeners(listenerType); 4761 } 4762 return result; 4763 } 4764 4765 /** 4766 * Notifies this component that it now has a parent component. 4767 * When this method is invoked, the chain of parent components is 4768 * set up with <code>KeyboardAction</code> event listeners. 4769 * This method is called by the toolkit internally and should 4770 * not be called directly by programs. 4771 * 4772 * @see #registerKeyboardAction 4773 */ 4774 public void addNotify() { 4775 super.addNotify(); 4776 firePropertyChange("ancestor", null, getParent()); 4777 4778 registerWithKeyboardManager(false); 4779 registerNextFocusableComponent(); 4780 } 4781 4782 4783 /** 4784 * Notifies this component that it no longer has a parent component. 4785 * When this method is invoked, any <code>KeyboardAction</code>s 4786 * set up in the chain of parent components are removed. 4787 * This method is called by the toolkit internally and should 4788 * not be called directly by programs. 4789 * 4790 * @see #registerKeyboardAction 4791 */ 4792 public void removeNotify() { 4793 super.removeNotify(); 4794 // This isn't strictly correct. The event shouldn't be 4795 // fired until *after* the parent is set to null. But 4796 // we only get notified before that happens 4797 firePropertyChange("ancestor", getParent(), null); 4798 4799 unregisterWithKeyboardManager(); 4800 deregisterNextFocusableComponent(); 4801 4802 if (getCreatedDoubleBuffer()) { 4803 RepaintManager.currentManager(this).resetDoubleBuffer(); 4804 setCreatedDoubleBuffer(false); 4805 } 4806 if (autoscrolls) { 4807 Autoscroller.stop(this); 4808 } 4809 } 4810 4811 4812 /** 4813 * Adds the specified region to the dirty region list if the component 4814 * is showing. The component will be repainted after all of the 4815 * currently pending events have been dispatched. 4816 * 4817 * @param tm this parameter is not used 4818 * @param x the x value of the dirty region 4819 * @param y the y value of the dirty region 4820 * @param width the width of the dirty region 4821 * @param height the height of the dirty region 4822 * @see #isPaintingOrigin() 4823 * @see java.awt.Component#isShowing 4824 * @see RepaintManager#addDirtyRegion 4825 */ 4826 public void repaint(long tm, int x, int y, int width, int height) { 4827 RepaintManager.currentManager(SunToolkit.targetToAppContext(this)) 4828 .addDirtyRegion(this, x, y, width, height); 4829 } 4830 4831 4832 /** 4833 * Adds the specified region to the dirty region list if the component 4834 * is showing. The component will be repainted after all of the 4835 * currently pending events have been dispatched. 4836 * 4837 * @param r a <code>Rectangle</code> containing the dirty region 4838 * @see #isPaintingOrigin() 4839 * @see java.awt.Component#isShowing 4840 * @see RepaintManager#addDirtyRegion 4841 */ 4842 public void repaint(Rectangle r) { 4843 repaint(0,r.x,r.y,r.width,r.height); 4844 } 4845 4846 4847 /** 4848 * Supports deferred automatic layout. 4849 * <p> 4850 * Calls <code>invalidate</code> and then adds this component's 4851 * <code>validateRoot</code> to a list of components that need to be 4852 * validated. Validation will occur after all currently pending 4853 * events have been dispatched. In other words after this method 4854 * is called, the first validateRoot (if any) found when walking 4855 * up the containment hierarchy of this component will be validated. 4856 * By default, <code>JRootPane</code>, <code>JScrollPane</code>, 4857 * and <code>JTextField</code> return true 4858 * from <code>isValidateRoot</code>. 4859 * <p> 4860 * This method will automatically be called on this component 4861 * when a property value changes such that size, location, or 4862 * internal layout of this component has been affected. This automatic 4863 * updating differs from the AWT because programs generally no 4864 * longer need to invoke <code>validate</code> to get the contents of the 4865 * GUI to update. 4866 * 4867 * @see java.awt.Component#invalidate 4868 * @see java.awt.Container#validate 4869 * @see #isValidateRoot 4870 * @see RepaintManager#addInvalidComponent 4871 */ 4872 public void revalidate() { 4873 if (getParent() == null) { 4874 // Note: We don't bother invalidating here as once added 4875 // to a valid parent invalidate will be invoked (addImpl 4876 // invokes addNotify which will invoke invalidate on the 4877 // new Component). Also, if we do add a check to isValid 4878 // here it can potentially be called before the constructor 4879 // which was causing some people grief. 4880 return; 4881 } 4882 if (SunToolkit.isDispatchThreadForAppContext(this)) { 4883 invalidate(); 4884 RepaintManager.currentManager(this).addInvalidComponent(this); 4885 } 4886 else { 4887 // To avoid a flood of Runnables when constructing GUIs off 4888 // the EDT, a flag is maintained as to whether or not 4889 // a Runnable has been scheduled. 4890 if (revalidateRunnableScheduled.getAndSet(true)) { 4891 return; 4892 } 4893 SunToolkit.executeOnEventHandlerThread(this, () -> { 4894 revalidateRunnableScheduled.set(false); 4895 revalidate(); 4896 }); 4897 } 4898 } 4899 4900 /** 4901 * If this method returns true, <code>revalidate</code> calls by 4902 * descendants of this component will cause the entire tree 4903 * beginning with this root to be validated. 4904 * Returns false by default. <code>JScrollPane</code> overrides 4905 * this method and returns true. 4906 * 4907 * @return always returns false 4908 * @see #revalidate 4909 * @see java.awt.Component#invalidate 4910 * @see java.awt.Container#validate 4911 * @see java.awt.Container#isValidateRoot 4912 */ 4913 @Override 4914 public boolean isValidateRoot() { 4915 return false; 4916 } 4917 4918 4919 /** 4920 * Returns true if this component tiles its children -- that is, if 4921 * it can guarantee that the children will not overlap. The 4922 * repainting system is substantially more efficient in this 4923 * common case. <code>JComponent</code> subclasses that can't make this 4924 * guarantee, such as <code>JLayeredPane</code>, 4925 * should override this method to return false. 4926 * 4927 * @return always returns true 4928 */ 4929 public boolean isOptimizedDrawingEnabled() { 4930 return true; 4931 } 4932 4933 /** 4934 * Returns {@code true} if a paint triggered on a child component should cause 4935 * painting to originate from this Component, or one of its ancestors. 4936 * <p> 4937 * Calling {@link #repaint} or {@link #paintImmediately(int, int, int, int)} 4938 * on a Swing component will result in calling 4939 * the {@link JComponent#paintImmediately(int, int, int, int)} method of 4940 * the first ancestor which {@code isPaintingOrigin()} returns {@code true}, if there are any. 4941 * <p> 4942 * {@code JComponent} subclasses that need to be painted when any of their 4943 * children are repainted should override this method to return {@code true}. 4944 * 4945 * @return always returns {@code false} 4946 * 4947 * @see #paintImmediately(int, int, int, int) 4948 */ 4949 protected boolean isPaintingOrigin() { 4950 return false; 4951 } 4952 4953 /** 4954 * Paints the specified region in this component and all of its 4955 * descendants that overlap the region, immediately. 4956 * <p> 4957 * It's rarely necessary to call this method. In most cases it's 4958 * more efficient to call repaint, which defers the actual painting 4959 * and can collapse redundant requests into a single paint call. 4960 * This method is useful if one needs to update the display while 4961 * the current event is being dispatched. 4962 * <p> 4963 * This method is to be overridden when the dirty region needs to be changed 4964 * for components that are painting origins. 4965 * 4966 * @param x the x value of the region to be painted 4967 * @param y the y value of the region to be painted 4968 * @param w the width of the region to be painted 4969 * @param h the height of the region to be painted 4970 * @see #repaint 4971 * @see #isPaintingOrigin() 4972 */ 4973 public void paintImmediately(int x,int y,int w, int h) { 4974 Component c = this; 4975 Component parent; 4976 4977 if(!isShowing()) { 4978 return; 4979 } 4980 4981 JComponent paintingOigin = SwingUtilities.getPaintingOrigin(this); 4982 if (paintingOigin != null) { 4983 Rectangle rectangle = SwingUtilities.convertRectangle( 4984 c, new Rectangle(x, y, w, h), paintingOigin); 4985 paintingOigin.paintImmediately(rectangle.x, rectangle.y, rectangle.width, rectangle.height); 4986 return; 4987 } 4988 4989 while(!c.isOpaque()) { 4990 parent = c.getParent(); 4991 if(parent != null) { 4992 x += c.getX(); 4993 y += c.getY(); 4994 c = parent; 4995 } else { 4996 break; 4997 } 4998 4999 if(!(c instanceof JComponent)) { 5000 break; 5001 } 5002 } 5003 if(c instanceof JComponent) { 5004 ((JComponent)c)._paintImmediately(x,y,w,h); 5005 } else { 5006 c.repaint(x,y,w,h); 5007 } 5008 } 5009 5010 /** 5011 * Paints the specified region now. 5012 * 5013 * @param r a <code>Rectangle</code> containing the region to be painted 5014 */ 5015 public void paintImmediately(Rectangle r) { 5016 paintImmediately(r.x,r.y,r.width,r.height); 5017 } 5018 5019 /** 5020 * Returns whether this component should be guaranteed to be on top. 5021 * For example, it would make no sense for <code>Menu</code>s to pop up 5022 * under another component, so they would always return true. 5023 * Most components will want to return false, hence that is the default. 5024 * 5025 * @return always returns false 5026 */ 5027 // package private 5028 boolean alwaysOnTop() { 5029 return false; 5030 } 5031 5032 void setPaintingChild(Component paintingChild) { 5033 this.paintingChild = paintingChild; 5034 } 5035 5036 @SuppressWarnings("deprecation") 5037 void _paintImmediately(int x, int y, int w, int h) { 5038 Graphics g; 5039 Container c; 5040 Rectangle b; 5041 5042 int tmpX, tmpY, tmpWidth, tmpHeight; 5043 int offsetX=0,offsetY=0; 5044 5045 boolean hasBuffer = false; 5046 5047 JComponent bufferedComponent = null; 5048 JComponent paintingComponent = this; 5049 5050 RepaintManager repaintManager = RepaintManager.currentManager(this); 5051 // parent Container's up to Window or Applet. First container is 5052 // the direct parent. Note that in testing it was faster to 5053 // alloc a new Vector vs keeping a stack of them around, and gc 5054 // seemed to have a minimal effect on this. 5055 java.util.List<Component> path = new java.util.ArrayList<Component>(7); 5056 int pIndex = -1; 5057 int pCount = 0; 5058 5059 tmpX = tmpY = tmpWidth = tmpHeight = 0; 5060 5061 Rectangle paintImmediatelyClip = fetchRectangle(); 5062 paintImmediatelyClip.x = x; 5063 paintImmediatelyClip.y = y; 5064 paintImmediatelyClip.width = w; 5065 paintImmediatelyClip.height = h; 5066 5067 5068 // System.out.println("1) ************* in _paintImmediately for " + this); 5069 5070 boolean ontop = alwaysOnTop() && isOpaque(); 5071 if (ontop) { 5072 SwingUtilities.computeIntersection(0, 0, getWidth(), getHeight(), 5073 paintImmediatelyClip); 5074 if (paintImmediatelyClip.width == 0) { 5075 recycleRectangle(paintImmediatelyClip); 5076 return; 5077 } 5078 } 5079 Component child; 5080 for (c = this, child = null; 5081 c != null && !(c instanceof Window) && !(c instanceof Applet); 5082 child = c, c = c.getParent()) { 5083 JComponent jc = (c instanceof JComponent) ? (JComponent)c : 5084 null; 5085 path.add(c); 5086 if(!ontop && jc != null && !jc.isOptimizedDrawingEnabled()) { 5087 boolean resetPC; 5088 5089 // Children of c may overlap, three possible cases for the 5090 // painting region: 5091 // . Completely obscured by an opaque sibling, in which 5092 // case there is no need to paint. 5093 // . Partially obscured by a sibling: need to start 5094 // painting from c. 5095 // . Otherwise we aren't obscured and thus don't need to 5096 // start painting from parent. 5097 if (c != this) { 5098 if (jc.isPaintingOrigin()) { 5099 resetPC = true; 5100 } 5101 else { 5102 Component[] children = c.getComponents(); 5103 int i = 0; 5104 for (; i<children.length; i++) { 5105 if (children[i] == child) break; 5106 } 5107 switch (jc.getObscuredState(i, 5108 paintImmediatelyClip.x, 5109 paintImmediatelyClip.y, 5110 paintImmediatelyClip.width, 5111 paintImmediatelyClip.height)) { 5112 case NOT_OBSCURED: 5113 resetPC = false; 5114 break; 5115 case COMPLETELY_OBSCURED: 5116 recycleRectangle(paintImmediatelyClip); 5117 return; 5118 default: 5119 resetPC = true; 5120 break; 5121 } 5122 } 5123 } 5124 else { 5125 resetPC = false; 5126 } 5127 5128 if (resetPC) { 5129 // Get rid of any buffer since we draw from here and 5130 // we might draw something larger 5131 paintingComponent = jc; 5132 pIndex = pCount; 5133 offsetX = offsetY = 0; 5134 hasBuffer = false; 5135 } 5136 } 5137 pCount++; 5138 5139 // look to see if the parent (and therefor this component) 5140 // is double buffered 5141 if(repaintManager.isDoubleBufferingEnabled() && jc != null && 5142 jc.isDoubleBuffered()) { 5143 hasBuffer = true; 5144 bufferedComponent = jc; 5145 } 5146 5147 // if we aren't on top, include the parent's clip 5148 if (!ontop) { 5149 int bx = c.getX(); 5150 int by = c.getY(); 5151 tmpWidth = c.getWidth(); 5152 tmpHeight = c.getHeight(); 5153 SwingUtilities.computeIntersection(tmpX,tmpY,tmpWidth,tmpHeight,paintImmediatelyClip); 5154 paintImmediatelyClip.x += bx; 5155 paintImmediatelyClip.y += by; 5156 offsetX += bx; 5157 offsetY += by; 5158 } 5159 } 5160 5161 // If the clip width or height is negative, don't bother painting 5162 if(c == null || c.getPeer() == null || 5163 paintImmediatelyClip.width <= 0 || 5164 paintImmediatelyClip.height <= 0) { 5165 recycleRectangle(paintImmediatelyClip); 5166 return; 5167 } 5168 5169 paintingComponent.setFlag(IS_REPAINTING, true); 5170 5171 paintImmediatelyClip.x -= offsetX; 5172 paintImmediatelyClip.y -= offsetY; 5173 5174 // Notify the Components that are going to be painted of the 5175 // child component to paint to. 5176 if(paintingComponent != this) { 5177 Component comp; 5178 int i = pIndex; 5179 for(; i > 0 ; i--) { 5180 comp = path.get(i); 5181 if(comp instanceof JComponent) { 5182 ((JComponent)comp).setPaintingChild(path.get(i-1)); 5183 } 5184 } 5185 } 5186 try { 5187 if ((g = safelyGetGraphics(paintingComponent, c)) != null) { 5188 try { 5189 if (hasBuffer) { 5190 RepaintManager rm = RepaintManager.currentManager( 5191 bufferedComponent); 5192 rm.beginPaint(); 5193 try { 5194 rm.paint(paintingComponent, bufferedComponent, g, 5195 paintImmediatelyClip.x, 5196 paintImmediatelyClip.y, 5197 paintImmediatelyClip.width, 5198 paintImmediatelyClip.height); 5199 } finally { 5200 rm.endPaint(); 5201 } 5202 } else { 5203 g.setClip(paintImmediatelyClip.x, paintImmediatelyClip.y, 5204 paintImmediatelyClip.width, paintImmediatelyClip.height); 5205 paintingComponent.paint(g); 5206 } 5207 } finally { 5208 g.dispose(); 5209 } 5210 } 5211 } 5212 finally { 5213 // Reset the painting child for the parent components. 5214 if(paintingComponent != this) { 5215 Component comp; 5216 int i = pIndex; 5217 for(; i > 0 ; i--) { 5218 comp = path.get(i); 5219 if(comp instanceof JComponent) { 5220 ((JComponent)comp).setPaintingChild(null); 5221 } 5222 } 5223 } 5224 paintingComponent.setFlag(IS_REPAINTING, false); 5225 } 5226 recycleRectangle(paintImmediatelyClip); 5227 } 5228 5229 /** 5230 * Paints to the specified graphics. This does not set the clip and it 5231 * does not adjust the Graphics in anyway, callers must do that first. 5232 * This method is package-private for RepaintManager.PaintManager and 5233 * its subclasses to call, it is NOT intended for general use outside 5234 * of that. 5235 */ 5236 void paintToOffscreen(Graphics g, int x, int y, int w, int h, int maxX, 5237 int maxY) { 5238 try { 5239 setFlag(ANCESTOR_USING_BUFFER, true); 5240 if ((y + h) < maxY || (x + w) < maxX) { 5241 setFlag(IS_PAINTING_TILE, true); 5242 } 5243 if (getFlag(IS_REPAINTING)) { 5244 // Called from paintImmediately (RepaintManager) to fill 5245 // repaint request 5246 paint(g); 5247 } else { 5248 // Called from paint() (AWT) to repair damage 5249 if(!rectangleIsObscured(x, y, w, h)) { 5250 paintComponent(g); 5251 paintBorder(g); 5252 } 5253 paintChildren(g); 5254 } 5255 } finally { 5256 setFlag(ANCESTOR_USING_BUFFER, false); 5257 setFlag(IS_PAINTING_TILE, false); 5258 } 5259 } 5260 5261 /** 5262 * Returns whether or not the region of the specified component is 5263 * obscured by a sibling. 5264 * 5265 * @return NOT_OBSCURED if non of the siblings above the Component obscure 5266 * it, COMPLETELY_OBSCURED if one of the siblings completely 5267 * obscures the Component or PARTIALLY_OBSCURED if the Component is 5268 * only partially obscured. 5269 */ 5270 private int getObscuredState(int compIndex, int x, int y, int width, 5271 int height) { 5272 int retValue = NOT_OBSCURED; 5273 Rectangle tmpRect = fetchRectangle(); 5274 5275 for (int i = compIndex - 1 ; i >= 0 ; i--) { 5276 Component sibling = getComponent(i); 5277 if (!sibling.isVisible()) { 5278 continue; 5279 } 5280 Rectangle siblingRect; 5281 boolean opaque; 5282 if (sibling instanceof JComponent) { 5283 opaque = sibling.isOpaque(); 5284 if (!opaque) { 5285 if (retValue == PARTIALLY_OBSCURED) { 5286 continue; 5287 } 5288 } 5289 } 5290 else { 5291 opaque = true; 5292 } 5293 siblingRect = sibling.getBounds(tmpRect); 5294 if (opaque && x >= siblingRect.x && (x + width) <= 5295 (siblingRect.x + siblingRect.width) && 5296 y >= siblingRect.y && (y + height) <= 5297 (siblingRect.y + siblingRect.height)) { 5298 recycleRectangle(tmpRect); 5299 return COMPLETELY_OBSCURED; 5300 } 5301 else if (retValue == NOT_OBSCURED && 5302 !((x + width <= siblingRect.x) || 5303 (y + height <= siblingRect.y) || 5304 (x >= siblingRect.x + siblingRect.width) || 5305 (y >= siblingRect.y + siblingRect.height))) { 5306 retValue = PARTIALLY_OBSCURED; 5307 } 5308 } 5309 recycleRectangle(tmpRect); 5310 return retValue; 5311 } 5312 5313 /** 5314 * Returns true, which implies that before checking if a child should 5315 * be painted it is first check that the child is not obscured by another 5316 * sibling. This is only checked if <code>isOptimizedDrawingEnabled</code> 5317 * returns false. 5318 * 5319 * @return always returns true 5320 */ 5321 boolean checkIfChildObscuredBySibling() { 5322 return true; 5323 } 5324 5325 5326 private void setFlag(int aFlag, boolean aValue) { 5327 if(aValue) { 5328 flags |= (1 << aFlag); 5329 } else { 5330 flags &= ~(1 << aFlag); 5331 } 5332 } 5333 private boolean getFlag(int aFlag) { 5334 int mask = (1 << aFlag); 5335 return ((flags & mask) == mask); 5336 } 5337 // These functions must be static so that they can be called from 5338 // subclasses inside the package, but whose inheritance hierarhcy includes 5339 // classes outside of the package below JComponent (e.g., JTextArea). 5340 static void setWriteObjCounter(JComponent comp, byte count) { 5341 comp.flags = (comp.flags & ~(0xFF << WRITE_OBJ_COUNTER_FIRST)) | 5342 (count << WRITE_OBJ_COUNTER_FIRST); 5343 } 5344 static byte getWriteObjCounter(JComponent comp) { 5345 return (byte)((comp.flags >> WRITE_OBJ_COUNTER_FIRST) & 0xFF); 5346 } 5347 5348 /** Buffering **/ 5349 5350 /** 5351 * Sets whether this component should use a buffer to paint. 5352 * If set to true, all the drawing from this component will be done 5353 * in an offscreen painting buffer. The offscreen painting buffer will 5354 * the be copied onto the screen. 5355 * If a <code>Component</code> is buffered and one of its ancestor 5356 * is also buffered, the ancestor buffer will be used. 5357 * 5358 * @param aFlag if true, set this component to be double buffered 5359 */ 5360 public void setDoubleBuffered(boolean aFlag) { 5361 setFlag(IS_DOUBLE_BUFFERED,aFlag); 5362 } 5363 5364 /** 5365 * Returns whether this component should use a buffer to paint. 5366 * 5367 * @return true if this component is double buffered, otherwise false 5368 */ 5369 public boolean isDoubleBuffered() { 5370 return getFlag(IS_DOUBLE_BUFFERED); 5371 } 5372 5373 /** 5374 * Returns the <code>JRootPane</code> ancestor for this component. 5375 * 5376 * @return the <code>JRootPane</code> that contains this component, 5377 * or <code>null</code> if no <code>JRootPane</code> is found 5378 */ 5379 public JRootPane getRootPane() { 5380 return SwingUtilities.getRootPane(this); 5381 } 5382 5383 5384 /** Serialization **/ 5385 5386 /** 5387 * This is called from Component by way of reflection. Do NOT change 5388 * the name unless you change the code in Component as well. 5389 */ 5390 void compWriteObjectNotify() { 5391 byte count = JComponent.getWriteObjCounter(this); 5392 JComponent.setWriteObjCounter(this, (byte)(count + 1)); 5393 if (count != 0) { 5394 return; 5395 } 5396 5397 uninstallUIAndProperties(); 5398 5399 /* JTableHeader is in a separate package, which prevents it from 5400 * being able to override this package-private method the way the 5401 * other components can. We don't want to make this method protected 5402 * because it would introduce public-api for a less-than-desirable 5403 * serialization scheme, so we compromise with this 'instanceof' hack 5404 * for now. 5405 */ 5406 if (getToolTipText() != null || 5407 this instanceof javax.swing.table.JTableHeader) { 5408 ToolTipManager.sharedInstance().unregisterComponent(JComponent.this); 5409 } 5410 } 5411 5412 /** 5413 * This object is the <code>ObjectInputStream</code> callback 5414 * that's called after a complete graph of objects (including at least 5415 * one <code>JComponent</code>) has been read. 5416 * It sets the UI property of each Swing component 5417 * that was read to the current default with <code>updateUI</code>. 5418 * <p> 5419 * As each component is read in we keep track of the current set of 5420 * root components here, in the roots vector. Note that there's only one 5421 * <code>ReadObjectCallback</code> per <code>ObjectInputStream</code>, 5422 * they're stored in the static <code>readObjectCallbacks</code> 5423 * hashtable. 5424 * 5425 * @see java.io.ObjectInputStream#registerValidation 5426 * @see SwingUtilities#updateComponentTreeUI 5427 */ 5428 private class ReadObjectCallback implements ObjectInputValidation 5429 { 5430 private final Vector<JComponent> roots = new Vector<JComponent>(1); 5431 private final ObjectInputStream inputStream; 5432 5433 ReadObjectCallback(ObjectInputStream s) throws Exception { 5434 inputStream = s; 5435 s.registerValidation(this, 0); 5436 } 5437 5438 /** 5439 * This is the method that's called after the entire graph 5440 * of objects has been read in. It initializes 5441 * the UI property of all of the copmonents with 5442 * <code>SwingUtilities.updateComponentTreeUI</code>. 5443 */ 5444 public void validateObject() throws InvalidObjectException { 5445 try { 5446 for (JComponent root : roots) { 5447 SwingUtilities.updateComponentTreeUI(root); 5448 } 5449 } 5450 finally { 5451 readObjectCallbacks.remove(inputStream); 5452 } 5453 } 5454 5455 /** 5456 * If <code>c</code> isn't a descendant of a component we've already 5457 * seen, then add it to the roots <code>Vector</code>. 5458 * 5459 * @param c the <code>JComponent</code> to add 5460 */ 5461 private void registerComponent(JComponent c) 5462 { 5463 /* If the Component c is a descendant of one of the 5464 * existing roots (or it IS an existing root), we're done. 5465 */ 5466 for (JComponent root : roots) { 5467 for(Component p = c; p != null; p = p.getParent()) { 5468 if (p == root) { 5469 return; 5470 } 5471 } 5472 } 5473 5474 /* Otherwise: if Component c is an ancestor of any of the 5475 * existing roots then remove them and add c (the "new root") 5476 * to the roots vector. 5477 */ 5478 for(int i = 0; i < roots.size(); i++) { 5479 JComponent root = roots.elementAt(i); 5480 for(Component p = root.getParent(); p != null; p = p.getParent()) { 5481 if (p == c) { 5482 roots.removeElementAt(i--); // !! 5483 break; 5484 } 5485 } 5486 } 5487 5488 roots.addElement(c); 5489 } 5490 } 5491 5492 5493 /** 5494 * We use the <code>ObjectInputStream</code> "registerValidation" 5495 * callback to update the UI for the entire tree of components 5496 * after they've all been read in. 5497 * 5498 * @param s the <code>ObjectInputStream</code> from which to read 5499 */ 5500 private void readObject(ObjectInputStream s) 5501 throws IOException, ClassNotFoundException 5502 { 5503 ObjectInputStream.GetField f = s.readFields(); 5504 5505 isAlignmentXSet = f.get("isAlignmentXSet", false); 5506 alignmentX = validateAlignment(f.get("alignmentX", 0f)); 5507 isAlignmentYSet = f.get("isAlignmentYSet", false); 5508 alignmentY = validateAlignment(f.get("alignmentY", 0f)); 5509 listenerList = (EventListenerList) f.get("listenerList", null); 5510 vetoableChangeSupport = (VetoableChangeSupport) f.get("vetoableChangeSupport", null); 5511 autoscrolls = f.get("autoscrolls", false); 5512 border = (Border) f.get("border", null); 5513 flags = f.get("flags", 0); 5514 inputVerifier = (InputVerifier) f.get("inputVerifier", null); 5515 verifyInputWhenFocusTarget = f.get("verifyInputWhenFocusTarget", false); 5516 popupMenu = (JPopupMenu) f.get("popupMenu", null); 5517 focusInputMap = (InputMap) f.get("focusInputMap", null); 5518 ancestorInputMap = (InputMap) f.get("ancestorInputMap", null); 5519 windowInputMap = (ComponentInputMap) f.get("windowInputMap", null); 5520 actionMap = (ActionMap) f.get("actionMap", null); 5521 5522 /* If there's no ReadObjectCallback for this stream yet, that is, if 5523 * this is the first call to JComponent.readObject() for this 5524 * graph of objects, then create a callback and stash it 5525 * in the readObjectCallbacks table. Note that the ReadObjectCallback 5526 * constructor takes care of calling s.registerValidation(). 5527 */ 5528 ReadObjectCallback cb = readObjectCallbacks.get(s); 5529 if (cb == null) { 5530 try { 5531 readObjectCallbacks.put(s, cb = new ReadObjectCallback(s)); 5532 } 5533 catch (Exception e) { 5534 throw new IOException(e.toString()); 5535 } 5536 } 5537 cb.registerComponent(this); 5538 5539 // Read back the client properties. 5540 int cpCount = s.readInt(); 5541 if (cpCount > 0) { 5542 clientProperties = new ArrayTable(); 5543 for (int counter = 0; counter < cpCount; counter++) { 5544 clientProperties.put(s.readObject(), 5545 s.readObject()); 5546 } 5547 } 5548 if (getToolTipText() != null) { 5549 ToolTipManager.sharedInstance().registerComponent(this); 5550 } 5551 setWriteObjCounter(this, (byte)0); 5552 revalidateRunnableScheduled = new AtomicBoolean(false); 5553 } 5554 5555 5556 /** 5557 * Before writing a <code>JComponent</code> to an 5558 * <code>ObjectOutputStream</code> we temporarily uninstall its UI. 5559 * This is tricky to do because we want to uninstall 5560 * the UI before any of the <code>JComponent</code>'s children 5561 * (or its <code>LayoutManager</code> etc.) are written, 5562 * and we don't want to restore the UI until the most derived 5563 * <code>JComponent</code> subclass has been stored. 5564 * 5565 * @param s the <code>ObjectOutputStream</code> in which to write 5566 */ 5567 private void writeObject(ObjectOutputStream s) throws IOException { 5568 s.defaultWriteObject(); 5569 if (getUIClassID().equals(uiClassID)) { 5570 byte count = JComponent.getWriteObjCounter(this); 5571 JComponent.setWriteObjCounter(this, --count); 5572 if (count == 0 && ui != null) { 5573 ui.installUI(this); 5574 } 5575 } 5576 ArrayTable.writeArrayTable(s, clientProperties); 5577 } 5578 5579 5580 /** 5581 * Returns a string representation of this <code>JComponent</code>. 5582 * This method 5583 * is intended to be used only for debugging purposes, and the 5584 * content and format of the returned string may vary between 5585 * implementations. The returned string may be empty but may not 5586 * be <code>null</code>. 5587 * 5588 * @return a string representation of this <code>JComponent</code> 5589 */ 5590 protected String paramString() { 5591 String preferredSizeString = (isPreferredSizeSet() ? 5592 getPreferredSize().toString() : ""); 5593 String minimumSizeString = (isMinimumSizeSet() ? 5594 getMinimumSize().toString() : ""); 5595 String maximumSizeString = (isMaximumSizeSet() ? 5596 getMaximumSize().toString() : ""); 5597 String borderString = (border == null ? "" 5598 : (border == this ? "this" : border.toString())); 5599 5600 return super.paramString() + 5601 ",alignmentX=" + alignmentX + 5602 ",alignmentY=" + alignmentY + 5603 ",border=" + borderString + 5604 ",flags=" + flags + // should beef this up a bit 5605 ",maximumSize=" + maximumSizeString + 5606 ",minimumSize=" + minimumSizeString + 5607 ",preferredSize=" + preferredSizeString; 5608 } 5609 5610 /** 5611 * {@inheritDoc} 5612 */ 5613 @Override 5614 @Deprecated 5615 public void hide() { 5616 boolean showing = isShowing(); 5617 super.hide(); 5618 if (showing) { 5619 Container parent = getParent(); 5620 if (parent != null) { 5621 Rectangle r = getBounds(); 5622 parent.repaint(r.x, r.y, r.width, r.height); 5623 } 5624 revalidate(); 5625 } 5626 } 5627 5628 }