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