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