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