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