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