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