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