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