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