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