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