1 /* 2 * Copyright (c) 1995, 2014, 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 java.awt; 26 27 import java.io.PrintStream; 28 import java.io.PrintWriter; 29 import java.util.Objects; 30 import java.util.Vector; 31 import java.util.Locale; 32 import java.util.EventListener; 33 import java.util.HashSet; 34 import java.util.Map; 35 import java.util.Set; 36 import java.util.Collections; 37 import java.awt.peer.ComponentPeer; 38 import java.awt.peer.ContainerPeer; 39 import java.awt.peer.LightweightPeer; 40 import java.awt.image.BufferStrategy; 41 import java.awt.image.ImageObserver; 42 import java.awt.image.ImageProducer; 43 import java.awt.image.ColorModel; 44 import java.awt.image.VolatileImage; 45 import java.awt.event.*; 46 import java.io.Serializable; 47 import java.io.ObjectOutputStream; 48 import java.io.ObjectInputStream; 49 import java.io.IOException; 50 import java.beans.PropertyChangeListener; 51 import java.beans.PropertyChangeSupport; 52 import java.beans.Transient; 53 import java.awt.im.InputContext; 54 import java.awt.im.InputMethodRequests; 55 import java.awt.dnd.DropTarget; 56 import java.lang.reflect.InvocationTargetException; 57 import java.lang.reflect.Method; 58 import java.security.AccessController; 59 import java.security.PrivilegedAction; 60 import java.security.AccessControlContext; 61 import javax.accessibility.*; 62 import java.applet.Applet; 63 64 import sun.security.action.GetPropertyAction; 65 import sun.awt.AppContext; 66 import sun.awt.AWTAccessor; 67 import sun.awt.ConstrainableGraphics; 68 import sun.awt.SubRegionShowable; 69 import sun.awt.SunToolkit; 70 import sun.awt.WindowClosingListener; 71 import sun.awt.CausedFocusEvent; 72 import sun.awt.EmbeddedFrame; 73 import sun.awt.dnd.SunDropTargetEvent; 74 import sun.awt.im.CompositionArea; 75 import sun.font.FontManager; 76 import sun.font.FontManagerFactory; 77 import sun.font.SunFontManager; 78 import sun.java2d.SunGraphics2D; 79 import sun.java2d.pipe.Region; 80 import sun.awt.image.VSyncedBSManager; 81 import sun.java2d.pipe.hw.ExtendedBufferCapabilities; 82 import static sun.java2d.pipe.hw.ExtendedBufferCapabilities.VSyncType.*; 83 import sun.awt.RequestFocusController; 84 import sun.java2d.SunGraphicsEnvironment; 85 import sun.util.logging.PlatformLogger; 86 87 /** 88 * A <em>component</em> is an object having a graphical representation 89 * that can be displayed on the screen and that can interact with the 90 * user. Examples of components are the buttons, checkboxes, and scrollbars 91 * of a typical graphical user interface. <p> 92 * The <code>Component</code> class is the abstract superclass of 93 * the nonmenu-related Abstract Window Toolkit components. Class 94 * <code>Component</code> can also be extended directly to create a 95 * lightweight component. A lightweight component is a component that is 96 * not associated with a native window. On the contrary, a heavyweight 97 * component is associated with a native window. The {@link #isLightweight()} 98 * method may be used to distinguish between the two kinds of the components. 99 * <p> 100 * Lightweight and heavyweight components may be mixed in a single component 101 * hierarchy. However, for correct operating of such a mixed hierarchy of 102 * components, the whole hierarchy must be valid. When the hierarchy gets 103 * invalidated, like after changing the bounds of components, or 104 * adding/removing components to/from containers, the whole hierarchy must be 105 * validated afterwards by means of the {@link Container#validate()} method 106 * invoked on the top-most invalid container of the hierarchy. 107 * 108 * <h3>Serialization</h3> 109 * It is important to note that only AWT listeners which conform 110 * to the <code>Serializable</code> protocol will be saved when 111 * the object is stored. If an AWT object has listeners that 112 * aren't marked serializable, they will be dropped at 113 * <code>writeObject</code> time. Developers will need, as always, 114 * to consider the implications of making an object serializable. 115 * One situation to watch out for is this: 116 * <pre> 117 * import java.awt.*; 118 * import java.awt.event.*; 119 * import java.io.Serializable; 120 * 121 * class MyApp implements ActionListener, Serializable 122 * { 123 * BigObjectThatShouldNotBeSerializedWithAButton bigOne; 124 * Button aButton = new Button(); 125 * 126 * MyApp() 127 * { 128 * // Oops, now aButton has a listener with a reference 129 * // to bigOne! 130 * aButton.addActionListener(this); 131 * } 132 * 133 * public void actionPerformed(ActionEvent e) 134 * { 135 * System.out.println("Hello There"); 136 * } 137 * } 138 * </pre> 139 * In this example, serializing <code>aButton</code> by itself 140 * will cause <code>MyApp</code> and everything it refers to 141 * to be serialized as well. The problem is that the listener 142 * is serializable by coincidence, not by design. To separate 143 * the decisions about <code>MyApp</code> and the 144 * <code>ActionListener</code> being serializable one can use a 145 * nested class, as in the following example: 146 * <pre> 147 * import java.awt.*; 148 * import java.awt.event.*; 149 * import java.io.Serializable; 150 * 151 * class MyApp implements java.io.Serializable 152 * { 153 * BigObjectThatShouldNotBeSerializedWithAButton bigOne; 154 * Button aButton = new Button(); 155 * 156 * static class MyActionListener implements ActionListener 157 * { 158 * public void actionPerformed(ActionEvent e) 159 * { 160 * System.out.println("Hello There"); 161 * } 162 * } 163 * 164 * MyApp() 165 * { 166 * aButton.addActionListener(new MyActionListener()); 167 * } 168 * } 169 * </pre> 170 * <p> 171 * <b>Note</b>: For more information on the paint mechanisms utilitized 172 * by AWT and Swing, including information on how to write the most 173 * efficient painting code, see 174 * <a href="http://www.oracle.com/technetwork/java/painting-140037.html">Painting in AWT and Swing</a>. 175 * <p> 176 * For details on the focus subsystem, see 177 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html"> 178 * How to Use the Focus Subsystem</a>, 179 * a section in <em>The Java Tutorial</em>, and the 180 * <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a> 181 * for more information. 182 * 183 * @author Arthur van Hoff 184 * @author Sami Shaio 185 */ 186 public abstract class Component implements ImageObserver, MenuContainer, 187 Serializable 188 { 189 190 private static final PlatformLogger log = PlatformLogger.getLogger("java.awt.Component"); 191 private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.Component"); 192 private static final PlatformLogger focusLog = PlatformLogger.getLogger("java.awt.focus.Component"); 193 private static final PlatformLogger mixingLog = PlatformLogger.getLogger("java.awt.mixing.Component"); 194 195 /** 196 * The peer of the component. The peer implements the component's 197 * behavior. The peer is set when the <code>Component</code> is 198 * added to a container that also is a peer. 199 * @see #addNotify 200 * @see #removeNotify 201 */ 202 transient ComponentPeer peer; 203 204 /** 205 * The parent of the object. It may be <code>null</code> 206 * for top-level components. 207 * @see #getParent 208 */ 209 transient Container parent; 210 211 /** 212 * The <code>AppContext</code> of the component. Applets/Plugin may 213 * change the AppContext. 214 */ 215 transient AppContext appContext; 216 217 /** 218 * The x position of the component in the parent's coordinate system. 219 * 220 * @serial 221 * @see #getLocation 222 */ 223 int x; 224 225 /** 226 * The y position of the component in the parent's coordinate system. 227 * 228 * @serial 229 * @see #getLocation 230 */ 231 int y; 232 233 /** 234 * The width of the component. 235 * 236 * @serial 237 * @see #getSize 238 */ 239 int width; 240 241 /** 242 * The height of the component. 243 * 244 * @serial 245 * @see #getSize 246 */ 247 int height; 248 249 /** 250 * The foreground color for this component. 251 * <code>foreground</code> can be <code>null</code>. 252 * 253 * @serial 254 * @see #getForeground 255 * @see #setForeground 256 */ 257 Color foreground; 258 259 /** 260 * The background color for this component. 261 * <code>background</code> can be <code>null</code>. 262 * 263 * @serial 264 * @see #getBackground 265 * @see #setBackground 266 */ 267 Color background; 268 269 /** 270 * The font used by this component. 271 * The <code>font</code> can be <code>null</code>. 272 * 273 * @serial 274 * @see #getFont 275 * @see #setFont 276 */ 277 volatile Font font; 278 279 /** 280 * The font which the peer is currently using. 281 * (<code>null</code> if no peer exists.) 282 */ 283 Font peerFont; 284 285 /** 286 * The cursor displayed when pointer is over this component. 287 * This value can be <code>null</code>. 288 * 289 * @serial 290 * @see #getCursor 291 * @see #setCursor 292 */ 293 Cursor cursor; 294 295 /** 296 * The locale for the component. 297 * 298 * @serial 299 * @see #getLocale 300 * @see #setLocale 301 */ 302 Locale locale; 303 304 /** 305 * A reference to a <code>GraphicsConfiguration</code> object 306 * used to describe the characteristics of a graphics 307 * destination. 308 * This value can be <code>null</code>. 309 * 310 * @since 1.3 311 * @serial 312 * @see GraphicsConfiguration 313 * @see #getGraphicsConfiguration 314 */ 315 private transient GraphicsConfiguration graphicsConfig = null; 316 317 /** 318 * A reference to a <code>BufferStrategy</code> object 319 * used to manipulate the buffers on this component. 320 * 321 * @since 1.4 322 * @see java.awt.image.BufferStrategy 323 * @see #getBufferStrategy() 324 */ 325 transient BufferStrategy bufferStrategy = null; 326 327 /** 328 * True when the object should ignore all repaint events. 329 * 330 * @since 1.4 331 * @serial 332 * @see #setIgnoreRepaint 333 * @see #getIgnoreRepaint 334 */ 335 boolean ignoreRepaint = false; 336 337 /** 338 * True when the object is visible. An object that is not 339 * visible is not drawn on the screen. 340 * 341 * @serial 342 * @see #isVisible 343 * @see #setVisible 344 */ 345 boolean visible = true; 346 347 /** 348 * True when the object is enabled. An object that is not 349 * enabled does not interact with the user. 350 * 351 * @serial 352 * @see #isEnabled 353 * @see #setEnabled 354 */ 355 boolean enabled = true; 356 357 /** 358 * True when the object is valid. An invalid object needs to 359 * be layed out. This flag is set to false when the object 360 * size is changed. 361 * 362 * @serial 363 * @see #isValid 364 * @see #validate 365 * @see #invalidate 366 */ 367 private volatile boolean valid = false; 368 369 /** 370 * The <code>DropTarget</code> associated with this component. 371 * 372 * @since 1.2 373 * @serial 374 * @see #setDropTarget 375 * @see #getDropTarget 376 */ 377 DropTarget dropTarget; 378 379 /** 380 * @serial 381 * @see #add 382 */ 383 Vector<PopupMenu> popups; 384 385 /** 386 * A component's name. 387 * This field can be <code>null</code>. 388 * 389 * @serial 390 * @see #getName 391 * @see #setName(String) 392 */ 393 private String name; 394 395 /** 396 * A bool to determine whether the name has 397 * been set explicitly. <code>nameExplicitlySet</code> will 398 * be false if the name has not been set and 399 * true if it has. 400 * 401 * @serial 402 * @see #getName 403 * @see #setName(String) 404 */ 405 private boolean nameExplicitlySet = false; 406 407 /** 408 * Indicates whether this Component can be focused. 409 * 410 * @serial 411 * @see #setFocusable 412 * @see #isFocusable 413 * @since 1.4 414 */ 415 private boolean focusable = true; 416 417 private static final int FOCUS_TRAVERSABLE_UNKNOWN = 0; 418 private static final int FOCUS_TRAVERSABLE_DEFAULT = 1; 419 private static final int FOCUS_TRAVERSABLE_SET = 2; 420 421 /** 422 * Tracks whether this Component is relying on default focus travesability. 423 * 424 * @serial 425 * @since 1.4 426 */ 427 private int isFocusTraversableOverridden = FOCUS_TRAVERSABLE_UNKNOWN; 428 429 /** 430 * The focus traversal keys. These keys will generate focus traversal 431 * behavior for Components for which focus traversal keys are enabled. If a 432 * value of null is specified for a traversal key, this Component inherits 433 * that traversal key from its parent. If all ancestors of this Component 434 * have null specified for that traversal key, then the current 435 * KeyboardFocusManager's default traversal key is used. 436 * 437 * @serial 438 * @see #setFocusTraversalKeys 439 * @see #getFocusTraversalKeys 440 * @since 1.4 441 */ 442 Set<AWTKeyStroke>[] focusTraversalKeys; 443 444 private static final String[] focusTraversalKeyPropertyNames = { 445 "forwardFocusTraversalKeys", 446 "backwardFocusTraversalKeys", 447 "upCycleFocusTraversalKeys", 448 "downCycleFocusTraversalKeys" 449 }; 450 451 /** 452 * Indicates whether focus traversal keys are enabled for this Component. 453 * Components for which focus traversal keys are disabled receive key 454 * events for focus traversal keys. Components for which focus traversal 455 * keys are enabled do not see these events; instead, the events are 456 * automatically converted to traversal operations. 457 * 458 * @serial 459 * @see #setFocusTraversalKeysEnabled 460 * @see #getFocusTraversalKeysEnabled 461 * @since 1.4 462 */ 463 private boolean focusTraversalKeysEnabled = true; 464 465 /** 466 * The locking object for AWT component-tree and layout operations. 467 * 468 * @see #getTreeLock 469 */ 470 static final Object LOCK = new AWTTreeLock(); 471 static class AWTTreeLock {} 472 473 /* 474 * The component's AccessControlContext. 475 */ 476 private transient volatile AccessControlContext acc = 477 AccessController.getContext(); 478 479 /** 480 * Minimum size. 481 * (This field perhaps should have been transient). 482 * 483 * @serial 484 */ 485 Dimension minSize; 486 487 /** 488 * Whether or not setMinimumSize has been invoked with a non-null value. 489 */ 490 boolean minSizeSet; 491 492 /** 493 * Preferred size. 494 * (This field perhaps should have been transient). 495 * 496 * @serial 497 */ 498 Dimension prefSize; 499 500 /** 501 * Whether or not setPreferredSize has been invoked with a non-null value. 502 */ 503 boolean prefSizeSet; 504 505 /** 506 * Maximum size 507 * 508 * @serial 509 */ 510 Dimension maxSize; 511 512 /** 513 * Whether or not setMaximumSize has been invoked with a non-null value. 514 */ 515 boolean maxSizeSet; 516 517 /** 518 * The orientation for this component. 519 * @see #getComponentOrientation 520 * @see #setComponentOrientation 521 */ 522 transient ComponentOrientation componentOrientation 523 = ComponentOrientation.UNKNOWN; 524 525 /** 526 * <code>newEventsOnly</code> will be true if the event is 527 * one of the event types enabled for the component. 528 * It will then allow for normal processing to 529 * continue. If it is false the event is passed 530 * to the component's parent and up the ancestor 531 * tree until the event has been consumed. 532 * 533 * @serial 534 * @see #dispatchEvent 535 */ 536 boolean newEventsOnly = false; 537 transient ComponentListener componentListener; 538 transient FocusListener focusListener; 539 transient HierarchyListener hierarchyListener; 540 transient HierarchyBoundsListener hierarchyBoundsListener; 541 transient KeyListener keyListener; 542 transient MouseListener mouseListener; 543 transient MouseMotionListener mouseMotionListener; 544 transient MouseWheelListener mouseWheelListener; 545 transient InputMethodListener inputMethodListener; 546 547 transient RuntimeException windowClosingException = null; 548 549 /** Internal, constants for serialization */ 550 final static String actionListenerK = "actionL"; 551 final static String adjustmentListenerK = "adjustmentL"; 552 final static String componentListenerK = "componentL"; 553 final static String containerListenerK = "containerL"; 554 final static String focusListenerK = "focusL"; 555 final static String itemListenerK = "itemL"; 556 final static String keyListenerK = "keyL"; 557 final static String mouseListenerK = "mouseL"; 558 final static String mouseMotionListenerK = "mouseMotionL"; 559 final static String mouseWheelListenerK = "mouseWheelL"; 560 final static String textListenerK = "textL"; 561 final static String ownedWindowK = "ownedL"; 562 final static String windowListenerK = "windowL"; 563 final static String inputMethodListenerK = "inputMethodL"; 564 final static String hierarchyListenerK = "hierarchyL"; 565 final static String hierarchyBoundsListenerK = "hierarchyBoundsL"; 566 final static String windowStateListenerK = "windowStateL"; 567 final static String windowFocusListenerK = "windowFocusL"; 568 569 /** 570 * The <code>eventMask</code> is ONLY set by subclasses via 571 * <code>enableEvents</code>. 572 * The mask should NOT be set when listeners are registered 573 * so that we can distinguish the difference between when 574 * listeners request events and subclasses request them. 575 * One bit is used to indicate whether input methods are 576 * enabled; this bit is set by <code>enableInputMethods</code> and is 577 * on by default. 578 * 579 * @serial 580 * @see #enableInputMethods 581 * @see AWTEvent 582 */ 583 long eventMask = AWTEvent.INPUT_METHODS_ENABLED_MASK; 584 585 /** 586 * Static properties for incremental drawing. 587 * @see #imageUpdate 588 */ 589 static boolean isInc; 590 static int incRate; 591 static { 592 /* ensure that the necessary native libraries are loaded */ 593 Toolkit.loadLibraries(); 594 /* initialize JNI field and method ids */ 595 if (!GraphicsEnvironment.isHeadless()) { 596 initIDs(); 597 } 598 599 String s = java.security.AccessController.doPrivileged( 600 new GetPropertyAction("awt.image.incrementaldraw")); 601 isInc = (s == null || s.equals("true")); 602 603 s = java.security.AccessController.doPrivileged( 604 new GetPropertyAction("awt.image.redrawrate")); 605 incRate = (s != null) ? Integer.parseInt(s) : 100; 606 } 607 608 /** 609 * Ease-of-use constant for <code>getAlignmentY()</code>. 610 * Specifies an alignment to the top of the component. 611 * @see #getAlignmentY 612 */ 613 public static final float TOP_ALIGNMENT = 0.0f; 614 615 /** 616 * Ease-of-use constant for <code>getAlignmentY</code> and 617 * <code>getAlignmentX</code>. Specifies an alignment to 618 * the center of the component 619 * @see #getAlignmentX 620 * @see #getAlignmentY 621 */ 622 public static final float CENTER_ALIGNMENT = 0.5f; 623 624 /** 625 * Ease-of-use constant for <code>getAlignmentY</code>. 626 * Specifies an alignment to the bottom of the component. 627 * @see #getAlignmentY 628 */ 629 public static final float BOTTOM_ALIGNMENT = 1.0f; 630 631 /** 632 * Ease-of-use constant for <code>getAlignmentX</code>. 633 * Specifies an alignment to the left side of the component. 634 * @see #getAlignmentX 635 */ 636 public static final float LEFT_ALIGNMENT = 0.0f; 637 638 /** 639 * Ease-of-use constant for <code>getAlignmentX</code>. 640 * Specifies an alignment to the right side of the component. 641 * @see #getAlignmentX 642 */ 643 public static final float RIGHT_ALIGNMENT = 1.0f; 644 645 /* 646 * JDK 1.1 serialVersionUID 647 */ 648 private static final long serialVersionUID = -7644114512714619750L; 649 650 /** 651 * If any <code>PropertyChangeListeners</code> have been registered, 652 * the <code>changeSupport</code> field describes them. 653 * 654 * @serial 655 * @since 1.2 656 * @see #addPropertyChangeListener 657 * @see #removePropertyChangeListener 658 * @see #firePropertyChange 659 */ 660 private PropertyChangeSupport changeSupport; 661 662 /* 663 * In some cases using "this" as an object to synchronize by 664 * can lead to a deadlock if client code also uses synchronization 665 * by a component object. For every such situation revealed we should 666 * consider possibility of replacing "this" with the package private 667 * objectLock object introduced below. So far there're 3 issues known: 668 * - CR 6708322 (the getName/setName methods); 669 * - CR 6608764 (the PropertyChangeListener machinery); 670 * - CR 7108598 (the Container.paint/KeyboardFocusManager.clearMostRecentFocusOwner methods). 671 * 672 * Note: this field is considered final, though readObject() prohibits 673 * initializing final fields. 674 */ 675 private transient Object objectLock = new Object(); 676 Object getObjectLock() { 677 return objectLock; 678 } 679 680 /* 681 * Returns the acc this component was constructed with. 682 */ 683 final AccessControlContext getAccessControlContext() { 684 if (acc == null) { 685 throw new SecurityException("Component is missing AccessControlContext"); 686 } 687 return acc; 688 } 689 690 boolean isPacked = false; 691 692 /** 693 * Pseudoparameter for direct Geometry API (setLocation, setBounds setSize 694 * to signal setBounds what's changing. Should be used under TreeLock. 695 * This is only needed due to the inability to change the cross-calling 696 * order of public and deprecated methods. 697 */ 698 private int boundsOp = ComponentPeer.DEFAULT_OPERATION; 699 700 /** 701 * Enumeration of the common ways the baseline of a component can 702 * change as the size changes. The baseline resize behavior is 703 * primarily for layout managers that need to know how the 704 * position of the baseline changes as the component size changes. 705 * In general the baseline resize behavior will be valid for sizes 706 * greater than or equal to the minimum size (the actual minimum 707 * size; not a developer specified minimum size). For sizes 708 * smaller than the minimum size the baseline may change in a way 709 * other than the baseline resize behavior indicates. Similarly, 710 * as the size approaches <code>Integer.MAX_VALUE</code> and/or 711 * <code>Short.MAX_VALUE</code> the baseline may change in a way 712 * other than the baseline resize behavior indicates. 713 * 714 * @see #getBaselineResizeBehavior 715 * @see #getBaseline(int,int) 716 * @since 1.6 717 */ 718 public enum BaselineResizeBehavior { 719 /** 720 * Indicates the baseline remains fixed relative to the 721 * y-origin. That is, <code>getBaseline</code> returns 722 * the same value regardless of the height or width. For example, a 723 * <code>JLabel</code> containing non-empty text with a 724 * vertical alignment of <code>TOP</code> should have a 725 * baseline type of <code>CONSTANT_ASCENT</code>. 726 */ 727 CONSTANT_ASCENT, 728 729 /** 730 * Indicates the baseline remains fixed relative to the height 731 * and does not change as the width is varied. That is, for 732 * any height H the difference between H and 733 * <code>getBaseline(w, H)</code> is the same. For example, a 734 * <code>JLabel</code> containing non-empty text with a 735 * vertical alignment of <code>BOTTOM</code> should have a 736 * baseline type of <code>CONSTANT_DESCENT</code>. 737 */ 738 CONSTANT_DESCENT, 739 740 /** 741 * Indicates the baseline remains a fixed distance from 742 * the center of the component. That is, for any height H the 743 * difference between <code>getBaseline(w, H)</code> and 744 * <code>H / 2</code> is the same (plus or minus one depending upon 745 * rounding error). 746 * <p> 747 * Because of possible rounding errors it is recommended 748 * you ask for the baseline with two consecutive heights and use 749 * the return value to determine if you need to pad calculations 750 * by 1. The following shows how to calculate the baseline for 751 * any height: 752 * <pre> 753 * Dimension preferredSize = component.getPreferredSize(); 754 * int baseline = getBaseline(preferredSize.width, 755 * preferredSize.height); 756 * int nextBaseline = getBaseline(preferredSize.width, 757 * preferredSize.height + 1); 758 * // Amount to add to height when calculating where baseline 759 * // lands for a particular height: 760 * int padding = 0; 761 * // Where the baseline is relative to the mid point 762 * int baselineOffset = baseline - height / 2; 763 * if (preferredSize.height % 2 == 0 && 764 * baseline != nextBaseline) { 765 * padding = 1; 766 * } 767 * else if (preferredSize.height % 2 == 1 && 768 * baseline == nextBaseline) { 769 * baselineOffset--; 770 * padding = 1; 771 * } 772 * // The following calculates where the baseline lands for 773 * // the height z: 774 * int calculatedBaseline = (z + padding) / 2 + baselineOffset; 775 * </pre> 776 */ 777 CENTER_OFFSET, 778 779 /** 780 * Indicates the baseline resize behavior can not be expressed using 781 * any of the other constants. This may also indicate the baseline 782 * varies with the width of the component. This is also returned 783 * by components that do not have a baseline. 784 */ 785 OTHER 786 } 787 788 /* 789 * The shape set with the applyCompoundShape() method. It uncludes the result 790 * of the HW/LW mixing related shape computation. It may also include 791 * the user-specified shape of the component. 792 * The 'null' value means the component has normal shape (or has no shape at all) 793 * and applyCompoundShape() will skip the following shape identical to normal. 794 */ 795 private transient Region compoundShape = null; 796 797 /* 798 * Represents the shape of this lightweight component to be cut out from 799 * heavyweight components should they intersect. Possible values: 800 * 1. null - consider the shape rectangular 801 * 2. EMPTY_REGION - nothing gets cut out (children still get cut out) 802 * 3. non-empty - this shape gets cut out. 803 */ 804 private transient Region mixingCutoutRegion = null; 805 806 /* 807 * Indicates whether addNotify() is complete 808 * (i.e. the peer is created). 809 */ 810 private transient boolean isAddNotifyComplete = false; 811 812 /** 813 * Should only be used in subclass getBounds to check that part of bounds 814 * is actualy changing 815 */ 816 int getBoundsOp() { 817 assert Thread.holdsLock(getTreeLock()); 818 return boundsOp; 819 } 820 821 void setBoundsOp(int op) { 822 assert Thread.holdsLock(getTreeLock()); 823 if (op == ComponentPeer.RESET_OPERATION) { 824 boundsOp = ComponentPeer.DEFAULT_OPERATION; 825 } else 826 if (boundsOp == ComponentPeer.DEFAULT_OPERATION) { 827 boundsOp = op; 828 } 829 } 830 831 // Whether this Component has had the background erase flag 832 // specified via SunToolkit.disableBackgroundErase(). This is 833 // needed in order to make this function work on X11 platforms, 834 // where currently there is no chance to interpose on the creation 835 // of the peer and therefore the call to XSetBackground. 836 transient boolean backgroundEraseDisabled; 837 838 static { 839 AWTAccessor.setComponentAccessor(new AWTAccessor.ComponentAccessor() { 840 public void setBackgroundEraseDisabled(Component comp, boolean disabled) { 841 comp.backgroundEraseDisabled = disabled; 842 } 843 public boolean getBackgroundEraseDisabled(Component comp) { 844 return comp.backgroundEraseDisabled; 845 } 846 public Rectangle getBounds(Component comp) { 847 return new Rectangle(comp.x, comp.y, comp.width, comp.height); 848 } 849 public void setMixingCutoutShape(Component comp, Shape shape) { 850 Region region = shape == null ? null : 851 Region.getInstance(shape, null); 852 853 synchronized (comp.getTreeLock()) { 854 boolean needShowing = false; 855 boolean needHiding = false; 856 857 if (!comp.isNonOpaqueForMixing()) { 858 needHiding = true; 859 } 860 861 comp.mixingCutoutRegion = region; 862 863 if (!comp.isNonOpaqueForMixing()) { 864 needShowing = true; 865 } 866 867 if (comp.isMixingNeeded()) { 868 if (needHiding) { 869 comp.mixOnHiding(comp.isLightweight()); 870 } 871 if (needShowing) { 872 comp.mixOnShowing(); 873 } 874 } 875 } 876 } 877 878 public void setGraphicsConfiguration(Component comp, 879 GraphicsConfiguration gc) 880 { 881 comp.setGraphicsConfiguration(gc); 882 } 883 public boolean requestFocus(Component comp, CausedFocusEvent.Cause cause) { 884 return comp.requestFocus(cause); 885 } 886 public boolean canBeFocusOwner(Component comp) { 887 return comp.canBeFocusOwner(); 888 } 889 890 public boolean isVisible(Component comp) { 891 return comp.isVisible_NoClientCode(); 892 } 893 public void setRequestFocusController 894 (RequestFocusController requestController) 895 { 896 Component.setRequestFocusController(requestController); 897 } 898 public AppContext getAppContext(Component comp) { 899 return comp.appContext; 900 } 901 public void setAppContext(Component comp, AppContext appContext) { 902 comp.appContext = appContext; 903 } 904 public Container getParent(Component comp) { 905 return comp.getParent_NoClientCode(); 906 } 907 public void setParent(Component comp, Container parent) { 908 comp.parent = parent; 909 } 910 public void setSize(Component comp, int width, int height) { 911 comp.width = width; 912 comp.height = height; 913 } 914 public Point getLocation(Component comp) { 915 return comp.location_NoClientCode(); 916 } 917 public void setLocation(Component comp, int x, int y) { 918 comp.x = x; 919 comp.y = y; 920 } 921 public boolean isEnabled(Component comp) { 922 return comp.isEnabledImpl(); 923 } 924 public boolean isDisplayable(Component comp) { 925 return comp.peer != null; 926 } 927 public Cursor getCursor(Component comp) { 928 return comp.getCursor_NoClientCode(); 929 } 930 public ComponentPeer getPeer(Component comp) { 931 return comp.peer; 932 } 933 public void setPeer(Component comp, ComponentPeer peer) { 934 comp.peer = peer; 935 } 936 public boolean isLightweight(Component comp) { 937 return (comp.peer instanceof LightweightPeer); 938 } 939 public boolean getIgnoreRepaint(Component comp) { 940 return comp.ignoreRepaint; 941 } 942 public int getWidth(Component comp) { 943 return comp.width; 944 } 945 public int getHeight(Component comp) { 946 return comp.height; 947 } 948 public int getX(Component comp) { 949 return comp.x; 950 } 951 public int getY(Component comp) { 952 return comp.y; 953 } 954 public Color getForeground(Component comp) { 955 return comp.foreground; 956 } 957 public Color getBackground(Component comp) { 958 return comp.background; 959 } 960 public void setBackground(Component comp, Color background) { 961 comp.background = background; 962 } 963 public Font getFont(Component comp) { 964 return comp.getFont_NoClientCode(); 965 } 966 public void processEvent(Component comp, AWTEvent e) { 967 comp.processEvent(e); 968 } 969 970 public AccessControlContext getAccessControlContext(Component comp) { 971 return comp.getAccessControlContext(); 972 } 973 974 public void revalidateSynchronously(Component comp) { 975 comp.revalidateSynchronously(); 976 } 977 978 @Override 979 public void createBufferStrategy(Component comp, int numBuffers, 980 BufferCapabilities caps) throws AWTException { 981 comp.createBufferStrategy(numBuffers, caps); 982 } 983 984 @Override 985 public BufferStrategy getBufferStrategy(Component comp) { 986 return comp.getBufferStrategy(); 987 } 988 }); 989 } 990 991 /** 992 * Constructs a new component. Class <code>Component</code> can be 993 * extended directly to create a lightweight component that does not 994 * utilize an opaque native window. A lightweight component must be 995 * hosted by a native container somewhere higher up in the component 996 * tree (for example, by a <code>Frame</code> object). 997 */ 998 protected Component() { 999 appContext = AppContext.getAppContext(); 1000 } 1001 1002 @SuppressWarnings({"rawtypes", "unchecked"}) 1003 void initializeFocusTraversalKeys() { 1004 focusTraversalKeys = new Set[3]; 1005 } 1006 1007 /** 1008 * Constructs a name for this component. Called by <code>getName</code> 1009 * when the name is <code>null</code>. 1010 */ 1011 String constructComponentName() { 1012 return null; // For strict compliance with prior platform versions, a Component 1013 // that doesn't set its name should return null from 1014 // getName() 1015 } 1016 1017 /** 1018 * Gets the name of the component. 1019 * @return this component's name 1020 * @see #setName 1021 * @since JDK1.1 1022 */ 1023 public String getName() { 1024 if (name == null && !nameExplicitlySet) { 1025 synchronized(getObjectLock()) { 1026 if (name == null && !nameExplicitlySet) 1027 name = constructComponentName(); 1028 } 1029 } 1030 return name; 1031 } 1032 1033 /** 1034 * Sets the name of the component to the specified string. 1035 * @param name the string that is to be this 1036 * component's name 1037 * @see #getName 1038 * @since JDK1.1 1039 */ 1040 public void setName(String name) { 1041 String oldName; 1042 synchronized(getObjectLock()) { 1043 oldName = this.name; 1044 this.name = name; 1045 nameExplicitlySet = true; 1046 } 1047 firePropertyChange("name", oldName, name); 1048 } 1049 1050 /** 1051 * Gets the parent of this component. 1052 * @return the parent container of this component 1053 * @since JDK1.0 1054 */ 1055 public Container getParent() { 1056 return getParent_NoClientCode(); 1057 } 1058 1059 // NOTE: This method may be called by privileged threads. 1060 // This functionality is implemented in a package-private method 1061 // to insure that it cannot be overridden by client subclasses. 1062 // DO NOT INVOKE CLIENT CODE ON THIS THREAD! 1063 final Container getParent_NoClientCode() { 1064 return parent; 1065 } 1066 1067 // This method is overridden in the Window class to return null, 1068 // because the parent field of the Window object contains 1069 // the owner of the window, not its parent. 1070 Container getContainer() { 1071 return getParent_NoClientCode(); 1072 } 1073 1074 /** 1075 * @deprecated As of JDK version 1.1, 1076 * programs should not directly manipulate peers; 1077 * replaced by <code>boolean isDisplayable()</code>. 1078 */ 1079 @Deprecated 1080 public ComponentPeer getPeer() { 1081 return peer; 1082 } 1083 1084 /** 1085 * Associate a <code>DropTarget</code> with this component. 1086 * The <code>Component</code> will receive drops only if it 1087 * is enabled. 1088 * 1089 * @see #isEnabled 1090 * @param dt The DropTarget 1091 */ 1092 1093 public synchronized void setDropTarget(DropTarget dt) { 1094 if (dt == dropTarget || (dropTarget != null && dropTarget.equals(dt))) 1095 return; 1096 1097 DropTarget old; 1098 1099 if ((old = dropTarget) != null) { 1100 if (peer != null) dropTarget.removeNotify(peer); 1101 1102 DropTarget t = dropTarget; 1103 1104 dropTarget = null; 1105 1106 try { 1107 t.setComponent(null); 1108 } catch (IllegalArgumentException iae) { 1109 // ignore it. 1110 } 1111 } 1112 1113 // if we have a new one, and we have a peer, add it! 1114 1115 if ((dropTarget = dt) != null) { 1116 try { 1117 dropTarget.setComponent(this); 1118 if (peer != null) dropTarget.addNotify(peer); 1119 } catch (IllegalArgumentException iae) { 1120 if (old != null) { 1121 try { 1122 old.setComponent(this); 1123 if (peer != null) dropTarget.addNotify(peer); 1124 } catch (IllegalArgumentException iae1) { 1125 // ignore it! 1126 } 1127 } 1128 } 1129 } 1130 } 1131 1132 /** 1133 * Gets the <code>DropTarget</code> associated with this 1134 * <code>Component</code>. 1135 */ 1136 1137 public synchronized DropTarget getDropTarget() { return dropTarget; } 1138 1139 /** 1140 * Gets the <code>GraphicsConfiguration</code> associated with this 1141 * <code>Component</code>. 1142 * If the <code>Component</code> has not been assigned a specific 1143 * <code>GraphicsConfiguration</code>, 1144 * the <code>GraphicsConfiguration</code> of the 1145 * <code>Component</code> object's top-level container is 1146 * returned. 1147 * If the <code>Component</code> has been created, but not yet added 1148 * to a <code>Container</code>, this method returns <code>null</code>. 1149 * 1150 * @return the <code>GraphicsConfiguration</code> used by this 1151 * <code>Component</code> or <code>null</code> 1152 * @since 1.3 1153 */ 1154 public GraphicsConfiguration getGraphicsConfiguration() { 1155 synchronized(getTreeLock()) { 1156 return getGraphicsConfiguration_NoClientCode(); 1157 } 1158 } 1159 1160 final GraphicsConfiguration getGraphicsConfiguration_NoClientCode() { 1161 return graphicsConfig; 1162 } 1163 1164 void setGraphicsConfiguration(GraphicsConfiguration gc) { 1165 synchronized(getTreeLock()) { 1166 if (updateGraphicsData(gc)) { 1167 removeNotify(); 1168 addNotify(); 1169 } 1170 } 1171 } 1172 1173 boolean updateGraphicsData(GraphicsConfiguration gc) { 1174 checkTreeLock(); 1175 1176 if (graphicsConfig == gc) { 1177 return false; 1178 } 1179 1180 graphicsConfig = gc; 1181 1182 ComponentPeer peer = getPeer(); 1183 if (peer != null) { 1184 return peer.updateGraphicsData(gc); 1185 } 1186 return false; 1187 } 1188 1189 /** 1190 * Checks that this component's <code>GraphicsDevice</code> 1191 * <code>idString</code> matches the string argument. 1192 */ 1193 void checkGD(String stringID) { 1194 if (graphicsConfig != null) { 1195 if (!graphicsConfig.getDevice().getIDstring().equals(stringID)) { 1196 throw new IllegalArgumentException( 1197 "adding a container to a container on a different GraphicsDevice"); 1198 } 1199 } 1200 } 1201 1202 /** 1203 * Gets this component's locking object (the object that owns the thread 1204 * synchronization monitor) for AWT component-tree and layout 1205 * operations. 1206 * @return this component's locking object 1207 */ 1208 public final Object getTreeLock() { 1209 return LOCK; 1210 } 1211 1212 final void checkTreeLock() { 1213 if (!Thread.holdsLock(getTreeLock())) { 1214 throw new IllegalStateException("This function should be called while holding treeLock"); 1215 } 1216 } 1217 1218 /** 1219 * Gets the toolkit of this component. Note that 1220 * the frame that contains a component controls which 1221 * toolkit is used by that component. Therefore if the component 1222 * is moved from one frame to another, the toolkit it uses may change. 1223 * @return the toolkit of this component 1224 * @since JDK1.0 1225 */ 1226 public Toolkit getToolkit() { 1227 return getToolkitImpl(); 1228 } 1229 1230 /* 1231 * This is called by the native code, so client code can't 1232 * be called on the toolkit thread. 1233 */ 1234 final Toolkit getToolkitImpl() { 1235 Container parent = this.parent; 1236 if (parent != null) { 1237 return parent.getToolkitImpl(); 1238 } 1239 return Toolkit.getDefaultToolkit(); 1240 } 1241 1242 /** 1243 * Determines whether this component is valid. A component is valid 1244 * when it is correctly sized and positioned within its parent 1245 * container and all its children are also valid. 1246 * In order to account for peers' size requirements, components are invalidated 1247 * before they are first shown on the screen. By the time the parent container 1248 * is fully realized, all its components will be valid. 1249 * @return <code>true</code> if the component is valid, <code>false</code> 1250 * otherwise 1251 * @see #validate 1252 * @see #invalidate 1253 * @since JDK1.0 1254 */ 1255 public boolean isValid() { 1256 return (peer != null) && valid; 1257 } 1258 1259 /** 1260 * Determines whether this component is displayable. A component is 1261 * displayable when it is connected to a native screen resource. 1262 * <p> 1263 * A component is made displayable either when it is added to 1264 * a displayable containment hierarchy or when its containment 1265 * hierarchy is made displayable. 1266 * A containment hierarchy is made displayable when its ancestor 1267 * window is either packed or made visible. 1268 * <p> 1269 * A component is made undisplayable either when it is removed from 1270 * a displayable containment hierarchy or when its containment hierarchy 1271 * is made undisplayable. A containment hierarchy is made 1272 * undisplayable when its ancestor window is disposed. 1273 * 1274 * @return <code>true</code> if the component is displayable, 1275 * <code>false</code> otherwise 1276 * @see Container#add(Component) 1277 * @see Window#pack 1278 * @see Window#show 1279 * @see Container#remove(Component) 1280 * @see Window#dispose 1281 * @since 1.2 1282 */ 1283 public boolean isDisplayable() { 1284 return getPeer() != null; 1285 } 1286 1287 /** 1288 * Determines whether this component should be visible when its 1289 * parent is visible. Components are 1290 * initially visible, with the exception of top level components such 1291 * as <code>Frame</code> objects. 1292 * @return <code>true</code> if the component is visible, 1293 * <code>false</code> otherwise 1294 * @see #setVisible 1295 * @since JDK1.0 1296 */ 1297 @Transient 1298 public boolean isVisible() { 1299 return isVisible_NoClientCode(); 1300 } 1301 final boolean isVisible_NoClientCode() { 1302 return visible; 1303 } 1304 1305 /** 1306 * Determines whether this component will be displayed on the screen. 1307 * @return <code>true</code> if the component and all of its ancestors 1308 * until a toplevel window or null parent are visible, 1309 * <code>false</code> otherwise 1310 */ 1311 boolean isRecursivelyVisible() { 1312 return visible && (parent == null || parent.isRecursivelyVisible()); 1313 } 1314 1315 /** 1316 * Translates absolute coordinates into coordinates in the coordinate 1317 * space of this component. 1318 */ 1319 Point pointRelativeToComponent(Point absolute) { 1320 Point compCoords = getLocationOnScreen(); 1321 return new Point(absolute.x - compCoords.x, 1322 absolute.y - compCoords.y); 1323 } 1324 1325 /** 1326 * Assuming that mouse location is stored in PointerInfo passed 1327 * to this method, it finds a Component that is in the same 1328 * Window as this Component and is located under the mouse pointer. 1329 * If no such Component exists, null is returned. 1330 * NOTE: this method should be called under the protection of 1331 * tree lock, as it is done in Component.getMousePosition() and 1332 * Container.getMousePosition(boolean). 1333 */ 1334 Component findUnderMouseInWindow(PointerInfo pi) { 1335 if (!isShowing()) { 1336 return null; 1337 } 1338 Window win = getContainingWindow(); 1339 if (!Toolkit.getDefaultToolkit().getMouseInfoPeer().isWindowUnderMouse(win)) { 1340 return null; 1341 } 1342 final boolean INCLUDE_DISABLED = true; 1343 Point relativeToWindow = win.pointRelativeToComponent(pi.getLocation()); 1344 Component inTheSameWindow = win.findComponentAt(relativeToWindow.x, 1345 relativeToWindow.y, 1346 INCLUDE_DISABLED); 1347 return inTheSameWindow; 1348 } 1349 1350 /** 1351 * Returns the position of the mouse pointer in this <code>Component</code>'s 1352 * coordinate space if the <code>Component</code> is directly under the mouse 1353 * pointer, otherwise returns <code>null</code>. 1354 * If the <code>Component</code> is not showing on the screen, this method 1355 * returns <code>null</code> even if the mouse pointer is above the area 1356 * where the <code>Component</code> would be displayed. 1357 * If the <code>Component</code> is partially or fully obscured by other 1358 * <code>Component</code>s or native windows, this method returns a non-null 1359 * value only if the mouse pointer is located above the unobscured part of the 1360 * <code>Component</code>. 1361 * <p> 1362 * For <code>Container</code>s it returns a non-null value if the mouse is 1363 * above the <code>Container</code> itself or above any of its descendants. 1364 * Use {@link Container#getMousePosition(boolean)} if you need to exclude children. 1365 * <p> 1366 * Sometimes the exact mouse coordinates are not important, and the only thing 1367 * that matters is whether a specific <code>Component</code> is under the mouse 1368 * pointer. If the return value of this method is <code>null</code>, mouse 1369 * pointer is not directly above the <code>Component</code>. 1370 * 1371 * @exception HeadlessException if GraphicsEnvironment.isHeadless() returns true 1372 * @see #isShowing 1373 * @see Container#getMousePosition 1374 * @return mouse coordinates relative to this <code>Component</code>, or null 1375 * @since 1.5 1376 */ 1377 public Point getMousePosition() throws HeadlessException { 1378 if (GraphicsEnvironment.isHeadless()) { 1379 throw new HeadlessException(); 1380 } 1381 1382 PointerInfo pi = java.security.AccessController.doPrivileged( 1383 new java.security.PrivilegedAction<PointerInfo>() { 1384 public PointerInfo run() { 1385 return MouseInfo.getPointerInfo(); 1386 } 1387 } 1388 ); 1389 1390 synchronized (getTreeLock()) { 1391 Component inTheSameWindow = findUnderMouseInWindow(pi); 1392 if (!isSameOrAncestorOf(inTheSameWindow, true)) { 1393 return null; 1394 } 1395 return pointRelativeToComponent(pi.getLocation()); 1396 } 1397 } 1398 1399 /** 1400 * Overridden in Container. Must be called under TreeLock. 1401 */ 1402 boolean isSameOrAncestorOf(Component comp, boolean allowChildren) { 1403 return comp == this; 1404 } 1405 1406 /** 1407 * Determines whether this component is showing on screen. This means 1408 * that the component must be visible, and it must be in a container 1409 * that is visible and showing. 1410 * <p> 1411 * <strong>Note:</strong> sometimes there is no way to detect whether the 1412 * {@code Component} is actually visible to the user. This can happen when: 1413 * <ul> 1414 * <li>the component has been added to a visible {@code ScrollPane} but 1415 * the {@code Component} is not currently in the scroll pane's view port. 1416 * <li>the {@code Component} is obscured by another {@code Component} or 1417 * {@code Container}. 1418 * </ul> 1419 * @return <code>true</code> if the component is showing, 1420 * <code>false</code> otherwise 1421 * @see #setVisible 1422 * @since JDK1.0 1423 */ 1424 public boolean isShowing() { 1425 if (visible && (peer != null)) { 1426 Container parent = this.parent; 1427 return (parent == null) || parent.isShowing(); 1428 } 1429 return false; 1430 } 1431 1432 /** 1433 * Determines whether this component is enabled. An enabled component 1434 * can respond to user input and generate events. Components are 1435 * enabled initially by default. A component may be enabled or disabled by 1436 * calling its <code>setEnabled</code> method. 1437 * @return <code>true</code> if the component is enabled, 1438 * <code>false</code> otherwise 1439 * @see #setEnabled 1440 * @since JDK1.0 1441 */ 1442 public boolean isEnabled() { 1443 return isEnabledImpl(); 1444 } 1445 1446 /* 1447 * This is called by the native code, so client code can't 1448 * be called on the toolkit thread. 1449 */ 1450 final boolean isEnabledImpl() { 1451 return enabled; 1452 } 1453 1454 /** 1455 * Enables or disables this component, depending on the value of the 1456 * parameter <code>b</code>. An enabled component can respond to user 1457 * input and generate events. Components are enabled initially by default. 1458 * 1459 * <p>Note: Disabling a lightweight component does not prevent it from 1460 * receiving MouseEvents. 1461 * <p>Note: Disabling a heavyweight container prevents all components 1462 * in this container from receiving any input events. But disabling a 1463 * lightweight container affects only this container. 1464 * 1465 * @param b If <code>true</code>, this component is 1466 * enabled; otherwise this component is disabled 1467 * @see #isEnabled 1468 * @see #isLightweight 1469 * @since JDK1.1 1470 */ 1471 public void setEnabled(boolean b) { 1472 enable(b); 1473 } 1474 1475 /** 1476 * @deprecated As of JDK version 1.1, 1477 * replaced by <code>setEnabled(boolean)</code>. 1478 */ 1479 @Deprecated 1480 public void enable() { 1481 if (!enabled) { 1482 synchronized (getTreeLock()) { 1483 enabled = true; 1484 ComponentPeer peer = this.peer; 1485 if (peer != null) { 1486 peer.setEnabled(true); 1487 if (visible) { 1488 updateCursorImmediately(); 1489 } 1490 } 1491 } 1492 if (accessibleContext != null) { 1493 accessibleContext.firePropertyChange( 1494 AccessibleContext.ACCESSIBLE_STATE_PROPERTY, 1495 null, AccessibleState.ENABLED); 1496 } 1497 } 1498 } 1499 1500 /** 1501 * @deprecated As of JDK version 1.1, 1502 * replaced by <code>setEnabled(boolean)</code>. 1503 */ 1504 @Deprecated 1505 public void enable(boolean b) { 1506 if (b) { 1507 enable(); 1508 } else { 1509 disable(); 1510 } 1511 } 1512 1513 /** 1514 * @deprecated As of JDK version 1.1, 1515 * replaced by <code>setEnabled(boolean)</code>. 1516 */ 1517 @Deprecated 1518 public void disable() { 1519 if (enabled) { 1520 KeyboardFocusManager.clearMostRecentFocusOwner(this); 1521 synchronized (getTreeLock()) { 1522 enabled = false; 1523 // A disabled lw container is allowed to contain a focus owner. 1524 if ((isFocusOwner() || (containsFocus() && !isLightweight())) && 1525 KeyboardFocusManager.isAutoFocusTransferEnabled()) 1526 { 1527 // Don't clear the global focus owner. If transferFocus 1528 // fails, we want the focus to stay on the disabled 1529 // Component so that keyboard traversal, et. al. still 1530 // makes sense to the user. 1531 transferFocus(false); 1532 } 1533 ComponentPeer peer = this.peer; 1534 if (peer != null) { 1535 peer.setEnabled(false); 1536 if (visible) { 1537 updateCursorImmediately(); 1538 } 1539 } 1540 } 1541 if (accessibleContext != null) { 1542 accessibleContext.firePropertyChange( 1543 AccessibleContext.ACCESSIBLE_STATE_PROPERTY, 1544 null, AccessibleState.ENABLED); 1545 } 1546 } 1547 } 1548 1549 /** 1550 * Returns true if this component is painted to an offscreen image 1551 * ("buffer") that's copied to the screen later. Component 1552 * subclasses that support double buffering should override this 1553 * method to return true if double buffering is enabled. 1554 * 1555 * @return false by default 1556 */ 1557 public boolean isDoubleBuffered() { 1558 return false; 1559 } 1560 1561 /** 1562 * Enables or disables input method support for this component. If input 1563 * method support is enabled and the component also processes key events, 1564 * incoming events are offered to 1565 * the current input method and will only be processed by the component or 1566 * dispatched to its listeners if the input method does not consume them. 1567 * By default, input method support is enabled. 1568 * 1569 * @param enable true to enable, false to disable 1570 * @see #processKeyEvent 1571 * @since 1.2 1572 */ 1573 public void enableInputMethods(boolean enable) { 1574 if (enable) { 1575 if ((eventMask & AWTEvent.INPUT_METHODS_ENABLED_MASK) != 0) 1576 return; 1577 1578 // If this component already has focus, then activate the 1579 // input method by dispatching a synthesized focus gained 1580 // event. 1581 if (isFocusOwner()) { 1582 InputContext inputContext = getInputContext(); 1583 if (inputContext != null) { 1584 FocusEvent focusGainedEvent = 1585 new FocusEvent(this, FocusEvent.FOCUS_GAINED); 1586 inputContext.dispatchEvent(focusGainedEvent); 1587 } 1588 } 1589 1590 eventMask |= AWTEvent.INPUT_METHODS_ENABLED_MASK; 1591 } else { 1592 if ((eventMask & AWTEvent.INPUT_METHODS_ENABLED_MASK) != 0) { 1593 InputContext inputContext = getInputContext(); 1594 if (inputContext != null) { 1595 inputContext.endComposition(); 1596 inputContext.removeNotify(this); 1597 } 1598 } 1599 eventMask &= ~AWTEvent.INPUT_METHODS_ENABLED_MASK; 1600 } 1601 } 1602 1603 /** 1604 * Shows or hides this component depending on the value of parameter 1605 * <code>b</code>. 1606 * <p> 1607 * This method changes layout-related information, and therefore, 1608 * invalidates the component hierarchy. 1609 * 1610 * @param b if <code>true</code>, shows this component; 1611 * otherwise, hides this component 1612 * @see #isVisible 1613 * @see #invalidate 1614 * @since JDK1.1 1615 */ 1616 public void setVisible(boolean b) { 1617 show(b); 1618 } 1619 1620 /** 1621 * @deprecated As of JDK version 1.1, 1622 * replaced by <code>setVisible(boolean)</code>. 1623 */ 1624 @Deprecated 1625 public void show() { 1626 if (!visible) { 1627 synchronized (getTreeLock()) { 1628 visible = true; 1629 mixOnShowing(); 1630 ComponentPeer peer = this.peer; 1631 if (peer != null) { 1632 peer.setVisible(true); 1633 createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, 1634 this, parent, 1635 HierarchyEvent.SHOWING_CHANGED, 1636 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK)); 1637 if (peer instanceof LightweightPeer) { 1638 repaint(); 1639 } 1640 updateCursorImmediately(); 1641 } 1642 1643 if (componentListener != null || 1644 (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0 || 1645 Toolkit.enabledOnToolkit(AWTEvent.COMPONENT_EVENT_MASK)) { 1646 ComponentEvent e = new ComponentEvent(this, 1647 ComponentEvent.COMPONENT_SHOWN); 1648 Toolkit.getEventQueue().postEvent(e); 1649 } 1650 } 1651 Container parent = this.parent; 1652 if (parent != null) { 1653 parent.invalidate(); 1654 } 1655 } 1656 } 1657 1658 /** 1659 * @deprecated As of JDK version 1.1, 1660 * replaced by <code>setVisible(boolean)</code>. 1661 */ 1662 @Deprecated 1663 public void show(boolean b) { 1664 if (b) { 1665 show(); 1666 } else { 1667 hide(); 1668 } 1669 } 1670 1671 boolean containsFocus() { 1672 return isFocusOwner(); 1673 } 1674 1675 void clearMostRecentFocusOwnerOnHide() { 1676 KeyboardFocusManager.clearMostRecentFocusOwner(this); 1677 } 1678 1679 void clearCurrentFocusCycleRootOnHide() { 1680 /* do nothing */ 1681 } 1682 1683 /* 1684 * Delete references from LightweithDispatcher of a heavyweight parent 1685 */ 1686 void clearLightweightDispatcherOnRemove(Component removedComponent) { 1687 if (parent != null) { 1688 parent.clearLightweightDispatcherOnRemove(removedComponent); 1689 } 1690 } 1691 1692 /** 1693 * @deprecated As of JDK version 1.1, 1694 * replaced by <code>setVisible(boolean)</code>. 1695 */ 1696 @Deprecated 1697 public void hide() { 1698 isPacked = false; 1699 1700 if (visible) { 1701 clearCurrentFocusCycleRootOnHide(); 1702 clearMostRecentFocusOwnerOnHide(); 1703 synchronized (getTreeLock()) { 1704 visible = false; 1705 mixOnHiding(isLightweight()); 1706 if (containsFocus() && KeyboardFocusManager.isAutoFocusTransferEnabled()) { 1707 transferFocus(true); 1708 } 1709 ComponentPeer peer = this.peer; 1710 if (peer != null) { 1711 peer.setVisible(false); 1712 createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, 1713 this, parent, 1714 HierarchyEvent.SHOWING_CHANGED, 1715 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK)); 1716 if (peer instanceof LightweightPeer) { 1717 repaint(); 1718 } 1719 updateCursorImmediately(); 1720 } 1721 if (componentListener != null || 1722 (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0 || 1723 Toolkit.enabledOnToolkit(AWTEvent.COMPONENT_EVENT_MASK)) { 1724 ComponentEvent e = new ComponentEvent(this, 1725 ComponentEvent.COMPONENT_HIDDEN); 1726 Toolkit.getEventQueue().postEvent(e); 1727 } 1728 } 1729 Container parent = this.parent; 1730 if (parent != null) { 1731 parent.invalidate(); 1732 } 1733 } 1734 } 1735 1736 /** 1737 * Gets the foreground color of this component. 1738 * @return this component's foreground color; if this component does 1739 * not have a foreground color, the foreground color of its parent 1740 * is returned 1741 * @see #setForeground 1742 * @since JDK1.0 1743 * @beaninfo 1744 * bound: true 1745 */ 1746 @Transient 1747 public Color getForeground() { 1748 Color foreground = this.foreground; 1749 if (foreground != null) { 1750 return foreground; 1751 } 1752 Container parent = this.parent; 1753 return (parent != null) ? parent.getForeground() : null; 1754 } 1755 1756 /** 1757 * Sets the foreground color of this component. 1758 * @param c the color to become this component's 1759 * foreground color; if this parameter is <code>null</code> 1760 * then this component will inherit 1761 * the foreground color of its parent 1762 * @see #getForeground 1763 * @since JDK1.0 1764 */ 1765 public void setForeground(Color c) { 1766 Color oldColor = foreground; 1767 ComponentPeer peer = this.peer; 1768 foreground = c; 1769 if (peer != null) { 1770 c = getForeground(); 1771 if (c != null) { 1772 peer.setForeground(c); 1773 } 1774 } 1775 // This is a bound property, so report the change to 1776 // any registered listeners. (Cheap if there are none.) 1777 firePropertyChange("foreground", oldColor, c); 1778 } 1779 1780 /** 1781 * Returns whether the foreground color has been explicitly set for this 1782 * Component. If this method returns <code>false</code>, this Component is 1783 * inheriting its foreground color from an ancestor. 1784 * 1785 * @return <code>true</code> if the foreground color has been explicitly 1786 * set for this Component; <code>false</code> otherwise. 1787 * @since 1.4 1788 */ 1789 public boolean isForegroundSet() { 1790 return (foreground != null); 1791 } 1792 1793 /** 1794 * Gets the background color of this component. 1795 * @return this component's background color; if this component does 1796 * not have a background color, 1797 * the background color of its parent is returned 1798 * @see #setBackground 1799 * @since JDK1.0 1800 */ 1801 @Transient 1802 public Color getBackground() { 1803 Color background = this.background; 1804 if (background != null) { 1805 return background; 1806 } 1807 Container parent = this.parent; 1808 return (parent != null) ? parent.getBackground() : null; 1809 } 1810 1811 /** 1812 * Sets the background color of this component. 1813 * <p> 1814 * The background color affects each component differently and the 1815 * parts of the component that are affected by the background color 1816 * may differ between operating systems. 1817 * 1818 * @param c the color to become this component's color; 1819 * if this parameter is <code>null</code>, then this 1820 * component will inherit the background color of its parent 1821 * @see #getBackground 1822 * @since JDK1.0 1823 * @beaninfo 1824 * bound: true 1825 */ 1826 public void setBackground(Color c) { 1827 Color oldColor = background; 1828 ComponentPeer peer = this.peer; 1829 background = c; 1830 if (peer != null) { 1831 c = getBackground(); 1832 if (c != null) { 1833 peer.setBackground(c); 1834 } 1835 } 1836 // This is a bound property, so report the change to 1837 // any registered listeners. (Cheap if there are none.) 1838 firePropertyChange("background", oldColor, c); 1839 } 1840 1841 /** 1842 * Returns whether the background color has been explicitly set for this 1843 * Component. If this method returns <code>false</code>, this Component is 1844 * inheriting its background color from an ancestor. 1845 * 1846 * @return <code>true</code> if the background color has been explicitly 1847 * set for this Component; <code>false</code> otherwise. 1848 * @since 1.4 1849 */ 1850 public boolean isBackgroundSet() { 1851 return (background != null); 1852 } 1853 1854 /** 1855 * Gets the font of this component. 1856 * @return this component's font; if a font has not been set 1857 * for this component, the font of its parent is returned 1858 * @see #setFont 1859 * @since JDK1.0 1860 */ 1861 @Transient 1862 public Font getFont() { 1863 return getFont_NoClientCode(); 1864 } 1865 1866 // NOTE: This method may be called by privileged threads. 1867 // This functionality is implemented in a package-private method 1868 // to insure that it cannot be overridden by client subclasses. 1869 // DO NOT INVOKE CLIENT CODE ON THIS THREAD! 1870 final Font getFont_NoClientCode() { 1871 Font font = this.font; 1872 if (font != null) { 1873 return font; 1874 } 1875 Container parent = this.parent; 1876 return (parent != null) ? parent.getFont_NoClientCode() : null; 1877 } 1878 1879 /** 1880 * Sets the font of this component. 1881 * <p> 1882 * This method changes layout-related information, and therefore, 1883 * invalidates the component hierarchy. 1884 * 1885 * @param f the font to become this component's font; 1886 * if this parameter is <code>null</code> then this 1887 * component will inherit the font of its parent 1888 * @see #getFont 1889 * @see #invalidate 1890 * @since JDK1.0 1891 * @beaninfo 1892 * bound: true 1893 */ 1894 public void setFont(Font f) { 1895 Font oldFont, newFont; 1896 synchronized(getTreeLock()) { 1897 oldFont = font; 1898 newFont = font = f; 1899 ComponentPeer peer = this.peer; 1900 if (peer != null) { 1901 f = getFont(); 1902 if (f != null) { 1903 peer.setFont(f); 1904 peerFont = f; 1905 } 1906 } 1907 } 1908 // This is a bound property, so report the change to 1909 // any registered listeners. (Cheap if there are none.) 1910 firePropertyChange("font", oldFont, newFont); 1911 1912 // This could change the preferred size of the Component. 1913 // Fix for 6213660. Should compare old and new fonts and do not 1914 // call invalidate() if they are equal. 1915 if (f != oldFont && (oldFont == null || 1916 !oldFont.equals(f))) { 1917 invalidateIfValid(); 1918 } 1919 } 1920 1921 /** 1922 * Returns whether the font has been explicitly set for this Component. If 1923 * this method returns <code>false</code>, this Component is inheriting its 1924 * font from an ancestor. 1925 * 1926 * @return <code>true</code> if the font has been explicitly set for this 1927 * Component; <code>false</code> otherwise. 1928 * @since 1.4 1929 */ 1930 public boolean isFontSet() { 1931 return (font != null); 1932 } 1933 1934 /** 1935 * Gets the locale of this component. 1936 * @return this component's locale; if this component does not 1937 * have a locale, the locale of its parent is returned 1938 * @see #setLocale 1939 * @exception IllegalComponentStateException if the <code>Component</code> 1940 * does not have its own locale and has not yet been added to 1941 * a containment hierarchy such that the locale can be determined 1942 * from the containing parent 1943 * @since JDK1.1 1944 */ 1945 public Locale getLocale() { 1946 Locale locale = this.locale; 1947 if (locale != null) { 1948 return locale; 1949 } 1950 Container parent = this.parent; 1951 1952 if (parent == null) { 1953 throw new IllegalComponentStateException("This component must have a parent in order to determine its locale"); 1954 } else { 1955 return parent.getLocale(); 1956 } 1957 } 1958 1959 /** 1960 * Sets the locale of this component. This is a bound property. 1961 * <p> 1962 * This method changes layout-related information, and therefore, 1963 * invalidates the component hierarchy. 1964 * 1965 * @param l the locale to become this component's locale 1966 * @see #getLocale 1967 * @see #invalidate 1968 * @since JDK1.1 1969 */ 1970 public void setLocale(Locale l) { 1971 Locale oldValue = locale; 1972 locale = l; 1973 1974 // This is a bound property, so report the change to 1975 // any registered listeners. (Cheap if there are none.) 1976 firePropertyChange("locale", oldValue, l); 1977 1978 // This could change the preferred size of the Component. 1979 invalidateIfValid(); 1980 } 1981 1982 /** 1983 * Gets the instance of <code>ColorModel</code> used to display 1984 * the component on the output device. 1985 * @return the color model used by this component 1986 * @see java.awt.image.ColorModel 1987 * @see java.awt.peer.ComponentPeer#getColorModel() 1988 * @see Toolkit#getColorModel() 1989 * @since JDK1.0 1990 */ 1991 public ColorModel getColorModel() { 1992 ComponentPeer peer = this.peer; 1993 if ((peer != null) && ! (peer instanceof LightweightPeer)) { 1994 return peer.getColorModel(); 1995 } else if (GraphicsEnvironment.isHeadless()) { 1996 return ColorModel.getRGBdefault(); 1997 } // else 1998 return getToolkit().getColorModel(); 1999 } 2000 2001 /** 2002 * Gets the location of this component in the form of a 2003 * point specifying the component's top-left corner. 2004 * The location will be relative to the parent's coordinate space. 2005 * <p> 2006 * Due to the asynchronous nature of native event handling, this 2007 * method can return outdated values (for instance, after several calls 2008 * of <code>setLocation()</code> in rapid succession). For this 2009 * reason, the recommended method of obtaining a component's position is 2010 * within <code>java.awt.event.ComponentListener.componentMoved()</code>, 2011 * which is called after the operating system has finished moving the 2012 * component. 2013 * </p> 2014 * @return an instance of <code>Point</code> representing 2015 * the top-left corner of the component's bounds in 2016 * the coordinate space of the component's parent 2017 * @see #setLocation 2018 * @see #getLocationOnScreen 2019 * @since JDK1.1 2020 */ 2021 public Point getLocation() { 2022 return location(); 2023 } 2024 2025 /** 2026 * Gets the location of this component in the form of a point 2027 * specifying the component's top-left corner in the screen's 2028 * coordinate space. 2029 * @return an instance of <code>Point</code> representing 2030 * the top-left corner of the component's bounds in the 2031 * coordinate space of the screen 2032 * @throws IllegalComponentStateException if the 2033 * component is not showing on the screen 2034 * @see #setLocation 2035 * @see #getLocation 2036 */ 2037 public Point getLocationOnScreen() { 2038 synchronized (getTreeLock()) { 2039 return getLocationOnScreen_NoTreeLock(); 2040 } 2041 } 2042 2043 /* 2044 * a package private version of getLocationOnScreen 2045 * used by GlobalCursormanager to update cursor 2046 */ 2047 final Point getLocationOnScreen_NoTreeLock() { 2048 2049 if (peer != null && isShowing()) { 2050 if (peer instanceof LightweightPeer) { 2051 // lightweight component location needs to be translated 2052 // relative to a native component. 2053 Container host = getNativeContainer(); 2054 Point pt = host.peer.getLocationOnScreen(); 2055 for(Component c = this; c != host; c = c.getParent()) { 2056 pt.x += c.x; 2057 pt.y += c.y; 2058 } 2059 return pt; 2060 } else { 2061 Point pt = peer.getLocationOnScreen(); 2062 return pt; 2063 } 2064 } else { 2065 throw new IllegalComponentStateException("component must be showing on the screen to determine its location"); 2066 } 2067 } 2068 2069 2070 /** 2071 * @deprecated As of JDK version 1.1, 2072 * replaced by <code>getLocation()</code>. 2073 */ 2074 @Deprecated 2075 public Point location() { 2076 return location_NoClientCode(); 2077 } 2078 2079 private Point location_NoClientCode() { 2080 return new Point(x, y); 2081 } 2082 2083 /** 2084 * Moves this component to a new location. The top-left corner of 2085 * the new location is specified by the <code>x</code> and <code>y</code> 2086 * parameters in the coordinate space of this component's parent. 2087 * <p> 2088 * This method changes layout-related information, and therefore, 2089 * invalidates the component hierarchy. 2090 * 2091 * @param x the <i>x</i>-coordinate of the new location's 2092 * top-left corner in the parent's coordinate space 2093 * @param y the <i>y</i>-coordinate of the new location's 2094 * top-left corner in the parent's coordinate space 2095 * @see #getLocation 2096 * @see #setBounds 2097 * @see #invalidate 2098 * @since JDK1.1 2099 */ 2100 public void setLocation(int x, int y) { 2101 move(x, y); 2102 } 2103 2104 /** 2105 * @deprecated As of JDK version 1.1, 2106 * replaced by <code>setLocation(int, int)</code>. 2107 */ 2108 @Deprecated 2109 public void move(int x, int y) { 2110 synchronized(getTreeLock()) { 2111 setBoundsOp(ComponentPeer.SET_LOCATION); 2112 setBounds(x, y, width, height); 2113 } 2114 } 2115 2116 /** 2117 * Moves this component to a new location. The top-left corner of 2118 * the new location is specified by point <code>p</code>. Point 2119 * <code>p</code> is given in the parent's coordinate space. 2120 * <p> 2121 * This method changes layout-related information, and therefore, 2122 * invalidates the component hierarchy. 2123 * 2124 * @param p the point defining the top-left corner 2125 * of the new location, given in the coordinate space of this 2126 * component's parent 2127 * @see #getLocation 2128 * @see #setBounds 2129 * @see #invalidate 2130 * @since JDK1.1 2131 */ 2132 public void setLocation(Point p) { 2133 setLocation(p.x, p.y); 2134 } 2135 2136 /** 2137 * Returns the size of this component in the form of a 2138 * <code>Dimension</code> object. The <code>height</code> 2139 * field of the <code>Dimension</code> object contains 2140 * this component's height, and the <code>width</code> 2141 * field of the <code>Dimension</code> object contains 2142 * this component's width. 2143 * @return a <code>Dimension</code> object that indicates the 2144 * size of this component 2145 * @see #setSize 2146 * @since JDK1.1 2147 */ 2148 public Dimension getSize() { 2149 return size(); 2150 } 2151 2152 /** 2153 * @deprecated As of JDK version 1.1, 2154 * replaced by <code>getSize()</code>. 2155 */ 2156 @Deprecated 2157 public Dimension size() { 2158 return new Dimension(width, height); 2159 } 2160 2161 /** 2162 * Resizes this component so that it has width <code>width</code> 2163 * and height <code>height</code>. 2164 * <p> 2165 * This method changes layout-related information, and therefore, 2166 * invalidates the component hierarchy. 2167 * 2168 * @param width the new width of this component in pixels 2169 * @param height the new height of this component in pixels 2170 * @see #getSize 2171 * @see #setBounds 2172 * @see #invalidate 2173 * @since JDK1.1 2174 */ 2175 public void setSize(int width, int height) { 2176 resize(width, height); 2177 } 2178 2179 /** 2180 * @deprecated As of JDK version 1.1, 2181 * replaced by <code>setSize(int, int)</code>. 2182 */ 2183 @Deprecated 2184 public void resize(int width, int height) { 2185 synchronized(getTreeLock()) { 2186 setBoundsOp(ComponentPeer.SET_SIZE); 2187 setBounds(x, y, width, height); 2188 } 2189 } 2190 2191 /** 2192 * Resizes this component so that it has width <code>d.width</code> 2193 * and height <code>d.height</code>. 2194 * <p> 2195 * This method changes layout-related information, and therefore, 2196 * invalidates the component hierarchy. 2197 * 2198 * @param d the dimension specifying the new size 2199 * of this component 2200 * @throws NullPointerException if {@code d} is {@code null} 2201 * @see #setSize 2202 * @see #setBounds 2203 * @see #invalidate 2204 * @since JDK1.1 2205 */ 2206 public void setSize(Dimension d) { 2207 resize(d); 2208 } 2209 2210 /** 2211 * @deprecated As of JDK version 1.1, 2212 * replaced by <code>setSize(Dimension)</code>. 2213 */ 2214 @Deprecated 2215 public void resize(Dimension d) { 2216 setSize(d.width, d.height); 2217 } 2218 2219 /** 2220 * Gets the bounds of this component in the form of a 2221 * <code>Rectangle</code> object. The bounds specify this 2222 * component's width, height, and location relative to 2223 * its parent. 2224 * @return a rectangle indicating this component's bounds 2225 * @see #setBounds 2226 * @see #getLocation 2227 * @see #getSize 2228 */ 2229 public Rectangle getBounds() { 2230 return bounds(); 2231 } 2232 2233 /** 2234 * @deprecated As of JDK version 1.1, 2235 * replaced by <code>getBounds()</code>. 2236 */ 2237 @Deprecated 2238 public Rectangle bounds() { 2239 return new Rectangle(x, y, width, height); 2240 } 2241 2242 /** 2243 * Moves and resizes this component. The new location of the top-left 2244 * corner is specified by <code>x</code> and <code>y</code>, and the 2245 * new size is specified by <code>width</code> and <code>height</code>. 2246 * <p> 2247 * This method changes layout-related information, and therefore, 2248 * invalidates the component hierarchy. 2249 * 2250 * @param x the new <i>x</i>-coordinate of this component 2251 * @param y the new <i>y</i>-coordinate of this component 2252 * @param width the new <code>width</code> of this component 2253 * @param height the new <code>height</code> of this 2254 * component 2255 * @see #getBounds 2256 * @see #setLocation(int, int) 2257 * @see #setLocation(Point) 2258 * @see #setSize(int, int) 2259 * @see #setSize(Dimension) 2260 * @see #invalidate 2261 * @since JDK1.1 2262 */ 2263 public void setBounds(int x, int y, int width, int height) { 2264 reshape(x, y, width, height); 2265 } 2266 2267 /** 2268 * @deprecated As of JDK version 1.1, 2269 * replaced by <code>setBounds(int, int, int, int)</code>. 2270 */ 2271 @Deprecated 2272 public void reshape(int x, int y, int width, int height) { 2273 synchronized (getTreeLock()) { 2274 try { 2275 setBoundsOp(ComponentPeer.SET_BOUNDS); 2276 boolean resized = (this.width != width) || (this.height != height); 2277 boolean moved = (this.x != x) || (this.y != y); 2278 if (!resized && !moved) { 2279 return; 2280 } 2281 int oldX = this.x; 2282 int oldY = this.y; 2283 int oldWidth = this.width; 2284 int oldHeight = this.height; 2285 this.x = x; 2286 this.y = y; 2287 this.width = width; 2288 this.height = height; 2289 2290 if (resized) { 2291 isPacked = false; 2292 } 2293 2294 boolean needNotify = true; 2295 mixOnReshaping(); 2296 if (peer != null) { 2297 // LightwightPeer is an empty stub so can skip peer.reshape 2298 if (!(peer instanceof LightweightPeer)) { 2299 reshapeNativePeer(x, y, width, height, getBoundsOp()); 2300 // Check peer actualy changed coordinates 2301 resized = (oldWidth != this.width) || (oldHeight != this.height); 2302 moved = (oldX != this.x) || (oldY != this.y); 2303 // fix for 5025858: do not send ComponentEvents for toplevel 2304 // windows here as it is done from peer or native code when 2305 // the window is really resized or moved, otherwise some 2306 // events may be sent twice 2307 if (this instanceof Window) { 2308 needNotify = false; 2309 } 2310 } 2311 if (resized) { 2312 invalidate(); 2313 } 2314 if (parent != null) { 2315 parent.invalidateIfValid(); 2316 } 2317 } 2318 if (needNotify) { 2319 notifyNewBounds(resized, moved); 2320 } 2321 repaintParentIfNeeded(oldX, oldY, oldWidth, oldHeight); 2322 } finally { 2323 setBoundsOp(ComponentPeer.RESET_OPERATION); 2324 } 2325 } 2326 } 2327 2328 private void repaintParentIfNeeded(int oldX, int oldY, int oldWidth, 2329 int oldHeight) 2330 { 2331 if (parent != null && peer instanceof LightweightPeer && isShowing()) { 2332 // Have the parent redraw the area this component occupied. 2333 parent.repaint(oldX, oldY, oldWidth, oldHeight); 2334 // Have the parent redraw the area this component *now* occupies. 2335 repaint(); 2336 } 2337 } 2338 2339 private void reshapeNativePeer(int x, int y, int width, int height, int op) { 2340 // native peer might be offset by more than direct 2341 // parent since parent might be lightweight. 2342 int nativeX = x; 2343 int nativeY = y; 2344 for (Component c = parent; 2345 (c != null) && (c.peer instanceof LightweightPeer); 2346 c = c.parent) 2347 { 2348 nativeX += c.x; 2349 nativeY += c.y; 2350 } 2351 peer.setBounds(nativeX, nativeY, width, height, op); 2352 } 2353 2354 @SuppressWarnings("deprecation") 2355 private void notifyNewBounds(boolean resized, boolean moved) { 2356 if (componentListener != null 2357 || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0 2358 || Toolkit.enabledOnToolkit(AWTEvent.COMPONENT_EVENT_MASK)) 2359 { 2360 if (resized) { 2361 ComponentEvent e = new ComponentEvent(this, 2362 ComponentEvent.COMPONENT_RESIZED); 2363 Toolkit.getEventQueue().postEvent(e); 2364 } 2365 if (moved) { 2366 ComponentEvent e = new ComponentEvent(this, 2367 ComponentEvent.COMPONENT_MOVED); 2368 Toolkit.getEventQueue().postEvent(e); 2369 } 2370 } else { 2371 if (this instanceof Container && ((Container)this).countComponents() > 0) { 2372 boolean enabledOnToolkit = 2373 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK); 2374 if (resized) { 2375 2376 ((Container)this).createChildHierarchyEvents( 2377 HierarchyEvent.ANCESTOR_RESIZED, 0, enabledOnToolkit); 2378 } 2379 if (moved) { 2380 ((Container)this).createChildHierarchyEvents( 2381 HierarchyEvent.ANCESTOR_MOVED, 0, enabledOnToolkit); 2382 } 2383 } 2384 } 2385 } 2386 2387 /** 2388 * Moves and resizes this component to conform to the new 2389 * bounding rectangle <code>r</code>. This component's new 2390 * position is specified by <code>r.x</code> and <code>r.y</code>, 2391 * and its new size is specified by <code>r.width</code> and 2392 * <code>r.height</code> 2393 * <p> 2394 * This method changes layout-related information, and therefore, 2395 * invalidates the component hierarchy. 2396 * 2397 * @param r the new bounding rectangle for this component 2398 * @throws NullPointerException if {@code r} is {@code null} 2399 * @see #getBounds 2400 * @see #setLocation(int, int) 2401 * @see #setLocation(Point) 2402 * @see #setSize(int, int) 2403 * @see #setSize(Dimension) 2404 * @see #invalidate 2405 * @since JDK1.1 2406 */ 2407 public void setBounds(Rectangle r) { 2408 setBounds(r.x, r.y, r.width, r.height); 2409 } 2410 2411 2412 /** 2413 * Returns the current x coordinate of the components origin. 2414 * This method is preferable to writing 2415 * <code>component.getBounds().x</code>, 2416 * or <code>component.getLocation().x</code> because it doesn't 2417 * cause any heap allocations. 2418 * 2419 * @return the current x coordinate of the components origin 2420 * @since 1.2 2421 */ 2422 public int getX() { 2423 return x; 2424 } 2425 2426 2427 /** 2428 * Returns the current y coordinate of the components origin. 2429 * This method is preferable to writing 2430 * <code>component.getBounds().y</code>, 2431 * or <code>component.getLocation().y</code> because it 2432 * doesn't cause any heap allocations. 2433 * 2434 * @return the current y coordinate of the components origin 2435 * @since 1.2 2436 */ 2437 public int getY() { 2438 return y; 2439 } 2440 2441 2442 /** 2443 * Returns the current width of this component. 2444 * This method is preferable to writing 2445 * <code>component.getBounds().width</code>, 2446 * or <code>component.getSize().width</code> because it 2447 * doesn't cause any heap allocations. 2448 * 2449 * @return the current width of this component 2450 * @since 1.2 2451 */ 2452 public int getWidth() { 2453 return width; 2454 } 2455 2456 2457 /** 2458 * Returns the current height of this component. 2459 * This method is preferable to writing 2460 * <code>component.getBounds().height</code>, 2461 * or <code>component.getSize().height</code> because it 2462 * doesn't cause any heap allocations. 2463 * 2464 * @return the current height of this component 2465 * @since 1.2 2466 */ 2467 public int getHeight() { 2468 return height; 2469 } 2470 2471 /** 2472 * Stores the bounds of this component into "return value" <b>rv</b> and 2473 * return <b>rv</b>. If rv is <code>null</code> a new 2474 * <code>Rectangle</code> is allocated. 2475 * This version of <code>getBounds</code> is useful if the caller 2476 * wants to avoid allocating a new <code>Rectangle</code> object 2477 * on the heap. 2478 * 2479 * @param rv the return value, modified to the components bounds 2480 * @return rv 2481 */ 2482 public Rectangle getBounds(Rectangle rv) { 2483 if (rv == null) { 2484 return new Rectangle(getX(), getY(), getWidth(), getHeight()); 2485 } 2486 else { 2487 rv.setBounds(getX(), getY(), getWidth(), getHeight()); 2488 return rv; 2489 } 2490 } 2491 2492 /** 2493 * Stores the width/height of this component into "return value" <b>rv</b> 2494 * and return <b>rv</b>. If rv is <code>null</code> a new 2495 * <code>Dimension</code> object is allocated. This version of 2496 * <code>getSize</code> is useful if the caller wants to avoid 2497 * allocating a new <code>Dimension</code> object on the heap. 2498 * 2499 * @param rv the return value, modified to the components size 2500 * @return rv 2501 */ 2502 public Dimension getSize(Dimension rv) { 2503 if (rv == null) { 2504 return new Dimension(getWidth(), getHeight()); 2505 } 2506 else { 2507 rv.setSize(getWidth(), getHeight()); 2508 return rv; 2509 } 2510 } 2511 2512 /** 2513 * Stores the x,y origin of this component into "return value" <b>rv</b> 2514 * and return <b>rv</b>. If rv is <code>null</code> a new 2515 * <code>Point</code> is allocated. 2516 * This version of <code>getLocation</code> is useful if the 2517 * caller wants to avoid allocating a new <code>Point</code> 2518 * object on the heap. 2519 * 2520 * @param rv the return value, modified to the components location 2521 * @return rv 2522 */ 2523 public Point getLocation(Point rv) { 2524 if (rv == null) { 2525 return new Point(getX(), getY()); 2526 } 2527 else { 2528 rv.setLocation(getX(), getY()); 2529 return rv; 2530 } 2531 } 2532 2533 /** 2534 * Returns true if this component is completely opaque, returns 2535 * false by default. 2536 * <p> 2537 * An opaque component paints every pixel within its 2538 * rectangular region. A non-opaque component paints only some of 2539 * its pixels, allowing the pixels underneath it to "show through". 2540 * A component that does not fully paint its pixels therefore 2541 * provides a degree of transparency. 2542 * <p> 2543 * Subclasses that guarantee to always completely paint their 2544 * contents should override this method and return true. 2545 * 2546 * @return true if this component is completely opaque 2547 * @see #isLightweight 2548 * @since 1.2 2549 */ 2550 public boolean isOpaque() { 2551 if (getPeer() == null) { 2552 return false; 2553 } 2554 else { 2555 return !isLightweight(); 2556 } 2557 } 2558 2559 2560 /** 2561 * A lightweight component doesn't have a native toolkit peer. 2562 * Subclasses of <code>Component</code> and <code>Container</code>, 2563 * other than the ones defined in this package like <code>Button</code> 2564 * or <code>Scrollbar</code>, are lightweight. 2565 * All of the Swing components are lightweights. 2566 * <p> 2567 * This method will always return <code>false</code> if this component 2568 * is not displayable because it is impossible to determine the 2569 * weight of an undisplayable component. 2570 * 2571 * @return true if this component has a lightweight peer; false if 2572 * it has a native peer or no peer 2573 * @see #isDisplayable 2574 * @since 1.2 2575 */ 2576 public boolean isLightweight() { 2577 return getPeer() instanceof LightweightPeer; 2578 } 2579 2580 2581 /** 2582 * Sets the preferred size of this component to a constant 2583 * value. Subsequent calls to <code>getPreferredSize</code> will always 2584 * return this value. Setting the preferred size to <code>null</code> 2585 * restores the default behavior. 2586 * 2587 * @param preferredSize The new preferred size, or null 2588 * @see #getPreferredSize 2589 * @see #isPreferredSizeSet 2590 * @since 1.5 2591 */ 2592 public void setPreferredSize(Dimension preferredSize) { 2593 Dimension old; 2594 // If the preferred size was set, use it as the old value, otherwise 2595 // use null to indicate we didn't previously have a set preferred 2596 // size. 2597 if (prefSizeSet) { 2598 old = this.prefSize; 2599 } 2600 else { 2601 old = null; 2602 } 2603 this.prefSize = preferredSize; 2604 prefSizeSet = (preferredSize != null); 2605 firePropertyChange("preferredSize", old, preferredSize); 2606 } 2607 2608 2609 /** 2610 * Returns true if the preferred size has been set to a 2611 * non-<code>null</code> value otherwise returns false. 2612 * 2613 * @return true if <code>setPreferredSize</code> has been invoked 2614 * with a non-null value. 2615 * @since 1.5 2616 */ 2617 public boolean isPreferredSizeSet() { 2618 return prefSizeSet; 2619 } 2620 2621 2622 /** 2623 * Gets the preferred size of this component. 2624 * @return a dimension object indicating this component's preferred size 2625 * @see #getMinimumSize 2626 * @see LayoutManager 2627 */ 2628 public Dimension getPreferredSize() { 2629 return preferredSize(); 2630 } 2631 2632 2633 /** 2634 * @deprecated As of JDK version 1.1, 2635 * replaced by <code>getPreferredSize()</code>. 2636 */ 2637 @Deprecated 2638 public Dimension preferredSize() { 2639 /* Avoid grabbing the lock if a reasonable cached size value 2640 * is available. 2641 */ 2642 Dimension dim = prefSize; 2643 if (dim == null || !(isPreferredSizeSet() || isValid())) { 2644 synchronized (getTreeLock()) { 2645 prefSize = (peer != null) ? 2646 peer.getPreferredSize() : 2647 getMinimumSize(); 2648 dim = prefSize; 2649 } 2650 } 2651 return new Dimension(dim); 2652 } 2653 2654 /** 2655 * Sets the minimum size of this component to a constant 2656 * value. Subsequent calls to <code>getMinimumSize</code> will always 2657 * return this value. Setting the minimum size to <code>null</code> 2658 * restores the default behavior. 2659 * 2660 * @param minimumSize the new minimum size of this component 2661 * @see #getMinimumSize 2662 * @see #isMinimumSizeSet 2663 * @since 1.5 2664 */ 2665 public void setMinimumSize(Dimension minimumSize) { 2666 Dimension old; 2667 // If the minimum size was set, use it as the old value, otherwise 2668 // use null to indicate we didn't previously have a set minimum 2669 // size. 2670 if (minSizeSet) { 2671 old = this.minSize; 2672 } 2673 else { 2674 old = null; 2675 } 2676 this.minSize = minimumSize; 2677 minSizeSet = (minimumSize != null); 2678 firePropertyChange("minimumSize", old, minimumSize); 2679 } 2680 2681 /** 2682 * Returns whether or not <code>setMinimumSize</code> has been 2683 * invoked with a non-null value. 2684 * 2685 * @return true if <code>setMinimumSize</code> has been invoked with a 2686 * non-null value. 2687 * @since 1.5 2688 */ 2689 public boolean isMinimumSizeSet() { 2690 return minSizeSet; 2691 } 2692 2693 /** 2694 * Gets the minimum size of this component. 2695 * @return a dimension object indicating this component's minimum size 2696 * @see #getPreferredSize 2697 * @see LayoutManager 2698 */ 2699 public Dimension getMinimumSize() { 2700 return minimumSize(); 2701 } 2702 2703 /** 2704 * @deprecated As of JDK version 1.1, 2705 * replaced by <code>getMinimumSize()</code>. 2706 */ 2707 @Deprecated 2708 public Dimension minimumSize() { 2709 /* Avoid grabbing the lock if a reasonable cached size value 2710 * is available. 2711 */ 2712 Dimension dim = minSize; 2713 if (dim == null || !(isMinimumSizeSet() || isValid())) { 2714 synchronized (getTreeLock()) { 2715 minSize = (peer != null) ? 2716 peer.getMinimumSize() : 2717 size(); 2718 dim = minSize; 2719 } 2720 } 2721 return new Dimension(dim); 2722 } 2723 2724 /** 2725 * Sets the maximum size of this component to a constant 2726 * value. Subsequent calls to <code>getMaximumSize</code> will always 2727 * return this value. Setting the maximum size to <code>null</code> 2728 * restores the default behavior. 2729 * 2730 * @param maximumSize a <code>Dimension</code> containing the 2731 * desired maximum allowable size 2732 * @see #getMaximumSize 2733 * @see #isMaximumSizeSet 2734 * @since 1.5 2735 */ 2736 public void setMaximumSize(Dimension maximumSize) { 2737 // If the maximum size was set, use it as the old value, otherwise 2738 // use null to indicate we didn't previously have a set maximum 2739 // size. 2740 Dimension old; 2741 if (maxSizeSet) { 2742 old = this.maxSize; 2743 } 2744 else { 2745 old = null; 2746 } 2747 this.maxSize = maximumSize; 2748 maxSizeSet = (maximumSize != null); 2749 firePropertyChange("maximumSize", old, maximumSize); 2750 } 2751 2752 /** 2753 * Returns true if the maximum size has been set to a non-<code>null</code> 2754 * value otherwise returns false. 2755 * 2756 * @return true if <code>maximumSize</code> is non-<code>null</code>, 2757 * false otherwise 2758 * @since 1.5 2759 */ 2760 public boolean isMaximumSizeSet() { 2761 return maxSizeSet; 2762 } 2763 2764 /** 2765 * Gets the maximum size of this component. 2766 * @return a dimension object indicating this component's maximum size 2767 * @see #getMinimumSize 2768 * @see #getPreferredSize 2769 * @see LayoutManager 2770 */ 2771 public Dimension getMaximumSize() { 2772 if (isMaximumSizeSet()) { 2773 return new Dimension(maxSize); 2774 } 2775 return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE); 2776 } 2777 2778 /** 2779 * Returns the alignment along the x axis. This specifies how 2780 * the component would like to be aligned relative to other 2781 * components. The value should be a number between 0 and 1 2782 * where 0 represents alignment along the origin, 1 is aligned 2783 * the furthest away from the origin, 0.5 is centered, etc. 2784 */ 2785 public float getAlignmentX() { 2786 return CENTER_ALIGNMENT; 2787 } 2788 2789 /** 2790 * Returns the alignment along the y axis. This specifies how 2791 * the component would like to be aligned relative to other 2792 * components. The value should be a number between 0 and 1 2793 * where 0 represents alignment along the origin, 1 is aligned 2794 * the furthest away from the origin, 0.5 is centered, etc. 2795 */ 2796 public float getAlignmentY() { 2797 return CENTER_ALIGNMENT; 2798 } 2799 2800 /** 2801 * Returns the baseline. The baseline is measured from the top of 2802 * the component. This method is primarily meant for 2803 * <code>LayoutManager</code>s to align components along their 2804 * baseline. A return value less than 0 indicates this component 2805 * does not have a reasonable baseline and that 2806 * <code>LayoutManager</code>s should not align this component on 2807 * its baseline. 2808 * <p> 2809 * The default implementation returns -1. Subclasses that support 2810 * baseline should override appropriately. If a value >= 0 is 2811 * returned, then the component has a valid baseline for any 2812 * size >= the minimum size and <code>getBaselineResizeBehavior</code> 2813 * can be used to determine how the baseline changes with size. 2814 * 2815 * @param width the width to get the baseline for 2816 * @param height the height to get the baseline for 2817 * @return the baseline or < 0 indicating there is no reasonable 2818 * baseline 2819 * @throws IllegalArgumentException if width or height is < 0 2820 * @see #getBaselineResizeBehavior 2821 * @see java.awt.FontMetrics 2822 * @since 1.6 2823 */ 2824 public int getBaseline(int width, int height) { 2825 if (width < 0 || height < 0) { 2826 throw new IllegalArgumentException( 2827 "Width and height must be >= 0"); 2828 } 2829 return -1; 2830 } 2831 2832 /** 2833 * Returns an enum indicating how the baseline of the component 2834 * changes as the size changes. This method is primarily meant for 2835 * layout managers and GUI builders. 2836 * <p> 2837 * The default implementation returns 2838 * <code>BaselineResizeBehavior.OTHER</code>. Subclasses that have a 2839 * baseline should override appropriately. Subclasses should 2840 * never return <code>null</code>; if the baseline can not be 2841 * calculated return <code>BaselineResizeBehavior.OTHER</code>. Callers 2842 * should first ask for the baseline using 2843 * <code>getBaseline</code> and if a value >= 0 is returned use 2844 * this method. It is acceptable for this method to return a 2845 * value other than <code>BaselineResizeBehavior.OTHER</code> even if 2846 * <code>getBaseline</code> returns a value less than 0. 2847 * 2848 * @return an enum indicating how the baseline changes as the component 2849 * size changes 2850 * @see #getBaseline(int, int) 2851 * @since 1.6 2852 */ 2853 public BaselineResizeBehavior getBaselineResizeBehavior() { 2854 return BaselineResizeBehavior.OTHER; 2855 } 2856 2857 /** 2858 * Prompts the layout manager to lay out this component. This is 2859 * usually called when the component (more specifically, container) 2860 * is validated. 2861 * @see #validate 2862 * @see LayoutManager 2863 */ 2864 public void doLayout() { 2865 layout(); 2866 } 2867 2868 /** 2869 * @deprecated As of JDK version 1.1, 2870 * replaced by <code>doLayout()</code>. 2871 */ 2872 @Deprecated 2873 public void layout() { 2874 } 2875 2876 /** 2877 * Validates this component. 2878 * <p> 2879 * The meaning of the term <i>validating</i> is defined by the ancestors of 2880 * this class. See {@link Container#validate} for more details. 2881 * 2882 * @see #invalidate 2883 * @see #doLayout() 2884 * @see LayoutManager 2885 * @see Container#validate 2886 * @since JDK1.0 2887 */ 2888 public void validate() { 2889 synchronized (getTreeLock()) { 2890 ComponentPeer peer = this.peer; 2891 boolean wasValid = isValid(); 2892 if (!wasValid && peer != null) { 2893 Font newfont = getFont(); 2894 Font oldfont = peerFont; 2895 if (newfont != oldfont && (oldfont == null 2896 || !oldfont.equals(newfont))) { 2897 peer.setFont(newfont); 2898 peerFont = newfont; 2899 } 2900 peer.layout(); 2901 } 2902 valid = true; 2903 if (!wasValid) { 2904 mixOnValidating(); 2905 } 2906 } 2907 } 2908 2909 /** 2910 * Invalidates this component and its ancestors. 2911 * <p> 2912 * By default, all the ancestors of the component up to the top-most 2913 * container of the hierarchy are marked invalid. If the {@code 2914 * java.awt.smartInvalidate} system property is set to {@code true}, 2915 * invalidation stops on the nearest validate root of this component. 2916 * Marking a container <i>invalid</i> indicates that the container needs to 2917 * be laid out. 2918 * <p> 2919 * This method is called automatically when any layout-related information 2920 * changes (e.g. setting the bounds of the component, or adding the 2921 * component to a container). 2922 * <p> 2923 * This method might be called often, so it should work fast. 2924 * 2925 * @see #validate 2926 * @see #doLayout 2927 * @see LayoutManager 2928 * @see java.awt.Container#isValidateRoot 2929 * @since JDK1.0 2930 */ 2931 public void invalidate() { 2932 synchronized (getTreeLock()) { 2933 /* Nullify cached layout and size information. 2934 * For efficiency, propagate invalidate() upwards only if 2935 * some other component hasn't already done so first. 2936 */ 2937 valid = false; 2938 if (!isPreferredSizeSet()) { 2939 prefSize = null; 2940 } 2941 if (!isMinimumSizeSet()) { 2942 minSize = null; 2943 } 2944 if (!isMaximumSizeSet()) { 2945 maxSize = null; 2946 } 2947 invalidateParent(); 2948 } 2949 } 2950 2951 /** 2952 * Invalidates the parent of this component if any. 2953 * 2954 * This method MUST BE invoked under the TreeLock. 2955 */ 2956 void invalidateParent() { 2957 if (parent != null) { 2958 parent.invalidateIfValid(); 2959 } 2960 } 2961 2962 /** Invalidates the component unless it is already invalid. 2963 */ 2964 final void invalidateIfValid() { 2965 if (isValid()) { 2966 invalidate(); 2967 } 2968 } 2969 2970 /** 2971 * Revalidates the component hierarchy up to the nearest validate root. 2972 * <p> 2973 * This method first invalidates the component hierarchy starting from this 2974 * component up to the nearest validate root. Afterwards, the component 2975 * hierarchy is validated starting from the nearest validate root. 2976 * <p> 2977 * This is a convenience method supposed to help application developers 2978 * avoid looking for validate roots manually. Basically, it's equivalent to 2979 * first calling the {@link #invalidate()} method on this component, and 2980 * then calling the {@link #validate()} method on the nearest validate 2981 * root. 2982 * 2983 * @see Container#isValidateRoot 2984 * @since 1.7 2985 */ 2986 public void revalidate() { 2987 revalidateSynchronously(); 2988 } 2989 2990 /** 2991 * Revalidates the component synchronously. 2992 */ 2993 final void revalidateSynchronously() { 2994 synchronized (getTreeLock()) { 2995 invalidate(); 2996 2997 Container root = getContainer(); 2998 if (root == null) { 2999 // There's no parents. Just validate itself. 3000 validate(); 3001 } else { 3002 while (!root.isValidateRoot()) { 3003 if (root.getContainer() == null) { 3004 // If there's no validate roots, we'll validate the 3005 // topmost container 3006 break; 3007 } 3008 3009 root = root.getContainer(); 3010 } 3011 3012 root.validate(); 3013 } 3014 } 3015 } 3016 3017 /** 3018 * Creates a graphics context for this component. This method will 3019 * return <code>null</code> if this component is currently not 3020 * displayable. 3021 * @return a graphics context for this component, or <code>null</code> 3022 * if it has none 3023 * @see #paint 3024 * @since JDK1.0 3025 */ 3026 public Graphics getGraphics() { 3027 if (peer instanceof LightweightPeer) { 3028 // This is for a lightweight component, need to 3029 // translate coordinate spaces and clip relative 3030 // to the parent. 3031 if (parent == null) return null; 3032 Graphics g = parent.getGraphics(); 3033 if (g == null) return null; 3034 if (g instanceof ConstrainableGraphics) { 3035 ((ConstrainableGraphics) g).constrain(x, y, width, height); 3036 } else { 3037 g.translate(x,y); 3038 g.setClip(0, 0, width, height); 3039 } 3040 g.setFont(getFont()); 3041 return g; 3042 } else { 3043 ComponentPeer peer = this.peer; 3044 return (peer != null) ? peer.getGraphics() : null; 3045 } 3046 } 3047 3048 final Graphics getGraphics_NoClientCode() { 3049 ComponentPeer peer = this.peer; 3050 if (peer instanceof LightweightPeer) { 3051 // This is for a lightweight component, need to 3052 // translate coordinate spaces and clip relative 3053 // to the parent. 3054 Container parent = this.parent; 3055 if (parent == null) return null; 3056 Graphics g = parent.getGraphics_NoClientCode(); 3057 if (g == null) return null; 3058 if (g instanceof ConstrainableGraphics) { 3059 ((ConstrainableGraphics) g).constrain(x, y, width, height); 3060 } else { 3061 g.translate(x,y); 3062 g.setClip(0, 0, width, height); 3063 } 3064 g.setFont(getFont_NoClientCode()); 3065 return g; 3066 } else { 3067 return (peer != null) ? peer.getGraphics() : null; 3068 } 3069 } 3070 3071 /** 3072 * Gets the font metrics for the specified font. 3073 * Warning: Since Font metrics are affected by the 3074 * {@link java.awt.font.FontRenderContext FontRenderContext} and 3075 * this method does not provide one, it can return only metrics for 3076 * the default render context which may not match that used when 3077 * rendering on the Component if {@link Graphics2D} functionality is being 3078 * used. Instead metrics can be obtained at rendering time by calling 3079 * {@link Graphics#getFontMetrics()} or text measurement APIs on the 3080 * {@link Font Font} class. 3081 * @param font the font for which font metrics is to be 3082 * obtained 3083 * @return the font metrics for <code>font</code> 3084 * @see #getFont 3085 * @see #getPeer 3086 * @see java.awt.peer.ComponentPeer#getFontMetrics(Font) 3087 * @see Toolkit#getFontMetrics(Font) 3088 * @since JDK1.0 3089 */ 3090 public FontMetrics getFontMetrics(Font font) { 3091 // This is an unsupported hack, but left in for a customer. 3092 // Do not remove. 3093 FontManager fm = FontManagerFactory.getInstance(); 3094 if (fm instanceof SunFontManager 3095 && ((SunFontManager) fm).usePlatformFontMetrics()) { 3096 3097 if (peer != null && 3098 !(peer instanceof LightweightPeer)) { 3099 return peer.getFontMetrics(font); 3100 } 3101 } 3102 return sun.font.FontDesignMetrics.getMetrics(font); 3103 } 3104 3105 /** 3106 * Sets the cursor image to the specified cursor. This cursor 3107 * image is displayed when the <code>contains</code> method for 3108 * this component returns true for the current cursor location, and 3109 * this Component is visible, displayable, and enabled. Setting the 3110 * cursor of a <code>Container</code> causes that cursor to be displayed 3111 * within all of the container's subcomponents, except for those 3112 * that have a non-<code>null</code> cursor. 3113 * <p> 3114 * The method may have no visual effect if the Java platform 3115 * implementation and/or the native system do not support 3116 * changing the mouse cursor shape. 3117 * @param cursor One of the constants defined 3118 * by the <code>Cursor</code> class; 3119 * if this parameter is <code>null</code> 3120 * then this component will inherit 3121 * the cursor of its parent 3122 * @see #isEnabled 3123 * @see #isShowing 3124 * @see #getCursor 3125 * @see #contains 3126 * @see Toolkit#createCustomCursor 3127 * @see Cursor 3128 * @since JDK1.1 3129 */ 3130 public void setCursor(Cursor cursor) { 3131 this.cursor = cursor; 3132 updateCursorImmediately(); 3133 } 3134 3135 /** 3136 * Updates the cursor. May not be invoked from the native 3137 * message pump. 3138 */ 3139 final void updateCursorImmediately() { 3140 if (peer instanceof LightweightPeer) { 3141 Container nativeContainer = getNativeContainer(); 3142 3143 if (nativeContainer == null) return; 3144 3145 ComponentPeer cPeer = nativeContainer.getPeer(); 3146 3147 if (cPeer != null) { 3148 cPeer.updateCursorImmediately(); 3149 } 3150 } else if (peer != null) { 3151 peer.updateCursorImmediately(); 3152 } 3153 } 3154 3155 /** 3156 * Gets the cursor set in the component. If the component does 3157 * not have a cursor set, the cursor of its parent is returned. 3158 * If no cursor is set in the entire hierarchy, 3159 * <code>Cursor.DEFAULT_CURSOR</code> is returned. 3160 * @see #setCursor 3161 * @since JDK1.1 3162 */ 3163 public Cursor getCursor() { 3164 return getCursor_NoClientCode(); 3165 } 3166 3167 final Cursor getCursor_NoClientCode() { 3168 Cursor cursor = this.cursor; 3169 if (cursor != null) { 3170 return cursor; 3171 } 3172 Container parent = this.parent; 3173 if (parent != null) { 3174 return parent.getCursor_NoClientCode(); 3175 } else { 3176 return Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR); 3177 } 3178 } 3179 3180 /** 3181 * Returns whether the cursor has been explicitly set for this Component. 3182 * If this method returns <code>false</code>, this Component is inheriting 3183 * its cursor from an ancestor. 3184 * 3185 * @return <code>true</code> if the cursor has been explicitly set for this 3186 * Component; <code>false</code> otherwise. 3187 * @since 1.4 3188 */ 3189 public boolean isCursorSet() { 3190 return (cursor != null); 3191 } 3192 3193 /** 3194 * Paints this component. 3195 * <p> 3196 * This method is called when the contents of the component should 3197 * be painted; such as when the component is first being shown or 3198 * is damaged and in need of repair. The clip rectangle in the 3199 * <code>Graphics</code> parameter is set to the area 3200 * which needs to be painted. 3201 * Subclasses of <code>Component</code> that override this 3202 * method need not call <code>super.paint(g)</code>. 3203 * <p> 3204 * For performance reasons, <code>Component</code>s with zero width 3205 * or height aren't considered to need painting when they are first shown, 3206 * and also aren't considered to need repair. 3207 * <p> 3208 * <b>Note</b>: For more information on the paint mechanisms utilitized 3209 * by AWT and Swing, including information on how to write the most 3210 * efficient painting code, see 3211 * <a href="http://www.oracle.com/technetwork/java/painting-140037.html">Painting in AWT and Swing</a>. 3212 * 3213 * @param g the graphics context to use for painting 3214 * @see #update 3215 * @since JDK1.0 3216 */ 3217 public void paint(Graphics g) { 3218 } 3219 3220 /** 3221 * Updates this component. 3222 * <p> 3223 * If this component is not a lightweight component, the 3224 * AWT calls the <code>update</code> method in response to 3225 * a call to <code>repaint</code>. You can assume that 3226 * the background is not cleared. 3227 * <p> 3228 * The <code>update</code> method of <code>Component</code> 3229 * calls this component's <code>paint</code> method to redraw 3230 * this component. This method is commonly overridden by subclasses 3231 * which need to do additional work in response to a call to 3232 * <code>repaint</code>. 3233 * Subclasses of Component that override this method should either 3234 * call <code>super.update(g)</code>, or call <code>paint(g)</code> 3235 * directly from their <code>update</code> method. 3236 * <p> 3237 * The origin of the graphics context, its 3238 * (<code>0</code>, <code>0</code>) coordinate point, is the 3239 * top-left corner of this component. The clipping region of the 3240 * graphics context is the bounding rectangle of this component. 3241 * 3242 * <p> 3243 * <b>Note</b>: For more information on the paint mechanisms utilitized 3244 * by AWT and Swing, including information on how to write the most 3245 * efficient painting code, see 3246 * <a href="http://www.oracle.com/technetwork/java/painting-140037.html">Painting in AWT and Swing</a>. 3247 * 3248 * @param g the specified context to use for updating 3249 * @see #paint 3250 * @see #repaint() 3251 * @since JDK1.0 3252 */ 3253 public void update(Graphics g) { 3254 paint(g); 3255 } 3256 3257 /** 3258 * Paints this component and all of its subcomponents. 3259 * <p> 3260 * The origin of the graphics context, its 3261 * (<code>0</code>, <code>0</code>) coordinate point, is the 3262 * top-left corner of this component. The clipping region of the 3263 * graphics context is the bounding rectangle of this component. 3264 * 3265 * @param g the graphics context to use for painting 3266 * @see #paint 3267 * @since JDK1.0 3268 */ 3269 public void paintAll(Graphics g) { 3270 if (isShowing()) { 3271 GraphicsCallback.PeerPaintCallback.getInstance(). 3272 runOneComponent(this, new Rectangle(0, 0, width, height), 3273 g, g.getClip(), 3274 GraphicsCallback.LIGHTWEIGHTS | 3275 GraphicsCallback.HEAVYWEIGHTS); 3276 } 3277 } 3278 3279 /** 3280 * Simulates the peer callbacks into java.awt for painting of 3281 * lightweight Components. 3282 * @param g the graphics context to use for painting 3283 * @see #paintAll 3284 */ 3285 void lightweightPaint(Graphics g) { 3286 paint(g); 3287 } 3288 3289 /** 3290 * Paints all the heavyweight subcomponents. 3291 */ 3292 void paintHeavyweightComponents(Graphics g) { 3293 } 3294 3295 /** 3296 * Repaints this component. 3297 * <p> 3298 * If this component is a lightweight component, this method 3299 * causes a call to this component's <code>paint</code> 3300 * method as soon as possible. Otherwise, this method causes 3301 * a call to this component's <code>update</code> method as soon 3302 * as possible. 3303 * <p> 3304 * <b>Note</b>: For more information on the paint mechanisms utilitized 3305 * by AWT and Swing, including information on how to write the most 3306 * efficient painting code, see 3307 * <a href="http://www.oracle.com/technetwork/java/painting-140037.html">Painting in AWT and Swing</a>. 3308 3309 * 3310 * @see #update(Graphics) 3311 * @since JDK1.0 3312 */ 3313 public void repaint() { 3314 repaint(0, 0, 0, width, height); 3315 } 3316 3317 /** 3318 * Repaints the component. If this component is a lightweight 3319 * component, this results in a call to <code>paint</code> 3320 * within <code>tm</code> milliseconds. 3321 * <p> 3322 * <b>Note</b>: For more information on the paint mechanisms utilitized 3323 * by AWT and Swing, including information on how to write the most 3324 * efficient painting code, see 3325 * <a href="http://www.oracle.com/technetwork/java/painting-140037.html">Painting in AWT and Swing</a>. 3326 * 3327 * @param tm maximum time in milliseconds before update 3328 * @see #paint 3329 * @see #update(Graphics) 3330 * @since JDK1.0 3331 */ 3332 public void repaint(long tm) { 3333 repaint(tm, 0, 0, width, height); 3334 } 3335 3336 /** 3337 * Repaints the specified rectangle of this component. 3338 * <p> 3339 * If this component is a lightweight component, this method 3340 * causes a call to this component's <code>paint</code> method 3341 * as soon as possible. Otherwise, this method causes a call to 3342 * this component's <code>update</code> method as soon as possible. 3343 * <p> 3344 * <b>Note</b>: For more information on the paint mechanisms utilitized 3345 * by AWT and Swing, including information on how to write the most 3346 * efficient painting code, see 3347 * <a href="http://www.oracle.com/technetwork/java/painting-140037.html">Painting in AWT and Swing</a>. 3348 * 3349 * @param x the <i>x</i> coordinate 3350 * @param y the <i>y</i> coordinate 3351 * @param width the width 3352 * @param height the height 3353 * @see #update(Graphics) 3354 * @since JDK1.0 3355 */ 3356 public void repaint(int x, int y, int width, int height) { 3357 repaint(0, x, y, width, height); 3358 } 3359 3360 /** 3361 * Repaints the specified rectangle of this component within 3362 * <code>tm</code> milliseconds. 3363 * <p> 3364 * If this component is a lightweight component, this method causes 3365 * a call to this component's <code>paint</code> method. 3366 * Otherwise, this method causes a call to this component's 3367 * <code>update</code> method. 3368 * <p> 3369 * <b>Note</b>: For more information on the paint mechanisms utilitized 3370 * by AWT and Swing, including information on how to write the most 3371 * efficient painting code, see 3372 * <a href="http://www.oracle.com/technetwork/java/painting-140037.html">Painting in AWT and Swing</a>. 3373 * 3374 * @param tm maximum time in milliseconds before update 3375 * @param x the <i>x</i> coordinate 3376 * @param y the <i>y</i> coordinate 3377 * @param width the width 3378 * @param height the height 3379 * @see #update(Graphics) 3380 * @since JDK1.0 3381 */ 3382 public void repaint(long tm, int x, int y, int width, int height) { 3383 if (this.peer instanceof LightweightPeer) { 3384 // Needs to be translated to parent coordinates since 3385 // a parent native container provides the actual repaint 3386 // services. Additionally, the request is restricted to 3387 // the bounds of the component. 3388 if (parent != null) { 3389 if (x < 0) { 3390 width += x; 3391 x = 0; 3392 } 3393 if (y < 0) { 3394 height += y; 3395 y = 0; 3396 } 3397 3398 int pwidth = (width > this.width) ? this.width : width; 3399 int pheight = (height > this.height) ? this.height : height; 3400 3401 if (pwidth <= 0 || pheight <= 0) { 3402 return; 3403 } 3404 3405 int px = this.x + x; 3406 int py = this.y + y; 3407 parent.repaint(tm, px, py, pwidth, pheight); 3408 } 3409 } else { 3410 if (isVisible() && (this.peer != null) && 3411 (width > 0) && (height > 0)) { 3412 PaintEvent e = new PaintEvent(this, PaintEvent.UPDATE, 3413 new Rectangle(x, y, width, height)); 3414 Toolkit.getEventQueue().postEvent(e); 3415 } 3416 } 3417 } 3418 3419 /** 3420 * Prints this component. Applications should override this method 3421 * for components that must do special processing before being 3422 * printed or should be printed differently than they are painted. 3423 * <p> 3424 * The default implementation of this method calls the 3425 * <code>paint</code> method. 3426 * <p> 3427 * The origin of the graphics context, its 3428 * (<code>0</code>, <code>0</code>) coordinate point, is the 3429 * top-left corner of this component. The clipping region of the 3430 * graphics context is the bounding rectangle of this component. 3431 * @param g the graphics context to use for printing 3432 * @see #paint(Graphics) 3433 * @since JDK1.0 3434 */ 3435 public void print(Graphics g) { 3436 paint(g); 3437 } 3438 3439 /** 3440 * Prints this component and all of its subcomponents. 3441 * <p> 3442 * The origin of the graphics context, its 3443 * (<code>0</code>, <code>0</code>) coordinate point, is the 3444 * top-left corner of this component. The clipping region of the 3445 * graphics context is the bounding rectangle of this component. 3446 * @param g the graphics context to use for printing 3447 * @see #print(Graphics) 3448 * @since JDK1.0 3449 */ 3450 public void printAll(Graphics g) { 3451 if (isShowing()) { 3452 GraphicsCallback.PeerPrintCallback.getInstance(). 3453 runOneComponent(this, new Rectangle(0, 0, width, height), 3454 g, g.getClip(), 3455 GraphicsCallback.LIGHTWEIGHTS | 3456 GraphicsCallback.HEAVYWEIGHTS); 3457 } 3458 } 3459 3460 /** 3461 * Simulates the peer callbacks into java.awt for printing of 3462 * lightweight Components. 3463 * @param g the graphics context to use for printing 3464 * @see #printAll 3465 */ 3466 void lightweightPrint(Graphics g) { 3467 print(g); 3468 } 3469 3470 /** 3471 * Prints all the heavyweight subcomponents. 3472 */ 3473 void printHeavyweightComponents(Graphics g) { 3474 } 3475 3476 private Insets getInsets_NoClientCode() { 3477 ComponentPeer peer = this.peer; 3478 if (peer instanceof ContainerPeer) { 3479 return (Insets)((ContainerPeer)peer).getInsets().clone(); 3480 } 3481 return new Insets(0, 0, 0, 0); 3482 } 3483 3484 /** 3485 * Repaints the component when the image has changed. 3486 * This <code>imageUpdate</code> method of an <code>ImageObserver</code> 3487 * is called when more information about an 3488 * image which had been previously requested using an asynchronous 3489 * routine such as the <code>drawImage</code> method of 3490 * <code>Graphics</code> becomes available. 3491 * See the definition of <code>imageUpdate</code> for 3492 * more information on this method and its arguments. 3493 * <p> 3494 * The <code>imageUpdate</code> method of <code>Component</code> 3495 * incrementally draws an image on the component as more of the bits 3496 * of the image are available. 3497 * <p> 3498 * If the system property <code>awt.image.incrementaldraw</code> 3499 * is missing or has the value <code>true</code>, the image is 3500 * incrementally drawn. If the system property has any other value, 3501 * then the image is not drawn until it has been completely loaded. 3502 * <p> 3503 * Also, if incremental drawing is in effect, the value of the 3504 * system property <code>awt.image.redrawrate</code> is interpreted 3505 * as an integer to give the maximum redraw rate, in milliseconds. If 3506 * the system property is missing or cannot be interpreted as an 3507 * integer, the redraw rate is once every 100ms. 3508 * <p> 3509 * The interpretation of the <code>x</code>, <code>y</code>, 3510 * <code>width</code>, and <code>height</code> arguments depends on 3511 * the value of the <code>infoflags</code> argument. 3512 * 3513 * @param img the image being observed 3514 * @param infoflags see <code>imageUpdate</code> for more information 3515 * @param x the <i>x</i> coordinate 3516 * @param y the <i>y</i> coordinate 3517 * @param w the width 3518 * @param h the height 3519 * @return <code>false</code> if the infoflags indicate that the 3520 * image is completely loaded; <code>true</code> otherwise. 3521 * 3522 * @see java.awt.image.ImageObserver 3523 * @see Graphics#drawImage(Image, int, int, Color, java.awt.image.ImageObserver) 3524 * @see Graphics#drawImage(Image, int, int, java.awt.image.ImageObserver) 3525 * @see Graphics#drawImage(Image, int, int, int, int, Color, java.awt.image.ImageObserver) 3526 * @see Graphics#drawImage(Image, int, int, int, int, java.awt.image.ImageObserver) 3527 * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int) 3528 * @since JDK1.0 3529 */ 3530 public boolean imageUpdate(Image img, int infoflags, 3531 int x, int y, int w, int h) { 3532 int rate = -1; 3533 if ((infoflags & (FRAMEBITS|ALLBITS)) != 0) { 3534 rate = 0; 3535 } else if ((infoflags & SOMEBITS) != 0) { 3536 if (isInc) { 3537 rate = incRate; 3538 if (rate < 0) { 3539 rate = 0; 3540 } 3541 } 3542 } 3543 if (rate >= 0) { 3544 repaint(rate, 0, 0, width, height); 3545 } 3546 return (infoflags & (ALLBITS|ABORT)) == 0; 3547 } 3548 3549 /** 3550 * Creates an image from the specified image producer. 3551 * @param producer the image producer 3552 * @return the image produced 3553 * @since JDK1.0 3554 */ 3555 public Image createImage(ImageProducer producer) { 3556 ComponentPeer peer = this.peer; 3557 if ((peer != null) && ! (peer instanceof LightweightPeer)) { 3558 return peer.createImage(producer); 3559 } 3560 return getToolkit().createImage(producer); 3561 } 3562 3563 /** 3564 * Creates an off-screen drawable image 3565 * to be used for double buffering. 3566 * @param width the specified width 3567 * @param height the specified height 3568 * @return an off-screen drawable image, which can be used for double 3569 * buffering. The return value may be <code>null</code> if the 3570 * component is not displayable. This will always happen if 3571 * <code>GraphicsEnvironment.isHeadless()</code> returns 3572 * <code>true</code>. 3573 * @see #isDisplayable 3574 * @see GraphicsEnvironment#isHeadless 3575 * @since JDK1.0 3576 */ 3577 public Image createImage(int width, int height) { 3578 ComponentPeer peer = this.peer; 3579 if (peer instanceof LightweightPeer) { 3580 if (parent != null) { return parent.createImage(width, height); } 3581 else { return null;} 3582 } else { 3583 return (peer != null) ? peer.createImage(width, height) : null; 3584 } 3585 } 3586 3587 /** 3588 * Creates a volatile off-screen drawable image 3589 * to be used for double buffering. 3590 * @param width the specified width. 3591 * @param height the specified height. 3592 * @return an off-screen drawable image, which can be used for double 3593 * buffering. The return value may be <code>null</code> if the 3594 * component is not displayable. This will always happen if 3595 * <code>GraphicsEnvironment.isHeadless()</code> returns 3596 * <code>true</code>. 3597 * @see java.awt.image.VolatileImage 3598 * @see #isDisplayable 3599 * @see GraphicsEnvironment#isHeadless 3600 * @since 1.4 3601 */ 3602 public VolatileImage createVolatileImage(int width, int height) { 3603 ComponentPeer peer = this.peer; 3604 if (peer instanceof LightweightPeer) { 3605 if (parent != null) { 3606 return parent.createVolatileImage(width, height); 3607 } 3608 else { return null;} 3609 } else { 3610 return (peer != null) ? 3611 peer.createVolatileImage(width, height) : null; 3612 } 3613 } 3614 3615 /** 3616 * Creates a volatile off-screen drawable image, with the given capabilities. 3617 * The contents of this image may be lost at any time due 3618 * to operating system issues, so the image must be managed 3619 * via the <code>VolatileImage</code> interface. 3620 * @param width the specified width. 3621 * @param height the specified height. 3622 * @param caps the image capabilities 3623 * @exception AWTException if an image with the specified capabilities cannot 3624 * be created 3625 * @return a VolatileImage object, which can be used 3626 * to manage surface contents loss and capabilities. 3627 * @see java.awt.image.VolatileImage 3628 * @since 1.4 3629 */ 3630 public VolatileImage createVolatileImage(int width, int height, 3631 ImageCapabilities caps) throws AWTException { 3632 // REMIND : check caps 3633 return createVolatileImage(width, height); 3634 } 3635 3636 /** 3637 * Prepares an image for rendering on this component. The image 3638 * data is downloaded asynchronously in another thread and the 3639 * appropriate screen representation of the image is generated. 3640 * @param image the <code>Image</code> for which to 3641 * prepare a screen representation 3642 * @param observer the <code>ImageObserver</code> object 3643 * to be notified as the image is being prepared 3644 * @return <code>true</code> if the image has already been fully 3645 * prepared; <code>false</code> otherwise 3646 * @since JDK1.0 3647 */ 3648 public boolean prepareImage(Image image, ImageObserver observer) { 3649 return prepareImage(image, -1, -1, observer); 3650 } 3651 3652 /** 3653 * Prepares an image for rendering on this component at the 3654 * specified width and height. 3655 * <p> 3656 * The image data is downloaded asynchronously in another thread, 3657 * and an appropriately scaled screen representation of the image is 3658 * generated. 3659 * @param image the instance of <code>Image</code> 3660 * for which to prepare a screen representation 3661 * @param width the width of the desired screen representation 3662 * @param height the height of the desired screen representation 3663 * @param observer the <code>ImageObserver</code> object 3664 * to be notified as the image is being prepared 3665 * @return <code>true</code> if the image has already been fully 3666 * prepared; <code>false</code> otherwise 3667 * @see java.awt.image.ImageObserver 3668 * @since JDK1.0 3669 */ 3670 public boolean prepareImage(Image image, int width, int height, 3671 ImageObserver observer) { 3672 ComponentPeer peer = this.peer; 3673 if (peer instanceof LightweightPeer) { 3674 return (parent != null) 3675 ? parent.prepareImage(image, width, height, observer) 3676 : getToolkit().prepareImage(image, width, height, observer); 3677 } else { 3678 return (peer != null) 3679 ? peer.prepareImage(image, width, height, observer) 3680 : getToolkit().prepareImage(image, width, height, observer); 3681 } 3682 } 3683 3684 /** 3685 * Returns the status of the construction of a screen representation 3686 * of the specified image. 3687 * <p> 3688 * This method does not cause the image to begin loading. An 3689 * application must use the <code>prepareImage</code> method 3690 * to force the loading of an image. 3691 * <p> 3692 * Information on the flags returned by this method can be found 3693 * with the discussion of the <code>ImageObserver</code> interface. 3694 * @param image the <code>Image</code> object whose status 3695 * is being checked 3696 * @param observer the <code>ImageObserver</code> 3697 * object to be notified as the image is being prepared 3698 * @return the bitwise inclusive <b>OR</b> of 3699 * <code>ImageObserver</code> flags indicating what 3700 * information about the image is currently available 3701 * @see #prepareImage(Image, int, int, java.awt.image.ImageObserver) 3702 * @see Toolkit#checkImage(Image, int, int, java.awt.image.ImageObserver) 3703 * @see java.awt.image.ImageObserver 3704 * @since JDK1.0 3705 */ 3706 public int checkImage(Image image, ImageObserver observer) { 3707 return checkImage(image, -1, -1, observer); 3708 } 3709 3710 /** 3711 * Returns the status of the construction of a screen representation 3712 * of the specified image. 3713 * <p> 3714 * This method does not cause the image to begin loading. An 3715 * application must use the <code>prepareImage</code> method 3716 * to force the loading of an image. 3717 * <p> 3718 * The <code>checkImage</code> method of <code>Component</code> 3719 * calls its peer's <code>checkImage</code> method to calculate 3720 * the flags. If this component does not yet have a peer, the 3721 * component's toolkit's <code>checkImage</code> method is called 3722 * instead. 3723 * <p> 3724 * Information on the flags returned by this method can be found 3725 * with the discussion of the <code>ImageObserver</code> interface. 3726 * @param image the <code>Image</code> object whose status 3727 * is being checked 3728 * @param width the width of the scaled version 3729 * whose status is to be checked 3730 * @param height the height of the scaled version 3731 * whose status is to be checked 3732 * @param observer the <code>ImageObserver</code> object 3733 * to be notified as the image is being prepared 3734 * @return the bitwise inclusive <b>OR</b> of 3735 * <code>ImageObserver</code> flags indicating what 3736 * information about the image is currently available 3737 * @see #prepareImage(Image, int, int, java.awt.image.ImageObserver) 3738 * @see Toolkit#checkImage(Image, int, int, java.awt.image.ImageObserver) 3739 * @see java.awt.image.ImageObserver 3740 * @since JDK1.0 3741 */ 3742 public int checkImage(Image image, int width, int height, 3743 ImageObserver observer) { 3744 ComponentPeer peer = this.peer; 3745 if (peer instanceof LightweightPeer) { 3746 return (parent != null) 3747 ? parent.checkImage(image, width, height, observer) 3748 : getToolkit().checkImage(image, width, height, observer); 3749 } else { 3750 return (peer != null) 3751 ? peer.checkImage(image, width, height, observer) 3752 : getToolkit().checkImage(image, width, height, observer); 3753 } 3754 } 3755 3756 /** 3757 * Creates a new strategy for multi-buffering on this component. 3758 * Multi-buffering is useful for rendering performance. This method 3759 * attempts to create the best strategy available with the number of 3760 * buffers supplied. It will always create a <code>BufferStrategy</code> 3761 * with that number of buffers. 3762 * A page-flipping strategy is attempted first, then a blitting strategy 3763 * using accelerated buffers. Finally, an unaccelerated blitting 3764 * strategy is used. 3765 * <p> 3766 * Each time this method is called, 3767 * the existing buffer strategy for this component is discarded. 3768 * @param numBuffers number of buffers to create, including the front buffer 3769 * @exception IllegalArgumentException if numBuffers is less than 1. 3770 * @exception IllegalStateException if the component is not displayable 3771 * @see #isDisplayable 3772 * @see Window#getBufferStrategy() 3773 * @see Canvas#getBufferStrategy() 3774 * @since 1.4 3775 */ 3776 void createBufferStrategy(int numBuffers) { 3777 BufferCapabilities bufferCaps; 3778 if (numBuffers > 1) { 3779 // Try to create a page-flipping strategy 3780 bufferCaps = new BufferCapabilities(new ImageCapabilities(true), 3781 new ImageCapabilities(true), 3782 BufferCapabilities.FlipContents.UNDEFINED); 3783 try { 3784 createBufferStrategy(numBuffers, bufferCaps); 3785 return; // Success 3786 } catch (AWTException e) { 3787 // Failed 3788 } 3789 } 3790 // Try a blitting (but still accelerated) strategy 3791 bufferCaps = new BufferCapabilities(new ImageCapabilities(true), 3792 new ImageCapabilities(true), 3793 null); 3794 try { 3795 createBufferStrategy(numBuffers, bufferCaps); 3796 return; // Success 3797 } catch (AWTException e) { 3798 // Failed 3799 } 3800 // Try an unaccelerated blitting strategy 3801 bufferCaps = new BufferCapabilities(new ImageCapabilities(false), 3802 new ImageCapabilities(false), 3803 null); 3804 try { 3805 createBufferStrategy(numBuffers, bufferCaps); 3806 return; // Success 3807 } catch (AWTException e) { 3808 // Code should never reach here (an unaccelerated blitting 3809 // strategy should always work) 3810 throw new InternalError("Could not create a buffer strategy", e); 3811 } 3812 } 3813 3814 /** 3815 * Creates a new strategy for multi-buffering on this component with the 3816 * required buffer capabilities. This is useful, for example, if only 3817 * accelerated memory or page flipping is desired (as specified by the 3818 * buffer capabilities). 3819 * <p> 3820 * Each time this method 3821 * is called, <code>dispose</code> will be invoked on the existing 3822 * <code>BufferStrategy</code>. 3823 * @param numBuffers number of buffers to create 3824 * @param caps the required capabilities for creating the buffer strategy; 3825 * cannot be <code>null</code> 3826 * @exception AWTException if the capabilities supplied could not be 3827 * supported or met; this may happen, for example, if there is not enough 3828 * accelerated memory currently available, or if page flipping is specified 3829 * but not possible. 3830 * @exception IllegalArgumentException if numBuffers is less than 1, or if 3831 * caps is <code>null</code> 3832 * @see Window#getBufferStrategy() 3833 * @see Canvas#getBufferStrategy() 3834 * @since 1.4 3835 */ 3836 void createBufferStrategy(int numBuffers, 3837 BufferCapabilities caps) throws AWTException { 3838 // Check arguments 3839 if (numBuffers < 1) { 3840 throw new IllegalArgumentException( 3841 "Number of buffers must be at least 1"); 3842 } 3843 if (caps == null) { 3844 throw new IllegalArgumentException("No capabilities specified"); 3845 } 3846 // Destroy old buffers 3847 if (bufferStrategy != null) { 3848 bufferStrategy.dispose(); 3849 } 3850 if (numBuffers == 1) { 3851 bufferStrategy = new SingleBufferStrategy(caps); 3852 } else { 3853 SunGraphicsEnvironment sge = (SunGraphicsEnvironment) 3854 GraphicsEnvironment.getLocalGraphicsEnvironment(); 3855 if (!caps.isPageFlipping() && sge.isFlipStrategyPreferred(peer)) { 3856 caps = new ProxyCapabilities(caps); 3857 } 3858 // assert numBuffers > 1; 3859 if (caps.isPageFlipping()) { 3860 bufferStrategy = new FlipSubRegionBufferStrategy(numBuffers, caps); 3861 } else { 3862 bufferStrategy = new BltSubRegionBufferStrategy(numBuffers, caps); 3863 } 3864 } 3865 } 3866 3867 /** 3868 * This is a proxy capabilities class used when a FlipBufferStrategy 3869 * is created instead of the requested Blit strategy. 3870 * 3871 * @see sun.java2d.SunGraphicsEnvironment#isFlipStrategyPreferred(ComponentPeer) 3872 */ 3873 private class ProxyCapabilities extends ExtendedBufferCapabilities { 3874 private BufferCapabilities orig; 3875 private ProxyCapabilities(BufferCapabilities orig) { 3876 super(orig.getFrontBufferCapabilities(), 3877 orig.getBackBufferCapabilities(), 3878 orig.getFlipContents() == 3879 BufferCapabilities.FlipContents.BACKGROUND ? 3880 BufferCapabilities.FlipContents.BACKGROUND : 3881 BufferCapabilities.FlipContents.COPIED); 3882 this.orig = orig; 3883 } 3884 } 3885 3886 /** 3887 * @return the buffer strategy used by this component 3888 * @see Window#createBufferStrategy 3889 * @see Canvas#createBufferStrategy 3890 * @since 1.4 3891 */ 3892 BufferStrategy getBufferStrategy() { 3893 return bufferStrategy; 3894 } 3895 3896 /** 3897 * @return the back buffer currently used by this component's 3898 * BufferStrategy. If there is no BufferStrategy or no 3899 * back buffer, this method returns null. 3900 */ 3901 Image getBackBuffer() { 3902 if (bufferStrategy != null) { 3903 if (bufferStrategy instanceof BltBufferStrategy) { 3904 BltBufferStrategy bltBS = (BltBufferStrategy)bufferStrategy; 3905 return bltBS.getBackBuffer(); 3906 } else if (bufferStrategy instanceof FlipBufferStrategy) { 3907 FlipBufferStrategy flipBS = (FlipBufferStrategy)bufferStrategy; 3908 return flipBS.getBackBuffer(); 3909 } 3910 } 3911 return null; 3912 } 3913 3914 /** 3915 * Inner class for flipping buffers on a component. That component must 3916 * be a <code>Canvas</code> or <code>Window</code>. 3917 * @see Canvas 3918 * @see Window 3919 * @see java.awt.image.BufferStrategy 3920 * @author Michael Martak 3921 * @since 1.4 3922 */ 3923 protected class FlipBufferStrategy extends BufferStrategy { 3924 /** 3925 * The number of buffers 3926 */ 3927 protected int numBuffers; // = 0 3928 /** 3929 * The buffering capabilities 3930 */ 3931 protected BufferCapabilities caps; // = null 3932 /** 3933 * The drawing buffer 3934 */ 3935 protected Image drawBuffer; // = null 3936 /** 3937 * The drawing buffer as a volatile image 3938 */ 3939 protected VolatileImage drawVBuffer; // = null 3940 /** 3941 * Whether or not the drawing buffer has been recently restored from 3942 * a lost state. 3943 */ 3944 protected boolean validatedContents; // = false 3945 /** 3946 * Size of the back buffers. (Note: these fields were added in 6.0 3947 * but kept package-private to avoid exposing them in the spec. 3948 * None of these fields/methods really should have been marked 3949 * protected when they were introduced in 1.4, but now we just have 3950 * to live with that decision.) 3951 */ 3952 int width; 3953 int height; 3954 3955 /** 3956 * Creates a new flipping buffer strategy for this component. 3957 * The component must be a <code>Canvas</code> or <code>Window</code>. 3958 * @see Canvas 3959 * @see Window 3960 * @param numBuffers the number of buffers 3961 * @param caps the capabilities of the buffers 3962 * @exception AWTException if the capabilities supplied could not be 3963 * supported or met 3964 * @exception ClassCastException if the component is not a canvas or 3965 * window. 3966 * @exception IllegalStateException if the component has no peer 3967 * @exception IllegalArgumentException if {@code numBuffers} is less than two, 3968 * or if {@code BufferCapabilities.isPageFlipping} is not 3969 * {@code true}. 3970 * @see #createBuffers(int, BufferCapabilities) 3971 */ 3972 protected FlipBufferStrategy(int numBuffers, BufferCapabilities caps) 3973 throws AWTException 3974 { 3975 if (!(Component.this instanceof Window) && 3976 !(Component.this instanceof Canvas)) 3977 { 3978 throw new ClassCastException( 3979 "Component must be a Canvas or Window"); 3980 } 3981 this.numBuffers = numBuffers; 3982 this.caps = caps; 3983 createBuffers(numBuffers, caps); 3984 } 3985 3986 /** 3987 * Creates one or more complex, flipping buffers with the given 3988 * capabilities. 3989 * @param numBuffers number of buffers to create; must be greater than 3990 * one 3991 * @param caps the capabilities of the buffers. 3992 * <code>BufferCapabilities.isPageFlipping</code> must be 3993 * <code>true</code>. 3994 * @exception AWTException if the capabilities supplied could not be 3995 * supported or met 3996 * @exception IllegalStateException if the component has no peer 3997 * @exception IllegalArgumentException if numBuffers is less than two, 3998 * or if <code>BufferCapabilities.isPageFlipping</code> is not 3999 * <code>true</code>. 4000 * @see java.awt.BufferCapabilities#isPageFlipping() 4001 */ 4002 protected void createBuffers(int numBuffers, BufferCapabilities caps) 4003 throws AWTException 4004 { 4005 if (numBuffers < 2) { 4006 throw new IllegalArgumentException( 4007 "Number of buffers cannot be less than two"); 4008 } else if (peer == null) { 4009 throw new IllegalStateException( 4010 "Component must have a valid peer"); 4011 } else if (caps == null || !caps.isPageFlipping()) { 4012 throw new IllegalArgumentException( 4013 "Page flipping capabilities must be specified"); 4014 } 4015 4016 // save the current bounds 4017 width = getWidth(); 4018 height = getHeight(); 4019 4020 if (drawBuffer != null) { 4021 // dispose the existing backbuffers 4022 drawBuffer = null; 4023 drawVBuffer = null; 4024 destroyBuffers(); 4025 // ... then recreate the backbuffers 4026 } 4027 4028 if (caps instanceof ExtendedBufferCapabilities) { 4029 ExtendedBufferCapabilities ebc = 4030 (ExtendedBufferCapabilities)caps; 4031 if (ebc.getVSync() == VSYNC_ON) { 4032 // if this buffer strategy is not allowed to be v-synced, 4033 // change the caps that we pass to the peer but keep on 4034 // trying to create v-synced buffers; 4035 // do not throw IAE here in case it is disallowed, see 4036 // ExtendedBufferCapabilities for more info 4037 if (!VSyncedBSManager.vsyncAllowed(this)) { 4038 caps = ebc.derive(VSYNC_DEFAULT); 4039 } 4040 } 4041 } 4042 4043 peer.createBuffers(numBuffers, caps); 4044 updateInternalBuffers(); 4045 } 4046 4047 /** 4048 * Updates internal buffers (both volatile and non-volatile) 4049 * by requesting the back-buffer from the peer. 4050 */ 4051 private void updateInternalBuffers() { 4052 // get the images associated with the draw buffer 4053 drawBuffer = getBackBuffer(); 4054 if (drawBuffer instanceof VolatileImage) { 4055 drawVBuffer = (VolatileImage)drawBuffer; 4056 } else { 4057 drawVBuffer = null; 4058 } 4059 } 4060 4061 /** 4062 * @return direct access to the back buffer, as an image. 4063 * @exception IllegalStateException if the buffers have not yet 4064 * been created 4065 */ 4066 protected Image getBackBuffer() { 4067 if (peer != null) { 4068 return peer.getBackBuffer(); 4069 } else { 4070 throw new IllegalStateException( 4071 "Component must have a valid peer"); 4072 } 4073 } 4074 4075 /** 4076 * Flipping moves the contents of the back buffer to the front buffer, 4077 * either by copying or by moving the video pointer. 4078 * @param flipAction an integer value describing the flipping action 4079 * for the contents of the back buffer. This should be one of the 4080 * values of the <code>BufferCapabilities.FlipContents</code> 4081 * property. 4082 * @exception IllegalStateException if the buffers have not yet 4083 * been created 4084 * @see java.awt.BufferCapabilities#getFlipContents() 4085 */ 4086 protected void flip(BufferCapabilities.FlipContents flipAction) { 4087 if (peer != null) { 4088 Image backBuffer = getBackBuffer(); 4089 if (backBuffer != null) { 4090 peer.flip(0, 0, 4091 backBuffer.getWidth(null), 4092 backBuffer.getHeight(null), flipAction); 4093 } 4094 } else { 4095 throw new IllegalStateException( 4096 "Component must have a valid peer"); 4097 } 4098 } 4099 4100 void flipSubRegion(int x1, int y1, int x2, int y2, 4101 BufferCapabilities.FlipContents flipAction) 4102 { 4103 if (peer != null) { 4104 peer.flip(x1, y1, x2, y2, flipAction); 4105 } else { 4106 throw new IllegalStateException( 4107 "Component must have a valid peer"); 4108 } 4109 } 4110 4111 /** 4112 * Destroys the buffers created through this object 4113 */ 4114 protected void destroyBuffers() { 4115 VSyncedBSManager.releaseVsync(this); 4116 if (peer != null) { 4117 peer.destroyBuffers(); 4118 } else { 4119 throw new IllegalStateException( 4120 "Component must have a valid peer"); 4121 } 4122 } 4123 4124 /** 4125 * @return the buffering capabilities of this strategy 4126 */ 4127 public BufferCapabilities getCapabilities() { 4128 if (caps instanceof ProxyCapabilities) { 4129 return ((ProxyCapabilities)caps).orig; 4130 } else { 4131 return caps; 4132 } 4133 } 4134 4135 /** 4136 * @return the graphics on the drawing buffer. This method may not 4137 * be synchronized for performance reasons; use of this method by multiple 4138 * threads should be handled at the application level. Disposal of the 4139 * graphics object must be handled by the application. 4140 */ 4141 public Graphics getDrawGraphics() { 4142 revalidate(); 4143 return drawBuffer.getGraphics(); 4144 } 4145 4146 /** 4147 * Restore the drawing buffer if it has been lost 4148 */ 4149 protected void revalidate() { 4150 revalidate(true); 4151 } 4152 4153 void revalidate(boolean checkSize) { 4154 validatedContents = false; 4155 4156 if (checkSize && (getWidth() != width || getHeight() != height)) { 4157 // component has been resized; recreate the backbuffers 4158 try { 4159 createBuffers(numBuffers, caps); 4160 } catch (AWTException e) { 4161 // shouldn't be possible 4162 } 4163 validatedContents = true; 4164 } 4165 4166 // get the buffers from the peer every time since they 4167 // might have been replaced in response to a display change event 4168 updateInternalBuffers(); 4169 4170 // now validate the backbuffer 4171 if (drawVBuffer != null) { 4172 GraphicsConfiguration gc = 4173 getGraphicsConfiguration_NoClientCode(); 4174 int returnCode = drawVBuffer.validate(gc); 4175 if (returnCode == VolatileImage.IMAGE_INCOMPATIBLE) { 4176 try { 4177 createBuffers(numBuffers, caps); 4178 } catch (AWTException e) { 4179 // shouldn't be possible 4180 } 4181 if (drawVBuffer != null) { 4182 // backbuffers were recreated, so validate again 4183 drawVBuffer.validate(gc); 4184 } 4185 validatedContents = true; 4186 } else if (returnCode == VolatileImage.IMAGE_RESTORED) { 4187 validatedContents = true; 4188 } 4189 } 4190 } 4191 4192 /** 4193 * @return whether the drawing buffer was lost since the last call to 4194 * <code>getDrawGraphics</code> 4195 */ 4196 public boolean contentsLost() { 4197 if (drawVBuffer == null) { 4198 return false; 4199 } 4200 return drawVBuffer.contentsLost(); 4201 } 4202 4203 /** 4204 * @return whether the drawing buffer was recently restored from a lost 4205 * state and reinitialized to the default background color (white) 4206 */ 4207 public boolean contentsRestored() { 4208 return validatedContents; 4209 } 4210 4211 /** 4212 * Makes the next available buffer visible by either blitting or 4213 * flipping. 4214 */ 4215 public void show() { 4216 flip(caps.getFlipContents()); 4217 } 4218 4219 /** 4220 * Makes specified region of the the next available buffer visible 4221 * by either blitting or flipping. 4222 */ 4223 void showSubRegion(int x1, int y1, int x2, int y2) { 4224 flipSubRegion(x1, y1, x2, y2, caps.getFlipContents()); 4225 } 4226 4227 /** 4228 * {@inheritDoc} 4229 * @since 1.6 4230 */ 4231 public void dispose() { 4232 if (Component.this.bufferStrategy == this) { 4233 Component.this.bufferStrategy = null; 4234 if (peer != null) { 4235 destroyBuffers(); 4236 } 4237 } 4238 } 4239 4240 } // Inner class FlipBufferStrategy 4241 4242 /** 4243 * Inner class for blitting offscreen surfaces to a component. 4244 * 4245 * @author Michael Martak 4246 * @since 1.4 4247 */ 4248 protected class BltBufferStrategy extends BufferStrategy { 4249 4250 /** 4251 * The buffering capabilities 4252 */ 4253 protected BufferCapabilities caps; // = null 4254 /** 4255 * The back buffers 4256 */ 4257 protected VolatileImage[] backBuffers; // = null 4258 /** 4259 * Whether or not the drawing buffer has been recently restored from 4260 * a lost state. 4261 */ 4262 protected boolean validatedContents; // = false 4263 /** 4264 * Size of the back buffers 4265 */ 4266 protected int width; 4267 protected int height; 4268 4269 /** 4270 * Insets for the hosting Component. The size of the back buffer 4271 * is constrained by these. 4272 */ 4273 private Insets insets; 4274 4275 /** 4276 * Creates a new blt buffer strategy around a component 4277 * @param numBuffers number of buffers to create, including the 4278 * front buffer 4279 * @param caps the capabilities of the buffers 4280 */ 4281 protected BltBufferStrategy(int numBuffers, BufferCapabilities caps) { 4282 this.caps = caps; 4283 createBackBuffers(numBuffers - 1); 4284 } 4285 4286 /** 4287 * {@inheritDoc} 4288 * @since 1.6 4289 */ 4290 public void dispose() { 4291 if (backBuffers != null) { 4292 for (int counter = backBuffers.length - 1; counter >= 0; 4293 counter--) { 4294 if (backBuffers[counter] != null) { 4295 backBuffers[counter].flush(); 4296 backBuffers[counter] = null; 4297 } 4298 } 4299 } 4300 if (Component.this.bufferStrategy == this) { 4301 Component.this.bufferStrategy = null; 4302 } 4303 } 4304 4305 /** 4306 * Creates the back buffers 4307 */ 4308 protected void createBackBuffers(int numBuffers) { 4309 if (numBuffers == 0) { 4310 backBuffers = null; 4311 } else { 4312 // save the current bounds 4313 width = getWidth(); 4314 height = getHeight(); 4315 insets = getInsets_NoClientCode(); 4316 int iWidth = width - insets.left - insets.right; 4317 int iHeight = height - insets.top - insets.bottom; 4318 4319 // It is possible for the component's width and/or height 4320 // to be 0 here. Force the size of the backbuffers to 4321 // be > 0 so that creating the image won't fail. 4322 iWidth = Math.max(1, iWidth); 4323 iHeight = Math.max(1, iHeight); 4324 if (backBuffers == null) { 4325 backBuffers = new VolatileImage[numBuffers]; 4326 } else { 4327 // flush any existing backbuffers 4328 for (int i = 0; i < numBuffers; i++) { 4329 if (backBuffers[i] != null) { 4330 backBuffers[i].flush(); 4331 backBuffers[i] = null; 4332 } 4333 } 4334 } 4335 4336 // create the backbuffers 4337 for (int i = 0; i < numBuffers; i++) { 4338 backBuffers[i] = createVolatileImage(iWidth, iHeight); 4339 } 4340 } 4341 } 4342 4343 /** 4344 * @return the buffering capabilities of this strategy 4345 */ 4346 public BufferCapabilities getCapabilities() { 4347 return caps; 4348 } 4349 4350 /** 4351 * @return the draw graphics 4352 */ 4353 public Graphics getDrawGraphics() { 4354 revalidate(); 4355 Image backBuffer = getBackBuffer(); 4356 if (backBuffer == null) { 4357 return getGraphics(); 4358 } 4359 SunGraphics2D g = (SunGraphics2D)backBuffer.getGraphics(); 4360 g.constrain(-insets.left, -insets.top, 4361 backBuffer.getWidth(null) + insets.left, 4362 backBuffer.getHeight(null) + insets.top); 4363 return g; 4364 } 4365 4366 /** 4367 * @return direct access to the back buffer, as an image. 4368 * If there is no back buffer, returns null. 4369 */ 4370 Image getBackBuffer() { 4371 if (backBuffers != null) { 4372 return backBuffers[backBuffers.length - 1]; 4373 } else { 4374 return null; 4375 } 4376 } 4377 4378 /** 4379 * Makes the next available buffer visible. 4380 */ 4381 public void show() { 4382 showSubRegion(insets.left, insets.top, 4383 width - insets.right, 4384 height - insets.bottom); 4385 } 4386 4387 /** 4388 * Package-private method to present a specific rectangular area 4389 * of this buffer. This class currently shows only the entire 4390 * buffer, by calling showSubRegion() with the full dimensions of 4391 * the buffer. Subclasses (e.g., BltSubRegionBufferStrategy 4392 * and FlipSubRegionBufferStrategy) may have region-specific show 4393 * methods that call this method with actual sub regions of the 4394 * buffer. 4395 */ 4396 void showSubRegion(int x1, int y1, int x2, int y2) { 4397 if (backBuffers == null) { 4398 return; 4399 } 4400 // Adjust location to be relative to client area. 4401 x1 -= insets.left; 4402 x2 -= insets.left; 4403 y1 -= insets.top; 4404 y2 -= insets.top; 4405 Graphics g = getGraphics_NoClientCode(); 4406 if (g == null) { 4407 // Not showing, bail 4408 return; 4409 } 4410 try { 4411 // First image copy is in terms of Frame's coordinates, need 4412 // to translate to client area. 4413 g.translate(insets.left, insets.top); 4414 for (int i = 0; i < backBuffers.length; i++) { 4415 g.drawImage(backBuffers[i], 4416 x1, y1, x2, y2, 4417 x1, y1, x2, y2, 4418 null); 4419 g.dispose(); 4420 g = null; 4421 g = backBuffers[i].getGraphics(); 4422 } 4423 } finally { 4424 if (g != null) { 4425 g.dispose(); 4426 } 4427 } 4428 } 4429 4430 /** 4431 * Restore the drawing buffer if it has been lost 4432 */ 4433 protected void revalidate() { 4434 revalidate(true); 4435 } 4436 4437 void revalidate(boolean checkSize) { 4438 validatedContents = false; 4439 4440 if (backBuffers == null) { 4441 return; 4442 } 4443 4444 if (checkSize) { 4445 Insets insets = getInsets_NoClientCode(); 4446 if (getWidth() != width || getHeight() != height || 4447 !insets.equals(this.insets)) { 4448 // component has been resized; recreate the backbuffers 4449 createBackBuffers(backBuffers.length); 4450 validatedContents = true; 4451 } 4452 } 4453 4454 // now validate the backbuffer 4455 GraphicsConfiguration gc = getGraphicsConfiguration_NoClientCode(); 4456 int returnCode = 4457 backBuffers[backBuffers.length - 1].validate(gc); 4458 if (returnCode == VolatileImage.IMAGE_INCOMPATIBLE) { 4459 if (checkSize) { 4460 createBackBuffers(backBuffers.length); 4461 // backbuffers were recreated, so validate again 4462 backBuffers[backBuffers.length - 1].validate(gc); 4463 } 4464 // else case means we're called from Swing on the toolkit 4465 // thread, don't recreate buffers as that'll deadlock 4466 // (creating VolatileImages invokes getting GraphicsConfig 4467 // which grabs treelock). 4468 validatedContents = true; 4469 } else if (returnCode == VolatileImage.IMAGE_RESTORED) { 4470 validatedContents = true; 4471 } 4472 } 4473 4474 /** 4475 * @return whether the drawing buffer was lost since the last call to 4476 * <code>getDrawGraphics</code> 4477 */ 4478 public boolean contentsLost() { 4479 if (backBuffers == null) { 4480 return false; 4481 } else { 4482 return backBuffers[backBuffers.length - 1].contentsLost(); 4483 } 4484 } 4485 4486 /** 4487 * @return whether the drawing buffer was recently restored from a lost 4488 * state and reinitialized to the default background color (white) 4489 */ 4490 public boolean contentsRestored() { 4491 return validatedContents; 4492 } 4493 } // Inner class BltBufferStrategy 4494 4495 /** 4496 * Private class to perform sub-region flipping. 4497 */ 4498 private class FlipSubRegionBufferStrategy extends FlipBufferStrategy 4499 implements SubRegionShowable 4500 { 4501 4502 protected FlipSubRegionBufferStrategy(int numBuffers, 4503 BufferCapabilities caps) 4504 throws AWTException 4505 { 4506 super(numBuffers, caps); 4507 } 4508 4509 public void show(int x1, int y1, int x2, int y2) { 4510 showSubRegion(x1, y1, x2, y2); 4511 } 4512 4513 // This is invoked by Swing on the toolkit thread. 4514 public boolean showIfNotLost(int x1, int y1, int x2, int y2) { 4515 if (!contentsLost()) { 4516 showSubRegion(x1, y1, x2, y2); 4517 return !contentsLost(); 4518 } 4519 return false; 4520 } 4521 } 4522 4523 /** 4524 * Private class to perform sub-region blitting. Swing will use 4525 * this subclass via the SubRegionShowable interface in order to 4526 * copy only the area changed during a repaint. 4527 * See javax.swing.BufferStrategyPaintManager. 4528 */ 4529 private class BltSubRegionBufferStrategy extends BltBufferStrategy 4530 implements SubRegionShowable 4531 { 4532 4533 protected BltSubRegionBufferStrategy(int numBuffers, 4534 BufferCapabilities caps) 4535 { 4536 super(numBuffers, caps); 4537 } 4538 4539 public void show(int x1, int y1, int x2, int y2) { 4540 showSubRegion(x1, y1, x2, y2); 4541 } 4542 4543 // This method is called by Swing on the toolkit thread. 4544 public boolean showIfNotLost(int x1, int y1, int x2, int y2) { 4545 if (!contentsLost()) { 4546 showSubRegion(x1, y1, x2, y2); 4547 return !contentsLost(); 4548 } 4549 return false; 4550 } 4551 } 4552 4553 /** 4554 * Inner class for flipping buffers on a component. That component must 4555 * be a <code>Canvas</code> or <code>Window</code>. 4556 * @see Canvas 4557 * @see Window 4558 * @see java.awt.image.BufferStrategy 4559 * @author Michael Martak 4560 * @since 1.4 4561 */ 4562 private class SingleBufferStrategy extends BufferStrategy { 4563 4564 private BufferCapabilities caps; 4565 4566 public SingleBufferStrategy(BufferCapabilities caps) { 4567 this.caps = caps; 4568 } 4569 public BufferCapabilities getCapabilities() { 4570 return caps; 4571 } 4572 public Graphics getDrawGraphics() { 4573 return getGraphics(); 4574 } 4575 public boolean contentsLost() { 4576 return false; 4577 } 4578 public boolean contentsRestored() { 4579 return false; 4580 } 4581 public void show() { 4582 // Do nothing 4583 } 4584 } // Inner class SingleBufferStrategy 4585 4586 /** 4587 * Sets whether or not paint messages received from the operating system 4588 * should be ignored. This does not affect paint events generated in 4589 * software by the AWT, unless they are an immediate response to an 4590 * OS-level paint message. 4591 * <p> 4592 * This is useful, for example, if running under full-screen mode and 4593 * better performance is desired, or if page-flipping is used as the 4594 * buffer strategy. 4595 * 4596 * @since 1.4 4597 * @see #getIgnoreRepaint 4598 * @see Canvas#createBufferStrategy 4599 * @see Window#createBufferStrategy 4600 * @see java.awt.image.BufferStrategy 4601 * @see GraphicsDevice#setFullScreenWindow 4602 */ 4603 public void setIgnoreRepaint(boolean ignoreRepaint) { 4604 this.ignoreRepaint = ignoreRepaint; 4605 } 4606 4607 /** 4608 * @return whether or not paint messages received from the operating system 4609 * should be ignored. 4610 * 4611 * @since 1.4 4612 * @see #setIgnoreRepaint 4613 */ 4614 public boolean getIgnoreRepaint() { 4615 return ignoreRepaint; 4616 } 4617 4618 /** 4619 * Checks whether this component "contains" the specified point, 4620 * where <code>x</code> and <code>y</code> are defined to be 4621 * relative to the coordinate system of this component. 4622 * @param x the <i>x</i> coordinate of the point 4623 * @param y the <i>y</i> coordinate of the point 4624 * @see #getComponentAt(int, int) 4625 * @since JDK1.1 4626 */ 4627 public boolean contains(int x, int y) { 4628 return inside(x, y); 4629 } 4630 4631 /** 4632 * @deprecated As of JDK version 1.1, 4633 * replaced by contains(int, int). 4634 */ 4635 @Deprecated 4636 public boolean inside(int x, int y) { 4637 return (x >= 0) && (x < width) && (y >= 0) && (y < height); 4638 } 4639 4640 /** 4641 * Checks whether this component "contains" the specified point, 4642 * where the point's <i>x</i> and <i>y</i> coordinates are defined 4643 * to be relative to the coordinate system of this component. 4644 * @param p the point 4645 * @throws NullPointerException if {@code p} is {@code null} 4646 * @see #getComponentAt(Point) 4647 * @since JDK1.1 4648 */ 4649 public boolean contains(Point p) { 4650 return contains(p.x, p.y); 4651 } 4652 4653 /** 4654 * Determines if this component or one of its immediate 4655 * subcomponents contains the (<i>x</i>, <i>y</i>) location, 4656 * and if so, returns the containing component. This method only 4657 * looks one level deep. If the point (<i>x</i>, <i>y</i>) is 4658 * inside a subcomponent that itself has subcomponents, it does not 4659 * go looking down the subcomponent tree. 4660 * <p> 4661 * The <code>locate</code> method of <code>Component</code> simply 4662 * returns the component itself if the (<i>x</i>, <i>y</i>) 4663 * coordinate location is inside its bounding box, and <code>null</code> 4664 * otherwise. 4665 * @param x the <i>x</i> coordinate 4666 * @param y the <i>y</i> coordinate 4667 * @return the component or subcomponent that contains the 4668 * (<i>x</i>, <i>y</i>) location; 4669 * <code>null</code> if the location 4670 * is outside this component 4671 * @see #contains(int, int) 4672 * @since JDK1.0 4673 */ 4674 public Component getComponentAt(int x, int y) { 4675 return locate(x, y); 4676 } 4677 4678 /** 4679 * @deprecated As of JDK version 1.1, 4680 * replaced by getComponentAt(int, int). 4681 */ 4682 @Deprecated 4683 public Component locate(int x, int y) { 4684 return contains(x, y) ? this : null; 4685 } 4686 4687 /** 4688 * Returns the component or subcomponent that contains the 4689 * specified point. 4690 * @param p the point 4691 * @see java.awt.Component#contains 4692 * @since JDK1.1 4693 */ 4694 public Component getComponentAt(Point p) { 4695 return getComponentAt(p.x, p.y); 4696 } 4697 4698 /** 4699 * @deprecated As of JDK version 1.1, 4700 * replaced by <code>dispatchEvent(AWTEvent e)</code>. 4701 */ 4702 @Deprecated 4703 public void deliverEvent(Event e) { 4704 postEvent(e); 4705 } 4706 4707 /** 4708 * Dispatches an event to this component or one of its sub components. 4709 * Calls <code>processEvent</code> before returning for 1.1-style 4710 * events which have been enabled for the <code>Component</code>. 4711 * @param e the event 4712 */ 4713 public final void dispatchEvent(AWTEvent e) { 4714 dispatchEventImpl(e); 4715 } 4716 4717 @SuppressWarnings("deprecation") 4718 void dispatchEventImpl(AWTEvent e) { 4719 int id = e.getID(); 4720 4721 // Check that this component belongs to this app-context 4722 AppContext compContext = appContext; 4723 if (compContext != null && !compContext.equals(AppContext.getAppContext())) { 4724 if (eventLog.isLoggable(PlatformLogger.Level.FINE)) { 4725 eventLog.fine("Event " + e + " is being dispatched on the wrong AppContext"); 4726 } 4727 } 4728 4729 if (eventLog.isLoggable(PlatformLogger.Level.FINEST)) { 4730 eventLog.finest("{0}", e); 4731 } 4732 4733 /* 4734 * 0. Set timestamp and modifiers of current event. 4735 */ 4736 if (!(e instanceof KeyEvent)) { 4737 // Timestamp of a key event is set later in DKFM.preDispatchKeyEvent(KeyEvent). 4738 EventQueue.setCurrentEventAndMostRecentTime(e); 4739 } 4740 4741 /* 4742 * 1. Pre-dispatchers. Do any necessary retargeting/reordering here 4743 * before we notify AWTEventListeners. 4744 */ 4745 4746 if (e instanceof SunDropTargetEvent) { 4747 ((SunDropTargetEvent)e).dispatch(); 4748 return; 4749 } 4750 4751 if (!e.focusManagerIsDispatching) { 4752 // Invoke the private focus retargeting method which provides 4753 // lightweight Component support 4754 if (e.isPosted) { 4755 e = KeyboardFocusManager.retargetFocusEvent(e); 4756 e.isPosted = true; 4757 } 4758 4759 // Now, with the event properly targeted to a lightweight 4760 // descendant if necessary, invoke the public focus retargeting 4761 // and dispatching function 4762 if (KeyboardFocusManager.getCurrentKeyboardFocusManager(). 4763 dispatchEvent(e)) 4764 { 4765 return; 4766 } 4767 } 4768 if ((e instanceof FocusEvent) && focusLog.isLoggable(PlatformLogger.Level.FINEST)) { 4769 focusLog.finest("" + e); 4770 } 4771 // MouseWheel may need to be retargeted here so that 4772 // AWTEventListener sees the event go to the correct 4773 // Component. If the MouseWheelEvent needs to go to an ancestor, 4774 // the event is dispatched to the ancestor, and dispatching here 4775 // stops. 4776 if (id == MouseEvent.MOUSE_WHEEL && 4777 (!eventTypeEnabled(id)) && 4778 (peer != null && !peer.handlesWheelScrolling()) && 4779 (dispatchMouseWheelToAncestor((MouseWheelEvent)e))) 4780 { 4781 return; 4782 } 4783 4784 /* 4785 * 2. Allow the Toolkit to pass this to AWTEventListeners. 4786 */ 4787 Toolkit toolkit = Toolkit.getDefaultToolkit(); 4788 toolkit.notifyAWTEventListeners(e); 4789 4790 4791 /* 4792 * 3. If no one has consumed a key event, allow the 4793 * KeyboardFocusManager to process it. 4794 */ 4795 if (!e.isConsumed()) { 4796 if (e instanceof java.awt.event.KeyEvent) { 4797 KeyboardFocusManager.getCurrentKeyboardFocusManager(). 4798 processKeyEvent(this, (KeyEvent)e); 4799 if (e.isConsumed()) { 4800 return; 4801 } 4802 } 4803 } 4804 4805 /* 4806 * 4. Allow input methods to process the event 4807 */ 4808 if (areInputMethodsEnabled()) { 4809 // We need to pass on InputMethodEvents since some host 4810 // input method adapters send them through the Java 4811 // event queue instead of directly to the component, 4812 // and the input context also handles the Java composition window 4813 if(((e instanceof InputMethodEvent) && !(this instanceof CompositionArea)) 4814 || 4815 // Otherwise, we only pass on input and focus events, because 4816 // a) input methods shouldn't know about semantic or component-level events 4817 // b) passing on the events takes time 4818 // c) isConsumed() is always true for semantic events. 4819 (e instanceof InputEvent) || (e instanceof FocusEvent)) { 4820 InputContext inputContext = getInputContext(); 4821 4822 4823 if (inputContext != null) { 4824 inputContext.dispatchEvent(e); 4825 if (e.isConsumed()) { 4826 if ((e instanceof FocusEvent) && focusLog.isLoggable(PlatformLogger.Level.FINEST)) { 4827 focusLog.finest("3579: Skipping " + e); 4828 } 4829 return; 4830 } 4831 } 4832 } 4833 } else { 4834 // When non-clients get focus, we need to explicitly disable the native 4835 // input method. The native input method is actually not disabled when 4836 // the active/passive/peered clients loose focus. 4837 if (id == FocusEvent.FOCUS_GAINED) { 4838 InputContext inputContext = getInputContext(); 4839 if (inputContext != null && inputContext instanceof sun.awt.im.InputContext) { 4840 ((sun.awt.im.InputContext)inputContext).disableNativeIM(); 4841 } 4842 } 4843 } 4844 4845 4846 /* 4847 * 5. Pre-process any special events before delivery 4848 */ 4849 switch(id) { 4850 // Handling of the PAINT and UPDATE events is now done in the 4851 // peer's handleEvent() method so the background can be cleared 4852 // selectively for non-native components on Windows only. 4853 // - Fred.Ecks@Eng.sun.com, 5-8-98 4854 4855 case KeyEvent.KEY_PRESSED: 4856 case KeyEvent.KEY_RELEASED: 4857 Container p = (Container)((this instanceof Container) ? this : parent); 4858 if (p != null) { 4859 p.preProcessKeyEvent((KeyEvent)e); 4860 if (e.isConsumed()) { 4861 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) { 4862 focusLog.finest("Pre-process consumed event"); 4863 } 4864 return; 4865 } 4866 } 4867 break; 4868 4869 case WindowEvent.WINDOW_CLOSING: 4870 if (toolkit instanceof WindowClosingListener) { 4871 windowClosingException = ((WindowClosingListener) 4872 toolkit).windowClosingNotify((WindowEvent)e); 4873 if (checkWindowClosingException()) { 4874 return; 4875 } 4876 } 4877 break; 4878 4879 default: 4880 break; 4881 } 4882 4883 /* 4884 * 6. Deliver event for normal processing 4885 */ 4886 if (newEventsOnly) { 4887 // Filtering needs to really be moved to happen at a lower 4888 // level in order to get maximum performance gain; it is 4889 // here temporarily to ensure the API spec is honored. 4890 // 4891 if (eventEnabled(e)) { 4892 processEvent(e); 4893 } 4894 } else if (id == MouseEvent.MOUSE_WHEEL) { 4895 // newEventsOnly will be false for a listenerless ScrollPane, but 4896 // MouseWheelEvents still need to be dispatched to it so scrolling 4897 // can be done. 4898 autoProcessMouseWheel((MouseWheelEvent)e); 4899 } else if (!(e instanceof MouseEvent && !postsOldMouseEvents())) { 4900 // 4901 // backward compatibility 4902 // 4903 Event olde = e.convertToOld(); 4904 if (olde != null) { 4905 int key = olde.key; 4906 int modifiers = olde.modifiers; 4907 4908 postEvent(olde); 4909 if (olde.isConsumed()) { 4910 e.consume(); 4911 } 4912 // if target changed key or modifier values, copy them 4913 // back to original event 4914 // 4915 switch(olde.id) { 4916 case Event.KEY_PRESS: 4917 case Event.KEY_RELEASE: 4918 case Event.KEY_ACTION: 4919 case Event.KEY_ACTION_RELEASE: 4920 if (olde.key != key) { 4921 ((KeyEvent)e).setKeyChar(olde.getKeyEventChar()); 4922 } 4923 if (olde.modifiers != modifiers) { 4924 ((KeyEvent)e).setModifiers(olde.modifiers); 4925 } 4926 break; 4927 default: 4928 break; 4929 } 4930 } 4931 } 4932 4933 /* 4934 * 8. Special handling for 4061116 : Hook for browser to close modal 4935 * dialogs. 4936 */ 4937 if (id == WindowEvent.WINDOW_CLOSING && !e.isConsumed()) { 4938 if (toolkit instanceof WindowClosingListener) { 4939 windowClosingException = 4940 ((WindowClosingListener)toolkit). 4941 windowClosingDelivered((WindowEvent)e); 4942 if (checkWindowClosingException()) { 4943 return; 4944 } 4945 } 4946 } 4947 4948 /* 4949 * 9. Allow the peer to process the event. 4950 * Except KeyEvents, they will be processed by peer after 4951 * all KeyEventPostProcessors 4952 * (see DefaultKeyboardFocusManager.dispatchKeyEvent()) 4953 */ 4954 if (!(e instanceof KeyEvent)) { 4955 ComponentPeer tpeer = peer; 4956 if (e instanceof FocusEvent && (tpeer == null || tpeer instanceof LightweightPeer)) { 4957 // if focus owner is lightweight then its native container 4958 // processes event 4959 Component source = (Component)e.getSource(); 4960 if (source != null) { 4961 Container target = source.getNativeContainer(); 4962 if (target != null) { 4963 tpeer = target.getPeer(); 4964 } 4965 } 4966 } 4967 if (tpeer != null) { 4968 tpeer.handleEvent(e); 4969 } 4970 } 4971 } // dispatchEventImpl() 4972 4973 /* 4974 * If newEventsOnly is false, method is called so that ScrollPane can 4975 * override it and handle common-case mouse wheel scrolling. NOP 4976 * for Component. 4977 */ 4978 void autoProcessMouseWheel(MouseWheelEvent e) {} 4979 4980 /* 4981 * Dispatch given MouseWheelEvent to the first ancestor for which 4982 * MouseWheelEvents are enabled. 4983 * 4984 * Returns whether or not event was dispatched to an ancestor 4985 */ 4986 boolean dispatchMouseWheelToAncestor(MouseWheelEvent e) { 4987 int newX, newY; 4988 newX = e.getX() + getX(); // Coordinates take into account at least 4989 newY = e.getY() + getY(); // the cursor's position relative to this 4990 // Component (e.getX()), and this Component's 4991 // position relative to its parent. 4992 MouseWheelEvent newMWE; 4993 4994 if (eventLog.isLoggable(PlatformLogger.Level.FINEST)) { 4995 eventLog.finest("dispatchMouseWheelToAncestor"); 4996 eventLog.finest("orig event src is of " + e.getSource().getClass()); 4997 } 4998 4999 /* parent field for Window refers to the owning Window. 5000 * MouseWheelEvents should NOT be propagated into owning Windows 5001 */ 5002 synchronized (getTreeLock()) { 5003 Container anc = getParent(); 5004 while (anc != null && !anc.eventEnabled(e)) { 5005 // fix coordinates to be relative to new event source 5006 newX += anc.getX(); 5007 newY += anc.getY(); 5008 5009 if (!(anc instanceof Window)) { 5010 anc = anc.getParent(); 5011 } 5012 else { 5013 break; 5014 } 5015 } 5016 5017 if (eventLog.isLoggable(PlatformLogger.Level.FINEST)) { 5018 eventLog.finest("new event src is " + anc.getClass()); 5019 } 5020 5021 if (anc != null && anc.eventEnabled(e)) { 5022 // Change event to be from new source, with new x,y 5023 // For now, just create a new event - yucky 5024 5025 newMWE = new MouseWheelEvent(anc, // new source 5026 e.getID(), 5027 e.getWhen(), 5028 e.getModifiers(), 5029 newX, // x relative to new source 5030 newY, // y relative to new source 5031 e.getXOnScreen(), 5032 e.getYOnScreen(), 5033 e.getClickCount(), 5034 e.isPopupTrigger(), 5035 e.getScrollType(), 5036 e.getScrollAmount(), 5037 e.getWheelRotation(), 5038 e.getPreciseWheelRotation()); 5039 ((AWTEvent)e).copyPrivateDataInto(newMWE); 5040 // When dispatching a wheel event to 5041 // ancestor, there is no need trying to find descendant 5042 // lightweights to dispatch event to. 5043 // If we dispatch the event to toplevel ancestor, 5044 // this could encolse the loop: 6480024. 5045 anc.dispatchEventToSelf(newMWE); 5046 if (newMWE.isConsumed()) { 5047 e.consume(); 5048 } 5049 return true; 5050 } 5051 } 5052 return false; 5053 } 5054 5055 boolean checkWindowClosingException() { 5056 if (windowClosingException != null) { 5057 if (this instanceof Dialog) { 5058 ((Dialog)this).interruptBlocking(); 5059 } else { 5060 windowClosingException.fillInStackTrace(); 5061 windowClosingException.printStackTrace(); 5062 windowClosingException = null; 5063 } 5064 return true; 5065 } 5066 return false; 5067 } 5068 5069 boolean areInputMethodsEnabled() { 5070 // in 1.2, we assume input method support is required for all 5071 // components that handle key events, but components can turn off 5072 // input methods by calling enableInputMethods(false). 5073 return ((eventMask & AWTEvent.INPUT_METHODS_ENABLED_MASK) != 0) && 5074 ((eventMask & AWTEvent.KEY_EVENT_MASK) != 0 || keyListener != null); 5075 } 5076 5077 // REMIND: remove when filtering is handled at lower level 5078 boolean eventEnabled(AWTEvent e) { 5079 return eventTypeEnabled(e.id); 5080 } 5081 5082 boolean eventTypeEnabled(int type) { 5083 switch(type) { 5084 case ComponentEvent.COMPONENT_MOVED: 5085 case ComponentEvent.COMPONENT_RESIZED: 5086 case ComponentEvent.COMPONENT_SHOWN: 5087 case ComponentEvent.COMPONENT_HIDDEN: 5088 if ((eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0 || 5089 componentListener != null) { 5090 return true; 5091 } 5092 break; 5093 case FocusEvent.FOCUS_GAINED: 5094 case FocusEvent.FOCUS_LOST: 5095 if ((eventMask & AWTEvent.FOCUS_EVENT_MASK) != 0 || 5096 focusListener != null) { 5097 return true; 5098 } 5099 break; 5100 case KeyEvent.KEY_PRESSED: 5101 case KeyEvent.KEY_RELEASED: 5102 case KeyEvent.KEY_TYPED: 5103 if ((eventMask & AWTEvent.KEY_EVENT_MASK) != 0 || 5104 keyListener != null) { 5105 return true; 5106 } 5107 break; 5108 case MouseEvent.MOUSE_PRESSED: 5109 case MouseEvent.MOUSE_RELEASED: 5110 case MouseEvent.MOUSE_ENTERED: 5111 case MouseEvent.MOUSE_EXITED: 5112 case MouseEvent.MOUSE_CLICKED: 5113 if ((eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0 || 5114 mouseListener != null) { 5115 return true; 5116 } 5117 break; 5118 case MouseEvent.MOUSE_MOVED: 5119 case MouseEvent.MOUSE_DRAGGED: 5120 if ((eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0 || 5121 mouseMotionListener != null) { 5122 return true; 5123 } 5124 break; 5125 case MouseEvent.MOUSE_WHEEL: 5126 if ((eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0 || 5127 mouseWheelListener != null) { 5128 return true; 5129 } 5130 break; 5131 case InputMethodEvent.INPUT_METHOD_TEXT_CHANGED: 5132 case InputMethodEvent.CARET_POSITION_CHANGED: 5133 if ((eventMask & AWTEvent.INPUT_METHOD_EVENT_MASK) != 0 || 5134 inputMethodListener != null) { 5135 return true; 5136 } 5137 break; 5138 case HierarchyEvent.HIERARCHY_CHANGED: 5139 if ((eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0 || 5140 hierarchyListener != null) { 5141 return true; 5142 } 5143 break; 5144 case HierarchyEvent.ANCESTOR_MOVED: 5145 case HierarchyEvent.ANCESTOR_RESIZED: 5146 if ((eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0 || 5147 hierarchyBoundsListener != null) { 5148 return true; 5149 } 5150 break; 5151 case ActionEvent.ACTION_PERFORMED: 5152 if ((eventMask & AWTEvent.ACTION_EVENT_MASK) != 0) { 5153 return true; 5154 } 5155 break; 5156 case TextEvent.TEXT_VALUE_CHANGED: 5157 if ((eventMask & AWTEvent.TEXT_EVENT_MASK) != 0) { 5158 return true; 5159 } 5160 break; 5161 case ItemEvent.ITEM_STATE_CHANGED: 5162 if ((eventMask & AWTEvent.ITEM_EVENT_MASK) != 0) { 5163 return true; 5164 } 5165 break; 5166 case AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED: 5167 if ((eventMask & AWTEvent.ADJUSTMENT_EVENT_MASK) != 0) { 5168 return true; 5169 } 5170 break; 5171 default: 5172 break; 5173 } 5174 // 5175 // Always pass on events defined by external programs. 5176 // 5177 if (type > AWTEvent.RESERVED_ID_MAX) { 5178 return true; 5179 } 5180 return false; 5181 } 5182 5183 /** 5184 * @deprecated As of JDK version 1.1, 5185 * replaced by dispatchEvent(AWTEvent). 5186 */ 5187 @Deprecated 5188 public boolean postEvent(Event e) { 5189 ComponentPeer peer = this.peer; 5190 5191 if (handleEvent(e)) { 5192 e.consume(); 5193 return true; 5194 } 5195 5196 Component parent = this.parent; 5197 int eventx = e.x; 5198 int eventy = e.y; 5199 if (parent != null) { 5200 e.translate(x, y); 5201 if (parent.postEvent(e)) { 5202 e.consume(); 5203 return true; 5204 } 5205 // restore coords 5206 e.x = eventx; 5207 e.y = eventy; 5208 } 5209 return false; 5210 } 5211 5212 // Event source interfaces 5213 5214 /** 5215 * Adds the specified component listener to receive component events from 5216 * this component. 5217 * If listener <code>l</code> is <code>null</code>, 5218 * no exception is thrown and no action is performed. 5219 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" 5220 * >AWT Threading Issues</a> for details on AWT's threading model. 5221 * 5222 * @param l the component listener 5223 * @see java.awt.event.ComponentEvent 5224 * @see java.awt.event.ComponentListener 5225 * @see #removeComponentListener 5226 * @see #getComponentListeners 5227 * @since JDK1.1 5228 */ 5229 public synchronized void addComponentListener(ComponentListener l) { 5230 if (l == null) { 5231 return; 5232 } 5233 componentListener = AWTEventMulticaster.add(componentListener, l); 5234 newEventsOnly = true; 5235 } 5236 5237 /** 5238 * Removes the specified component listener so that it no longer 5239 * receives component events from this component. This method performs 5240 * no function, nor does it throw an exception, if the listener 5241 * specified by the argument was not previously added to this component. 5242 * If listener <code>l</code> is <code>null</code>, 5243 * no exception is thrown and no action is performed. 5244 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" 5245 * >AWT Threading Issues</a> for details on AWT's threading model. 5246 * @param l the component listener 5247 * @see java.awt.event.ComponentEvent 5248 * @see java.awt.event.ComponentListener 5249 * @see #addComponentListener 5250 * @see #getComponentListeners 5251 * @since JDK1.1 5252 */ 5253 public synchronized void removeComponentListener(ComponentListener l) { 5254 if (l == null) { 5255 return; 5256 } 5257 componentListener = AWTEventMulticaster.remove(componentListener, l); 5258 } 5259 5260 /** 5261 * Returns an array of all the component listeners 5262 * registered on this component. 5263 * 5264 * @return all <code>ComponentListener</code>s of this component 5265 * or an empty array if no component 5266 * listeners are currently registered 5267 * 5268 * @see #addComponentListener 5269 * @see #removeComponentListener 5270 * @since 1.4 5271 */ 5272 public synchronized ComponentListener[] getComponentListeners() { 5273 return getListeners(ComponentListener.class); 5274 } 5275 5276 /** 5277 * Adds the specified focus listener to receive focus events from 5278 * this component when this component gains input focus. 5279 * If listener <code>l</code> is <code>null</code>, 5280 * no exception is thrown and no action is performed. 5281 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" 5282 * >AWT Threading Issues</a> for details on AWT's threading model. 5283 * 5284 * @param l the focus listener 5285 * @see java.awt.event.FocusEvent 5286 * @see java.awt.event.FocusListener 5287 * @see #removeFocusListener 5288 * @see #getFocusListeners 5289 * @since JDK1.1 5290 */ 5291 public synchronized void addFocusListener(FocusListener l) { 5292 if (l == null) { 5293 return; 5294 } 5295 focusListener = AWTEventMulticaster.add(focusListener, l); 5296 newEventsOnly = true; 5297 5298 // if this is a lightweight component, enable focus events 5299 // in the native container. 5300 if (peer instanceof LightweightPeer) { 5301 parent.proxyEnableEvents(AWTEvent.FOCUS_EVENT_MASK); 5302 } 5303 } 5304 5305 /** 5306 * Removes the specified focus listener so that it no longer 5307 * receives focus events from this component. This method performs 5308 * no function, nor does it throw an exception, if the listener 5309 * specified by the argument was not previously added to this component. 5310 * If listener <code>l</code> is <code>null</code>, 5311 * no exception is thrown and no action is performed. 5312 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" 5313 * >AWT Threading Issues</a> for details on AWT's threading model. 5314 * 5315 * @param l the focus listener 5316 * @see java.awt.event.FocusEvent 5317 * @see java.awt.event.FocusListener 5318 * @see #addFocusListener 5319 * @see #getFocusListeners 5320 * @since JDK1.1 5321 */ 5322 public synchronized void removeFocusListener(FocusListener l) { 5323 if (l == null) { 5324 return; 5325 } 5326 focusListener = AWTEventMulticaster.remove(focusListener, l); 5327 } 5328 5329 /** 5330 * Returns an array of all the focus listeners 5331 * registered on this component. 5332 * 5333 * @return all of this component's <code>FocusListener</code>s 5334 * or an empty array if no component 5335 * listeners are currently registered 5336 * 5337 * @see #addFocusListener 5338 * @see #removeFocusListener 5339 * @since 1.4 5340 */ 5341 public synchronized FocusListener[] getFocusListeners() { 5342 return getListeners(FocusListener.class); 5343 } 5344 5345 /** 5346 * Adds the specified hierarchy listener to receive hierarchy changed 5347 * events from this component when the hierarchy to which this container 5348 * belongs changes. 5349 * If listener <code>l</code> is <code>null</code>, 5350 * no exception is thrown and no action is performed. 5351 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" 5352 * >AWT Threading Issues</a> for details on AWT's threading model. 5353 * 5354 * @param l the hierarchy listener 5355 * @see java.awt.event.HierarchyEvent 5356 * @see java.awt.event.HierarchyListener 5357 * @see #removeHierarchyListener 5358 * @see #getHierarchyListeners 5359 * @since 1.3 5360 */ 5361 public void addHierarchyListener(HierarchyListener l) { 5362 if (l == null) { 5363 return; 5364 } 5365 boolean notifyAncestors; 5366 synchronized (this) { 5367 notifyAncestors = 5368 (hierarchyListener == null && 5369 (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) == 0); 5370 hierarchyListener = AWTEventMulticaster.add(hierarchyListener, l); 5371 notifyAncestors = (notifyAncestors && hierarchyListener != null); 5372 newEventsOnly = true; 5373 } 5374 if (notifyAncestors) { 5375 synchronized (getTreeLock()) { 5376 adjustListeningChildrenOnParent(AWTEvent.HIERARCHY_EVENT_MASK, 5377 1); 5378 } 5379 } 5380 } 5381 5382 /** 5383 * Removes the specified hierarchy listener so that it no longer 5384 * receives hierarchy changed events from this component. This method 5385 * performs no function, nor does it throw an exception, if the listener 5386 * specified by the argument was not previously added to this component. 5387 * If listener <code>l</code> is <code>null</code>, 5388 * no exception is thrown and no action is performed. 5389 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" 5390 * >AWT Threading Issues</a> for details on AWT's threading model. 5391 * 5392 * @param l the hierarchy listener 5393 * @see java.awt.event.HierarchyEvent 5394 * @see java.awt.event.HierarchyListener 5395 * @see #addHierarchyListener 5396 * @see #getHierarchyListeners 5397 * @since 1.3 5398 */ 5399 public void removeHierarchyListener(HierarchyListener l) { 5400 if (l == null) { 5401 return; 5402 } 5403 boolean notifyAncestors; 5404 synchronized (this) { 5405 notifyAncestors = 5406 (hierarchyListener != null && 5407 (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) == 0); 5408 hierarchyListener = 5409 AWTEventMulticaster.remove(hierarchyListener, l); 5410 notifyAncestors = (notifyAncestors && hierarchyListener == null); 5411 } 5412 if (notifyAncestors) { 5413 synchronized (getTreeLock()) { 5414 adjustListeningChildrenOnParent(AWTEvent.HIERARCHY_EVENT_MASK, 5415 -1); 5416 } 5417 } 5418 } 5419 5420 /** 5421 * Returns an array of all the hierarchy listeners 5422 * registered on this component. 5423 * 5424 * @return all of this component's <code>HierarchyListener</code>s 5425 * or an empty array if no hierarchy 5426 * listeners are currently registered 5427 * 5428 * @see #addHierarchyListener 5429 * @see #removeHierarchyListener 5430 * @since 1.4 5431 */ 5432 public synchronized HierarchyListener[] getHierarchyListeners() { 5433 return getListeners(HierarchyListener.class); 5434 } 5435 5436 /** 5437 * Adds the specified hierarchy bounds listener to receive hierarchy 5438 * bounds events from this component when the hierarchy to which this 5439 * container belongs changes. 5440 * If listener <code>l</code> is <code>null</code>, 5441 * no exception is thrown and no action is performed. 5442 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" 5443 * >AWT Threading Issues</a> for details on AWT's threading model. 5444 * 5445 * @param l the hierarchy bounds listener 5446 * @see java.awt.event.HierarchyEvent 5447 * @see java.awt.event.HierarchyBoundsListener 5448 * @see #removeHierarchyBoundsListener 5449 * @see #getHierarchyBoundsListeners 5450 * @since 1.3 5451 */ 5452 public void addHierarchyBoundsListener(HierarchyBoundsListener l) { 5453 if (l == null) { 5454 return; 5455 } 5456 boolean notifyAncestors; 5457 synchronized (this) { 5458 notifyAncestors = 5459 (hierarchyBoundsListener == null && 5460 (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) == 0); 5461 hierarchyBoundsListener = 5462 AWTEventMulticaster.add(hierarchyBoundsListener, l); 5463 notifyAncestors = (notifyAncestors && 5464 hierarchyBoundsListener != null); 5465 newEventsOnly = true; 5466 } 5467 if (notifyAncestors) { 5468 synchronized (getTreeLock()) { 5469 adjustListeningChildrenOnParent( 5470 AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, 1); 5471 } 5472 } 5473 } 5474 5475 /** 5476 * Removes the specified hierarchy bounds listener so that it no longer 5477 * receives hierarchy bounds events from this component. This method 5478 * performs no function, nor does it throw an exception, if the listener 5479 * specified by the argument was not previously added to this component. 5480 * If listener <code>l</code> is <code>null</code>, 5481 * no exception is thrown and no action is performed. 5482 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" 5483 * >AWT Threading Issues</a> for details on AWT's threading model. 5484 * 5485 * @param l the hierarchy bounds listener 5486 * @see java.awt.event.HierarchyEvent 5487 * @see java.awt.event.HierarchyBoundsListener 5488 * @see #addHierarchyBoundsListener 5489 * @see #getHierarchyBoundsListeners 5490 * @since 1.3 5491 */ 5492 public void removeHierarchyBoundsListener(HierarchyBoundsListener l) { 5493 if (l == null) { 5494 return; 5495 } 5496 boolean notifyAncestors; 5497 synchronized (this) { 5498 notifyAncestors = 5499 (hierarchyBoundsListener != null && 5500 (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) == 0); 5501 hierarchyBoundsListener = 5502 AWTEventMulticaster.remove(hierarchyBoundsListener, l); 5503 notifyAncestors = (notifyAncestors && 5504 hierarchyBoundsListener == null); 5505 } 5506 if (notifyAncestors) { 5507 synchronized (getTreeLock()) { 5508 adjustListeningChildrenOnParent( 5509 AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, -1); 5510 } 5511 } 5512 } 5513 5514 // Should only be called while holding the tree lock 5515 int numListening(long mask) { 5516 // One mask or the other, but not neither or both. 5517 if (eventLog.isLoggable(PlatformLogger.Level.FINE)) { 5518 if ((mask != AWTEvent.HIERARCHY_EVENT_MASK) && 5519 (mask != AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK)) 5520 { 5521 eventLog.fine("Assertion failed"); 5522 } 5523 } 5524 if ((mask == AWTEvent.HIERARCHY_EVENT_MASK && 5525 (hierarchyListener != null || 5526 (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0)) || 5527 (mask == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK && 5528 (hierarchyBoundsListener != null || 5529 (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0))) { 5530 return 1; 5531 } else { 5532 return 0; 5533 } 5534 } 5535 5536 // Should only be called while holding tree lock 5537 int countHierarchyMembers() { 5538 return 1; 5539 } 5540 // Should only be called while holding the tree lock 5541 int createHierarchyEvents(int id, Component changed, 5542 Container changedParent, long changeFlags, 5543 boolean enabledOnToolkit) { 5544 switch (id) { 5545 case HierarchyEvent.HIERARCHY_CHANGED: 5546 if (hierarchyListener != null || 5547 (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0 || 5548 enabledOnToolkit) { 5549 HierarchyEvent e = new HierarchyEvent(this, id, changed, 5550 changedParent, 5551 changeFlags); 5552 dispatchEvent(e); 5553 return 1; 5554 } 5555 break; 5556 case HierarchyEvent.ANCESTOR_MOVED: 5557 case HierarchyEvent.ANCESTOR_RESIZED: 5558 if (eventLog.isLoggable(PlatformLogger.Level.FINE)) { 5559 if (changeFlags != 0) { 5560 eventLog.fine("Assertion (changeFlags == 0) failed"); 5561 } 5562 } 5563 if (hierarchyBoundsListener != null || 5564 (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0 || 5565 enabledOnToolkit) { 5566 HierarchyEvent e = new HierarchyEvent(this, id, changed, 5567 changedParent); 5568 dispatchEvent(e); 5569 return 1; 5570 } 5571 break; 5572 default: 5573 // assert false 5574 if (eventLog.isLoggable(PlatformLogger.Level.FINE)) { 5575 eventLog.fine("This code must never be reached"); 5576 } 5577 break; 5578 } 5579 return 0; 5580 } 5581 5582 /** 5583 * Returns an array of all the hierarchy bounds listeners 5584 * registered on this component. 5585 * 5586 * @return all of this component's <code>HierarchyBoundsListener</code>s 5587 * or an empty array if no hierarchy bounds 5588 * listeners are currently registered 5589 * 5590 * @see #addHierarchyBoundsListener 5591 * @see #removeHierarchyBoundsListener 5592 * @since 1.4 5593 */ 5594 public synchronized HierarchyBoundsListener[] getHierarchyBoundsListeners() { 5595 return getListeners(HierarchyBoundsListener.class); 5596 } 5597 5598 /* 5599 * Should only be called while holding the tree lock. 5600 * It's added only for overriding in java.awt.Window 5601 * because parent in Window is owner. 5602 */ 5603 void adjustListeningChildrenOnParent(long mask, int num) { 5604 if (parent != null) { 5605 parent.adjustListeningChildren(mask, num); 5606 } 5607 } 5608 5609 /** 5610 * Adds the specified key listener to receive key events from 5611 * this component. 5612 * If l is null, no exception is thrown and no action is performed. 5613 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" 5614 * >AWT Threading Issues</a> for details on AWT's threading model. 5615 * 5616 * @param l the key listener. 5617 * @see java.awt.event.KeyEvent 5618 * @see java.awt.event.KeyListener 5619 * @see #removeKeyListener 5620 * @see #getKeyListeners 5621 * @since JDK1.1 5622 */ 5623 public synchronized void addKeyListener(KeyListener l) { 5624 if (l == null) { 5625 return; 5626 } 5627 keyListener = AWTEventMulticaster.add(keyListener, l); 5628 newEventsOnly = true; 5629 5630 // if this is a lightweight component, enable key events 5631 // in the native container. 5632 if (peer instanceof LightweightPeer) { 5633 parent.proxyEnableEvents(AWTEvent.KEY_EVENT_MASK); 5634 } 5635 } 5636 5637 /** 5638 * Removes the specified key listener so that it no longer 5639 * receives key events from this component. This method performs 5640 * no function, nor does it throw an exception, if the listener 5641 * specified by the argument was not previously added to this component. 5642 * If listener <code>l</code> is <code>null</code>, 5643 * no exception is thrown and no action is performed. 5644 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" 5645 * >AWT Threading Issues</a> for details on AWT's threading model. 5646 * 5647 * @param l the key listener 5648 * @see java.awt.event.KeyEvent 5649 * @see java.awt.event.KeyListener 5650 * @see #addKeyListener 5651 * @see #getKeyListeners 5652 * @since JDK1.1 5653 */ 5654 public synchronized void removeKeyListener(KeyListener l) { 5655 if (l == null) { 5656 return; 5657 } 5658 keyListener = AWTEventMulticaster.remove(keyListener, l); 5659 } 5660 5661 /** 5662 * Returns an array of all the key listeners 5663 * registered on this component. 5664 * 5665 * @return all of this component's <code>KeyListener</code>s 5666 * or an empty array if no key 5667 * listeners are currently registered 5668 * 5669 * @see #addKeyListener 5670 * @see #removeKeyListener 5671 * @since 1.4 5672 */ 5673 public synchronized KeyListener[] getKeyListeners() { 5674 return getListeners(KeyListener.class); 5675 } 5676 5677 /** 5678 * Adds the specified mouse listener to receive mouse events from 5679 * this component. 5680 * If listener <code>l</code> is <code>null</code>, 5681 * no exception is thrown and no action is performed. 5682 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" 5683 * >AWT Threading Issues</a> for details on AWT's threading model. 5684 * 5685 * @param l the mouse listener 5686 * @see java.awt.event.MouseEvent 5687 * @see java.awt.event.MouseListener 5688 * @see #removeMouseListener 5689 * @see #getMouseListeners 5690 * @since JDK1.1 5691 */ 5692 public synchronized void addMouseListener(MouseListener l) { 5693 if (l == null) { 5694 return; 5695 } 5696 mouseListener = AWTEventMulticaster.add(mouseListener,l); 5697 newEventsOnly = true; 5698 5699 // if this is a lightweight component, enable mouse events 5700 // in the native container. 5701 if (peer instanceof LightweightPeer) { 5702 parent.proxyEnableEvents(AWTEvent.MOUSE_EVENT_MASK); 5703 } 5704 } 5705 5706 /** 5707 * Removes the specified mouse listener so that it no longer 5708 * receives mouse events from this component. This method performs 5709 * no function, nor does it throw an exception, if the listener 5710 * specified by the argument was not previously added to this component. 5711 * If listener <code>l</code> is <code>null</code>, 5712 * no exception is thrown and no action is performed. 5713 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" 5714 * >AWT Threading Issues</a> for details on AWT's threading model. 5715 * 5716 * @param l the mouse listener 5717 * @see java.awt.event.MouseEvent 5718 * @see java.awt.event.MouseListener 5719 * @see #addMouseListener 5720 * @see #getMouseListeners 5721 * @since JDK1.1 5722 */ 5723 public synchronized void removeMouseListener(MouseListener l) { 5724 if (l == null) { 5725 return; 5726 } 5727 mouseListener = AWTEventMulticaster.remove(mouseListener, l); 5728 } 5729 5730 /** 5731 * Returns an array of all the mouse listeners 5732 * registered on this component. 5733 * 5734 * @return all of this component's <code>MouseListener</code>s 5735 * or an empty array if no mouse 5736 * listeners are currently registered 5737 * 5738 * @see #addMouseListener 5739 * @see #removeMouseListener 5740 * @since 1.4 5741 */ 5742 public synchronized MouseListener[] getMouseListeners() { 5743 return getListeners(MouseListener.class); 5744 } 5745 5746 /** 5747 * Adds the specified mouse motion listener to receive mouse motion 5748 * events from this component. 5749 * If listener <code>l</code> is <code>null</code>, 5750 * no exception is thrown and no action is performed. 5751 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" 5752 * >AWT Threading Issues</a> for details on AWT's threading model. 5753 * 5754 * @param l the mouse motion listener 5755 * @see java.awt.event.MouseEvent 5756 * @see java.awt.event.MouseMotionListener 5757 * @see #removeMouseMotionListener 5758 * @see #getMouseMotionListeners 5759 * @since JDK1.1 5760 */ 5761 public synchronized void addMouseMotionListener(MouseMotionListener l) { 5762 if (l == null) { 5763 return; 5764 } 5765 mouseMotionListener = AWTEventMulticaster.add(mouseMotionListener,l); 5766 newEventsOnly = true; 5767 5768 // if this is a lightweight component, enable mouse events 5769 // in the native container. 5770 if (peer instanceof LightweightPeer) { 5771 parent.proxyEnableEvents(AWTEvent.MOUSE_MOTION_EVENT_MASK); 5772 } 5773 } 5774 5775 /** 5776 * Removes the specified mouse motion listener so that it no longer 5777 * receives mouse motion events from this component. This method performs 5778 * no function, nor does it throw an exception, if the listener 5779 * specified by the argument was not previously added to this component. 5780 * If listener <code>l</code> is <code>null</code>, 5781 * no exception is thrown and no action is performed. 5782 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" 5783 * >AWT Threading Issues</a> for details on AWT's threading model. 5784 * 5785 * @param l the mouse motion listener 5786 * @see java.awt.event.MouseEvent 5787 * @see java.awt.event.MouseMotionListener 5788 * @see #addMouseMotionListener 5789 * @see #getMouseMotionListeners 5790 * @since JDK1.1 5791 */ 5792 public synchronized void removeMouseMotionListener(MouseMotionListener l) { 5793 if (l == null) { 5794 return; 5795 } 5796 mouseMotionListener = AWTEventMulticaster.remove(mouseMotionListener, l); 5797 } 5798 5799 /** 5800 * Returns an array of all the mouse motion listeners 5801 * registered on this component. 5802 * 5803 * @return all of this component's <code>MouseMotionListener</code>s 5804 * or an empty array if no mouse motion 5805 * listeners are currently registered 5806 * 5807 * @see #addMouseMotionListener 5808 * @see #removeMouseMotionListener 5809 * @since 1.4 5810 */ 5811 public synchronized MouseMotionListener[] getMouseMotionListeners() { 5812 return getListeners(MouseMotionListener.class); 5813 } 5814 5815 /** 5816 * Adds the specified mouse wheel listener to receive mouse wheel events 5817 * from this component. Containers also receive mouse wheel events from 5818 * sub-components. 5819 * <p> 5820 * For information on how mouse wheel events are dispatched, see 5821 * the class description for {@link MouseWheelEvent}. 5822 * <p> 5823 * If l is <code>null</code>, no exception is thrown and no 5824 * action is performed. 5825 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" 5826 * >AWT Threading Issues</a> for details on AWT's threading model. 5827 * 5828 * @param l the mouse wheel listener 5829 * @see java.awt.event.MouseWheelEvent 5830 * @see java.awt.event.MouseWheelListener 5831 * @see #removeMouseWheelListener 5832 * @see #getMouseWheelListeners 5833 * @since 1.4 5834 */ 5835 public synchronized void addMouseWheelListener(MouseWheelListener l) { 5836 if (l == null) { 5837 return; 5838 } 5839 mouseWheelListener = AWTEventMulticaster.add(mouseWheelListener,l); 5840 newEventsOnly = true; 5841 5842 // if this is a lightweight component, enable mouse events 5843 // in the native container. 5844 if (peer instanceof LightweightPeer) { 5845 parent.proxyEnableEvents(AWTEvent.MOUSE_WHEEL_EVENT_MASK); 5846 } 5847 } 5848 5849 /** 5850 * Removes the specified mouse wheel listener so that it no longer 5851 * receives mouse wheel events from this component. This method performs 5852 * no function, nor does it throw an exception, if the listener 5853 * specified by the argument was not previously added to this component. 5854 * If l is null, no exception is thrown and no action is performed. 5855 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" 5856 * >AWT Threading Issues</a> for details on AWT's threading model. 5857 * 5858 * @param l the mouse wheel listener. 5859 * @see java.awt.event.MouseWheelEvent 5860 * @see java.awt.event.MouseWheelListener 5861 * @see #addMouseWheelListener 5862 * @see #getMouseWheelListeners 5863 * @since 1.4 5864 */ 5865 public synchronized void removeMouseWheelListener(MouseWheelListener l) { 5866 if (l == null) { 5867 return; 5868 } 5869 mouseWheelListener = AWTEventMulticaster.remove(mouseWheelListener, l); 5870 } 5871 5872 /** 5873 * Returns an array of all the mouse wheel listeners 5874 * registered on this component. 5875 * 5876 * @return all of this component's <code>MouseWheelListener</code>s 5877 * or an empty array if no mouse wheel 5878 * listeners are currently registered 5879 * 5880 * @see #addMouseWheelListener 5881 * @see #removeMouseWheelListener 5882 * @since 1.4 5883 */ 5884 public synchronized MouseWheelListener[] getMouseWheelListeners() { 5885 return getListeners(MouseWheelListener.class); 5886 } 5887 5888 /** 5889 * Adds the specified input method listener to receive 5890 * input method events from this component. A component will 5891 * only receive input method events from input methods 5892 * if it also overrides <code>getInputMethodRequests</code> to return an 5893 * <code>InputMethodRequests</code> instance. 5894 * If listener <code>l</code> is <code>null</code>, 5895 * no exception is thrown and no action is performed. 5896 * <p>Refer to <a href="{@docRoot}/java/awt/doc-files/AWTThreadIssues.html#ListenersThreads" 5897 * >AWT Threading Issues</a> for details on AWT's threading model. 5898 * 5899 * @param l the input method listener 5900 * @see java.awt.event.InputMethodEvent 5901 * @see java.awt.event.InputMethodListener 5902 * @see #removeInputMethodListener 5903 * @see #getInputMethodListeners 5904 * @see #getInputMethodRequests 5905 * @since 1.2 5906 */ 5907 public synchronized void addInputMethodListener(InputMethodListener l) { 5908 if (l == null) { 5909 return; 5910 } 5911 inputMethodListener = AWTEventMulticaster.add(inputMethodListener, l); 5912 newEventsOnly = true; 5913 } 5914 5915 /** 5916 * Removes the specified input method listener so that it no longer 5917 * receives input method events from this component. This method performs 5918 * no function, nor does it throw an exception, if the listener 5919 * specified by the argument was not previously added to this component. 5920 * If listener <code>l</code> is <code>null</code>, 5921 * no exception is thrown and no action is performed. 5922 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" 5923 * >AWT Threading Issues</a> for details on AWT's threading model. 5924 * 5925 * @param l the input method listener 5926 * @see java.awt.event.InputMethodEvent 5927 * @see java.awt.event.InputMethodListener 5928 * @see #addInputMethodListener 5929 * @see #getInputMethodListeners 5930 * @since 1.2 5931 */ 5932 public synchronized void removeInputMethodListener(InputMethodListener l) { 5933 if (l == null) { 5934 return; 5935 } 5936 inputMethodListener = AWTEventMulticaster.remove(inputMethodListener, l); 5937 } 5938 5939 /** 5940 * Returns an array of all the input method listeners 5941 * registered on this component. 5942 * 5943 * @return all of this component's <code>InputMethodListener</code>s 5944 * or an empty array if no input method 5945 * listeners are currently registered 5946 * 5947 * @see #addInputMethodListener 5948 * @see #removeInputMethodListener 5949 * @since 1.4 5950 */ 5951 public synchronized InputMethodListener[] getInputMethodListeners() { 5952 return getListeners(InputMethodListener.class); 5953 } 5954 5955 /** 5956 * Returns an array of all the objects currently registered 5957 * as <code><em>Foo</em>Listener</code>s 5958 * upon this <code>Component</code>. 5959 * <code><em>Foo</em>Listener</code>s are registered using the 5960 * <code>add<em>Foo</em>Listener</code> method. 5961 * 5962 * <p> 5963 * You can specify the <code>listenerType</code> argument 5964 * with a class literal, such as 5965 * <code><em>Foo</em>Listener.class</code>. 5966 * For example, you can query a 5967 * <code>Component</code> <code>c</code> 5968 * for its mouse listeners with the following code: 5969 * 5970 * <pre>MouseListener[] mls = (MouseListener[])(c.getListeners(MouseListener.class));</pre> 5971 * 5972 * If no such listeners exist, this method returns an empty array. 5973 * 5974 * @param listenerType the type of listeners requested; this parameter 5975 * should specify an interface that descends from 5976 * <code>java.util.EventListener</code> 5977 * @return an array of all objects registered as 5978 * <code><em>Foo</em>Listener</code>s on this component, 5979 * or an empty array if no such listeners have been added 5980 * @exception ClassCastException if <code>listenerType</code> 5981 * doesn't specify a class or interface that implements 5982 * <code>java.util.EventListener</code> 5983 * @throws NullPointerException if {@code listenerType} is {@code null} 5984 * @see #getComponentListeners 5985 * @see #getFocusListeners 5986 * @see #getHierarchyListeners 5987 * @see #getHierarchyBoundsListeners 5988 * @see #getKeyListeners 5989 * @see #getMouseListeners 5990 * @see #getMouseMotionListeners 5991 * @see #getMouseWheelListeners 5992 * @see #getInputMethodListeners 5993 * @see #getPropertyChangeListeners 5994 * 5995 * @since 1.3 5996 */ 5997 @SuppressWarnings("unchecked") 5998 public <T extends EventListener> T[] getListeners(Class<T> listenerType) { 5999 EventListener l = null; 6000 if (listenerType == ComponentListener.class) { 6001 l = componentListener; 6002 } else if (listenerType == FocusListener.class) { 6003 l = focusListener; 6004 } else if (listenerType == HierarchyListener.class) { 6005 l = hierarchyListener; 6006 } else if (listenerType == HierarchyBoundsListener.class) { 6007 l = hierarchyBoundsListener; 6008 } else if (listenerType == KeyListener.class) { 6009 l = keyListener; 6010 } else if (listenerType == MouseListener.class) { 6011 l = mouseListener; 6012 } else if (listenerType == MouseMotionListener.class) { 6013 l = mouseMotionListener; 6014 } else if (listenerType == MouseWheelListener.class) { 6015 l = mouseWheelListener; 6016 } else if (listenerType == InputMethodListener.class) { 6017 l = inputMethodListener; 6018 } else if (listenerType == PropertyChangeListener.class) { 6019 return (T[])getPropertyChangeListeners(); 6020 } 6021 return AWTEventMulticaster.getListeners(l, listenerType); 6022 } 6023 6024 /** 6025 * Gets the input method request handler which supports 6026 * requests from input methods for this component. A component 6027 * that supports on-the-spot text input must override this 6028 * method to return an <code>InputMethodRequests</code> instance. 6029 * At the same time, it also has to handle input method events. 6030 * 6031 * @return the input method request handler for this component, 6032 * <code>null</code> by default 6033 * @see #addInputMethodListener 6034 * @since 1.2 6035 */ 6036 public InputMethodRequests getInputMethodRequests() { 6037 return null; 6038 } 6039 6040 /** 6041 * Gets the input context used by this component for handling 6042 * the communication with input methods when text is entered 6043 * in this component. By default, the input context used for 6044 * the parent component is returned. Components may 6045 * override this to return a private input context. 6046 * 6047 * @return the input context used by this component; 6048 * <code>null</code> if no context can be determined 6049 * @since 1.2 6050 */ 6051 public InputContext getInputContext() { 6052 Container parent = this.parent; 6053 if (parent == null) { 6054 return null; 6055 } else { 6056 return parent.getInputContext(); 6057 } 6058 } 6059 6060 /** 6061 * Enables the events defined by the specified event mask parameter 6062 * to be delivered to this component. 6063 * <p> 6064 * Event types are automatically enabled when a listener for 6065 * that event type is added to the component. 6066 * <p> 6067 * This method only needs to be invoked by subclasses of 6068 * <code>Component</code> which desire to have the specified event 6069 * types delivered to <code>processEvent</code> regardless of whether 6070 * or not a listener is registered. 6071 * @param eventsToEnable the event mask defining the event types 6072 * @see #processEvent 6073 * @see #disableEvents 6074 * @see AWTEvent 6075 * @since JDK1.1 6076 */ 6077 protected final void enableEvents(long eventsToEnable) { 6078 long notifyAncestors = 0; 6079 synchronized (this) { 6080 if ((eventsToEnable & AWTEvent.HIERARCHY_EVENT_MASK) != 0 && 6081 hierarchyListener == null && 6082 (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) == 0) { 6083 notifyAncestors |= AWTEvent.HIERARCHY_EVENT_MASK; 6084 } 6085 if ((eventsToEnable & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0 && 6086 hierarchyBoundsListener == null && 6087 (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) == 0) { 6088 notifyAncestors |= AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK; 6089 } 6090 eventMask |= eventsToEnable; 6091 newEventsOnly = true; 6092 } 6093 6094 // if this is a lightweight component, enable mouse events 6095 // in the native container. 6096 if (peer instanceof LightweightPeer) { 6097 parent.proxyEnableEvents(eventMask); 6098 } 6099 if (notifyAncestors != 0) { 6100 synchronized (getTreeLock()) { 6101 adjustListeningChildrenOnParent(notifyAncestors, 1); 6102 } 6103 } 6104 } 6105 6106 /** 6107 * Disables the events defined by the specified event mask parameter 6108 * from being delivered to this component. 6109 * @param eventsToDisable the event mask defining the event types 6110 * @see #enableEvents 6111 * @since JDK1.1 6112 */ 6113 protected final void disableEvents(long eventsToDisable) { 6114 long notifyAncestors = 0; 6115 synchronized (this) { 6116 if ((eventsToDisable & AWTEvent.HIERARCHY_EVENT_MASK) != 0 && 6117 hierarchyListener == null && 6118 (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0) { 6119 notifyAncestors |= AWTEvent.HIERARCHY_EVENT_MASK; 6120 } 6121 if ((eventsToDisable & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK)!=0 && 6122 hierarchyBoundsListener == null && 6123 (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0) { 6124 notifyAncestors |= AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK; 6125 } 6126 eventMask &= ~eventsToDisable; 6127 } 6128 if (notifyAncestors != 0) { 6129 synchronized (getTreeLock()) { 6130 adjustListeningChildrenOnParent(notifyAncestors, -1); 6131 } 6132 } 6133 } 6134 6135 transient sun.awt.EventQueueItem[] eventCache; 6136 6137 /** 6138 * @see #isCoalescingEnabled 6139 * @see #checkCoalescing 6140 */ 6141 transient private boolean coalescingEnabled = checkCoalescing(); 6142 6143 /** 6144 * Weak map of known coalesceEvent overriders. 6145 * Value indicates whether overriden. 6146 * Bootstrap classes are not included. 6147 */ 6148 private static final Map<Class<?>, Boolean> coalesceMap = 6149 new java.util.WeakHashMap<Class<?>, Boolean>(); 6150 6151 /** 6152 * Indicates whether this class overrides coalesceEvents. 6153 * It is assumed that all classes that are loaded from the bootstrap 6154 * do not. 6155 * The boostrap class loader is assumed to be represented by null. 6156 * We do not check that the method really overrides 6157 * (it might be static, private or package private). 6158 */ 6159 private boolean checkCoalescing() { 6160 if (getClass().getClassLoader()==null) { 6161 return false; 6162 } 6163 final Class<? extends Component> clazz = getClass(); 6164 synchronized (coalesceMap) { 6165 // Check cache. 6166 Boolean value = coalesceMap.get(clazz); 6167 if (value != null) { 6168 return value; 6169 } 6170 6171 // Need to check non-bootstraps. 6172 Boolean enabled = java.security.AccessController.doPrivileged( 6173 new java.security.PrivilegedAction<Boolean>() { 6174 public Boolean run() { 6175 return isCoalesceEventsOverriden(clazz); 6176 } 6177 } 6178 ); 6179 coalesceMap.put(clazz, enabled); 6180 return enabled; 6181 } 6182 } 6183 6184 /** 6185 * Parameter types of coalesceEvents(AWTEvent,AWTEVent). 6186 */ 6187 private static final Class[] coalesceEventsParams = { 6188 AWTEvent.class, AWTEvent.class 6189 }; 6190 6191 /** 6192 * Indicates whether a class or its superclasses override coalesceEvents. 6193 * Must be called with lock on coalesceMap and privileged. 6194 * @see checkCoalsecing 6195 */ 6196 private static boolean isCoalesceEventsOverriden(Class<?> clazz) { 6197 assert Thread.holdsLock(coalesceMap); 6198 6199 // First check superclass - we may not need to bother ourselves. 6200 Class<?> superclass = clazz.getSuperclass(); 6201 if (superclass == null) { 6202 // Only occurs on implementations that 6203 // do not use null to represent the bootsrap class loader. 6204 return false; 6205 } 6206 if (superclass.getClassLoader() != null) { 6207 Boolean value = coalesceMap.get(superclass); 6208 if (value == null) { 6209 // Not done already - recurse. 6210 if (isCoalesceEventsOverriden(superclass)) { 6211 coalesceMap.put(superclass, true); 6212 return true; 6213 } 6214 } else if (value) { 6215 return true; 6216 } 6217 } 6218 6219 try { 6220 // Throws if not overriden. 6221 clazz.getDeclaredMethod( 6222 "coalesceEvents", coalesceEventsParams 6223 ); 6224 return true; 6225 } catch (NoSuchMethodException e) { 6226 // Not present in this class. 6227 return false; 6228 } 6229 } 6230 6231 /** 6232 * Indicates whether coalesceEvents may do something. 6233 */ 6234 final boolean isCoalescingEnabled() { 6235 return coalescingEnabled; 6236 } 6237 6238 6239 /** 6240 * Potentially coalesce an event being posted with an existing 6241 * event. This method is called by <code>EventQueue.postEvent</code> 6242 * if an event with the same ID as the event to be posted is found in 6243 * the queue (both events must have this component as their source). 6244 * This method either returns a coalesced event which replaces 6245 * the existing event (and the new event is then discarded), or 6246 * <code>null</code> to indicate that no combining should be done 6247 * (add the second event to the end of the queue). Either event 6248 * parameter may be modified and returned, as the other one is discarded 6249 * unless <code>null</code> is returned. 6250 * <p> 6251 * This implementation of <code>coalesceEvents</code> coalesces 6252 * two event types: mouse move (and drag) events, 6253 * and paint (and update) events. 6254 * For mouse move events the last event is always returned, causing 6255 * intermediate moves to be discarded. For paint events, the new 6256 * event is coalesced into a complex <code>RepaintArea</code> in the peer. 6257 * The new <code>AWTEvent</code> is always returned. 6258 * 6259 * @param existingEvent the event already on the <code>EventQueue</code> 6260 * @param newEvent the event being posted to the 6261 * <code>EventQueue</code> 6262 * @return a coalesced event, or <code>null</code> indicating that no 6263 * coalescing was done 6264 */ 6265 protected AWTEvent coalesceEvents(AWTEvent existingEvent, 6266 AWTEvent newEvent) { 6267 return null; 6268 } 6269 6270 /** 6271 * Processes events occurring on this component. By default this 6272 * method calls the appropriate 6273 * <code>process<event type>Event</code> 6274 * method for the given class of event. 6275 * <p>Note that if the event parameter is <code>null</code> 6276 * the behavior is unspecified and may result in an 6277 * exception. 6278 * 6279 * @param e the event 6280 * @see #processComponentEvent 6281 * @see #processFocusEvent 6282 * @see #processKeyEvent 6283 * @see #processMouseEvent 6284 * @see #processMouseMotionEvent 6285 * @see #processInputMethodEvent 6286 * @see #processHierarchyEvent 6287 * @see #processMouseWheelEvent 6288 * @since JDK1.1 6289 */ 6290 protected void processEvent(AWTEvent e) { 6291 if (e instanceof FocusEvent) { 6292 processFocusEvent((FocusEvent)e); 6293 6294 } else if (e instanceof MouseEvent) { 6295 switch(e.getID()) { 6296 case MouseEvent.MOUSE_PRESSED: 6297 case MouseEvent.MOUSE_RELEASED: 6298 case MouseEvent.MOUSE_CLICKED: 6299 case MouseEvent.MOUSE_ENTERED: 6300 case MouseEvent.MOUSE_EXITED: 6301 processMouseEvent((MouseEvent)e); 6302 break; 6303 case MouseEvent.MOUSE_MOVED: 6304 case MouseEvent.MOUSE_DRAGGED: 6305 processMouseMotionEvent((MouseEvent)e); 6306 break; 6307 case MouseEvent.MOUSE_WHEEL: 6308 processMouseWheelEvent((MouseWheelEvent)e); 6309 break; 6310 } 6311 6312 } else if (e instanceof KeyEvent) { 6313 processKeyEvent((KeyEvent)e); 6314 6315 } else if (e instanceof ComponentEvent) { 6316 processComponentEvent((ComponentEvent)e); 6317 } else if (e instanceof InputMethodEvent) { 6318 processInputMethodEvent((InputMethodEvent)e); 6319 } else if (e instanceof HierarchyEvent) { 6320 switch (e.getID()) { 6321 case HierarchyEvent.HIERARCHY_CHANGED: 6322 processHierarchyEvent((HierarchyEvent)e); 6323 break; 6324 case HierarchyEvent.ANCESTOR_MOVED: 6325 case HierarchyEvent.ANCESTOR_RESIZED: 6326 processHierarchyBoundsEvent((HierarchyEvent)e); 6327 break; 6328 } 6329 } 6330 } 6331 6332 /** 6333 * Processes component events occurring on this component by 6334 * dispatching them to any registered 6335 * <code>ComponentListener</code> objects. 6336 * <p> 6337 * This method is not called unless component events are 6338 * enabled for this component. Component events are enabled 6339 * when one of the following occurs: 6340 * <ul> 6341 * <li>A <code>ComponentListener</code> object is registered 6342 * via <code>addComponentListener</code>. 6343 * <li>Component events are enabled via <code>enableEvents</code>. 6344 * </ul> 6345 * <p>Note that if the event parameter is <code>null</code> 6346 * the behavior is unspecified and may result in an 6347 * exception. 6348 * 6349 * @param e the component event 6350 * @see java.awt.event.ComponentEvent 6351 * @see java.awt.event.ComponentListener 6352 * @see #addComponentListener 6353 * @see #enableEvents 6354 * @since JDK1.1 6355 */ 6356 protected void processComponentEvent(ComponentEvent e) { 6357 ComponentListener listener = componentListener; 6358 if (listener != null) { 6359 int id = e.getID(); 6360 switch(id) { 6361 case ComponentEvent.COMPONENT_RESIZED: 6362 listener.componentResized(e); 6363 break; 6364 case ComponentEvent.COMPONENT_MOVED: 6365 listener.componentMoved(e); 6366 break; 6367 case ComponentEvent.COMPONENT_SHOWN: 6368 listener.componentShown(e); 6369 break; 6370 case ComponentEvent.COMPONENT_HIDDEN: 6371 listener.componentHidden(e); 6372 break; 6373 } 6374 } 6375 } 6376 6377 /** 6378 * Processes focus events occurring on this component by 6379 * dispatching them to any registered 6380 * <code>FocusListener</code> objects. 6381 * <p> 6382 * This method is not called unless focus events are 6383 * enabled for this component. Focus events are enabled 6384 * when one of the following occurs: 6385 * <ul> 6386 * <li>A <code>FocusListener</code> object is registered 6387 * via <code>addFocusListener</code>. 6388 * <li>Focus events are enabled via <code>enableEvents</code>. 6389 * </ul> 6390 * <p> 6391 * If focus events are enabled for a <code>Component</code>, 6392 * the current <code>KeyboardFocusManager</code> determines 6393 * whether or not a focus event should be dispatched to 6394 * registered <code>FocusListener</code> objects. If the 6395 * events are to be dispatched, the <code>KeyboardFocusManager</code> 6396 * calls the <code>Component</code>'s <code>dispatchEvent</code> 6397 * method, which results in a call to the <code>Component</code>'s 6398 * <code>processFocusEvent</code> method. 6399 * <p> 6400 * If focus events are enabled for a <code>Component</code>, calling 6401 * the <code>Component</code>'s <code>dispatchEvent</code> method 6402 * with a <code>FocusEvent</code> as the argument will result in a 6403 * call to the <code>Component</code>'s <code>processFocusEvent</code> 6404 * method regardless of the current <code>KeyboardFocusManager</code>. 6405 * 6406 * <p>Note that if the event parameter is <code>null</code> 6407 * the behavior is unspecified and may result in an 6408 * exception. 6409 * 6410 * @param e the focus event 6411 * @see java.awt.event.FocusEvent 6412 * @see java.awt.event.FocusListener 6413 * @see java.awt.KeyboardFocusManager 6414 * @see #addFocusListener 6415 * @see #enableEvents 6416 * @see #dispatchEvent 6417 * @since JDK1.1 6418 */ 6419 protected void processFocusEvent(FocusEvent e) { 6420 FocusListener listener = focusListener; 6421 if (listener != null) { 6422 int id = e.getID(); 6423 switch(id) { 6424 case FocusEvent.FOCUS_GAINED: 6425 listener.focusGained(e); 6426 break; 6427 case FocusEvent.FOCUS_LOST: 6428 listener.focusLost(e); 6429 break; 6430 } 6431 } 6432 } 6433 6434 /** 6435 * Processes key events occurring on this component by 6436 * dispatching them to any registered 6437 * <code>KeyListener</code> objects. 6438 * <p> 6439 * This method is not called unless key events are 6440 * enabled for this component. Key events are enabled 6441 * when one of the following occurs: 6442 * <ul> 6443 * <li>A <code>KeyListener</code> object is registered 6444 * via <code>addKeyListener</code>. 6445 * <li>Key events are enabled via <code>enableEvents</code>. 6446 * </ul> 6447 * 6448 * <p> 6449 * If key events are enabled for a <code>Component</code>, 6450 * the current <code>KeyboardFocusManager</code> determines 6451 * whether or not a key event should be dispatched to 6452 * registered <code>KeyListener</code> objects. The 6453 * <code>DefaultKeyboardFocusManager</code> will not dispatch 6454 * key events to a <code>Component</code> that is not the focus 6455 * owner or is not showing. 6456 * <p> 6457 * As of J2SE 1.4, <code>KeyEvent</code>s are redirected to 6458 * the focus owner. Please see the 6459 * <a href="doc-files/FocusSpec.html">Focus Specification</a> 6460 * for further information. 6461 * <p> 6462 * Calling a <code>Component</code>'s <code>dispatchEvent</code> 6463 * method with a <code>KeyEvent</code> as the argument will 6464 * result in a call to the <code>Component</code>'s 6465 * <code>processKeyEvent</code> method regardless of the 6466 * current <code>KeyboardFocusManager</code> as long as the 6467 * component is showing, focused, and enabled, and key events 6468 * are enabled on it. 6469 * <p>If the event parameter is <code>null</code> 6470 * the behavior is unspecified and may result in an 6471 * exception. 6472 * 6473 * @param e the key event 6474 * @see java.awt.event.KeyEvent 6475 * @see java.awt.event.KeyListener 6476 * @see java.awt.KeyboardFocusManager 6477 * @see java.awt.DefaultKeyboardFocusManager 6478 * @see #processEvent 6479 * @see #dispatchEvent 6480 * @see #addKeyListener 6481 * @see #enableEvents 6482 * @see #isShowing 6483 * @since JDK1.1 6484 */ 6485 protected void processKeyEvent(KeyEvent e) { 6486 KeyListener listener = keyListener; 6487 if (listener != null) { 6488 int id = e.getID(); 6489 switch(id) { 6490 case KeyEvent.KEY_TYPED: 6491 listener.keyTyped(e); 6492 break; 6493 case KeyEvent.KEY_PRESSED: 6494 listener.keyPressed(e); 6495 break; 6496 case KeyEvent.KEY_RELEASED: 6497 listener.keyReleased(e); 6498 break; 6499 } 6500 } 6501 } 6502 6503 /** 6504 * Processes mouse events occurring on this component by 6505 * dispatching them to any registered 6506 * <code>MouseListener</code> objects. 6507 * <p> 6508 * This method is not called unless mouse events are 6509 * enabled for this component. Mouse events are enabled 6510 * when one of the following occurs: 6511 * <ul> 6512 * <li>A <code>MouseListener</code> object is registered 6513 * via <code>addMouseListener</code>. 6514 * <li>Mouse events are enabled via <code>enableEvents</code>. 6515 * </ul> 6516 * <p>Note that if the event parameter is <code>null</code> 6517 * the behavior is unspecified and may result in an 6518 * exception. 6519 * 6520 * @param e the mouse event 6521 * @see java.awt.event.MouseEvent 6522 * @see java.awt.event.MouseListener 6523 * @see #addMouseListener 6524 * @see #enableEvents 6525 * @since JDK1.1 6526 */ 6527 protected void processMouseEvent(MouseEvent e) { 6528 MouseListener listener = mouseListener; 6529 if (listener != null) { 6530 int id = e.getID(); 6531 switch(id) { 6532 case MouseEvent.MOUSE_PRESSED: 6533 listener.mousePressed(e); 6534 break; 6535 case MouseEvent.MOUSE_RELEASED: 6536 listener.mouseReleased(e); 6537 break; 6538 case MouseEvent.MOUSE_CLICKED: 6539 listener.mouseClicked(e); 6540 break; 6541 case MouseEvent.MOUSE_EXITED: 6542 listener.mouseExited(e); 6543 break; 6544 case MouseEvent.MOUSE_ENTERED: 6545 listener.mouseEntered(e); 6546 break; 6547 } 6548 } 6549 } 6550 6551 /** 6552 * Processes mouse motion events occurring on this component by 6553 * dispatching them to any registered 6554 * <code>MouseMotionListener</code> objects. 6555 * <p> 6556 * This method is not called unless mouse motion events are 6557 * enabled for this component. Mouse motion events are enabled 6558 * when one of the following occurs: 6559 * <ul> 6560 * <li>A <code>MouseMotionListener</code> object is registered 6561 * via <code>addMouseMotionListener</code>. 6562 * <li>Mouse motion events are enabled via <code>enableEvents</code>. 6563 * </ul> 6564 * <p>Note that if the event parameter is <code>null</code> 6565 * the behavior is unspecified and may result in an 6566 * exception. 6567 * 6568 * @param e the mouse motion event 6569 * @see java.awt.event.MouseEvent 6570 * @see java.awt.event.MouseMotionListener 6571 * @see #addMouseMotionListener 6572 * @see #enableEvents 6573 * @since JDK1.1 6574 */ 6575 protected void processMouseMotionEvent(MouseEvent e) { 6576 MouseMotionListener listener = mouseMotionListener; 6577 if (listener != null) { 6578 int id = e.getID(); 6579 switch(id) { 6580 case MouseEvent.MOUSE_MOVED: 6581 listener.mouseMoved(e); 6582 break; 6583 case MouseEvent.MOUSE_DRAGGED: 6584 listener.mouseDragged(e); 6585 break; 6586 } 6587 } 6588 } 6589 6590 /** 6591 * Processes mouse wheel events occurring on this component by 6592 * dispatching them to any registered 6593 * <code>MouseWheelListener</code> objects. 6594 * <p> 6595 * This method is not called unless mouse wheel events are 6596 * enabled for this component. Mouse wheel events are enabled 6597 * when one of the following occurs: 6598 * <ul> 6599 * <li>A <code>MouseWheelListener</code> object is registered 6600 * via <code>addMouseWheelListener</code>. 6601 * <li>Mouse wheel events are enabled via <code>enableEvents</code>. 6602 * </ul> 6603 * <p> 6604 * For information on how mouse wheel events are dispatched, see 6605 * the class description for {@link MouseWheelEvent}. 6606 * <p> 6607 * Note that if the event parameter is <code>null</code> 6608 * the behavior is unspecified and may result in an 6609 * exception. 6610 * 6611 * @param e the mouse wheel event 6612 * @see java.awt.event.MouseWheelEvent 6613 * @see java.awt.event.MouseWheelListener 6614 * @see #addMouseWheelListener 6615 * @see #enableEvents 6616 * @since 1.4 6617 */ 6618 protected void processMouseWheelEvent(MouseWheelEvent e) { 6619 MouseWheelListener listener = mouseWheelListener; 6620 if (listener != null) { 6621 int id = e.getID(); 6622 switch(id) { 6623 case MouseEvent.MOUSE_WHEEL: 6624 listener.mouseWheelMoved(e); 6625 break; 6626 } 6627 } 6628 } 6629 6630 boolean postsOldMouseEvents() { 6631 return false; 6632 } 6633 6634 /** 6635 * Processes input method events occurring on this component by 6636 * dispatching them to any registered 6637 * <code>InputMethodListener</code> objects. 6638 * <p> 6639 * This method is not called unless input method events 6640 * are enabled for this component. Input method events are enabled 6641 * when one of the following occurs: 6642 * <ul> 6643 * <li>An <code>InputMethodListener</code> object is registered 6644 * via <code>addInputMethodListener</code>. 6645 * <li>Input method events are enabled via <code>enableEvents</code>. 6646 * </ul> 6647 * <p>Note that if the event parameter is <code>null</code> 6648 * the behavior is unspecified and may result in an 6649 * exception. 6650 * 6651 * @param e the input method event 6652 * @see java.awt.event.InputMethodEvent 6653 * @see java.awt.event.InputMethodListener 6654 * @see #addInputMethodListener 6655 * @see #enableEvents 6656 * @since 1.2 6657 */ 6658 protected void processInputMethodEvent(InputMethodEvent e) { 6659 InputMethodListener listener = inputMethodListener; 6660 if (listener != null) { 6661 int id = e.getID(); 6662 switch (id) { 6663 case InputMethodEvent.INPUT_METHOD_TEXT_CHANGED: 6664 listener.inputMethodTextChanged(e); 6665 break; 6666 case InputMethodEvent.CARET_POSITION_CHANGED: 6667 listener.caretPositionChanged(e); 6668 break; 6669 } 6670 } 6671 } 6672 6673 /** 6674 * Processes hierarchy events occurring on this component by 6675 * dispatching them to any registered 6676 * <code>HierarchyListener</code> objects. 6677 * <p> 6678 * This method is not called unless hierarchy events 6679 * are enabled for this component. Hierarchy events are enabled 6680 * when one of the following occurs: 6681 * <ul> 6682 * <li>An <code>HierarchyListener</code> object is registered 6683 * via <code>addHierarchyListener</code>. 6684 * <li>Hierarchy events are enabled via <code>enableEvents</code>. 6685 * </ul> 6686 * <p>Note that if the event parameter is <code>null</code> 6687 * the behavior is unspecified and may result in an 6688 * exception. 6689 * 6690 * @param e the hierarchy event 6691 * @see java.awt.event.HierarchyEvent 6692 * @see java.awt.event.HierarchyListener 6693 * @see #addHierarchyListener 6694 * @see #enableEvents 6695 * @since 1.3 6696 */ 6697 protected void processHierarchyEvent(HierarchyEvent e) { 6698 HierarchyListener listener = hierarchyListener; 6699 if (listener != null) { 6700 int id = e.getID(); 6701 switch (id) { 6702 case HierarchyEvent.HIERARCHY_CHANGED: 6703 listener.hierarchyChanged(e); 6704 break; 6705 } 6706 } 6707 } 6708 6709 /** 6710 * Processes hierarchy bounds events occurring on this component by 6711 * dispatching them to any registered 6712 * <code>HierarchyBoundsListener</code> objects. 6713 * <p> 6714 * This method is not called unless hierarchy bounds events 6715 * are enabled for this component. Hierarchy bounds events are enabled 6716 * when one of the following occurs: 6717 * <ul> 6718 * <li>An <code>HierarchyBoundsListener</code> object is registered 6719 * via <code>addHierarchyBoundsListener</code>. 6720 * <li>Hierarchy bounds events are enabled via <code>enableEvents</code>. 6721 * </ul> 6722 * <p>Note that if the event parameter is <code>null</code> 6723 * the behavior is unspecified and may result in an 6724 * exception. 6725 * 6726 * @param e the hierarchy event 6727 * @see java.awt.event.HierarchyEvent 6728 * @see java.awt.event.HierarchyBoundsListener 6729 * @see #addHierarchyBoundsListener 6730 * @see #enableEvents 6731 * @since 1.3 6732 */ 6733 protected void processHierarchyBoundsEvent(HierarchyEvent e) { 6734 HierarchyBoundsListener listener = hierarchyBoundsListener; 6735 if (listener != null) { 6736 int id = e.getID(); 6737 switch (id) { 6738 case HierarchyEvent.ANCESTOR_MOVED: 6739 listener.ancestorMoved(e); 6740 break; 6741 case HierarchyEvent.ANCESTOR_RESIZED: 6742 listener.ancestorResized(e); 6743 break; 6744 } 6745 } 6746 } 6747 6748 /** 6749 * @deprecated As of JDK version 1.1 6750 * replaced by processEvent(AWTEvent). 6751 */ 6752 @Deprecated 6753 public boolean handleEvent(Event evt) { 6754 switch (evt.id) { 6755 case Event.MOUSE_ENTER: 6756 return mouseEnter(evt, evt.x, evt.y); 6757 6758 case Event.MOUSE_EXIT: 6759 return mouseExit(evt, evt.x, evt.y); 6760 6761 case Event.MOUSE_MOVE: 6762 return mouseMove(evt, evt.x, evt.y); 6763 6764 case Event.MOUSE_DOWN: 6765 return mouseDown(evt, evt.x, evt.y); 6766 6767 case Event.MOUSE_DRAG: 6768 return mouseDrag(evt, evt.x, evt.y); 6769 6770 case Event.MOUSE_UP: 6771 return mouseUp(evt, evt.x, evt.y); 6772 6773 case Event.KEY_PRESS: 6774 case Event.KEY_ACTION: 6775 return keyDown(evt, evt.key); 6776 6777 case Event.KEY_RELEASE: 6778 case Event.KEY_ACTION_RELEASE: 6779 return keyUp(evt, evt.key); 6780 6781 case Event.ACTION_EVENT: 6782 return action(evt, evt.arg); 6783 case Event.GOT_FOCUS: 6784 return gotFocus(evt, evt.arg); 6785 case Event.LOST_FOCUS: 6786 return lostFocus(evt, evt.arg); 6787 } 6788 return false; 6789 } 6790 6791 /** 6792 * @deprecated As of JDK version 1.1, 6793 * replaced by processMouseEvent(MouseEvent). 6794 */ 6795 @Deprecated 6796 public boolean mouseDown(Event evt, int x, int y) { 6797 return false; 6798 } 6799 6800 /** 6801 * @deprecated As of JDK version 1.1, 6802 * replaced by processMouseMotionEvent(MouseEvent). 6803 */ 6804 @Deprecated 6805 public boolean mouseDrag(Event evt, int x, int y) { 6806 return false; 6807 } 6808 6809 /** 6810 * @deprecated As of JDK version 1.1, 6811 * replaced by processMouseEvent(MouseEvent). 6812 */ 6813 @Deprecated 6814 public boolean mouseUp(Event evt, int x, int y) { 6815 return false; 6816 } 6817 6818 /** 6819 * @deprecated As of JDK version 1.1, 6820 * replaced by processMouseMotionEvent(MouseEvent). 6821 */ 6822 @Deprecated 6823 public boolean mouseMove(Event evt, int x, int y) { 6824 return false; 6825 } 6826 6827 /** 6828 * @deprecated As of JDK version 1.1, 6829 * replaced by processMouseEvent(MouseEvent). 6830 */ 6831 @Deprecated 6832 public boolean mouseEnter(Event evt, int x, int y) { 6833 return false; 6834 } 6835 6836 /** 6837 * @deprecated As of JDK version 1.1, 6838 * replaced by processMouseEvent(MouseEvent). 6839 */ 6840 @Deprecated 6841 public boolean mouseExit(Event evt, int x, int y) { 6842 return false; 6843 } 6844 6845 /** 6846 * @deprecated As of JDK version 1.1, 6847 * replaced by processKeyEvent(KeyEvent). 6848 */ 6849 @Deprecated 6850 public boolean keyDown(Event evt, int key) { 6851 return false; 6852 } 6853 6854 /** 6855 * @deprecated As of JDK version 1.1, 6856 * replaced by processKeyEvent(KeyEvent). 6857 */ 6858 @Deprecated 6859 public boolean keyUp(Event evt, int key) { 6860 return false; 6861 } 6862 6863 /** 6864 * @deprecated As of JDK version 1.1, 6865 * should register this component as ActionListener on component 6866 * which fires action events. 6867 */ 6868 @Deprecated 6869 public boolean action(Event evt, Object what) { 6870 return false; 6871 } 6872 6873 /** 6874 * Makes this <code>Component</code> displayable by connecting it to a 6875 * native screen resource. 6876 * This method is called internally by the toolkit and should 6877 * not be called directly by programs. 6878 * <p> 6879 * This method changes layout-related information, and therefore, 6880 * invalidates the component hierarchy. 6881 * 6882 * @see #isDisplayable 6883 * @see #removeNotify 6884 * @see #invalidate 6885 * @since JDK1.0 6886 */ 6887 public void addNotify() { 6888 synchronized (getTreeLock()) { 6889 ComponentPeer peer = this.peer; 6890 if (peer == null || peer instanceof LightweightPeer){ 6891 if (peer == null) { 6892 // Update both the Component's peer variable and the local 6893 // variable we use for thread safety. 6894 this.peer = peer = getToolkit().createComponent(this); 6895 } 6896 6897 // This is a lightweight component which means it won't be 6898 // able to get window-related events by itself. If any 6899 // have been enabled, then the nearest native container must 6900 // be enabled. 6901 if (parent != null) { 6902 long mask = 0; 6903 if ((mouseListener != null) || ((eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0)) { 6904 mask |= AWTEvent.MOUSE_EVENT_MASK; 6905 } 6906 if ((mouseMotionListener != null) || 6907 ((eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0)) { 6908 mask |= AWTEvent.MOUSE_MOTION_EVENT_MASK; 6909 } 6910 if ((mouseWheelListener != null ) || 6911 ((eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0)) { 6912 mask |= AWTEvent.MOUSE_WHEEL_EVENT_MASK; 6913 } 6914 if (focusListener != null || (eventMask & AWTEvent.FOCUS_EVENT_MASK) != 0) { 6915 mask |= AWTEvent.FOCUS_EVENT_MASK; 6916 } 6917 if (keyListener != null || (eventMask & AWTEvent.KEY_EVENT_MASK) != 0) { 6918 mask |= AWTEvent.KEY_EVENT_MASK; 6919 } 6920 if (mask != 0) { 6921 parent.proxyEnableEvents(mask); 6922 } 6923 } 6924 } else { 6925 // It's native. If the parent is lightweight it will need some 6926 // help. 6927 Container parent = getContainer(); 6928 if (parent != null && parent.isLightweight()) { 6929 relocateComponent(); 6930 if (!parent.isRecursivelyVisibleUpToHeavyweightContainer()) 6931 { 6932 peer.setVisible(false); 6933 } 6934 } 6935 } 6936 invalidate(); 6937 6938 int npopups = (popups != null? popups.size() : 0); 6939 for (int i = 0 ; i < npopups ; i++) { 6940 PopupMenu popup = popups.elementAt(i); 6941 popup.addNotify(); 6942 } 6943 6944 if (dropTarget != null) dropTarget.addNotify(peer); 6945 6946 peerFont = getFont(); 6947 6948 if (getContainer() != null && !isAddNotifyComplete) { 6949 getContainer().increaseComponentCount(this); 6950 } 6951 6952 6953 // Update stacking order 6954 updateZOrder(); 6955 6956 if (!isAddNotifyComplete) { 6957 mixOnShowing(); 6958 } 6959 6960 isAddNotifyComplete = true; 6961 6962 if (hierarchyListener != null || 6963 (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0 || 6964 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK)) { 6965 HierarchyEvent e = 6966 new HierarchyEvent(this, HierarchyEvent.HIERARCHY_CHANGED, 6967 this, parent, 6968 HierarchyEvent.DISPLAYABILITY_CHANGED | 6969 ((isRecursivelyVisible()) 6970 ? HierarchyEvent.SHOWING_CHANGED 6971 : 0)); 6972 dispatchEvent(e); 6973 } 6974 } 6975 } 6976 6977 /** 6978 * Makes this <code>Component</code> undisplayable by destroying it native 6979 * screen resource. 6980 * <p> 6981 * This method is called by the toolkit internally and should 6982 * not be called directly by programs. Code overriding 6983 * this method should call <code>super.removeNotify</code> as 6984 * the first line of the overriding method. 6985 * 6986 * @see #isDisplayable 6987 * @see #addNotify 6988 * @since JDK1.0 6989 */ 6990 public void removeNotify() { 6991 KeyboardFocusManager.clearMostRecentFocusOwner(this); 6992 if (KeyboardFocusManager.getCurrentKeyboardFocusManager(). 6993 getPermanentFocusOwner() == this) 6994 { 6995 KeyboardFocusManager.getCurrentKeyboardFocusManager(). 6996 setGlobalPermanentFocusOwner(null); 6997 } 6998 6999 synchronized (getTreeLock()) { 7000 clearLightweightDispatcherOnRemove(this); 7001 7002 if (isFocusOwner() && KeyboardFocusManager.isAutoFocusTransferEnabledFor(this)) { 7003 transferFocus(true); 7004 } 7005 7006 if (getContainer() != null && isAddNotifyComplete) { 7007 getContainer().decreaseComponentCount(this); 7008 } 7009 7010 int npopups = (popups != null? popups.size() : 0); 7011 for (int i = 0 ; i < npopups ; i++) { 7012 PopupMenu popup = popups.elementAt(i); 7013 popup.removeNotify(); 7014 } 7015 // If there is any input context for this component, notify 7016 // that this component is being removed. (This has to be done 7017 // before hiding peer.) 7018 if ((eventMask & AWTEvent.INPUT_METHODS_ENABLED_MASK) != 0) { 7019 InputContext inputContext = getInputContext(); 7020 if (inputContext != null) { 7021 inputContext.removeNotify(this); 7022 } 7023 } 7024 7025 ComponentPeer p = peer; 7026 if (p != null) { 7027 boolean isLightweight = isLightweight(); 7028 7029 if (bufferStrategy instanceof FlipBufferStrategy) { 7030 ((FlipBufferStrategy)bufferStrategy).destroyBuffers(); 7031 } 7032 7033 if (dropTarget != null) dropTarget.removeNotify(peer); 7034 7035 // Hide peer first to stop system events such as cursor moves. 7036 if (visible) { 7037 p.setVisible(false); 7038 } 7039 7040 peer = null; // Stop peer updates. 7041 peerFont = null; 7042 7043 Toolkit.getEventQueue().removeSourceEvents(this, false); 7044 KeyboardFocusManager.getCurrentKeyboardFocusManager(). 7045 discardKeyEvents(this); 7046 7047 p.dispose(); 7048 7049 mixOnHiding(isLightweight); 7050 7051 isAddNotifyComplete = false; 7052 // Nullifying compoundShape means that the component has normal shape 7053 // (or has no shape at all). 7054 this.compoundShape = null; 7055 } 7056 7057 if (hierarchyListener != null || 7058 (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0 || 7059 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK)) { 7060 HierarchyEvent e = 7061 new HierarchyEvent(this, HierarchyEvent.HIERARCHY_CHANGED, 7062 this, parent, 7063 HierarchyEvent.DISPLAYABILITY_CHANGED | 7064 ((isRecursivelyVisible()) 7065 ? HierarchyEvent.SHOWING_CHANGED 7066 : 0)); 7067 dispatchEvent(e); 7068 } 7069 } 7070 } 7071 7072 /** 7073 * @deprecated As of JDK version 1.1, 7074 * replaced by processFocusEvent(FocusEvent). 7075 */ 7076 @Deprecated 7077 public boolean gotFocus(Event evt, Object what) { 7078 return false; 7079 } 7080 7081 /** 7082 * @deprecated As of JDK version 1.1, 7083 * replaced by processFocusEvent(FocusEvent). 7084 */ 7085 @Deprecated 7086 public boolean lostFocus(Event evt, Object what) { 7087 return false; 7088 } 7089 7090 /** 7091 * Returns whether this <code>Component</code> can become the focus 7092 * owner. 7093 * 7094 * @return <code>true</code> if this <code>Component</code> is 7095 * focusable; <code>false</code> otherwise 7096 * @see #setFocusable 7097 * @since JDK1.1 7098 * @deprecated As of 1.4, replaced by <code>isFocusable()</code>. 7099 */ 7100 @Deprecated 7101 public boolean isFocusTraversable() { 7102 if (isFocusTraversableOverridden == FOCUS_TRAVERSABLE_UNKNOWN) { 7103 isFocusTraversableOverridden = FOCUS_TRAVERSABLE_DEFAULT; 7104 } 7105 return focusable; 7106 } 7107 7108 /** 7109 * Returns whether this Component can be focused. 7110 * 7111 * @return <code>true</code> if this Component is focusable; 7112 * <code>false</code> otherwise. 7113 * @see #setFocusable 7114 * @since 1.4 7115 */ 7116 public boolean isFocusable() { 7117 return isFocusTraversable(); 7118 } 7119 7120 /** 7121 * Sets the focusable state of this Component to the specified value. This 7122 * value overrides the Component's default focusability. 7123 * 7124 * @param focusable indicates whether this Component is focusable 7125 * @see #isFocusable 7126 * @since 1.4 7127 * @beaninfo 7128 * bound: true 7129 */ 7130 public void setFocusable(boolean focusable) { 7131 boolean oldFocusable; 7132 synchronized (this) { 7133 oldFocusable = this.focusable; 7134 this.focusable = focusable; 7135 } 7136 isFocusTraversableOverridden = FOCUS_TRAVERSABLE_SET; 7137 7138 firePropertyChange("focusable", oldFocusable, focusable); 7139 if (oldFocusable && !focusable) { 7140 if (isFocusOwner() && KeyboardFocusManager.isAutoFocusTransferEnabled()) { 7141 transferFocus(true); 7142 } 7143 KeyboardFocusManager.clearMostRecentFocusOwner(this); 7144 } 7145 } 7146 7147 final boolean isFocusTraversableOverridden() { 7148 return (isFocusTraversableOverridden != FOCUS_TRAVERSABLE_DEFAULT); 7149 } 7150 7151 /** 7152 * Sets the focus traversal keys for a given traversal operation for this 7153 * Component. 7154 * <p> 7155 * The default values for a Component's focus traversal keys are 7156 * implementation-dependent. Sun recommends that all implementations for a 7157 * particular native platform use the same default values. The 7158 * recommendations for Windows and Unix are listed below. These 7159 * recommendations are used in the Sun AWT implementations. 7160 * 7161 * <table border=1 summary="Recommended default values for a Component's focus traversal keys"> 7162 * <tr> 7163 * <th>Identifier</th> 7164 * <th>Meaning</th> 7165 * <th>Default</th> 7166 * </tr> 7167 * <tr> 7168 * <td>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</td> 7169 * <td>Normal forward keyboard traversal</td> 7170 * <td>TAB on KEY_PRESSED, CTRL-TAB on KEY_PRESSED</td> 7171 * </tr> 7172 * <tr> 7173 * <td>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</td> 7174 * <td>Normal reverse keyboard traversal</td> 7175 * <td>SHIFT-TAB on KEY_PRESSED, CTRL-SHIFT-TAB on KEY_PRESSED</td> 7176 * </tr> 7177 * <tr> 7178 * <td>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</td> 7179 * <td>Go up one focus traversal cycle</td> 7180 * <td>none</td> 7181 * </tr> 7182 * </table> 7183 * 7184 * To disable a traversal key, use an empty Set; Collections.EMPTY_SET is 7185 * recommended. 7186 * <p> 7187 * Using the AWTKeyStroke API, client code can specify on which of two 7188 * specific KeyEvents, KEY_PRESSED or KEY_RELEASED, the focus traversal 7189 * operation will occur. Regardless of which KeyEvent is specified, 7190 * however, all KeyEvents related to the focus traversal key, including the 7191 * associated KEY_TYPED event, will be consumed, and will not be dispatched 7192 * to any Component. It is a runtime error to specify a KEY_TYPED event as 7193 * mapping to a focus traversal operation, or to map the same event to 7194 * multiple default focus traversal operations. 7195 * <p> 7196 * If a value of null is specified for the Set, this Component inherits the 7197 * Set from its parent. If all ancestors of this Component have null 7198 * specified for the Set, then the current KeyboardFocusManager's default 7199 * Set is used. 7200 * <p> 7201 * This method may throw a {@code ClassCastException} if any {@code Object} 7202 * in {@code keystrokes} is not an {@code AWTKeyStroke}. 7203 * 7204 * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, 7205 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, or 7206 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS 7207 * @param keystrokes the Set of AWTKeyStroke for the specified operation 7208 * @see #getFocusTraversalKeys 7209 * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS 7210 * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS 7211 * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS 7212 * @throws IllegalArgumentException if id is not one of 7213 * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, 7214 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, or 7215 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or if keystrokes 7216 * contains null, or if any keystroke represents a KEY_TYPED event, 7217 * or if any keystroke already maps to another focus traversal 7218 * operation for this Component 7219 * @since 1.4 7220 * @beaninfo 7221 * bound: true 7222 */ 7223 public void setFocusTraversalKeys(int id, 7224 Set<? extends AWTKeyStroke> keystrokes) 7225 { 7226 if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH - 1) { 7227 throw new IllegalArgumentException("invalid focus traversal key identifier"); 7228 } 7229 7230 setFocusTraversalKeys_NoIDCheck(id, keystrokes); 7231 } 7232 7233 /** 7234 * Returns the Set of focus traversal keys for a given traversal operation 7235 * for this Component. (See 7236 * <code>setFocusTraversalKeys</code> for a full description of each key.) 7237 * <p> 7238 * If a Set of traversal keys has not been explicitly defined for this 7239 * Component, then this Component's parent's Set is returned. If no Set 7240 * has been explicitly defined for any of this Component's ancestors, then 7241 * the current KeyboardFocusManager's default Set is returned. 7242 * 7243 * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, 7244 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, or 7245 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS 7246 * @return the Set of AWTKeyStrokes for the specified operation. The Set 7247 * will be unmodifiable, and may be empty. null will never be 7248 * returned. 7249 * @see #setFocusTraversalKeys 7250 * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS 7251 * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS 7252 * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS 7253 * @throws IllegalArgumentException if id is not one of 7254 * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, 7255 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, or 7256 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS 7257 * @since 1.4 7258 */ 7259 public Set<AWTKeyStroke> getFocusTraversalKeys(int id) { 7260 if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH - 1) { 7261 throw new IllegalArgumentException("invalid focus traversal key identifier"); 7262 } 7263 7264 return getFocusTraversalKeys_NoIDCheck(id); 7265 } 7266 7267 // We define these methods so that Container does not need to repeat this 7268 // code. Container cannot call super.<method> because Container allows 7269 // DOWN_CYCLE_TRAVERSAL_KEY while Component does not. The Component method 7270 // would erroneously generate an IllegalArgumentException for 7271 // DOWN_CYCLE_TRAVERSAL_KEY. 7272 final void setFocusTraversalKeys_NoIDCheck(int id, Set<? extends AWTKeyStroke> keystrokes) { 7273 Set<AWTKeyStroke> oldKeys; 7274 7275 synchronized (this) { 7276 if (focusTraversalKeys == null) { 7277 initializeFocusTraversalKeys(); 7278 } 7279 7280 if (keystrokes != null) { 7281 for (AWTKeyStroke keystroke : keystrokes ) { 7282 7283 if (keystroke == null) { 7284 throw new IllegalArgumentException("cannot set null focus traversal key"); 7285 } 7286 7287 if (keystroke.getKeyChar() != KeyEvent.CHAR_UNDEFINED) { 7288 throw new IllegalArgumentException("focus traversal keys cannot map to KEY_TYPED events"); 7289 } 7290 7291 for (int i = 0; i < focusTraversalKeys.length; i++) { 7292 if (i == id) { 7293 continue; 7294 } 7295 7296 if (getFocusTraversalKeys_NoIDCheck(i).contains(keystroke)) 7297 { 7298 throw new IllegalArgumentException("focus traversal keys must be unique for a Component"); 7299 } 7300 } 7301 } 7302 } 7303 7304 oldKeys = focusTraversalKeys[id]; 7305 focusTraversalKeys[id] = (keystrokes != null) 7306 ? Collections.unmodifiableSet(new HashSet<AWTKeyStroke>(keystrokes)) 7307 : null; 7308 } 7309 7310 firePropertyChange(focusTraversalKeyPropertyNames[id], oldKeys, 7311 keystrokes); 7312 } 7313 final Set<AWTKeyStroke> getFocusTraversalKeys_NoIDCheck(int id) { 7314 // Okay to return Set directly because it is an unmodifiable view 7315 @SuppressWarnings("unchecked") 7316 Set<AWTKeyStroke> keystrokes = (focusTraversalKeys != null) 7317 ? focusTraversalKeys[id] 7318 : null; 7319 7320 if (keystrokes != null) { 7321 return keystrokes; 7322 } else { 7323 Container parent = this.parent; 7324 if (parent != null) { 7325 return parent.getFocusTraversalKeys(id); 7326 } else { 7327 return KeyboardFocusManager.getCurrentKeyboardFocusManager(). 7328 getDefaultFocusTraversalKeys(id); 7329 } 7330 } 7331 } 7332 7333 /** 7334 * Returns whether the Set of focus traversal keys for the given focus 7335 * traversal operation has been explicitly defined for this Component. If 7336 * this method returns <code>false</code>, this Component is inheriting the 7337 * Set from an ancestor, or from the current KeyboardFocusManager. 7338 * 7339 * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, 7340 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, or 7341 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS 7342 * @return <code>true</code> if the the Set of focus traversal keys for the 7343 * given focus traversal operation has been explicitly defined for 7344 * this Component; <code>false</code> otherwise. 7345 * @throws IllegalArgumentException if id is not one of 7346 * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, 7347 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, or 7348 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS 7349 * @since 1.4 7350 */ 7351 public boolean areFocusTraversalKeysSet(int id) { 7352 if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH - 1) { 7353 throw new IllegalArgumentException("invalid focus traversal key identifier"); 7354 } 7355 7356 return (focusTraversalKeys != null && focusTraversalKeys[id] != null); 7357 } 7358 7359 /** 7360 * Sets whether focus traversal keys are enabled for this Component. 7361 * Components for which focus traversal keys are disabled receive key 7362 * events for focus traversal keys. Components for which focus traversal 7363 * keys are enabled do not see these events; instead, the events are 7364 * automatically converted to traversal operations. 7365 * 7366 * @param focusTraversalKeysEnabled whether focus traversal keys are 7367 * enabled for this Component 7368 * @see #getFocusTraversalKeysEnabled 7369 * @see #setFocusTraversalKeys 7370 * @see #getFocusTraversalKeys 7371 * @since 1.4 7372 * @beaninfo 7373 * bound: true 7374 */ 7375 public void setFocusTraversalKeysEnabled(boolean 7376 focusTraversalKeysEnabled) { 7377 boolean oldFocusTraversalKeysEnabled; 7378 synchronized (this) { 7379 oldFocusTraversalKeysEnabled = this.focusTraversalKeysEnabled; 7380 this.focusTraversalKeysEnabled = focusTraversalKeysEnabled; 7381 } 7382 firePropertyChange("focusTraversalKeysEnabled", 7383 oldFocusTraversalKeysEnabled, 7384 focusTraversalKeysEnabled); 7385 } 7386 7387 /** 7388 * Returns whether focus traversal keys are enabled for this Component. 7389 * Components for which focus traversal keys are disabled receive key 7390 * events for focus traversal keys. Components for which focus traversal 7391 * keys are enabled do not see these events; instead, the events are 7392 * automatically converted to traversal operations. 7393 * 7394 * @return whether focus traversal keys are enabled for this Component 7395 * @see #setFocusTraversalKeysEnabled 7396 * @see #setFocusTraversalKeys 7397 * @see #getFocusTraversalKeys 7398 * @since 1.4 7399 */ 7400 public boolean getFocusTraversalKeysEnabled() { 7401 return focusTraversalKeysEnabled; 7402 } 7403 7404 /** 7405 * Requests that this Component get the input focus, and that this 7406 * Component's top-level ancestor become the focused Window. This 7407 * component must be displayable, focusable, visible and all of 7408 * its ancestors (with the exception of the top-level Window) must 7409 * be visible for the request to be granted. Every effort will be 7410 * made to honor the request; however, in some cases it may be 7411 * impossible to do so. Developers must never assume that this 7412 * Component is the focus owner until this Component receives a 7413 * FOCUS_GAINED event. If this request is denied because this 7414 * Component's top-level Window cannot become the focused Window, 7415 * the request will be remembered and will be granted when the 7416 * Window is later focused by the user. 7417 * <p> 7418 * This method cannot be used to set the focus owner to no Component at 7419 * all. Use <code>KeyboardFocusManager.clearGlobalFocusOwner()</code> 7420 * instead. 7421 * <p> 7422 * Because the focus behavior of this method is platform-dependent, 7423 * developers are strongly encouraged to use 7424 * <code>requestFocusInWindow</code> when possible. 7425 * 7426 * <p>Note: Not all focus transfers result from invoking this method. As 7427 * such, a component may receive focus without this or any of the other 7428 * {@code requestFocus} methods of {@code Component} being invoked. 7429 * 7430 * @see #requestFocusInWindow 7431 * @see java.awt.event.FocusEvent 7432 * @see #addFocusListener 7433 * @see #isFocusable 7434 * @see #isDisplayable 7435 * @see KeyboardFocusManager#clearGlobalFocusOwner 7436 * @since JDK1.0 7437 */ 7438 public void requestFocus() { 7439 requestFocusHelper(false, true); 7440 } 7441 7442 boolean requestFocus(CausedFocusEvent.Cause cause) { 7443 return requestFocusHelper(false, true, cause); 7444 } 7445 7446 /** 7447 * Requests that this <code>Component</code> get the input focus, 7448 * and that this <code>Component</code>'s top-level ancestor 7449 * become the focused <code>Window</code>. This component must be 7450 * displayable, focusable, visible and all of its ancestors (with 7451 * the exception of the top-level Window) must be visible for the 7452 * request to be granted. Every effort will be made to honor the 7453 * request; however, in some cases it may be impossible to do 7454 * so. Developers must never assume that this component is the 7455 * focus owner until this component receives a FOCUS_GAINED 7456 * event. If this request is denied because this component's 7457 * top-level window cannot become the focused window, the request 7458 * will be remembered and will be granted when the window is later 7459 * focused by the user. 7460 * <p> 7461 * This method returns a boolean value. If <code>false</code> is returned, 7462 * the request is <b>guaranteed to fail</b>. If <code>true</code> is 7463 * returned, the request will succeed <b>unless</b> it is vetoed, or an 7464 * extraordinary event, such as disposal of the component's peer, occurs 7465 * before the request can be granted by the native windowing system. Again, 7466 * while a return value of <code>true</code> indicates that the request is 7467 * likely to succeed, developers must never assume that this component is 7468 * the focus owner until this component receives a FOCUS_GAINED event. 7469 * <p> 7470 * This method cannot be used to set the focus owner to no component at 7471 * all. Use <code>KeyboardFocusManager.clearGlobalFocusOwner</code> 7472 * instead. 7473 * <p> 7474 * Because the focus behavior of this method is platform-dependent, 7475 * developers are strongly encouraged to use 7476 * <code>requestFocusInWindow</code> when possible. 7477 * <p> 7478 * Every effort will be made to ensure that <code>FocusEvent</code>s 7479 * generated as a 7480 * result of this request will have the specified temporary value. However, 7481 * because specifying an arbitrary temporary state may not be implementable 7482 * on all native windowing systems, correct behavior for this method can be 7483 * guaranteed only for lightweight <code>Component</code>s. 7484 * This method is not intended 7485 * for general use, but exists instead as a hook for lightweight component 7486 * libraries, such as Swing. 7487 * 7488 * <p>Note: Not all focus transfers result from invoking this method. As 7489 * such, a component may receive focus without this or any of the other 7490 * {@code requestFocus} methods of {@code Component} being invoked. 7491 * 7492 * @param temporary true if the focus change is temporary, 7493 * such as when the window loses the focus; for 7494 * more information on temporary focus changes see the 7495 *<a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a> 7496 * @return <code>false</code> if the focus change request is guaranteed to 7497 * fail; <code>true</code> if it is likely to succeed 7498 * @see java.awt.event.FocusEvent 7499 * @see #addFocusListener 7500 * @see #isFocusable 7501 * @see #isDisplayable 7502 * @see KeyboardFocusManager#clearGlobalFocusOwner 7503 * @since 1.4 7504 */ 7505 protected boolean requestFocus(boolean temporary) { 7506 return requestFocusHelper(temporary, true); 7507 } 7508 7509 boolean requestFocus(boolean temporary, CausedFocusEvent.Cause cause) { 7510 return requestFocusHelper(temporary, true, cause); 7511 } 7512 /** 7513 * Requests that this Component get the input focus, if this 7514 * Component's top-level ancestor is already the focused 7515 * Window. This component must be displayable, focusable, visible 7516 * and all of its ancestors (with the exception of the top-level 7517 * Window) must be visible for the request to be granted. Every 7518 * effort will be made to honor the request; however, in some 7519 * cases it may be impossible to do so. Developers must never 7520 * assume that this Component is the focus owner until this 7521 * Component receives a FOCUS_GAINED event. 7522 * <p> 7523 * This method returns a boolean value. If <code>false</code> is returned, 7524 * the request is <b>guaranteed to fail</b>. If <code>true</code> is 7525 * returned, the request will succeed <b>unless</b> it is vetoed, or an 7526 * extraordinary event, such as disposal of the Component's peer, occurs 7527 * before the request can be granted by the native windowing system. Again, 7528 * while a return value of <code>true</code> indicates that the request is 7529 * likely to succeed, developers must never assume that this Component is 7530 * the focus owner until this Component receives a FOCUS_GAINED event. 7531 * <p> 7532 * This method cannot be used to set the focus owner to no Component at 7533 * all. Use <code>KeyboardFocusManager.clearGlobalFocusOwner()</code> 7534 * instead. 7535 * <p> 7536 * The focus behavior of this method can be implemented uniformly across 7537 * platforms, and thus developers are strongly encouraged to use this 7538 * method over <code>requestFocus</code> when possible. Code which relies 7539 * on <code>requestFocus</code> may exhibit different focus behavior on 7540 * different platforms. 7541 * 7542 * <p>Note: Not all focus transfers result from invoking this method. As 7543 * such, a component may receive focus without this or any of the other 7544 * {@code requestFocus} methods of {@code Component} being invoked. 7545 * 7546 * @return <code>false</code> if the focus change request is guaranteed to 7547 * fail; <code>true</code> if it is likely to succeed 7548 * @see #requestFocus 7549 * @see java.awt.event.FocusEvent 7550 * @see #addFocusListener 7551 * @see #isFocusable 7552 * @see #isDisplayable 7553 * @see KeyboardFocusManager#clearGlobalFocusOwner 7554 * @since 1.4 7555 */ 7556 public boolean requestFocusInWindow() { 7557 return requestFocusHelper(false, false); 7558 } 7559 7560 boolean requestFocusInWindow(CausedFocusEvent.Cause cause) { 7561 return requestFocusHelper(false, false, cause); 7562 } 7563 7564 /** 7565 * Requests that this <code>Component</code> get the input focus, 7566 * if this <code>Component</code>'s top-level ancestor is already 7567 * the focused <code>Window</code>. This component must be 7568 * displayable, focusable, visible and all of its ancestors (with 7569 * the exception of the top-level Window) must be visible for the 7570 * request to be granted. Every effort will be made to honor the 7571 * request; however, in some cases it may be impossible to do 7572 * so. Developers must never assume that this component is the 7573 * focus owner until this component receives a FOCUS_GAINED event. 7574 * <p> 7575 * This method returns a boolean value. If <code>false</code> is returned, 7576 * the request is <b>guaranteed to fail</b>. If <code>true</code> is 7577 * returned, the request will succeed <b>unless</b> it is vetoed, or an 7578 * extraordinary event, such as disposal of the component's peer, occurs 7579 * before the request can be granted by the native windowing system. Again, 7580 * while a return value of <code>true</code> indicates that the request is 7581 * likely to succeed, developers must never assume that this component is 7582 * the focus owner until this component receives a FOCUS_GAINED event. 7583 * <p> 7584 * This method cannot be used to set the focus owner to no component at 7585 * all. Use <code>KeyboardFocusManager.clearGlobalFocusOwner</code> 7586 * instead. 7587 * <p> 7588 * The focus behavior of this method can be implemented uniformly across 7589 * platforms, and thus developers are strongly encouraged to use this 7590 * method over <code>requestFocus</code> when possible. Code which relies 7591 * on <code>requestFocus</code> may exhibit different focus behavior on 7592 * different platforms. 7593 * <p> 7594 * Every effort will be made to ensure that <code>FocusEvent</code>s 7595 * generated as a 7596 * result of this request will have the specified temporary value. However, 7597 * because specifying an arbitrary temporary state may not be implementable 7598 * on all native windowing systems, correct behavior for this method can be 7599 * guaranteed only for lightweight components. This method is not intended 7600 * for general use, but exists instead as a hook for lightweight component 7601 * libraries, such as Swing. 7602 * 7603 * <p>Note: Not all focus transfers result from invoking this method. As 7604 * such, a component may receive focus without this or any of the other 7605 * {@code requestFocus} methods of {@code Component} being invoked. 7606 * 7607 * @param temporary true if the focus change is temporary, 7608 * such as when the window loses the focus; for 7609 * more information on temporary focus changes see the 7610 *<a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a> 7611 * @return <code>false</code> if the focus change request is guaranteed to 7612 * fail; <code>true</code> if it is likely to succeed 7613 * @see #requestFocus 7614 * @see java.awt.event.FocusEvent 7615 * @see #addFocusListener 7616 * @see #isFocusable 7617 * @see #isDisplayable 7618 * @see KeyboardFocusManager#clearGlobalFocusOwner 7619 * @since 1.4 7620 */ 7621 protected boolean requestFocusInWindow(boolean temporary) { 7622 return requestFocusHelper(temporary, false); 7623 } 7624 7625 boolean requestFocusInWindow(boolean temporary, CausedFocusEvent.Cause cause) { 7626 return requestFocusHelper(temporary, false, cause); 7627 } 7628 7629 final boolean requestFocusHelper(boolean temporary, 7630 boolean focusedWindowChangeAllowed) { 7631 return requestFocusHelper(temporary, focusedWindowChangeAllowed, CausedFocusEvent.Cause.UNKNOWN); 7632 } 7633 7634 final boolean requestFocusHelper(boolean temporary, 7635 boolean focusedWindowChangeAllowed, 7636 CausedFocusEvent.Cause cause) 7637 { 7638 // 1) Check if the event being dispatched is a system-generated mouse event. 7639 AWTEvent currentEvent = EventQueue.getCurrentEvent(); 7640 if (currentEvent instanceof MouseEvent && 7641 SunToolkit.isSystemGenerated(currentEvent)) 7642 { 7643 // 2) Sanity check: if the mouse event component source belongs to the same containing window. 7644 Component source = ((MouseEvent)currentEvent).getComponent(); 7645 if (source == null || source.getContainingWindow() == getContainingWindow()) { 7646 focusLog.finest("requesting focus by mouse event \"in window\""); 7647 7648 // If both the conditions are fulfilled the focus request should be strictly 7649 // bounded by the toplevel window. It's assumed that the mouse event activates 7650 // the window (if it wasn't active) and this makes it possible for a focus 7651 // request with a strong in-window requirement to change focus in the bounds 7652 // of the toplevel. If, by any means, due to asynchronous nature of the event 7653 // dispatching mechanism, the window happens to be natively inactive by the time 7654 // this focus request is eventually handled, it should not re-activate the 7655 // toplevel. Otherwise the result may not meet user expectations. See 6981400. 7656 focusedWindowChangeAllowed = false; 7657 } 7658 } 7659 if (!isRequestFocusAccepted(temporary, focusedWindowChangeAllowed, cause)) { 7660 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) { 7661 focusLog.finest("requestFocus is not accepted"); 7662 } 7663 return false; 7664 } 7665 // Update most-recent map 7666 KeyboardFocusManager.setMostRecentFocusOwner(this); 7667 7668 Component window = this; 7669 while ( (window != null) && !(window instanceof Window)) { 7670 if (!window.isVisible()) { 7671 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) { 7672 focusLog.finest("component is recurively invisible"); 7673 } 7674 return false; 7675 } 7676 window = window.parent; 7677 } 7678 7679 ComponentPeer peer = this.peer; 7680 Component heavyweight = (peer instanceof LightweightPeer) 7681 ? getNativeContainer() : this; 7682 if (heavyweight == null || !heavyweight.isVisible()) { 7683 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) { 7684 focusLog.finest("Component is not a part of visible hierarchy"); 7685 } 7686 return false; 7687 } 7688 peer = heavyweight.peer; 7689 if (peer == null) { 7690 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) { 7691 focusLog.finest("Peer is null"); 7692 } 7693 return false; 7694 } 7695 7696 // Focus this Component 7697 long time = 0; 7698 if (EventQueue.isDispatchThread()) { 7699 time = Toolkit.getEventQueue().getMostRecentKeyEventTime(); 7700 } else { 7701 // A focus request made from outside EDT should not be associated with any event 7702 // and so its time stamp is simply set to the current time. 7703 time = System.currentTimeMillis(); 7704 } 7705 7706 boolean success = peer.requestFocus 7707 (this, temporary, focusedWindowChangeAllowed, time, cause); 7708 if (!success) { 7709 KeyboardFocusManager.getCurrentKeyboardFocusManager 7710 (appContext).dequeueKeyEvents(time, this); 7711 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) { 7712 focusLog.finest("Peer request failed"); 7713 } 7714 } else { 7715 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) { 7716 focusLog.finest("Pass for " + this); 7717 } 7718 } 7719 return success; 7720 } 7721 7722 private boolean isRequestFocusAccepted(boolean temporary, 7723 boolean focusedWindowChangeAllowed, 7724 CausedFocusEvent.Cause cause) 7725 { 7726 if (!isFocusable() || !isVisible()) { 7727 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) { 7728 focusLog.finest("Not focusable or not visible"); 7729 } 7730 return false; 7731 } 7732 7733 ComponentPeer peer = this.peer; 7734 if (peer == null) { 7735 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) { 7736 focusLog.finest("peer is null"); 7737 } 7738 return false; 7739 } 7740 7741 Window window = getContainingWindow(); 7742 if (window == null || !window.isFocusableWindow()) { 7743 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) { 7744 focusLog.finest("Component doesn't have toplevel"); 7745 } 7746 return false; 7747 } 7748 7749 // We have passed all regular checks for focus request, 7750 // now let's call RequestFocusController and see what it says. 7751 Component focusOwner = KeyboardFocusManager.getMostRecentFocusOwner(window); 7752 if (focusOwner == null) { 7753 // sometimes most recent focus owner may be null, but focus owner is not 7754 // e.g. we reset most recent focus owner if user removes focus owner 7755 focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); 7756 if (focusOwner != null && focusOwner.getContainingWindow() != window) { 7757 focusOwner = null; 7758 } 7759 } 7760 7761 if (focusOwner == this || focusOwner == null) { 7762 // Controller is supposed to verify focus transfers and for this it 7763 // should know both from and to components. And it shouldn't verify 7764 // transfers from when these components are equal. 7765 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) { 7766 focusLog.finest("focus owner is null or this"); 7767 } 7768 return true; 7769 } 7770 7771 if (CausedFocusEvent.Cause.ACTIVATION == cause) { 7772 // we shouldn't call RequestFocusController in case we are 7773 // in activation. We do request focus on component which 7774 // has got temporary focus lost and then on component which is 7775 // most recent focus owner. But most recent focus owner can be 7776 // changed by requestFocsuXXX() call only, so this transfer has 7777 // been already approved. 7778 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) { 7779 focusLog.finest("cause is activation"); 7780 } 7781 return true; 7782 } 7783 7784 boolean ret = Component.requestFocusController.acceptRequestFocus(focusOwner, 7785 this, 7786 temporary, 7787 focusedWindowChangeAllowed, 7788 cause); 7789 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) { 7790 focusLog.finest("RequestFocusController returns {0}", ret); 7791 } 7792 7793 return ret; 7794 } 7795 7796 private static RequestFocusController requestFocusController = new DummyRequestFocusController(); 7797 7798 // Swing access this method through reflection to implement InputVerifier's functionality. 7799 // Perhaps, we should make this method public (later ;) 7800 private static class DummyRequestFocusController implements RequestFocusController { 7801 public boolean acceptRequestFocus(Component from, Component to, 7802 boolean temporary, boolean focusedWindowChangeAllowed, 7803 CausedFocusEvent.Cause cause) 7804 { 7805 return true; 7806 } 7807 }; 7808 7809 synchronized static void setRequestFocusController(RequestFocusController requestController) 7810 { 7811 if (requestController == null) { 7812 requestFocusController = new DummyRequestFocusController(); 7813 } else { 7814 requestFocusController = requestController; 7815 } 7816 } 7817 7818 /** 7819 * Returns the Container which is the focus cycle root of this Component's 7820 * focus traversal cycle. Each focus traversal cycle has only a single 7821 * focus cycle root and each Component which is not a Container belongs to 7822 * only a single focus traversal cycle. Containers which are focus cycle 7823 * roots belong to two cycles: one rooted at the Container itself, and one 7824 * rooted at the Container's nearest focus-cycle-root ancestor. For such 7825 * Containers, this method will return the Container's nearest focus-cycle- 7826 * root ancestor. 7827 * 7828 * @return this Component's nearest focus-cycle-root ancestor 7829 * @see Container#isFocusCycleRoot() 7830 * @since 1.4 7831 */ 7832 public Container getFocusCycleRootAncestor() { 7833 Container rootAncestor = this.parent; 7834 while (rootAncestor != null && !rootAncestor.isFocusCycleRoot()) { 7835 rootAncestor = rootAncestor.parent; 7836 } 7837 return rootAncestor; 7838 } 7839 7840 /** 7841 * Returns whether the specified Container is the focus cycle root of this 7842 * Component's focus traversal cycle. Each focus traversal cycle has only 7843 * a single focus cycle root and each Component which is not a Container 7844 * belongs to only a single focus traversal cycle. 7845 * 7846 * @param container the Container to be tested 7847 * @return <code>true</code> if the specified Container is a focus-cycle- 7848 * root of this Component; <code>false</code> otherwise 7849 * @see Container#isFocusCycleRoot() 7850 * @since 1.4 7851 */ 7852 public boolean isFocusCycleRoot(Container container) { 7853 Container rootAncestor = getFocusCycleRootAncestor(); 7854 return (rootAncestor == container); 7855 } 7856 7857 Container getTraversalRoot() { 7858 return getFocusCycleRootAncestor(); 7859 } 7860 7861 /** 7862 * Transfers the focus to the next component, as though this Component were 7863 * the focus owner. 7864 * @see #requestFocus() 7865 * @since JDK1.1 7866 */ 7867 public void transferFocus() { 7868 nextFocus(); 7869 } 7870 7871 /** 7872 * @deprecated As of JDK version 1.1, 7873 * replaced by transferFocus(). 7874 */ 7875 @Deprecated 7876 public void nextFocus() { 7877 transferFocus(false); 7878 } 7879 7880 boolean transferFocus(boolean clearOnFailure) { 7881 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { 7882 focusLog.finer("clearOnFailure = " + clearOnFailure); 7883 } 7884 Component toFocus = getNextFocusCandidate(); 7885 boolean res = false; 7886 if (toFocus != null && !toFocus.isFocusOwner() && toFocus != this) { 7887 res = toFocus.requestFocusInWindow(CausedFocusEvent.Cause.TRAVERSAL_FORWARD); 7888 } 7889 if (clearOnFailure && !res) { 7890 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { 7891 focusLog.finer("clear global focus owner"); 7892 } 7893 KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwnerPriv(); 7894 } 7895 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { 7896 focusLog.finer("returning result: " + res); 7897 } 7898 return res; 7899 } 7900 7901 final Component getNextFocusCandidate() { 7902 Container rootAncestor = getTraversalRoot(); 7903 Component comp = this; 7904 while (rootAncestor != null && 7905 !(rootAncestor.isShowing() && rootAncestor.canBeFocusOwner())) 7906 { 7907 comp = rootAncestor; 7908 rootAncestor = comp.getFocusCycleRootAncestor(); 7909 } 7910 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { 7911 focusLog.finer("comp = " + comp + ", root = " + rootAncestor); 7912 } 7913 Component candidate = null; 7914 if (rootAncestor != null) { 7915 FocusTraversalPolicy policy = rootAncestor.getFocusTraversalPolicy(); 7916 Component toFocus = policy.getComponentAfter(rootAncestor, comp); 7917 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { 7918 focusLog.finer("component after is " + toFocus); 7919 } 7920 if (toFocus == null) { 7921 toFocus = policy.getDefaultComponent(rootAncestor); 7922 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { 7923 focusLog.finer("default component is " + toFocus); 7924 } 7925 } 7926 if (toFocus == null) { 7927 Applet applet = EmbeddedFrame.getAppletIfAncestorOf(this); 7928 if (applet != null) { 7929 toFocus = applet; 7930 } 7931 } 7932 candidate = toFocus; 7933 } 7934 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { 7935 focusLog.finer("Focus transfer candidate: " + candidate); 7936 } 7937 return candidate; 7938 } 7939 7940 /** 7941 * Transfers the focus to the previous component, as though this Component 7942 * were the focus owner. 7943 * @see #requestFocus() 7944 * @since 1.4 7945 */ 7946 public void transferFocusBackward() { 7947 transferFocusBackward(false); 7948 } 7949 7950 boolean transferFocusBackward(boolean clearOnFailure) { 7951 Container rootAncestor = getTraversalRoot(); 7952 Component comp = this; 7953 while (rootAncestor != null && 7954 !(rootAncestor.isShowing() && rootAncestor.canBeFocusOwner())) 7955 { 7956 comp = rootAncestor; 7957 rootAncestor = comp.getFocusCycleRootAncestor(); 7958 } 7959 boolean res = false; 7960 if (rootAncestor != null) { 7961 FocusTraversalPolicy policy = rootAncestor.getFocusTraversalPolicy(); 7962 Component toFocus = policy.getComponentBefore(rootAncestor, comp); 7963 if (toFocus == null) { 7964 toFocus = policy.getDefaultComponent(rootAncestor); 7965 } 7966 if (toFocus != null) { 7967 res = toFocus.requestFocusInWindow(CausedFocusEvent.Cause.TRAVERSAL_BACKWARD); 7968 } 7969 } 7970 if (clearOnFailure && !res) { 7971 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { 7972 focusLog.finer("clear global focus owner"); 7973 } 7974 KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwnerPriv(); 7975 } 7976 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { 7977 focusLog.finer("returning result: " + res); 7978 } 7979 return res; 7980 } 7981 7982 /** 7983 * Transfers the focus up one focus traversal cycle. Typically, the focus 7984 * owner is set to this Component's focus cycle root, and the current focus 7985 * cycle root is set to the new focus owner's focus cycle root. If, 7986 * however, this Component's focus cycle root is a Window, then the focus 7987 * owner is set to the focus cycle root's default Component to focus, and 7988 * the current focus cycle root is unchanged. 7989 * 7990 * @see #requestFocus() 7991 * @see Container#isFocusCycleRoot() 7992 * @see Container#setFocusCycleRoot(boolean) 7993 * @since 1.4 7994 */ 7995 public void transferFocusUpCycle() { 7996 Container rootAncestor; 7997 for (rootAncestor = getFocusCycleRootAncestor(); 7998 rootAncestor != null && !(rootAncestor.isShowing() && 7999 rootAncestor.isFocusable() && 8000 rootAncestor.isEnabled()); 8001 rootAncestor = rootAncestor.getFocusCycleRootAncestor()) { 8002 } 8003 8004 if (rootAncestor != null) { 8005 Container rootAncestorRootAncestor = 8006 rootAncestor.getFocusCycleRootAncestor(); 8007 Container fcr = (rootAncestorRootAncestor != null) ? 8008 rootAncestorRootAncestor : rootAncestor; 8009 8010 KeyboardFocusManager.getCurrentKeyboardFocusManager(). 8011 setGlobalCurrentFocusCycleRootPriv(fcr); 8012 rootAncestor.requestFocus(CausedFocusEvent.Cause.TRAVERSAL_UP); 8013 } else { 8014 Window window = getContainingWindow(); 8015 8016 if (window != null) { 8017 Component toFocus = window.getFocusTraversalPolicy(). 8018 getDefaultComponent(window); 8019 if (toFocus != null) { 8020 KeyboardFocusManager.getCurrentKeyboardFocusManager(). 8021 setGlobalCurrentFocusCycleRootPriv(window); 8022 toFocus.requestFocus(CausedFocusEvent.Cause.TRAVERSAL_UP); 8023 } 8024 } 8025 } 8026 } 8027 8028 /** 8029 * Returns <code>true</code> if this <code>Component</code> is the 8030 * focus owner. This method is obsolete, and has been replaced by 8031 * <code>isFocusOwner()</code>. 8032 * 8033 * @return <code>true</code> if this <code>Component</code> is the 8034 * focus owner; <code>false</code> otherwise 8035 * @since 1.2 8036 */ 8037 public boolean hasFocus() { 8038 return (KeyboardFocusManager.getCurrentKeyboardFocusManager(). 8039 getFocusOwner() == this); 8040 } 8041 8042 /** 8043 * Returns <code>true</code> if this <code>Component</code> is the 8044 * focus owner. 8045 * 8046 * @return <code>true</code> if this <code>Component</code> is the 8047 * focus owner; <code>false</code> otherwise 8048 * @since 1.4 8049 */ 8050 public boolean isFocusOwner() { 8051 return hasFocus(); 8052 } 8053 8054 /* 8055 * Used to disallow auto-focus-transfer on disposal of the focus owner 8056 * in the process of disposing its parent container. 8057 */ 8058 private boolean autoFocusTransferOnDisposal = true; 8059 8060 void setAutoFocusTransferOnDisposal(boolean value) { 8061 autoFocusTransferOnDisposal = value; 8062 } 8063 8064 boolean isAutoFocusTransferOnDisposal() { 8065 return autoFocusTransferOnDisposal; 8066 } 8067 8068 /** 8069 * Adds the specified popup menu to the component. 8070 * @param popup the popup menu to be added to the component. 8071 * @see #remove(MenuComponent) 8072 * @exception NullPointerException if {@code popup} is {@code null} 8073 * @since JDK1.1 8074 */ 8075 public void add(PopupMenu popup) { 8076 synchronized (getTreeLock()) { 8077 if (popup.parent != null) { 8078 popup.parent.remove(popup); 8079 } 8080 if (popups == null) { 8081 popups = new Vector<PopupMenu>(); 8082 } 8083 popups.addElement(popup); 8084 popup.parent = this; 8085 8086 if (peer != null) { 8087 if (popup.peer == null) { 8088 popup.addNotify(); 8089 } 8090 } 8091 } 8092 } 8093 8094 /** 8095 * Removes the specified popup menu from the component. 8096 * @param popup the popup menu to be removed 8097 * @see #add(PopupMenu) 8098 * @since JDK1.1 8099 */ 8100 @SuppressWarnings("unchecked") 8101 public void remove(MenuComponent popup) { 8102 synchronized (getTreeLock()) { 8103 if (popups == null) { 8104 return; 8105 } 8106 int index = popups.indexOf(popup); 8107 if (index >= 0) { 8108 PopupMenu pmenu = (PopupMenu)popup; 8109 if (pmenu.peer != null) { 8110 pmenu.removeNotify(); 8111 } 8112 pmenu.parent = null; 8113 popups.removeElementAt(index); 8114 if (popups.size() == 0) { 8115 popups = null; 8116 } 8117 } 8118 } 8119 } 8120 8121 /** 8122 * Returns a string representing the state of this component. This 8123 * method is intended to be used only for debugging purposes, and the 8124 * content and format of the returned string may vary between 8125 * implementations. The returned string may be empty but may not be 8126 * <code>null</code>. 8127 * 8128 * @return a string representation of this component's state 8129 * @since JDK1.0 8130 */ 8131 protected String paramString() { 8132 final String thisName = Objects.toString(getName(), ""); 8133 final String invalid = isValid() ? "" : ",invalid"; 8134 final String hidden = visible ? "" : ",hidden"; 8135 final String disabled = enabled ? "" : ",disabled"; 8136 return thisName + ',' + x + ',' + y + ',' + width + 'x' + height 8137 + invalid + hidden + disabled; 8138 } 8139 8140 /** 8141 * Returns a string representation of this component and its values. 8142 * @return a string representation of this component 8143 * @since JDK1.0 8144 */ 8145 public String toString() { 8146 return getClass().getName() + '[' + paramString() + ']'; 8147 } 8148 8149 /** 8150 * Prints a listing of this component to the standard system output 8151 * stream <code>System.out</code>. 8152 * @see java.lang.System#out 8153 * @since JDK1.0 8154 */ 8155 public void list() { 8156 list(System.out, 0); 8157 } 8158 8159 /** 8160 * Prints a listing of this component to the specified output 8161 * stream. 8162 * @param out a print stream 8163 * @throws NullPointerException if {@code out} is {@code null} 8164 * @since JDK1.0 8165 */ 8166 public void list(PrintStream out) { 8167 list(out, 0); 8168 } 8169 8170 /** 8171 * Prints out a list, starting at the specified indentation, to the 8172 * specified print stream. 8173 * @param out a print stream 8174 * @param indent number of spaces to indent 8175 * @see java.io.PrintStream#println(java.lang.Object) 8176 * @throws NullPointerException if {@code out} is {@code null} 8177 * @since JDK1.0 8178 */ 8179 public void list(PrintStream out, int indent) { 8180 for (int i = 0 ; i < indent ; i++) { 8181 out.print(" "); 8182 } 8183 out.println(this); 8184 } 8185 8186 /** 8187 * Prints a listing to the specified print writer. 8188 * @param out the print writer to print to 8189 * @throws NullPointerException if {@code out} is {@code null} 8190 * @since JDK1.1 8191 */ 8192 public void list(PrintWriter out) { 8193 list(out, 0); 8194 } 8195 8196 /** 8197 * Prints out a list, starting at the specified indentation, to 8198 * the specified print writer. 8199 * @param out the print writer to print to 8200 * @param indent the number of spaces to indent 8201 * @throws NullPointerException if {@code out} is {@code null} 8202 * @see java.io.PrintStream#println(java.lang.Object) 8203 * @since JDK1.1 8204 */ 8205 public void list(PrintWriter out, int indent) { 8206 for (int i = 0 ; i < indent ; i++) { 8207 out.print(" "); 8208 } 8209 out.println(this); 8210 } 8211 8212 /* 8213 * Fetches the native container somewhere higher up in the component 8214 * tree that contains this component. 8215 */ 8216 final Container getNativeContainer() { 8217 Container p = getContainer(); 8218 while (p != null && p.peer instanceof LightweightPeer) { 8219 p = p.getContainer(); 8220 } 8221 return p; 8222 } 8223 8224 /** 8225 * Adds a PropertyChangeListener to the listener list. The listener is 8226 * registered for all bound properties of this class, including the 8227 * following: 8228 * <ul> 8229 * <li>this Component's font ("font")</li> 8230 * <li>this Component's background color ("background")</li> 8231 * <li>this Component's foreground color ("foreground")</li> 8232 * <li>this Component's focusability ("focusable")</li> 8233 * <li>this Component's focus traversal keys enabled state 8234 * ("focusTraversalKeysEnabled")</li> 8235 * <li>this Component's Set of FORWARD_TRAVERSAL_KEYS 8236 * ("forwardFocusTraversalKeys")</li> 8237 * <li>this Component's Set of BACKWARD_TRAVERSAL_KEYS 8238 * ("backwardFocusTraversalKeys")</li> 8239 * <li>this Component's Set of UP_CYCLE_TRAVERSAL_KEYS 8240 * ("upCycleFocusTraversalKeys")</li> 8241 * <li>this Component's preferred size ("preferredSize")</li> 8242 * <li>this Component's minimum size ("minimumSize")</li> 8243 * <li>this Component's maximum size ("maximumSize")</li> 8244 * <li>this Component's name ("name")</li> 8245 * </ul> 8246 * Note that if this <code>Component</code> is inheriting a bound property, then no 8247 * event will be fired in response to a change in the inherited property. 8248 * <p> 8249 * If <code>listener</code> is <code>null</code>, 8250 * no exception is thrown and no action is performed. 8251 * 8252 * @param listener the property change listener to be added 8253 * 8254 * @see #removePropertyChangeListener 8255 * @see #getPropertyChangeListeners 8256 * @see #addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener) 8257 */ 8258 public void addPropertyChangeListener( 8259 PropertyChangeListener listener) { 8260 synchronized (getObjectLock()) { 8261 if (listener == null) { 8262 return; 8263 } 8264 if (changeSupport == null) { 8265 changeSupport = new PropertyChangeSupport(this); 8266 } 8267 changeSupport.addPropertyChangeListener(listener); 8268 } 8269 } 8270 8271 /** 8272 * Removes a PropertyChangeListener from the listener list. This method 8273 * should be used to remove PropertyChangeListeners that were registered 8274 * for all bound properties of this class. 8275 * <p> 8276 * If listener is null, no exception is thrown and no action is performed. 8277 * 8278 * @param listener the PropertyChangeListener to be removed 8279 * 8280 * @see #addPropertyChangeListener 8281 * @see #getPropertyChangeListeners 8282 * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener) 8283 */ 8284 public void removePropertyChangeListener( 8285 PropertyChangeListener listener) { 8286 synchronized (getObjectLock()) { 8287 if (listener == null || changeSupport == null) { 8288 return; 8289 } 8290 changeSupport.removePropertyChangeListener(listener); 8291 } 8292 } 8293 8294 /** 8295 * Returns an array of all the property change listeners 8296 * registered on this component. 8297 * 8298 * @return all of this component's <code>PropertyChangeListener</code>s 8299 * or an empty array if no property change 8300 * listeners are currently registered 8301 * 8302 * @see #addPropertyChangeListener 8303 * @see #removePropertyChangeListener 8304 * @see #getPropertyChangeListeners(java.lang.String) 8305 * @see java.beans.PropertyChangeSupport#getPropertyChangeListeners 8306 * @since 1.4 8307 */ 8308 public PropertyChangeListener[] getPropertyChangeListeners() { 8309 synchronized (getObjectLock()) { 8310 if (changeSupport == null) { 8311 return new PropertyChangeListener[0]; 8312 } 8313 return changeSupport.getPropertyChangeListeners(); 8314 } 8315 } 8316 8317 /** 8318 * Adds a PropertyChangeListener to the listener list for a specific 8319 * property. The specified property may be user-defined, or one of the 8320 * following: 8321 * <ul> 8322 * <li>this Component's font ("font")</li> 8323 * <li>this Component's background color ("background")</li> 8324 * <li>this Component's foreground color ("foreground")</li> 8325 * <li>this Component's focusability ("focusable")</li> 8326 * <li>this Component's focus traversal keys enabled state 8327 * ("focusTraversalKeysEnabled")</li> 8328 * <li>this Component's Set of FORWARD_TRAVERSAL_KEYS 8329 * ("forwardFocusTraversalKeys")</li> 8330 * <li>this Component's Set of BACKWARD_TRAVERSAL_KEYS 8331 * ("backwardFocusTraversalKeys")</li> 8332 * <li>this Component's Set of UP_CYCLE_TRAVERSAL_KEYS 8333 * ("upCycleFocusTraversalKeys")</li> 8334 * </ul> 8335 * Note that if this <code>Component</code> is inheriting a bound property, then no 8336 * event will be fired in response to a change in the inherited property. 8337 * <p> 8338 * If <code>propertyName</code> or <code>listener</code> is <code>null</code>, 8339 * no exception is thrown and no action is taken. 8340 * 8341 * @param propertyName one of the property names listed above 8342 * @param listener the property change listener to be added 8343 * 8344 * @see #removePropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener) 8345 * @see #getPropertyChangeListeners(java.lang.String) 8346 * @see #addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener) 8347 */ 8348 public void addPropertyChangeListener( 8349 String propertyName, 8350 PropertyChangeListener listener) { 8351 synchronized (getObjectLock()) { 8352 if (listener == null) { 8353 return; 8354 } 8355 if (changeSupport == null) { 8356 changeSupport = new PropertyChangeSupport(this); 8357 } 8358 changeSupport.addPropertyChangeListener(propertyName, listener); 8359 } 8360 } 8361 8362 /** 8363 * Removes a <code>PropertyChangeListener</code> from the listener 8364 * list for a specific property. This method should be used to remove 8365 * <code>PropertyChangeListener</code>s 8366 * that were registered for a specific bound property. 8367 * <p> 8368 * If <code>propertyName</code> or <code>listener</code> is <code>null</code>, 8369 * no exception is thrown and no action is taken. 8370 * 8371 * @param propertyName a valid property name 8372 * @param listener the PropertyChangeListener to be removed 8373 * 8374 * @see #addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener) 8375 * @see #getPropertyChangeListeners(java.lang.String) 8376 * @see #removePropertyChangeListener(java.beans.PropertyChangeListener) 8377 */ 8378 public void removePropertyChangeListener( 8379 String propertyName, 8380 PropertyChangeListener listener) { 8381 synchronized (getObjectLock()) { 8382 if (listener == null || changeSupport == null) { 8383 return; 8384 } 8385 changeSupport.removePropertyChangeListener(propertyName, listener); 8386 } 8387 } 8388 8389 /** 8390 * Returns an array of all the listeners which have been associated 8391 * with the named property. 8392 * 8393 * @return all of the <code>PropertyChangeListener</code>s associated with 8394 * the named property; if no such listeners have been added or 8395 * if <code>propertyName</code> is <code>null</code>, an empty 8396 * array is returned 8397 * 8398 * @see #addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener) 8399 * @see #removePropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener) 8400 * @see #getPropertyChangeListeners 8401 * @since 1.4 8402 */ 8403 public PropertyChangeListener[] getPropertyChangeListeners( 8404 String propertyName) { 8405 synchronized (getObjectLock()) { 8406 if (changeSupport == null) { 8407 return new PropertyChangeListener[0]; 8408 } 8409 return changeSupport.getPropertyChangeListeners(propertyName); 8410 } 8411 } 8412 8413 /** 8414 * Support for reporting bound property changes for Object properties. 8415 * This method can be called when a bound property has changed and it will 8416 * send the appropriate PropertyChangeEvent to any registered 8417 * PropertyChangeListeners. 8418 * 8419 * @param propertyName the property whose value has changed 8420 * @param oldValue the property's previous value 8421 * @param newValue the property's new value 8422 */ 8423 protected void firePropertyChange(String propertyName, 8424 Object oldValue, Object newValue) { 8425 PropertyChangeSupport changeSupport; 8426 synchronized (getObjectLock()) { 8427 changeSupport = this.changeSupport; 8428 } 8429 if (changeSupport == null || 8430 (oldValue != null && newValue != null && oldValue.equals(newValue))) { 8431 return; 8432 } 8433 changeSupport.firePropertyChange(propertyName, oldValue, newValue); 8434 } 8435 8436 /** 8437 * Support for reporting bound property changes for boolean properties. 8438 * This method can be called when a bound property has changed and it will 8439 * send the appropriate PropertyChangeEvent to any registered 8440 * PropertyChangeListeners. 8441 * 8442 * @param propertyName the property whose value has changed 8443 * @param oldValue the property's previous value 8444 * @param newValue the property's new value 8445 * @since 1.4 8446 */ 8447 protected void firePropertyChange(String propertyName, 8448 boolean oldValue, boolean newValue) { 8449 PropertyChangeSupport changeSupport = this.changeSupport; 8450 if (changeSupport == null || oldValue == newValue) { 8451 return; 8452 } 8453 changeSupport.firePropertyChange(propertyName, oldValue, newValue); 8454 } 8455 8456 /** 8457 * Support for reporting bound property changes for integer properties. 8458 * This method can be called when a bound property has changed and it will 8459 * send the appropriate PropertyChangeEvent to any registered 8460 * PropertyChangeListeners. 8461 * 8462 * @param propertyName the property whose value has changed 8463 * @param oldValue the property's previous value 8464 * @param newValue the property's new value 8465 * @since 1.4 8466 */ 8467 protected void firePropertyChange(String propertyName, 8468 int oldValue, int newValue) { 8469 PropertyChangeSupport changeSupport = this.changeSupport; 8470 if (changeSupport == null || oldValue == newValue) { 8471 return; 8472 } 8473 changeSupport.firePropertyChange(propertyName, oldValue, newValue); 8474 } 8475 8476 /** 8477 * Reports a bound property change. 8478 * 8479 * @param propertyName the programmatic name of the property 8480 * that was changed 8481 * @param oldValue the old value of the property (as a byte) 8482 * @param newValue the new value of the property (as a byte) 8483 * @see #firePropertyChange(java.lang.String, java.lang.Object, 8484 * java.lang.Object) 8485 * @since 1.5 8486 */ 8487 public void firePropertyChange(String propertyName, byte oldValue, byte newValue) { 8488 if (changeSupport == null || oldValue == newValue) { 8489 return; 8490 } 8491 firePropertyChange(propertyName, Byte.valueOf(oldValue), Byte.valueOf(newValue)); 8492 } 8493 8494 /** 8495 * Reports a bound property change. 8496 * 8497 * @param propertyName the programmatic name of the property 8498 * that was changed 8499 * @param oldValue the old value of the property (as a char) 8500 * @param newValue the new value of the property (as a char) 8501 * @see #firePropertyChange(java.lang.String, java.lang.Object, 8502 * java.lang.Object) 8503 * @since 1.5 8504 */ 8505 public void firePropertyChange(String propertyName, char oldValue, char newValue) { 8506 if (changeSupport == null || oldValue == newValue) { 8507 return; 8508 } 8509 firePropertyChange(propertyName, new Character(oldValue), new Character(newValue)); 8510 } 8511 8512 /** 8513 * Reports a bound property change. 8514 * 8515 * @param propertyName the programmatic name of the property 8516 * that was changed 8517 * @param oldValue the old value of the property (as a short) 8518 * @param newValue the old value of the property (as a short) 8519 * @see #firePropertyChange(java.lang.String, java.lang.Object, 8520 * java.lang.Object) 8521 * @since 1.5 8522 */ 8523 public void firePropertyChange(String propertyName, short oldValue, short newValue) { 8524 if (changeSupport == null || oldValue == newValue) { 8525 return; 8526 } 8527 firePropertyChange(propertyName, Short.valueOf(oldValue), Short.valueOf(newValue)); 8528 } 8529 8530 8531 /** 8532 * Reports a bound property change. 8533 * 8534 * @param propertyName the programmatic name of the property 8535 * that was changed 8536 * @param oldValue the old value of the property (as a long) 8537 * @param newValue the new value of the property (as a long) 8538 * @see #firePropertyChange(java.lang.String, java.lang.Object, 8539 * java.lang.Object) 8540 * @since 1.5 8541 */ 8542 public void firePropertyChange(String propertyName, long oldValue, long newValue) { 8543 if (changeSupport == null || oldValue == newValue) { 8544 return; 8545 } 8546 firePropertyChange(propertyName, Long.valueOf(oldValue), Long.valueOf(newValue)); 8547 } 8548 8549 /** 8550 * Reports a bound property change. 8551 * 8552 * @param propertyName the programmatic name of the property 8553 * that was changed 8554 * @param oldValue the old value of the property (as a float) 8555 * @param newValue the new value of the property (as a float) 8556 * @see #firePropertyChange(java.lang.String, java.lang.Object, 8557 * java.lang.Object) 8558 * @since 1.5 8559 */ 8560 public void firePropertyChange(String propertyName, float oldValue, float newValue) { 8561 if (changeSupport == null || oldValue == newValue) { 8562 return; 8563 } 8564 firePropertyChange(propertyName, Float.valueOf(oldValue), Float.valueOf(newValue)); 8565 } 8566 8567 /** 8568 * Reports a bound property change. 8569 * 8570 * @param propertyName the programmatic name of the property 8571 * that was changed 8572 * @param oldValue the old value of the property (as a double) 8573 * @param newValue the new value of the property (as a double) 8574 * @see #firePropertyChange(java.lang.String, java.lang.Object, 8575 * java.lang.Object) 8576 * @since 1.5 8577 */ 8578 public void firePropertyChange(String propertyName, double oldValue, double newValue) { 8579 if (changeSupport == null || oldValue == newValue) { 8580 return; 8581 } 8582 firePropertyChange(propertyName, Double.valueOf(oldValue), Double.valueOf(newValue)); 8583 } 8584 8585 8586 // Serialization support. 8587 8588 /** 8589 * Component Serialized Data Version. 8590 * 8591 * @serial 8592 */ 8593 private int componentSerializedDataVersion = 4; 8594 8595 /** 8596 * This hack is for Swing serialization. It will invoke 8597 * the Swing package private method <code>compWriteObjectNotify</code>. 8598 */ 8599 private void doSwingSerialization() { 8600 Package swingPackage = Package.getPackage("javax.swing"); 8601 // For Swing serialization to correctly work Swing needs to 8602 // be notified before Component does it's serialization. This 8603 // hack accomodates this. 8604 // 8605 // Swing classes MUST be loaded by the bootstrap class loader, 8606 // otherwise we don't consider them. 8607 for (Class<?> klass = Component.this.getClass(); klass != null; 8608 klass = klass.getSuperclass()) { 8609 if (klass.getPackage() == swingPackage && 8610 klass.getClassLoader() == null) { 8611 final Class<?> swingClass = klass; 8612 // Find the first override of the compWriteObjectNotify method 8613 Method[] methods = AccessController.doPrivileged( 8614 new PrivilegedAction<Method[]>() { 8615 public Method[] run() { 8616 return swingClass.getDeclaredMethods(); 8617 } 8618 }); 8619 for (int counter = methods.length - 1; counter >= 0; 8620 counter--) { 8621 final Method method = methods[counter]; 8622 if (method.getName().equals("compWriteObjectNotify")){ 8623 // We found it, use doPrivileged to make it accessible 8624 // to use. 8625 AccessController.doPrivileged(new PrivilegedAction<Void>() { 8626 public Void run() { 8627 method.setAccessible(true); 8628 return null; 8629 } 8630 }); 8631 // Invoke the method 8632 try { 8633 method.invoke(this, (Object[]) null); 8634 } catch (IllegalAccessException iae) { 8635 } catch (InvocationTargetException ite) { 8636 } 8637 // We're done, bail. 8638 return; 8639 } 8640 } 8641 } 8642 } 8643 } 8644 8645 /** 8646 * Writes default serializable fields to stream. Writes 8647 * a variety of serializable listeners as optional data. 8648 * The non-serializable listeners are detected and 8649 * no attempt is made to serialize them. 8650 * 8651 * @param s the <code>ObjectOutputStream</code> to write 8652 * @serialData <code>null</code> terminated sequence of 8653 * 0 or more pairs; the pair consists of a <code>String</code> 8654 * and an <code>Object</code>; the <code>String</code> indicates 8655 * the type of object and is one of the following (as of 1.4): 8656 * <code>componentListenerK</code> indicating an 8657 * <code>ComponentListener</code> object; 8658 * <code>focusListenerK</code> indicating an 8659 * <code>FocusListener</code> object; 8660 * <code>keyListenerK</code> indicating an 8661 * <code>KeyListener</code> object; 8662 * <code>mouseListenerK</code> indicating an 8663 * <code>MouseListener</code> object; 8664 * <code>mouseMotionListenerK</code> indicating an 8665 * <code>MouseMotionListener</code> object; 8666 * <code>inputMethodListenerK</code> indicating an 8667 * <code>InputMethodListener</code> object; 8668 * <code>hierarchyListenerK</code> indicating an 8669 * <code>HierarchyListener</code> object; 8670 * <code>hierarchyBoundsListenerK</code> indicating an 8671 * <code>HierarchyBoundsListener</code> object; 8672 * <code>mouseWheelListenerK</code> indicating an 8673 * <code>MouseWheelListener</code> object 8674 * @serialData an optional <code>ComponentOrientation</code> 8675 * (after <code>inputMethodListener</code>, as of 1.2) 8676 * 8677 * @see AWTEventMulticaster#save(java.io.ObjectOutputStream, java.lang.String, java.util.EventListener) 8678 * @see #componentListenerK 8679 * @see #focusListenerK 8680 * @see #keyListenerK 8681 * @see #mouseListenerK 8682 * @see #mouseMotionListenerK 8683 * @see #inputMethodListenerK 8684 * @see #hierarchyListenerK 8685 * @see #hierarchyBoundsListenerK 8686 * @see #mouseWheelListenerK 8687 * @see #readObject(ObjectInputStream) 8688 */ 8689 private void writeObject(ObjectOutputStream s) 8690 throws IOException 8691 { 8692 doSwingSerialization(); 8693 8694 s.defaultWriteObject(); 8695 8696 AWTEventMulticaster.save(s, componentListenerK, componentListener); 8697 AWTEventMulticaster.save(s, focusListenerK, focusListener); 8698 AWTEventMulticaster.save(s, keyListenerK, keyListener); 8699 AWTEventMulticaster.save(s, mouseListenerK, mouseListener); 8700 AWTEventMulticaster.save(s, mouseMotionListenerK, mouseMotionListener); 8701 AWTEventMulticaster.save(s, inputMethodListenerK, inputMethodListener); 8702 8703 s.writeObject(null); 8704 s.writeObject(componentOrientation); 8705 8706 AWTEventMulticaster.save(s, hierarchyListenerK, hierarchyListener); 8707 AWTEventMulticaster.save(s, hierarchyBoundsListenerK, 8708 hierarchyBoundsListener); 8709 s.writeObject(null); 8710 8711 AWTEventMulticaster.save(s, mouseWheelListenerK, mouseWheelListener); 8712 s.writeObject(null); 8713 8714 } 8715 8716 /** 8717 * Reads the <code>ObjectInputStream</code> and if it isn't 8718 * <code>null</code> adds a listener to receive a variety 8719 * of events fired by the component. 8720 * Unrecognized keys or values will be ignored. 8721 * 8722 * @param s the <code>ObjectInputStream</code> to read 8723 * @see #writeObject(ObjectOutputStream) 8724 */ 8725 private void readObject(ObjectInputStream s) 8726 throws ClassNotFoundException, IOException 8727 { 8728 objectLock = new Object(); 8729 8730 acc = AccessController.getContext(); 8731 8732 s.defaultReadObject(); 8733 8734 appContext = AppContext.getAppContext(); 8735 coalescingEnabled = checkCoalescing(); 8736 if (componentSerializedDataVersion < 4) { 8737 // These fields are non-transient and rely on default 8738 // serialization. However, the default values are insufficient, 8739 // so we need to set them explicitly for object data streams prior 8740 // to 1.4. 8741 focusable = true; 8742 isFocusTraversableOverridden = FOCUS_TRAVERSABLE_UNKNOWN; 8743 initializeFocusTraversalKeys(); 8744 focusTraversalKeysEnabled = true; 8745 } 8746 8747 Object keyOrNull; 8748 while(null != (keyOrNull = s.readObject())) { 8749 String key = ((String)keyOrNull).intern(); 8750 8751 if (componentListenerK == key) 8752 addComponentListener((ComponentListener)(s.readObject())); 8753 8754 else if (focusListenerK == key) 8755 addFocusListener((FocusListener)(s.readObject())); 8756 8757 else if (keyListenerK == key) 8758 addKeyListener((KeyListener)(s.readObject())); 8759 8760 else if (mouseListenerK == key) 8761 addMouseListener((MouseListener)(s.readObject())); 8762 8763 else if (mouseMotionListenerK == key) 8764 addMouseMotionListener((MouseMotionListener)(s.readObject())); 8765 8766 else if (inputMethodListenerK == key) 8767 addInputMethodListener((InputMethodListener)(s.readObject())); 8768 8769 else // skip value for unrecognized key 8770 s.readObject(); 8771 8772 } 8773 8774 // Read the component's orientation if it's present 8775 Object orient = null; 8776 8777 try { 8778 orient = s.readObject(); 8779 } catch (java.io.OptionalDataException e) { 8780 // JDK 1.1 instances will not have this optional data. 8781 // e.eof will be true to indicate that there is no more 8782 // data available for this object. 8783 // If e.eof is not true, throw the exception as it 8784 // might have been caused by reasons unrelated to 8785 // componentOrientation. 8786 8787 if (!e.eof) { 8788 throw (e); 8789 } 8790 } 8791 8792 if (orient != null) { 8793 componentOrientation = (ComponentOrientation)orient; 8794 } else { 8795 componentOrientation = ComponentOrientation.UNKNOWN; 8796 } 8797 8798 try { 8799 while(null != (keyOrNull = s.readObject())) { 8800 String key = ((String)keyOrNull).intern(); 8801 8802 if (hierarchyListenerK == key) { 8803 addHierarchyListener((HierarchyListener)(s.readObject())); 8804 } 8805 else if (hierarchyBoundsListenerK == key) { 8806 addHierarchyBoundsListener((HierarchyBoundsListener) 8807 (s.readObject())); 8808 } 8809 else { 8810 // skip value for unrecognized key 8811 s.readObject(); 8812 } 8813 } 8814 } catch (java.io.OptionalDataException e) { 8815 // JDK 1.1/1.2 instances will not have this optional data. 8816 // e.eof will be true to indicate that there is no more 8817 // data available for this object. 8818 // If e.eof is not true, throw the exception as it 8819 // might have been caused by reasons unrelated to 8820 // hierarchy and hierarchyBounds listeners. 8821 8822 if (!e.eof) { 8823 throw (e); 8824 } 8825 } 8826 8827 try { 8828 while (null != (keyOrNull = s.readObject())) { 8829 String key = ((String)keyOrNull).intern(); 8830 8831 if (mouseWheelListenerK == key) { 8832 addMouseWheelListener((MouseWheelListener)(s.readObject())); 8833 } 8834 else { 8835 // skip value for unrecognized key 8836 s.readObject(); 8837 } 8838 } 8839 } catch (java.io.OptionalDataException e) { 8840 // pre-1.3 instances will not have this optional data. 8841 // e.eof will be true to indicate that there is no more 8842 // data available for this object. 8843 // If e.eof is not true, throw the exception as it 8844 // might have been caused by reasons unrelated to 8845 // mouse wheel listeners 8846 8847 if (!e.eof) { 8848 throw (e); 8849 } 8850 } 8851 8852 if (popups != null) { 8853 int npopups = popups.size(); 8854 for (int i = 0 ; i < npopups ; i++) { 8855 PopupMenu popup = popups.elementAt(i); 8856 popup.parent = this; 8857 } 8858 } 8859 } 8860 8861 /** 8862 * Sets the language-sensitive orientation that is to be used to order 8863 * the elements or text within this component. Language-sensitive 8864 * <code>LayoutManager</code> and <code>Component</code> 8865 * subclasses will use this property to 8866 * determine how to lay out and draw components. 8867 * <p> 8868 * At construction time, a component's orientation is set to 8869 * <code>ComponentOrientation.UNKNOWN</code>, 8870 * indicating that it has not been specified 8871 * explicitly. The UNKNOWN orientation behaves the same as 8872 * <code>ComponentOrientation.LEFT_TO_RIGHT</code>. 8873 * <p> 8874 * To set the orientation of a single component, use this method. 8875 * To set the orientation of an entire component 8876 * hierarchy, use 8877 * {@link #applyComponentOrientation applyComponentOrientation}. 8878 * <p> 8879 * This method changes layout-related information, and therefore, 8880 * invalidates the component hierarchy. 8881 * 8882 * 8883 * @see ComponentOrientation 8884 * @see #invalidate 8885 * 8886 * @author Laura Werner, IBM 8887 * @beaninfo 8888 * bound: true 8889 */ 8890 public void setComponentOrientation(ComponentOrientation o) { 8891 ComponentOrientation oldValue = componentOrientation; 8892 componentOrientation = o; 8893 8894 // This is a bound property, so report the change to 8895 // any registered listeners. (Cheap if there are none.) 8896 firePropertyChange("componentOrientation", oldValue, o); 8897 8898 // This could change the preferred size of the Component. 8899 invalidateIfValid(); 8900 } 8901 8902 /** 8903 * Retrieves the language-sensitive orientation that is to be used to order 8904 * the elements or text within this component. <code>LayoutManager</code> 8905 * and <code>Component</code> 8906 * subclasses that wish to respect orientation should call this method to 8907 * get the component's orientation before performing layout or drawing. 8908 * 8909 * @see ComponentOrientation 8910 * 8911 * @author Laura Werner, IBM 8912 */ 8913 public ComponentOrientation getComponentOrientation() { 8914 return componentOrientation; 8915 } 8916 8917 /** 8918 * Sets the <code>ComponentOrientation</code> property of this component 8919 * and all components contained within it. 8920 * <p> 8921 * This method changes layout-related information, and therefore, 8922 * invalidates the component hierarchy. 8923 * 8924 * 8925 * @param orientation the new component orientation of this component and 8926 * the components contained within it. 8927 * @exception NullPointerException if <code>orientation</code> is null. 8928 * @see #setComponentOrientation 8929 * @see #getComponentOrientation 8930 * @see #invalidate 8931 * @since 1.4 8932 */ 8933 public void applyComponentOrientation(ComponentOrientation orientation) { 8934 if (orientation == null) { 8935 throw new NullPointerException(); 8936 } 8937 setComponentOrientation(orientation); 8938 } 8939 8940 final boolean canBeFocusOwner() { 8941 // It is enabled, visible, focusable. 8942 if (isEnabled() && isDisplayable() && isVisible() && isFocusable()) { 8943 return true; 8944 } 8945 return false; 8946 } 8947 8948 /** 8949 * Checks that this component meets the prerequesites to be focus owner: 8950 * - it is enabled, visible, focusable 8951 * - it's parents are all enabled and showing 8952 * - top-level window is focusable 8953 * - if focus cycle root has DefaultFocusTraversalPolicy then it also checks that this policy accepts 8954 * this component as focus owner 8955 * @since 1.5 8956 */ 8957 final boolean canBeFocusOwnerRecursively() { 8958 // - it is enabled, visible, focusable 8959 if (!canBeFocusOwner()) { 8960 return false; 8961 } 8962 8963 // - it's parents are all enabled and showing 8964 synchronized(getTreeLock()) { 8965 if (parent != null) { 8966 return parent.canContainFocusOwner(this); 8967 } 8968 } 8969 return true; 8970 } 8971 8972 /** 8973 * Fix the location of the HW component in a LW container hierarchy. 8974 */ 8975 final void relocateComponent() { 8976 synchronized (getTreeLock()) { 8977 if (peer == null) { 8978 return; 8979 } 8980 int nativeX = x; 8981 int nativeY = y; 8982 for (Component cont = getContainer(); 8983 cont != null && cont.isLightweight(); 8984 cont = cont.getContainer()) 8985 { 8986 nativeX += cont.x; 8987 nativeY += cont.y; 8988 } 8989 peer.setBounds(nativeX, nativeY, width, height, 8990 ComponentPeer.SET_LOCATION); 8991 } 8992 } 8993 8994 /** 8995 * Returns the <code>Window</code> ancestor of the component. 8996 * @return Window ancestor of the component or component by itself if it is Window; 8997 * null, if component is not a part of window hierarchy 8998 */ 8999 Window getContainingWindow() { 9000 return SunToolkit.getContainingWindow(this); 9001 } 9002 9003 /** 9004 * Initialize JNI field and method IDs 9005 */ 9006 private static native void initIDs(); 9007 9008 /* 9009 * --- Accessibility Support --- 9010 * 9011 * Component will contain all of the methods in interface Accessible, 9012 * though it won't actually implement the interface - that will be up 9013 * to the individual objects which extend Component. 9014 */ 9015 9016 /** 9017 * The {@code AccessibleContext} associated with this {@code Component}. 9018 */ 9019 protected AccessibleContext accessibleContext = null; 9020 9021 /** 9022 * Gets the <code>AccessibleContext</code> associated 9023 * with this <code>Component</code>. 9024 * The method implemented by this base 9025 * class returns null. Classes that extend <code>Component</code> 9026 * should implement this method to return the 9027 * <code>AccessibleContext</code> associated with the subclass. 9028 * 9029 * 9030 * @return the <code>AccessibleContext</code> of this 9031 * <code>Component</code> 9032 * @since 1.3 9033 */ 9034 public AccessibleContext getAccessibleContext() { 9035 return accessibleContext; 9036 } 9037 9038 /** 9039 * Inner class of Component used to provide default support for 9040 * accessibility. This class is not meant to be used directly by 9041 * application developers, but is instead meant only to be 9042 * subclassed by component developers. 9043 * <p> 9044 * The class used to obtain the accessible role for this object. 9045 * @since 1.3 9046 */ 9047 protected abstract class AccessibleAWTComponent extends AccessibleContext 9048 implements Serializable, AccessibleComponent { 9049 9050 private static final long serialVersionUID = 642321655757800191L; 9051 9052 /** 9053 * Though the class is abstract, this should be called by 9054 * all sub-classes. 9055 */ 9056 protected AccessibleAWTComponent() { 9057 } 9058 9059 /** 9060 * Number of PropertyChangeListener objects registered. It's used 9061 * to add/remove ComponentListener and FocusListener to track 9062 * target Component's state. 9063 */ 9064 private volatile transient int propertyListenersCount = 0; 9065 9066 protected ComponentListener accessibleAWTComponentHandler = null; 9067 protected FocusListener accessibleAWTFocusHandler = null; 9068 9069 // accessibleAWTFocusHandler can be set either from 9070 // JComponent.AccessibleJComponent.addPropertyChangeListener or from this 9071 // object's addPropertyChangeListener the first time that method is called 9072 // if accessibleAWTFocusHandler is null at the time of the call. In the 9073 // former case Component.addFocusListener has already been called so it 9074 // should not be called again in this object's addPropertyChangeListener. 9075 // Also, removeFocusListener should only be called if this boolean is set. 9076 boolean focusHandlerSetFromComponent = false; 9077 9078 /** 9079 * Fire PropertyChange listener, if one is registered, 9080 * when shown/hidden.. 9081 * @since 1.3 9082 */ 9083 protected class AccessibleAWTComponentHandler implements ComponentListener { 9084 public void componentHidden(ComponentEvent e) { 9085 if (accessibleContext != null) { 9086 accessibleContext.firePropertyChange( 9087 AccessibleContext.ACCESSIBLE_STATE_PROPERTY, 9088 AccessibleState.VISIBLE, null); 9089 } 9090 } 9091 9092 public void componentShown(ComponentEvent e) { 9093 if (accessibleContext != null) { 9094 accessibleContext.firePropertyChange( 9095 AccessibleContext.ACCESSIBLE_STATE_PROPERTY, 9096 null, AccessibleState.VISIBLE); 9097 } 9098 } 9099 9100 public void componentMoved(ComponentEvent e) { 9101 } 9102 9103 public void componentResized(ComponentEvent e) { 9104 } 9105 } // inner class AccessibleAWTComponentHandler 9106 9107 9108 /** 9109 * Fire PropertyChange listener, if one is registered, 9110 * when focus events happen 9111 * @since 1.3 9112 */ 9113 protected class AccessibleAWTFocusHandler implements FocusListener { 9114 public void focusGained(FocusEvent event) { 9115 if (accessibleContext != null) { 9116 accessibleContext.firePropertyChange( 9117 AccessibleContext.ACCESSIBLE_STATE_PROPERTY, 9118 null, AccessibleState.FOCUSED); 9119 } 9120 } 9121 public void focusLost(FocusEvent event) { 9122 if (accessibleContext != null) { 9123 accessibleContext.firePropertyChange( 9124 AccessibleContext.ACCESSIBLE_STATE_PROPERTY, 9125 AccessibleState.FOCUSED, null); 9126 } 9127 } 9128 } // inner class AccessibleAWTFocusHandler 9129 9130 9131 /** 9132 * Adds a <code>PropertyChangeListener</code> to the listener list. 9133 * 9134 * @param listener the property change listener to be added 9135 */ 9136 public void addPropertyChangeListener(PropertyChangeListener listener) { 9137 if (accessibleAWTComponentHandler == null) { 9138 accessibleAWTComponentHandler = new AccessibleAWTComponentHandler(); 9139 } 9140 if (accessibleAWTFocusHandler == null) { 9141 focusHandlerSetFromComponent = true; 9142 accessibleAWTFocusHandler = new AccessibleAWTFocusHandler(); 9143 } 9144 if (propertyListenersCount++ == 0) { 9145 Component.this.addComponentListener(accessibleAWTComponentHandler); 9146 if (focusHandlerSetFromComponent) { 9147 Component.this.addFocusListener(accessibleAWTFocusHandler); 9148 } 9149 } 9150 super.addPropertyChangeListener(listener); 9151 } 9152 9153 /** 9154 * Remove a PropertyChangeListener from the listener list. 9155 * This removes a PropertyChangeListener that was registered 9156 * for all properties. 9157 * 9158 * @param listener The PropertyChangeListener to be removed 9159 */ 9160 public void removePropertyChangeListener(PropertyChangeListener listener) { 9161 if (--propertyListenersCount == 0) { 9162 Component.this.removeComponentListener(accessibleAWTComponentHandler); 9163 if (focusHandlerSetFromComponent) { 9164 Component.this.removeFocusListener(accessibleAWTFocusHandler); 9165 } 9166 } 9167 super.removePropertyChangeListener(listener); 9168 } 9169 9170 // AccessibleContext methods 9171 // 9172 /** 9173 * Gets the accessible name of this object. This should almost never 9174 * return <code>java.awt.Component.getName()</code>, 9175 * as that generally isn't a localized name, 9176 * and doesn't have meaning for the user. If the 9177 * object is fundamentally a text object (e.g. a menu item), the 9178 * accessible name should be the text of the object (e.g. "save"). 9179 * If the object has a tooltip, the tooltip text may also be an 9180 * appropriate String to return. 9181 * 9182 * @return the localized name of the object -- can be 9183 * <code>null</code> if this 9184 * object does not have a name 9185 * @see javax.accessibility.AccessibleContext#setAccessibleName 9186 */ 9187 public String getAccessibleName() { 9188 return accessibleName; 9189 } 9190 9191 /** 9192 * Gets the accessible description of this object. This should be 9193 * a concise, localized description of what this object is - what 9194 * is its meaning to the user. If the object has a tooltip, the 9195 * tooltip text may be an appropriate string to return, assuming 9196 * it contains a concise description of the object (instead of just 9197 * the name of the object - e.g. a "Save" icon on a toolbar that 9198 * had "save" as the tooltip text shouldn't return the tooltip 9199 * text as the description, but something like "Saves the current 9200 * text document" instead). 9201 * 9202 * @return the localized description of the object -- can be 9203 * <code>null</code> if this object does not have a description 9204 * @see javax.accessibility.AccessibleContext#setAccessibleDescription 9205 */ 9206 public String getAccessibleDescription() { 9207 return accessibleDescription; 9208 } 9209 9210 /** 9211 * Gets the role of this object. 9212 * 9213 * @return an instance of <code>AccessibleRole</code> 9214 * describing the role of the object 9215 * @see javax.accessibility.AccessibleRole 9216 */ 9217 public AccessibleRole getAccessibleRole() { 9218 return AccessibleRole.AWT_COMPONENT; 9219 } 9220 9221 /** 9222 * Gets the state of this object. 9223 * 9224 * @return an instance of <code>AccessibleStateSet</code> 9225 * containing the current state set of the object 9226 * @see javax.accessibility.AccessibleState 9227 */ 9228 public AccessibleStateSet getAccessibleStateSet() { 9229 return Component.this.getAccessibleStateSet(); 9230 } 9231 9232 /** 9233 * Gets the <code>Accessible</code> parent of this object. 9234 * If the parent of this object implements <code>Accessible</code>, 9235 * this method should simply return <code>getParent</code>. 9236 * 9237 * @return the <code>Accessible</code> parent of this 9238 * object -- can be <code>null</code> if this 9239 * object does not have an <code>Accessible</code> parent 9240 */ 9241 public Accessible getAccessibleParent() { 9242 if (accessibleParent != null) { 9243 return accessibleParent; 9244 } else { 9245 Container parent = getParent(); 9246 if (parent instanceof Accessible) { 9247 return (Accessible) parent; 9248 } 9249 } 9250 return null; 9251 } 9252 9253 /** 9254 * Gets the index of this object in its accessible parent. 9255 * 9256 * @return the index of this object in its parent; or -1 if this 9257 * object does not have an accessible parent 9258 * @see #getAccessibleParent 9259 */ 9260 public int getAccessibleIndexInParent() { 9261 return Component.this.getAccessibleIndexInParent(); 9262 } 9263 9264 /** 9265 * Returns the number of accessible children in the object. If all 9266 * of the children of this object implement <code>Accessible</code>, 9267 * then this method should return the number of children of this object. 9268 * 9269 * @return the number of accessible children in the object 9270 */ 9271 public int getAccessibleChildrenCount() { 9272 return 0; // Components don't have children 9273 } 9274 9275 /** 9276 * Returns the nth <code>Accessible</code> child of the object. 9277 * 9278 * @param i zero-based index of child 9279 * @return the nth <code>Accessible</code> child of the object 9280 */ 9281 public Accessible getAccessibleChild(int i) { 9282 return null; // Components don't have children 9283 } 9284 9285 /** 9286 * Returns the locale of this object. 9287 * 9288 * @return the locale of this object 9289 */ 9290 public Locale getLocale() { 9291 return Component.this.getLocale(); 9292 } 9293 9294 /** 9295 * Gets the <code>AccessibleComponent</code> associated 9296 * with this object if one exists. 9297 * Otherwise return <code>null</code>. 9298 * 9299 * @return the component 9300 */ 9301 public AccessibleComponent getAccessibleComponent() { 9302 return this; 9303 } 9304 9305 9306 // AccessibleComponent methods 9307 // 9308 /** 9309 * Gets the background color of this object. 9310 * 9311 * @return the background color, if supported, of the object; 9312 * otherwise, <code>null</code> 9313 */ 9314 public Color getBackground() { 9315 return Component.this.getBackground(); 9316 } 9317 9318 /** 9319 * Sets the background color of this object. 9320 * (For transparency, see <code>isOpaque</code>.) 9321 * 9322 * @param c the new <code>Color</code> for the background 9323 * @see Component#isOpaque 9324 */ 9325 public void setBackground(Color c) { 9326 Component.this.setBackground(c); 9327 } 9328 9329 /** 9330 * Gets the foreground color of this object. 9331 * 9332 * @return the foreground color, if supported, of the object; 9333 * otherwise, <code>null</code> 9334 */ 9335 public Color getForeground() { 9336 return Component.this.getForeground(); 9337 } 9338 9339 /** 9340 * Sets the foreground color of this object. 9341 * 9342 * @param c the new <code>Color</code> for the foreground 9343 */ 9344 public void setForeground(Color c) { 9345 Component.this.setForeground(c); 9346 } 9347 9348 /** 9349 * Gets the <code>Cursor</code> of this object. 9350 * 9351 * @return the <code>Cursor</code>, if supported, 9352 * of the object; otherwise, <code>null</code> 9353 */ 9354 public Cursor getCursor() { 9355 return Component.this.getCursor(); 9356 } 9357 9358 /** 9359 * Sets the <code>Cursor</code> of this object. 9360 * <p> 9361 * The method may have no visual effect if the Java platform 9362 * implementation and/or the native system do not support 9363 * changing the mouse cursor shape. 9364 * @param cursor the new <code>Cursor</code> for the object 9365 */ 9366 public void setCursor(Cursor cursor) { 9367 Component.this.setCursor(cursor); 9368 } 9369 9370 /** 9371 * Gets the <code>Font</code> of this object. 9372 * 9373 * @return the <code>Font</code>, if supported, 9374 * for the object; otherwise, <code>null</code> 9375 */ 9376 public Font getFont() { 9377 return Component.this.getFont(); 9378 } 9379 9380 /** 9381 * Sets the <code>Font</code> of this object. 9382 * 9383 * @param f the new <code>Font</code> for the object 9384 */ 9385 public void setFont(Font f) { 9386 Component.this.setFont(f); 9387 } 9388 9389 /** 9390 * Gets the <code>FontMetrics</code> of this object. 9391 * 9392 * @param f the <code>Font</code> 9393 * @return the <code>FontMetrics</code>, if supported, 9394 * the object; otherwise, <code>null</code> 9395 * @see #getFont 9396 */ 9397 public FontMetrics getFontMetrics(Font f) { 9398 if (f == null) { 9399 return null; 9400 } else { 9401 return Component.this.getFontMetrics(f); 9402 } 9403 } 9404 9405 /** 9406 * Determines if the object is enabled. 9407 * 9408 * @return true if object is enabled; otherwise, false 9409 */ 9410 public boolean isEnabled() { 9411 return Component.this.isEnabled(); 9412 } 9413 9414 /** 9415 * Sets the enabled state of the object. 9416 * 9417 * @param b if true, enables this object; otherwise, disables it 9418 */ 9419 public void setEnabled(boolean b) { 9420 boolean old = Component.this.isEnabled(); 9421 Component.this.setEnabled(b); 9422 if (b != old) { 9423 if (accessibleContext != null) { 9424 if (b) { 9425 accessibleContext.firePropertyChange( 9426 AccessibleContext.ACCESSIBLE_STATE_PROPERTY, 9427 null, AccessibleState.ENABLED); 9428 } else { 9429 accessibleContext.firePropertyChange( 9430 AccessibleContext.ACCESSIBLE_STATE_PROPERTY, 9431 AccessibleState.ENABLED, null); 9432 } 9433 } 9434 } 9435 } 9436 9437 /** 9438 * Determines if the object is visible. Note: this means that the 9439 * object intends to be visible; however, it may not in fact be 9440 * showing on the screen because one of the objects that this object 9441 * is contained by is not visible. To determine if an object is 9442 * showing on the screen, use <code>isShowing</code>. 9443 * 9444 * @return true if object is visible; otherwise, false 9445 */ 9446 public boolean isVisible() { 9447 return Component.this.isVisible(); 9448 } 9449 9450 /** 9451 * Sets the visible state of the object. 9452 * 9453 * @param b if true, shows this object; otherwise, hides it 9454 */ 9455 public void setVisible(boolean b) { 9456 boolean old = Component.this.isVisible(); 9457 Component.this.setVisible(b); 9458 if (b != old) { 9459 if (accessibleContext != null) { 9460 if (b) { 9461 accessibleContext.firePropertyChange( 9462 AccessibleContext.ACCESSIBLE_STATE_PROPERTY, 9463 null, AccessibleState.VISIBLE); 9464 } else { 9465 accessibleContext.firePropertyChange( 9466 AccessibleContext.ACCESSIBLE_STATE_PROPERTY, 9467 AccessibleState.VISIBLE, null); 9468 } 9469 } 9470 } 9471 } 9472 9473 /** 9474 * Determines if the object is showing. This is determined by checking 9475 * the visibility of the object and ancestors of the object. Note: 9476 * this will return true even if the object is obscured by another 9477 * (for example, it happens to be underneath a menu that was pulled 9478 * down). 9479 * 9480 * @return true if object is showing; otherwise, false 9481 */ 9482 public boolean isShowing() { 9483 return Component.this.isShowing(); 9484 } 9485 9486 /** 9487 * Checks whether the specified point is within this object's bounds, 9488 * where the point's x and y coordinates are defined to be relative to 9489 * the coordinate system of the object. 9490 * 9491 * @param p the <code>Point</code> relative to the 9492 * coordinate system of the object 9493 * @return true if object contains <code>Point</code>; otherwise false 9494 */ 9495 public boolean contains(Point p) { 9496 return Component.this.contains(p); 9497 } 9498 9499 /** 9500 * Returns the location of the object on the screen. 9501 * 9502 * @return location of object on screen -- can be 9503 * <code>null</code> if this object is not on the screen 9504 */ 9505 public Point getLocationOnScreen() { 9506 synchronized (Component.this.getTreeLock()) { 9507 if (Component.this.isShowing()) { 9508 return Component.this.getLocationOnScreen(); 9509 } else { 9510 return null; 9511 } 9512 } 9513 } 9514 9515 /** 9516 * Gets the location of the object relative to the parent in the form 9517 * of a point specifying the object's top-left corner in the screen's 9518 * coordinate space. 9519 * 9520 * @return an instance of Point representing the top-left corner of 9521 * the object's bounds in the coordinate space of the screen; 9522 * <code>null</code> if this object or its parent are not on the screen 9523 */ 9524 public Point getLocation() { 9525 return Component.this.getLocation(); 9526 } 9527 9528 /** 9529 * Sets the location of the object relative to the parent. 9530 * @param p the coordinates of the object 9531 */ 9532 public void setLocation(Point p) { 9533 Component.this.setLocation(p); 9534 } 9535 9536 /** 9537 * Gets the bounds of this object in the form of a Rectangle object. 9538 * The bounds specify this object's width, height, and location 9539 * relative to its parent. 9540 * 9541 * @return a rectangle indicating this component's bounds; 9542 * <code>null</code> if this object is not on the screen 9543 */ 9544 public Rectangle getBounds() { 9545 return Component.this.getBounds(); 9546 } 9547 9548 /** 9549 * Sets the bounds of this object in the form of a 9550 * <code>Rectangle</code> object. 9551 * The bounds specify this object's width, height, and location 9552 * relative to its parent. 9553 * 9554 * @param r a rectangle indicating this component's bounds 9555 */ 9556 public void setBounds(Rectangle r) { 9557 Component.this.setBounds(r); 9558 } 9559 9560 /** 9561 * Returns the size of this object in the form of a 9562 * <code>Dimension</code> object. The height field of the 9563 * <code>Dimension</code> object contains this objects's 9564 * height, and the width field of the <code>Dimension</code> 9565 * object contains this object's width. 9566 * 9567 * @return a <code>Dimension</code> object that indicates 9568 * the size of this component; <code>null</code> if 9569 * this object is not on the screen 9570 */ 9571 public Dimension getSize() { 9572 return Component.this.getSize(); 9573 } 9574 9575 /** 9576 * Resizes this object so that it has width and height. 9577 * 9578 * @param d - the dimension specifying the new size of the object 9579 */ 9580 public void setSize(Dimension d) { 9581 Component.this.setSize(d); 9582 } 9583 9584 /** 9585 * Returns the <code>Accessible</code> child, 9586 * if one exists, contained at the local 9587 * coordinate <code>Point</code>. Otherwise returns 9588 * <code>null</code>. 9589 * 9590 * @param p the point defining the top-left corner of 9591 * the <code>Accessible</code>, given in the 9592 * coordinate space of the object's parent 9593 * @return the <code>Accessible</code>, if it exists, 9594 * at the specified location; else <code>null</code> 9595 */ 9596 public Accessible getAccessibleAt(Point p) { 9597 return null; // Components don't have children 9598 } 9599 9600 /** 9601 * Returns whether this object can accept focus or not. 9602 * 9603 * @return true if object can accept focus; otherwise false 9604 */ 9605 public boolean isFocusTraversable() { 9606 return Component.this.isFocusTraversable(); 9607 } 9608 9609 /** 9610 * Requests focus for this object. 9611 */ 9612 public void requestFocus() { 9613 Component.this.requestFocus(); 9614 } 9615 9616 /** 9617 * Adds the specified focus listener to receive focus events from this 9618 * component. 9619 * 9620 * @param l the focus listener 9621 */ 9622 public void addFocusListener(FocusListener l) { 9623 Component.this.addFocusListener(l); 9624 } 9625 9626 /** 9627 * Removes the specified focus listener so it no longer receives focus 9628 * events from this component. 9629 * 9630 * @param l the focus listener 9631 */ 9632 public void removeFocusListener(FocusListener l) { 9633 Component.this.removeFocusListener(l); 9634 } 9635 9636 } // inner class AccessibleAWTComponent 9637 9638 9639 /** 9640 * Gets the index of this object in its accessible parent. 9641 * If this object does not have an accessible parent, returns 9642 * -1. 9643 * 9644 * @return the index of this object in its accessible parent 9645 */ 9646 int getAccessibleIndexInParent() { 9647 synchronized (getTreeLock()) { 9648 int index = -1; 9649 Container parent = this.getParent(); 9650 if (parent != null && parent instanceof Accessible) { 9651 Component ca[] = parent.getComponents(); 9652 for (int i = 0; i < ca.length; i++) { 9653 if (ca[i] instanceof Accessible) { 9654 index++; 9655 } 9656 if (this.equals(ca[i])) { 9657 return index; 9658 } 9659 } 9660 } 9661 return -1; 9662 } 9663 } 9664 9665 /** 9666 * Gets the current state set of this object. 9667 * 9668 * @return an instance of <code>AccessibleStateSet</code> 9669 * containing the current state set of the object 9670 * @see AccessibleState 9671 */ 9672 AccessibleStateSet getAccessibleStateSet() { 9673 synchronized (getTreeLock()) { 9674 AccessibleStateSet states = new AccessibleStateSet(); 9675 if (this.isEnabled()) { 9676 states.add(AccessibleState.ENABLED); 9677 } 9678 if (this.isFocusTraversable()) { 9679 states.add(AccessibleState.FOCUSABLE); 9680 } 9681 if (this.isVisible()) { 9682 states.add(AccessibleState.VISIBLE); 9683 } 9684 if (this.isShowing()) { 9685 states.add(AccessibleState.SHOWING); 9686 } 9687 if (this.isFocusOwner()) { 9688 states.add(AccessibleState.FOCUSED); 9689 } 9690 if (this instanceof Accessible) { 9691 AccessibleContext ac = ((Accessible) this).getAccessibleContext(); 9692 if (ac != null) { 9693 Accessible ap = ac.getAccessibleParent(); 9694 if (ap != null) { 9695 AccessibleContext pac = ap.getAccessibleContext(); 9696 if (pac != null) { 9697 AccessibleSelection as = pac.getAccessibleSelection(); 9698 if (as != null) { 9699 states.add(AccessibleState.SELECTABLE); 9700 int i = ac.getAccessibleIndexInParent(); 9701 if (i >= 0) { 9702 if (as.isAccessibleChildSelected(i)) { 9703 states.add(AccessibleState.SELECTED); 9704 } 9705 } 9706 } 9707 } 9708 } 9709 } 9710 } 9711 if (Component.isInstanceOf(this, "javax.swing.JComponent")) { 9712 if (((javax.swing.JComponent) this).isOpaque()) { 9713 states.add(AccessibleState.OPAQUE); 9714 } 9715 } 9716 return states; 9717 } 9718 } 9719 9720 /** 9721 * Checks that the given object is instance of the given class. 9722 * @param obj Object to be checked 9723 * @param className The name of the class. Must be fully-qualified class name. 9724 * @return true, if this object is instanceof given class, 9725 * false, otherwise, or if obj or className is null 9726 */ 9727 static boolean isInstanceOf(Object obj, String className) { 9728 if (obj == null) return false; 9729 if (className == null) return false; 9730 9731 Class<?> cls = obj.getClass(); 9732 while (cls != null) { 9733 if (cls.getName().equals(className)) { 9734 return true; 9735 } 9736 cls = cls.getSuperclass(); 9737 } 9738 return false; 9739 } 9740 9741 9742 // ************************** MIXING CODE ******************************* 9743 9744 /** 9745 * Check whether we can trust the current bounds of the component. 9746 * The return value of false indicates that the container of the 9747 * component is invalid, and therefore needs to be layed out, which would 9748 * probably mean changing the bounds of its children. 9749 * Null-layout of the container or absence of the container mean 9750 * the bounds of the component are final and can be trusted. 9751 */ 9752 final boolean areBoundsValid() { 9753 Container cont = getContainer(); 9754 return cont == null || cont.isValid() || cont.getLayout() == null; 9755 } 9756 9757 /** 9758 * Applies the shape to the component 9759 * @param shape Shape to be applied to the component 9760 */ 9761 void applyCompoundShape(Region shape) { 9762 checkTreeLock(); 9763 9764 if (!areBoundsValid()) { 9765 if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) { 9766 mixingLog.fine("this = " + this + "; areBoundsValid = " + areBoundsValid()); 9767 } 9768 return; 9769 } 9770 9771 if (!isLightweight()) { 9772 ComponentPeer peer = getPeer(); 9773 if (peer != null) { 9774 // The Region class has some optimizations. That's why 9775 // we should manually check whether it's empty and 9776 // substitute the object ourselves. Otherwise we end up 9777 // with some incorrect Region object with loX being 9778 // greater than the hiX for instance. 9779 if (shape.isEmpty()) { 9780 shape = Region.EMPTY_REGION; 9781 } 9782 9783 9784 // Note: the shape is not really copied/cloned. We create 9785 // the Region object ourselves, so there's no any possibility 9786 // to modify the object outside of the mixing code. 9787 // Nullifying compoundShape means that the component has normal shape 9788 // (or has no shape at all). 9789 if (shape.equals(getNormalShape())) { 9790 if (this.compoundShape == null) { 9791 return; 9792 } 9793 this.compoundShape = null; 9794 peer.applyShape(null); 9795 } else { 9796 if (shape.equals(getAppliedShape())) { 9797 return; 9798 } 9799 this.compoundShape = shape; 9800 Point compAbsolute = getLocationOnWindow(); 9801 if (mixingLog.isLoggable(PlatformLogger.Level.FINER)) { 9802 mixingLog.fine("this = " + this + 9803 "; compAbsolute=" + compAbsolute + "; shape=" + shape); 9804 } 9805 peer.applyShape(shape.getTranslatedRegion(-compAbsolute.x, -compAbsolute.y)); 9806 } 9807 } 9808 } 9809 } 9810 9811 /** 9812 * Returns the shape previously set with applyCompoundShape(). 9813 * If the component is LW or no shape was applied yet, 9814 * the method returns the normal shape. 9815 */ 9816 private Region getAppliedShape() { 9817 checkTreeLock(); 9818 //XXX: if we allow LW components to have a shape, this must be changed 9819 return (this.compoundShape == null || isLightweight()) ? getNormalShape() : this.compoundShape; 9820 } 9821 9822 Point getLocationOnWindow() { 9823 checkTreeLock(); 9824 Point curLocation = getLocation(); 9825 9826 for (Container parent = getContainer(); 9827 parent != null && !(parent instanceof Window); 9828 parent = parent.getContainer()) 9829 { 9830 curLocation.x += parent.getX(); 9831 curLocation.y += parent.getY(); 9832 } 9833 9834 return curLocation; 9835 } 9836 9837 /** 9838 * Returns the full shape of the component located in window coordinates 9839 */ 9840 final Region getNormalShape() { 9841 checkTreeLock(); 9842 //XXX: we may take into account a user-specified shape for this component 9843 Point compAbsolute = getLocationOnWindow(); 9844 return 9845 Region.getInstanceXYWH( 9846 compAbsolute.x, 9847 compAbsolute.y, 9848 getWidth(), 9849 getHeight() 9850 ); 9851 } 9852 9853 /** 9854 * Returns the "opaque shape" of the component. 9855 * 9856 * The opaque shape of a lightweight components is the actual shape that 9857 * needs to be cut off of the heavyweight components in order to mix this 9858 * lightweight component correctly with them. 9859 * 9860 * The method is overriden in the java.awt.Container to handle non-opaque 9861 * containers containing opaque children. 9862 * 9863 * See 6637655 for details. 9864 */ 9865 Region getOpaqueShape() { 9866 checkTreeLock(); 9867 if (mixingCutoutRegion != null) { 9868 return mixingCutoutRegion; 9869 } else { 9870 return getNormalShape(); 9871 } 9872 } 9873 9874 final int getSiblingIndexAbove() { 9875 checkTreeLock(); 9876 Container parent = getContainer(); 9877 if (parent == null) { 9878 return -1; 9879 } 9880 9881 int nextAbove = parent.getComponentZOrder(this) - 1; 9882 9883 return nextAbove < 0 ? -1 : nextAbove; 9884 } 9885 9886 final ComponentPeer getHWPeerAboveMe() { 9887 checkTreeLock(); 9888 9889 Container cont = getContainer(); 9890 int indexAbove = getSiblingIndexAbove(); 9891 9892 while (cont != null) { 9893 for (int i = indexAbove; i > -1; i--) { 9894 Component comp = cont.getComponent(i); 9895 if (comp != null && comp.isDisplayable() && !comp.isLightweight()) { 9896 return comp.getPeer(); 9897 } 9898 } 9899 // traversing the hierarchy up to the closest HW container; 9900 // further traversing may return a component that is not actually 9901 // a native sibling of this component and this kind of z-order 9902 // request may not be allowed by the underlying system (6852051). 9903 if (!cont.isLightweight()) { 9904 break; 9905 } 9906 9907 indexAbove = cont.getSiblingIndexAbove(); 9908 cont = cont.getContainer(); 9909 } 9910 9911 return null; 9912 } 9913 9914 final int getSiblingIndexBelow() { 9915 checkTreeLock(); 9916 Container parent = getContainer(); 9917 if (parent == null) { 9918 return -1; 9919 } 9920 9921 int nextBelow = parent.getComponentZOrder(this) + 1; 9922 9923 return nextBelow >= parent.getComponentCount() ? -1 : nextBelow; 9924 } 9925 9926 final boolean isNonOpaqueForMixing() { 9927 return mixingCutoutRegion != null && 9928 mixingCutoutRegion.isEmpty(); 9929 } 9930 9931 private Region calculateCurrentShape() { 9932 checkTreeLock(); 9933 Region s = getNormalShape(); 9934 9935 if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) { 9936 mixingLog.fine("this = " + this + "; normalShape=" + s); 9937 } 9938 9939 if (getContainer() != null) { 9940 Component comp = this; 9941 Container cont = comp.getContainer(); 9942 9943 while (cont != null) { 9944 for (int index = comp.getSiblingIndexAbove(); index != -1; --index) { 9945 /* It is assumed that: 9946 * 9947 * getComponent(getContainer().getComponentZOrder(comp)) == comp 9948 * 9949 * The assumption has been made according to the current 9950 * implementation of the Container class. 9951 */ 9952 Component c = cont.getComponent(index); 9953 if (c.isLightweight() && c.isShowing()) { 9954 s = s.getDifference(c.getOpaqueShape()); 9955 } 9956 } 9957 9958 if (cont.isLightweight()) { 9959 s = s.getIntersection(cont.getNormalShape()); 9960 } else { 9961 break; 9962 } 9963 9964 comp = cont; 9965 cont = cont.getContainer(); 9966 } 9967 } 9968 9969 if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) { 9970 mixingLog.fine("currentShape=" + s); 9971 } 9972 9973 return s; 9974 } 9975 9976 void applyCurrentShape() { 9977 checkTreeLock(); 9978 if (!areBoundsValid()) { 9979 if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) { 9980 mixingLog.fine("this = " + this + "; areBoundsValid = " + areBoundsValid()); 9981 } 9982 return; // Because applyCompoundShape() ignores such components anyway 9983 } 9984 if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) { 9985 mixingLog.fine("this = " + this); 9986 } 9987 applyCompoundShape(calculateCurrentShape()); 9988 } 9989 9990 final void subtractAndApplyShape(Region s) { 9991 checkTreeLock(); 9992 9993 if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) { 9994 mixingLog.fine("this = " + this + "; s=" + s); 9995 } 9996 9997 applyCompoundShape(getAppliedShape().getDifference(s)); 9998 } 9999 10000 private final void applyCurrentShapeBelowMe() { 10001 checkTreeLock(); 10002 Container parent = getContainer(); 10003 if (parent != null && parent.isShowing()) { 10004 // First, reapply shapes of my siblings 10005 parent.recursiveApplyCurrentShape(getSiblingIndexBelow()); 10006 10007 // Second, if my container is non-opaque, reapply shapes of siblings of my container 10008 Container parent2 = parent.getContainer(); 10009 while (!parent.isOpaque() && parent2 != null) { 10010 parent2.recursiveApplyCurrentShape(parent.getSiblingIndexBelow()); 10011 10012 parent = parent2; 10013 parent2 = parent.getContainer(); 10014 } 10015 } 10016 } 10017 10018 final void subtractAndApplyShapeBelowMe() { 10019 checkTreeLock(); 10020 Container parent = getContainer(); 10021 if (parent != null && isShowing()) { 10022 Region opaqueShape = getOpaqueShape(); 10023 10024 // First, cut my siblings 10025 parent.recursiveSubtractAndApplyShape(opaqueShape, getSiblingIndexBelow()); 10026 10027 // Second, if my container is non-opaque, cut siblings of my container 10028 Container parent2 = parent.getContainer(); 10029 while (!parent.isOpaque() && parent2 != null) { 10030 parent2.recursiveSubtractAndApplyShape(opaqueShape, parent.getSiblingIndexBelow()); 10031 10032 parent = parent2; 10033 parent2 = parent.getContainer(); 10034 } 10035 } 10036 } 10037 10038 void mixOnShowing() { 10039 synchronized (getTreeLock()) { 10040 if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) { 10041 mixingLog.fine("this = " + this); 10042 } 10043 if (!isMixingNeeded()) { 10044 return; 10045 } 10046 if (isLightweight()) { 10047 subtractAndApplyShapeBelowMe(); 10048 } else { 10049 applyCurrentShape(); 10050 } 10051 } 10052 } 10053 10054 void mixOnHiding(boolean isLightweight) { 10055 // We cannot be sure that the peer exists at this point, so we need the argument 10056 // to find out whether the hiding component is (well, actually was) a LW or a HW. 10057 synchronized (getTreeLock()) { 10058 if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) { 10059 mixingLog.fine("this = " + this + "; isLightweight = " + isLightweight); 10060 } 10061 if (!isMixingNeeded()) { 10062 return; 10063 } 10064 if (isLightweight) { 10065 applyCurrentShapeBelowMe(); 10066 } 10067 } 10068 } 10069 10070 void mixOnReshaping() { 10071 synchronized (getTreeLock()) { 10072 if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) { 10073 mixingLog.fine("this = " + this); 10074 } 10075 if (!isMixingNeeded()) { 10076 return; 10077 } 10078 if (isLightweight()) { 10079 applyCurrentShapeBelowMe(); 10080 } else { 10081 applyCurrentShape(); 10082 } 10083 } 10084 } 10085 10086 void mixOnZOrderChanging(int oldZorder, int newZorder) { 10087 synchronized (getTreeLock()) { 10088 boolean becameHigher = newZorder < oldZorder; 10089 Container parent = getContainer(); 10090 10091 if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) { 10092 mixingLog.fine("this = " + this + 10093 "; oldZorder=" + oldZorder + "; newZorder=" + newZorder + "; parent=" + parent); 10094 } 10095 if (!isMixingNeeded()) { 10096 return; 10097 } 10098 if (isLightweight()) { 10099 if (becameHigher) { 10100 if (parent != null && isShowing()) { 10101 parent.recursiveSubtractAndApplyShape(getOpaqueShape(), getSiblingIndexBelow(), oldZorder); 10102 } 10103 } else { 10104 if (parent != null) { 10105 parent.recursiveApplyCurrentShape(oldZorder, newZorder); 10106 } 10107 } 10108 } else { 10109 if (becameHigher) { 10110 applyCurrentShape(); 10111 } else { 10112 if (parent != null) { 10113 Region shape = getAppliedShape(); 10114 10115 for (int index = oldZorder; index < newZorder; index++) { 10116 Component c = parent.getComponent(index); 10117 if (c.isLightweight() && c.isShowing()) { 10118 shape = shape.getDifference(c.getOpaqueShape()); 10119 } 10120 } 10121 applyCompoundShape(shape); 10122 } 10123 } 10124 } 10125 } 10126 } 10127 10128 void mixOnValidating() { 10129 // This method gets overriden in the Container. Obviously, a plain 10130 // non-container components don't need to handle validation. 10131 } 10132 10133 final boolean isMixingNeeded() { 10134 if (SunToolkit.getSunAwtDisableMixing()) { 10135 if (mixingLog.isLoggable(PlatformLogger.Level.FINEST)) { 10136 mixingLog.finest("this = " + this + "; Mixing disabled via sun.awt.disableMixing"); 10137 } 10138 return false; 10139 } 10140 if (!areBoundsValid()) { 10141 if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) { 10142 mixingLog.fine("this = " + this + "; areBoundsValid = " + areBoundsValid()); 10143 } 10144 return false; 10145 } 10146 Window window = getContainingWindow(); 10147 if (window != null) { 10148 if (!window.hasHeavyweightDescendants() || !window.hasLightweightDescendants() || window.isDisposing()) { 10149 if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) { 10150 mixingLog.fine("containing window = " + window + 10151 "; has h/w descendants = " + window.hasHeavyweightDescendants() + 10152 "; has l/w descendants = " + window.hasLightweightDescendants() + 10153 "; disposing = " + window.isDisposing()); 10154 } 10155 return false; 10156 } 10157 } else { 10158 if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) { 10159 mixingLog.fine("this = " + this + "; containing window is null"); 10160 } 10161 return false; 10162 } 10163 return true; 10164 } 10165 10166 // ****************** END OF MIXING CODE ******************************** 10167 10168 // Note that the method is overriden in the Window class, 10169 // a window doesn't need to be updated in the Z-order. 10170 void updateZOrder() { 10171 peer.setZOrder(getHWPeerAboveMe()); 10172 } 10173 10174 }