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