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