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