1 /* 2 * Copyright 1995-2009 Sun Microsystems, Inc. All Rights Reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Sun designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Sun in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 22 * CA 95054 USA or visit www.sun.com if you need additional information or 23 * have any questions. 24 */ 25 package java.awt; 26 27 import java.awt.dnd.DropTarget; 28 29 import java.awt.event.*; 30 31 import java.awt.peer.ContainerPeer; 32 import java.awt.peer.ComponentPeer; 33 import java.awt.peer.LightweightPeer; 34 35 import java.beans.PropertyChangeListener; 36 37 import java.io.IOException; 38 import java.io.ObjectInputStream; 39 import java.io.ObjectOutputStream; 40 import java.io.ObjectStreamField; 41 import java.io.PrintStream; 42 import java.io.PrintWriter; 43 44 import java.util.Arrays; 45 import java.util.EventListener; 46 import java.util.HashSet; 47 import java.util.Set; 48 49 import java.util.logging.*; 50 51 import javax.accessibility.*; 52 53 import sun.awt.AppContext; 54 import sun.awt.CausedFocusEvent; 55 import sun.awt.PeerEvent; 56 import sun.awt.SunToolkit; 57 58 import sun.awt.dnd.SunDropTargetEvent; 59 60 import sun.java2d.pipe.Region; 61 62 /** 63 * A generic Abstract Window Toolkit(AWT) container object is a component 64 * that can contain other AWT components. 65 * <p> 66 * Components added to a container are tracked in a list. The order 67 * of the list will define the components' front-to-back stacking order 68 * within the container. If no index is specified when adding a 69 * component to a container, it will be added to the end of the list 70 * (and hence to the bottom of the stacking order). 71 * <p> 72 * <b>Note</b>: For details on the focus subsystem, see 73 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html"> 74 * How to Use the Focus Subsystem</a>, 75 * a section in <em>The Java Tutorial</em>, and the 76 * <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a> 77 * for more information. 78 * 79 * @author Arthur van Hoff 80 * @author Sami Shaio 81 * @see #add(java.awt.Component, int) 82 * @see #getComponent(int) 83 * @see LayoutManager 84 * @since JDK1.0 85 */ 86 public class Container extends Component { 87 88 private static final Logger log = Logger.getLogger("java.awt.Container"); 89 private static final Logger eventLog = Logger.getLogger("java.awt.event.Container"); 90 91 private static final Component[] EMPTY_ARRAY = new Component[0]; 92 93 /** 94 * The components in this container. 95 * @see #add 96 * @see #getComponents 97 */ 98 private java.util.List<Component> component = new java.util.ArrayList<Component>(); 99 100 /** 101 * Layout manager for this container. 102 * @see #doLayout 103 * @see #setLayout 104 * @see #getLayout 105 */ 106 LayoutManager layoutMgr; 107 108 /** 109 * Event router for lightweight components. If this container 110 * is native, this dispatcher takes care of forwarding and 111 * retargeting the events to lightweight components contained 112 * (if any). 113 */ 114 private LightweightDispatcher dispatcher; 115 116 /** 117 * The focus traversal policy that will manage keyboard traversal of this 118 * Container's children, if this Container is a focus cycle root. If the 119 * value is null, this Container inherits its policy from its focus-cycle- 120 * root ancestor. If all such ancestors of this Container have null 121 * policies, then the current KeyboardFocusManager's default policy is 122 * used. If the value is non-null, this policy will be inherited by all 123 * focus-cycle-root children that have no keyboard-traversal policy of 124 * their own (as will, recursively, their focus-cycle-root children). 125 * <p> 126 * If this Container is not a focus cycle root, the value will be 127 * remembered, but will not be used or inherited by this or any other 128 * Containers until this Container is made a focus cycle root. 129 * 130 * @see #setFocusTraversalPolicy 131 * @see #getFocusTraversalPolicy 132 * @since 1.4 133 */ 134 private transient FocusTraversalPolicy focusTraversalPolicy; 135 136 /** 137 * Indicates whether this Component is the root of a focus traversal cycle. 138 * Once focus enters a traversal cycle, typically it cannot leave it via 139 * focus traversal unless one of the up- or down-cycle keys is pressed. 140 * Normal traversal is limited to this Container, and all of this 141 * Container's descendants that are not descendants of inferior focus cycle 142 * roots. 143 * 144 * @see #setFocusCycleRoot 145 * @see #isFocusCycleRoot 146 * @since 1.4 147 */ 148 private boolean focusCycleRoot = false; 149 150 151 /** 152 * Stores the value of focusTraversalPolicyProvider property. 153 * @since 1.5 154 * @see #setFocusTraversalPolicyProvider 155 */ 156 private boolean focusTraversalPolicyProvider; 157 158 // keeps track of the threads that are printing this component 159 private transient Set printingThreads; 160 // True if there is at least one thread that's printing this component 161 private transient boolean printing = false; 162 163 transient ContainerListener containerListener; 164 165 /* HierarchyListener and HierarchyBoundsListener support */ 166 transient int listeningChildren; 167 transient int listeningBoundsChildren; 168 transient int descendantsCount; 169 170 /* Non-opaque window support -- see Window.setLayersOpaque */ 171 transient Color preserveBackgroundColor = null; 172 173 /** 174 * JDK 1.1 serialVersionUID 175 */ 176 private static final long serialVersionUID = 4613797578919906343L; 177 178 /** 179 * A constant which toggles one of the controllable behaviors 180 * of <code>getMouseEventTarget</code>. It is used to specify whether 181 * the method can return the Container on which it is originally called 182 * in case if none of its children are the current mouse event targets. 183 * 184 * @see #getMouseEventTarget(int, int, boolean, boolean, boolean) 185 */ 186 static final boolean INCLUDE_SELF = true; 187 188 /** 189 * A constant which toggles one of the controllable behaviors 190 * of <code>getMouseEventTarget</code>. It is used to specify whether 191 * the method should search only lightweight components. 192 * 193 * @see #getMouseEventTarget(int, int, boolean, boolean, boolean) 194 */ 195 static final boolean SEARCH_HEAVYWEIGHTS = true; 196 197 /* 198 * Number of HW or LW components in this container (including 199 * all descendant containers). 200 */ 201 private transient int numOfHWComponents = 0; 202 private transient int numOfLWComponents = 0; 203 204 private static final Logger mixingLog = Logger.getLogger("java.awt.mixing.Container"); 205 206 /** 207 * @serialField ncomponents int 208 * The number of components in this container. 209 * This value can be null. 210 * @serialField component Component[] 211 * The components in this container. 212 * @serialField layoutMgr LayoutManager 213 * Layout manager for this container. 214 * @serialField dispatcher LightweightDispatcher 215 * Event router for lightweight components. If this container 216 * is native, this dispatcher takes care of forwarding and 217 * retargeting the events to lightweight components contained 218 * (if any). 219 * @serialField maxSize Dimension 220 * Maximum size of this Container. 221 * @serialField focusCycleRoot boolean 222 * Indicates whether this Component is the root of a focus traversal cycle. 223 * Once focus enters a traversal cycle, typically it cannot leave it via 224 * focus traversal unless one of the up- or down-cycle keys is pressed. 225 * Normal traversal is limited to this Container, and all of this 226 * Container's descendants that are not descendants of inferior focus cycle 227 * roots. 228 * @serialField containerSerializedDataVersion int 229 * Container Serial Data Version. 230 * @serialField focusTraversalPolicyProvider boolean 231 * Stores the value of focusTraversalPolicyProvider property. 232 */ 233 private static final ObjectStreamField[] serialPersistentFields = { 234 new ObjectStreamField("ncomponents", Integer.TYPE), 235 new ObjectStreamField("component", Component[].class), 236 new ObjectStreamField("layoutMgr", LayoutManager.class), 237 new ObjectStreamField("dispatcher", LightweightDispatcher.class), 238 new ObjectStreamField("maxSize", Dimension.class), 239 new ObjectStreamField("focusCycleRoot", Boolean.TYPE), 240 new ObjectStreamField("containerSerializedDataVersion", Integer.TYPE), 241 new ObjectStreamField("focusTraversalPolicyProvider", Boolean.TYPE), 242 }; 243 244 static { 245 /* ensure that the necessary native libraries are loaded */ 246 Toolkit.loadLibraries(); 247 if (!GraphicsEnvironment.isHeadless()) { 248 initIDs(); 249 } 250 } 251 252 /** 253 * Initialize JNI field and method IDs for fields that may be 254 called from C. 255 */ 256 private static native void initIDs(); 257 258 /** 259 * Constructs a new Container. Containers can be extended directly, 260 * but are lightweight in this case and must be contained by a parent 261 * somewhere higher up in the component tree that is native. 262 * (such as Frame for example). 263 */ 264 public Container() { 265 } 266 267 void initializeFocusTraversalKeys() { 268 focusTraversalKeys = new Set[4]; 269 } 270 271 /** 272 * Gets the number of components in this panel. 273 * <p> 274 * Note: This method should be called under AWT tree lock. 275 * 276 * @return the number of components in this panel. 277 * @see #getComponent 278 * @since JDK1.1 279 * @see Component#getTreeLock() 280 */ 281 public int getComponentCount() { 282 return countComponents(); 283 } 284 285 /** 286 * @deprecated As of JDK version 1.1, 287 * replaced by getComponentCount(). 288 */ 289 @Deprecated 290 public int countComponents() { 291 // This method is not synchronized under AWT tree lock. 292 // Instead, the calling code is responsible for the 293 // synchronization. See 6784816 for details. 294 return component.size(); 295 } 296 297 /** 298 * Gets the nth component in this container. 299 * <p> 300 * Note: This method should be called under AWT tree lock. 301 * 302 * @param n the index of the component to get. 303 * @return the n<sup>th</sup> component in this container. 304 * @exception ArrayIndexOutOfBoundsException 305 * if the n<sup>th</sup> value does not exist. 306 * @see Component#getTreeLock() 307 */ 308 public Component getComponent(int n) { 309 // This method is not synchronized under AWT tree lock. 310 // Instead, the calling code is responsible for the 311 // synchronization. See 6784816 for details. 312 try { 313 return component.get(n); 314 } catch (IndexOutOfBoundsException z) { 315 throw new ArrayIndexOutOfBoundsException("No such child: " + n); 316 } 317 } 318 319 /** 320 * Gets all the components in this container. 321 * <p> 322 * Note: This method should be called under AWT tree lock. 323 * 324 * @return an array of all the components in this container. 325 * @see Component#getTreeLock() 326 */ 327 public Component[] getComponents() { 328 // This method is not synchronized under AWT tree lock. 329 // Instead, the calling code is responsible for the 330 // synchronization. See 6784816 for details. 331 return getComponents_NoClientCode(); 332 } 333 334 // NOTE: This method may be called by privileged threads. 335 // This functionality is implemented in a package-private method 336 // to insure that it cannot be overridden by client subclasses. 337 // DO NOT INVOKE CLIENT CODE ON THIS THREAD! 338 final Component[] getComponents_NoClientCode() { 339 return component.toArray(EMPTY_ARRAY); 340 } 341 342 /* 343 * Wrapper for getComponents() method with a proper synchronization. 344 */ 345 Component[] getComponentsSync() { 346 synchronized (getTreeLock()) { 347 return getComponents(); 348 } 349 } 350 351 /** 352 * Determines the insets of this container, which indicate the size 353 * of the container's border. 354 * <p> 355 * A <code>Frame</code> object, for example, has a top inset that 356 * corresponds to the height of the frame's title bar. 357 * @return the insets of this container. 358 * @see Insets 359 * @see LayoutManager 360 * @since JDK1.1 361 */ 362 public Insets getInsets() { 363 return insets(); 364 } 365 366 /** 367 * @deprecated As of JDK version 1.1, 368 * replaced by <code>getInsets()</code>. 369 */ 370 @Deprecated 371 public Insets insets() { 372 ComponentPeer peer = this.peer; 373 if (peer instanceof ContainerPeer) { 374 ContainerPeer cpeer = (ContainerPeer)peer; 375 return (Insets)cpeer.getInsets().clone(); 376 } 377 return new Insets(0, 0, 0, 0); 378 } 379 380 /** 381 * Appends the specified component to the end of this container. 382 * This is a convenience method for {@link #addImpl}. 383 * <p> 384 * Note: If a component has been added to a container that 385 * has been displayed, <code>validate</code> must be 386 * called on that container to display the new component. 387 * If multiple components are being added, you can improve 388 * efficiency by calling <code>validate</code> only once, 389 * after all the components have been added. 390 * 391 * @param comp the component to be added 392 * @exception NullPointerException if {@code comp} is {@code null} 393 * @see #addImpl 394 * @see #validate 395 * @see javax.swing.JComponent#revalidate() 396 * @return the component argument 397 */ 398 public Component add(Component comp) { 399 addImpl(comp, null, -1); 400 return comp; 401 } 402 403 /** 404 * Adds the specified component to this container. 405 * This is a convenience method for {@link #addImpl}. 406 * <p> 407 * This method is obsolete as of 1.1. Please use the 408 * method <code>add(Component, Object)</code> instead. 409 * @exception NullPointerException if {@code comp} is {@code null} 410 * @see #add(Component, Object) 411 */ 412 public Component add(String name, Component comp) { 413 addImpl(comp, name, -1); 414 return comp; 415 } 416 417 /** 418 * Adds the specified component to this container at the given 419 * position. 420 * This is a convenience method for {@link #addImpl}. 421 * <p> 422 * Note: If a component has been added to a container that 423 * has been displayed, <code>validate</code> must be 424 * called on that container to display the new component. 425 * If multiple components are being added, you can improve 426 * efficiency by calling <code>validate</code> only once, 427 * after all the components have been added. 428 * 429 * @param comp the component to be added 430 * @param index the position at which to insert the component, 431 * or <code>-1</code> to append the component to the end 432 * @exception NullPointerException if {@code comp} is {@code null} 433 * @exception IllegalArgumentException if {@code index} is invalid (see 434 * {@link #addImpl} for details) 435 * @return the component <code>comp</code> 436 * @see #addImpl 437 * @see #remove 438 * @see #validate 439 * @see javax.swing.JComponent#revalidate() 440 */ 441 public Component add(Component comp, int index) { 442 addImpl(comp, null, index); 443 return comp; 444 } 445 446 /** 447 * Checks that the component 448 * isn't supposed to be added into itself. 449 */ 450 private void checkAddToSelf(Component comp){ 451 if (comp instanceof Container) { 452 for (Container cn = this; cn != null; cn=cn.parent) { 453 if (cn == comp) { 454 throw new IllegalArgumentException("adding container's parent to itself"); 455 } 456 } 457 } 458 } 459 460 /** 461 * Checks that the component is not a Window instance. 462 */ 463 private void checkNotAWindow(Component comp){ 464 if (comp instanceof Window) { 465 throw new IllegalArgumentException("adding a window to a container"); 466 } 467 } 468 469 /** 470 * Checks that the component comp can be added to this container 471 * Checks : index in bounds of container's size, 472 * comp is not one of this container's parents, 473 * and comp is not a window. 474 * Comp and container must be on the same GraphicsDevice. 475 * if comp is container, all sub-components must be on 476 * same GraphicsDevice. 477 * 478 * @since 1.5 479 */ 480 private void checkAdding(Component comp, int index) { 481 checkTreeLock(); 482 483 GraphicsConfiguration thisGC = getGraphicsConfiguration(); 484 485 if (index > component.size() || index < 0) { 486 throw new IllegalArgumentException("illegal component position"); 487 } 488 if (comp.parent == this) { 489 if (index == component.size()) { 490 throw new IllegalArgumentException("illegal component position " + 491 index + " should be less then " + component.size()); 492 } 493 } 494 checkAddToSelf(comp); 495 checkNotAWindow(comp); 496 497 Window thisTopLevel = getContainingWindow(); 498 Window compTopLevel = comp.getContainingWindow(); 499 if (thisTopLevel != compTopLevel) { 500 throw new IllegalArgumentException("component and container should be in the same top-level window"); 501 } 502 if (thisGC != null) { 503 comp.checkGD(thisGC.getDevice().getIDstring()); 504 } 505 } 506 507 /** 508 * Removes component comp from this container without making unneccessary changes 509 * and generating unneccessary events. This function intended to perform optimized 510 * remove, for example, if newParent and current parent are the same it just changes 511 * index without calling removeNotify. 512 * Note: Should be called while holding treeLock 513 * Returns whether removeNotify was invoked 514 * @since: 1.5 515 */ 516 private boolean removeDelicately(Component comp, Container newParent, int newIndex) { 517 checkTreeLock(); 518 519 int index = getComponentZOrder(comp); 520 boolean needRemoveNotify = isRemoveNotifyNeeded(comp, this, newParent); 521 if (needRemoveNotify) { 522 comp.removeNotify(); 523 } 524 if (newParent != this) { 525 if (layoutMgr != null) { 526 layoutMgr.removeLayoutComponent(comp); 527 } 528 adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK, 529 -comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK)); 530 adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, 531 -comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK)); 532 adjustDescendants(-(comp.countHierarchyMembers())); 533 534 comp.parent = null; 535 if (needRemoveNotify) { 536 comp.setGraphicsConfiguration(null); 537 } 538 component.remove(index); 539 540 invalidateIfValid(); 541 } else { 542 // We should remove component and then 543 // add it by the newIndex without newIndex decrement if even we shift components to the left 544 // after remove. Consult the rules below: 545 // 2->4: 012345 -> 013425, 2->5: 012345 -> 013452 546 // 4->2: 012345 -> 014235 547 component.remove(index); 548 component.add(newIndex, comp); 549 } 550 if (comp.parent == null) { // was actually removed 551 if (containerListener != null || 552 (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 || 553 Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) { 554 ContainerEvent e = new ContainerEvent(this, 555 ContainerEvent.COMPONENT_REMOVED, 556 comp); 557 dispatchEvent(e); 558 559 } 560 comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp, 561 this, HierarchyEvent.PARENT_CHANGED, 562 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK)); 563 if (peer != null && layoutMgr == null && isVisible()) { 564 updateCursorImmediately(); 565 } 566 } 567 return needRemoveNotify; 568 } 569 570 /** 571 * Checks whether this container can contain component which is focus owner. 572 * Verifies that container is enable and showing, and if it is focus cycle root 573 * its FTP allows component to be focus owner 574 * @since 1.5 575 */ 576 boolean canContainFocusOwner(Component focusOwnerCandidate) { 577 if (!(isEnabled() && isDisplayable() 578 && isVisible() && isFocusable())) 579 { 580 return false; 581 } 582 if (isFocusCycleRoot()) { 583 FocusTraversalPolicy policy = getFocusTraversalPolicy(); 584 if (policy instanceof DefaultFocusTraversalPolicy) { 585 if (!((DefaultFocusTraversalPolicy)policy).accept(focusOwnerCandidate)) { 586 return false; 587 } 588 } 589 } 590 synchronized(getTreeLock()) { 591 if (parent != null) { 592 return parent.canContainFocusOwner(focusOwnerCandidate); 593 } 594 } 595 return true; 596 } 597 598 /** 599 * Checks whether or not this container has heavyweight children. 600 * Note: Should be called while holding tree lock 601 * @return true if there is at least one heavyweight children in a container, false otherwise 602 * @since 1.5 603 */ 604 final boolean hasHeavyweightDescendants() { 605 checkTreeLock(); 606 return numOfHWComponents > 0; 607 } 608 609 /** 610 * Checks whether or not this container has lightweight children. 611 * Note: Should be called while holding tree lock 612 * @return true if there is at least one lightweight children in a container, false otherwise 613 * @since 1.7 614 */ 615 final boolean hasLightweightDescendants() { 616 checkTreeLock(); 617 return numOfLWComponents > 0; 618 } 619 620 /** 621 * Returns closest heavyweight component to this container. If this container is heavyweight 622 * returns this. 623 * @since 1.5 624 */ 625 Container getHeavyweightContainer() { 626 checkTreeLock(); 627 if (peer != null && !(peer instanceof LightweightPeer)) { 628 return this; 629 } else { 630 return getNativeContainer(); 631 } 632 } 633 634 /** 635 * Detects whether or not remove from current parent and adding to new parent requires call of 636 * removeNotify on the component. Since removeNotify destroys native window this might (not) 637 * be required. For example, if new container and old containers are the same we don't need to 638 * destroy native window. 639 * @since: 1.5 640 */ 641 private static boolean isRemoveNotifyNeeded(Component comp, Container oldContainer, Container newContainer) { 642 if (oldContainer == null) { // Component didn't have parent - no removeNotify 643 return false; 644 } 645 if (comp.peer == null) { // Component didn't have peer - no removeNotify 646 return false; 647 } 648 if (newContainer.peer == null) { 649 // Component has peer but new Container doesn't - call removeNotify 650 return true; 651 } 652 653 // If component is lightweight non-Container or lightweight Container with all but heavyweight 654 // children there is no need to call remove notify 655 if (comp.isLightweight()) { 656 boolean isContainer = comp instanceof Container; 657 658 if (!isContainer || (isContainer && !((Container)comp).hasHeavyweightDescendants())) { 659 return false; 660 } 661 } 662 663 // If this point is reached, then the comp is either a HW or a LW container with HW descendants. 664 665 // All three components have peers, check for peer change 666 Container newNativeContainer = oldContainer.getHeavyweightContainer(); 667 Container oldNativeContainer = newContainer.getHeavyweightContainer(); 668 if (newNativeContainer != oldNativeContainer) { 669 // Native containers change - check whether or not current platform supports 670 // changing of widget hierarchy on native level without recreation. 671 // The current implementation forbids reparenting of LW containers with HW descendants 672 // into another native container w/o destroying the peers. Actually such an operation 673 // is quite rare. If we ever need to save the peers, we'll have to slightly change the 674 // addDelicately() method in order to handle such LW containers recursively, reparenting 675 // each HW descendant independently. 676 return !comp.peer.isReparentSupported(); 677 } else { 678 return false; 679 } 680 } 681 682 /** 683 * Moves the specified component to the specified z-order index in 684 * the container. The z-order determines the order that components 685 * are painted; the component with the highest z-order paints first 686 * and the component with the lowest z-order paints last. 687 * Where components overlap, the component with the lower 688 * z-order paints over the component with the higher z-order. 689 * <p> 690 * If the component is a child of some other container, it is 691 * removed from that container before being added to this container. 692 * The important difference between this method and 693 * <code>java.awt.Container.add(Component, int)</code> is that this method 694 * doesn't call <code>removeNotify</code> on the component while 695 * removing it from its previous container unless necessary and when 696 * allowed by the underlying native windowing system. This way, if the 697 * component has the keyboard focus, it maintains the focus when 698 * moved to the new position. 699 * <p> 700 * This property is guaranteed to apply only to lightweight 701 * non-<code>Container</code> components. 702 * <p> 703 * <b>Note</b>: Not all platforms support changing the z-order of 704 * heavyweight components from one container into another without 705 * the call to <code>removeNotify</code>. There is no way to detect 706 * whether a platform supports this, so developers shouldn't make 707 * any assumptions. 708 * 709 * @param comp the component to be moved 710 * @param index the position in the container's list to 711 * insert the component, where <code>getComponentCount()</code> 712 * appends to the end 713 * @exception NullPointerException if <code>comp</code> is 714 * <code>null</code> 715 * @exception IllegalArgumentException if <code>comp</code> is one of the 716 * container's parents 717 * @exception IllegalArgumentException if <code>index</code> is not in 718 * the range <code>[0, getComponentCount()]</code> for moving 719 * between containers, or not in the range 720 * <code>[0, getComponentCount()-1]</code> for moving inside 721 * a container 722 * @exception IllegalArgumentException if adding a container to itself 723 * @exception IllegalArgumentException if adding a <code>Window</code> 724 * to a container 725 * @see #getComponentZOrder(java.awt.Component) 726 * @since 1.5 727 */ 728 public void setComponentZOrder(Component comp, int index) { 729 synchronized (getTreeLock()) { 730 // Store parent because remove will clear it 731 Container curParent = comp.parent; 732 int oldZindex = getComponentZOrder(comp); 733 734 if (curParent == this && index == oldZindex) { 735 return; 736 } 737 checkAdding(comp, index); 738 739 boolean peerRecreated = (curParent != null) ? 740 curParent.removeDelicately(comp, this, index) : false; 741 742 addDelicately(comp, curParent, index); 743 744 // If the oldZindex == -1, the component gets inserted, 745 // rather than it changes its z-order. 746 if (!peerRecreated && oldZindex != -1) { 747 // The new 'index' cannot be == -1. 748 // It gets checked at the checkAdding() method. 749 // Therefore both oldZIndex and index denote 750 // some existing positions at this point and 751 // this is actually a Z-order changing. 752 comp.mixOnZOrderChanging(oldZindex, index); 753 } 754 } 755 } 756 757 /** 758 * Traverses the tree of components and reparents children heavyweight component 759 * to new heavyweight parent. 760 * @since 1.5 761 */ 762 private void reparentTraverse(ContainerPeer parentPeer, Container child) { 763 checkTreeLock(); 764 765 for (int i = 0; i < child.getComponentCount(); i++) { 766 Component comp = child.getComponent(i); 767 if (comp.isLightweight()) { 768 // If components is lightweight check if it is container 769 // If it is container it might contain heavyweight children we need to reparent 770 if (comp instanceof Container) { 771 reparentTraverse(parentPeer, (Container)comp); 772 } 773 } else { 774 // Q: Need to update NativeInLightFixer? 775 comp.getPeer().reparent(parentPeer); 776 } 777 } 778 } 779 780 /** 781 * Reparents child component peer to this container peer. 782 * Container must be heavyweight. 783 * @since 1.5 784 */ 785 private void reparentChild(Component comp) { 786 checkTreeLock(); 787 if (comp == null) { 788 return; 789 } 790 if (comp.isLightweight()) { 791 // If component is lightweight container we need to reparent all its explicit heavyweight children 792 if (comp instanceof Container) { 793 // Traverse component's tree till depth-first until encountering heavyweight component 794 reparentTraverse((ContainerPeer)getPeer(), (Container)comp); 795 } 796 } else { 797 comp.getPeer().reparent((ContainerPeer)getPeer()); 798 } 799 } 800 801 /** 802 * Adds component to this container. Tries to minimize side effects of this adding - 803 * doesn't call remove notify if it is not required. 804 * @since 1.5 805 */ 806 private void addDelicately(Component comp, Container curParent, int index) { 807 checkTreeLock(); 808 809 // Check if moving between containers 810 if (curParent != this) { 811 //index == -1 means add to the end. 812 if (index == -1) { 813 component.add(comp); 814 } else { 815 component.add(index, comp); 816 } 817 comp.parent = this; 818 comp.setGraphicsConfiguration(getGraphicsConfiguration()); 819 820 adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK, 821 comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK)); 822 adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, 823 comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK)); 824 adjustDescendants(comp.countHierarchyMembers()); 825 } else { 826 if (index < component.size()) { 827 component.set(index, comp); 828 } 829 } 830 831 invalidateIfValid(); 832 if (peer != null) { 833 if (comp.peer == null) { // Remove notify was called or it didn't have peer - create new one 834 comp.addNotify(); 835 } else { // Both container and child have peers, it means child peer should be reparented. 836 // In both cases we need to reparent native widgets. 837 Container newNativeContainer = getHeavyweightContainer(); 838 Container oldNativeContainer = curParent.getHeavyweightContainer(); 839 if (oldNativeContainer != newNativeContainer) { 840 // Native container changed - need to reparent native widgets 841 newNativeContainer.reparentChild(comp); 842 } 843 comp.updateZOrder(); 844 845 if (!comp.isLightweight() && isLightweight()) { 846 // If component is heavyweight and one of the containers is lightweight 847 // the location of the component should be fixed. 848 comp.relocateComponent(); 849 } 850 } 851 } 852 if (curParent != this) { 853 /* Notify the layout manager of the added component. */ 854 if (layoutMgr != null) { 855 if (layoutMgr instanceof LayoutManager2) { 856 ((LayoutManager2)layoutMgr).addLayoutComponent(comp, null); 857 } else { 858 layoutMgr.addLayoutComponent(null, comp); 859 } 860 } 861 if (containerListener != null || 862 (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 || 863 Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) { 864 ContainerEvent e = new ContainerEvent(this, 865 ContainerEvent.COMPONENT_ADDED, 866 comp); 867 dispatchEvent(e); 868 } 869 comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp, 870 this, HierarchyEvent.PARENT_CHANGED, 871 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK)); 872 873 // If component is focus owner or parent container of focus owner check that after reparenting 874 // focus owner moved out if new container prohibit this kind of focus owner. 875 if (comp.isFocusOwner() && !comp.canBeFocusOwnerRecursively()) { 876 comp.transferFocus(); 877 } else if (comp instanceof Container) { 878 Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); 879 if (focusOwner != null && isParentOf(focusOwner) && !focusOwner.canBeFocusOwnerRecursively()) { 880 focusOwner.transferFocus(); 881 } 882 } 883 } else { 884 comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp, 885 this, HierarchyEvent.HIERARCHY_CHANGED, 886 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK)); 887 } 888 889 if (peer != null && layoutMgr == null && isVisible()) { 890 updateCursorImmediately(); 891 } 892 } 893 894 /** 895 * Returns the z-order index of the component inside the container. 896 * The higher a component is in the z-order hierarchy, the lower 897 * its index. The component with the lowest z-order index is 898 * painted last, above all other child components. 899 * 900 * @param comp the component being queried 901 * @return the z-order index of the component; otherwise 902 * returns -1 if the component is <code>null</code> 903 * or doesn't belong to the container 904 * @see #setComponentZOrder(java.awt.Component, int) 905 * @since 1.5 906 */ 907 public int getComponentZOrder(Component comp) { 908 if (comp == null) { 909 return -1; 910 } 911 synchronized(getTreeLock()) { 912 // Quick check - container should be immediate parent of the component 913 if (comp.parent != this) { 914 return -1; 915 } 916 return component.indexOf(comp); 917 } 918 } 919 920 /** 921 * Adds the specified component to the end of this container. 922 * Also notifies the layout manager to add the component to 923 * this container's layout using the specified constraints object. 924 * This is a convenience method for {@link #addImpl}. 925 * <p> 926 * Note: If a component has been added to a container that 927 * has been displayed, <code>validate</code> must be 928 * called on that container to display the new component. 929 * If multiple components are being added, you can improve 930 * efficiency by calling <code>validate</code> only once, 931 * after all the components have been added. 932 * 933 * @param comp the component to be added 934 * @param constraints an object expressing 935 * layout contraints for this component 936 * @exception NullPointerException if {@code comp} is {@code null} 937 * @see #addImpl 938 * @see #validate 939 * @see javax.swing.JComponent#revalidate() 940 * @see LayoutManager 941 * @since JDK1.1 942 */ 943 public void add(Component comp, Object constraints) { 944 addImpl(comp, constraints, -1); 945 } 946 947 /** 948 * Adds the specified component to this container with the specified 949 * constraints at the specified index. Also notifies the layout 950 * manager to add the component to the this container's layout using 951 * the specified constraints object. 952 * This is a convenience method for {@link #addImpl}. 953 * <p> 954 * Note: If a component has been added to a container that 955 * has been displayed, <code>validate</code> must be 956 * called on that container to display the new component. 957 * If multiple components are being added, you can improve 958 * efficiency by calling <code>validate</code> only once, 959 * after all the components have been added. 960 * 961 * @param comp the component to be added 962 * @param constraints an object expressing layout contraints for this 963 * @param index the position in the container's list at which to insert 964 * the component; <code>-1</code> means insert at the end 965 * component 966 * @exception NullPointerException if {@code comp} is {@code null} 967 * @exception IllegalArgumentException if {@code index} is invalid (see 968 * {@link #addImpl} for details) 969 * @see #addImpl 970 * @see #validate 971 * @see javax.swing.JComponent#revalidate() 972 * @see #remove 973 * @see LayoutManager 974 */ 975 public void add(Component comp, Object constraints, int index) { 976 addImpl(comp, constraints, index); 977 } 978 979 /** 980 * Adds the specified component to this container at the specified 981 * index. This method also notifies the layout manager to add 982 * the component to this container's layout using the specified 983 * constraints object via the <code>addLayoutComponent</code> 984 * method. 985 * <p> 986 * The constraints are 987 * defined by the particular layout manager being used. For 988 * example, the <code>BorderLayout</code> class defines five 989 * constraints: <code>BorderLayout.NORTH</code>, 990 * <code>BorderLayout.SOUTH</code>, <code>BorderLayout.EAST</code>, 991 * <code>BorderLayout.WEST</code>, and <code>BorderLayout.CENTER</code>. 992 * <p> 993 * The <code>GridBagLayout</code> class requires a 994 * <code>GridBagConstraints</code> object. Failure to pass 995 * the correct type of constraints object results in an 996 * <code>IllegalArgumentException</code>. 997 * <p> 998 * If the current layout manager implements {@code LayoutManager2}, then 999 * {@link LayoutManager2#addLayoutComponent(Component,Object)} is invoked on 1000 * it. If the current layout manager does not implement 1001 * {@code LayoutManager2}, and constraints is a {@code String}, then 1002 * {@link LayoutManager#addLayoutComponent(String,Component)} is invoked on it. 1003 * <p> 1004 * If the component is not an ancestor of this container and has a non-null 1005 * parent, it is removed from its current parent before it is added to this 1006 * container. 1007 * <p> 1008 * This is the method to override if a program needs to track 1009 * every add request to a container as all other add methods defer 1010 * to this one. An overriding method should 1011 * usually include a call to the superclass's version of the method: 1012 * <p> 1013 * <blockquote> 1014 * <code>super.addImpl(comp, constraints, index)</code> 1015 * </blockquote> 1016 * <p> 1017 * @param comp the component to be added 1018 * @param constraints an object expressing layout constraints 1019 * for this component 1020 * @param index the position in the container's list at which to 1021 * insert the component, where <code>-1</code> 1022 * means append to the end 1023 * @exception IllegalArgumentException if {@code index} is invalid; 1024 * if {@code comp} is a child of this container, the valid 1025 * range is {@code [-1, getComponentCount()-1]}; if component is 1026 * not a child of this container, the valid range is 1027 * {@code [-1, getComponentCount()]} 1028 * 1029 * @exception IllegalArgumentException if {@code comp} is an ancestor of 1030 * this container 1031 * @exception IllegalArgumentException if adding a window to a container 1032 * @exception NullPointerException if {@code comp} is {@code null} 1033 * @see #add(Component) 1034 * @see #add(Component, int) 1035 * @see #add(Component, java.lang.Object) 1036 * @see LayoutManager 1037 * @see LayoutManager2 1038 * @since JDK1.1 1039 */ 1040 protected void addImpl(Component comp, Object constraints, int index) { 1041 synchronized (getTreeLock()) { 1042 /* Check for correct arguments: index in bounds, 1043 * comp cannot be one of this container's parents, 1044 * and comp cannot be a window. 1045 * comp and container must be on the same GraphicsDevice. 1046 * if comp is container, all sub-components must be on 1047 * same GraphicsDevice. 1048 */ 1049 GraphicsConfiguration thisGC = this.getGraphicsConfiguration(); 1050 1051 if (index > component.size() || (index < 0 && index != -1)) { 1052 throw new IllegalArgumentException( 1053 "illegal component position"); 1054 } 1055 checkAddToSelf(comp); 1056 checkNotAWindow(comp); 1057 if (thisGC != null) { 1058 comp.checkGD(thisGC.getDevice().getIDstring()); 1059 } 1060 1061 /* Reparent the component and tidy up the tree's state. */ 1062 if (comp.parent != null) { 1063 comp.parent.remove(comp); 1064 if (index > component.size()) { 1065 throw new IllegalArgumentException("illegal component position"); 1066 } 1067 } 1068 1069 //index == -1 means add to the end. 1070 if (index == -1) { 1071 component.add(comp); 1072 } else { 1073 component.add(index, comp); 1074 } 1075 comp.parent = this; 1076 comp.setGraphicsConfiguration(thisGC); 1077 1078 adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK, 1079 comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK)); 1080 adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, 1081 comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK)); 1082 adjustDescendants(comp.countHierarchyMembers()); 1083 1084 invalidateIfValid(); 1085 if (peer != null) { 1086 comp.addNotify(); 1087 } 1088 1089 /* Notify the layout manager of the added component. */ 1090 if (layoutMgr != null) { 1091 if (layoutMgr instanceof LayoutManager2) { 1092 ((LayoutManager2)layoutMgr).addLayoutComponent(comp, constraints); 1093 } else if (constraints instanceof String) { 1094 layoutMgr.addLayoutComponent((String)constraints, comp); 1095 } 1096 } 1097 if (containerListener != null || 1098 (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 || 1099 Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) { 1100 ContainerEvent e = new ContainerEvent(this, 1101 ContainerEvent.COMPONENT_ADDED, 1102 comp); 1103 dispatchEvent(e); 1104 } 1105 1106 comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp, 1107 this, HierarchyEvent.PARENT_CHANGED, 1108 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK)); 1109 if (peer != null && layoutMgr == null && isVisible()) { 1110 updateCursorImmediately(); 1111 } 1112 } 1113 } 1114 1115 @Override 1116 boolean updateGraphicsData(GraphicsConfiguration gc) { 1117 checkTreeLock(); 1118 1119 boolean ret = super.updateGraphicsData(gc); 1120 1121 for (Component comp : component) { 1122 if (comp != null) { 1123 ret |= comp.updateGraphicsData(gc); 1124 } 1125 } 1126 return ret; 1127 } 1128 1129 /** 1130 * Checks that all Components that this Container contains are on 1131 * the same GraphicsDevice as this Container. If not, throws an 1132 * IllegalArgumentException. 1133 */ 1134 void checkGD(String stringID) { 1135 for (Component comp : component) { 1136 if (comp != null) { 1137 comp.checkGD(stringID); 1138 } 1139 } 1140 } 1141 1142 /** 1143 * Removes the component, specified by <code>index</code>, 1144 * from this container. 1145 * This method also notifies the layout manager to remove the 1146 * component from this container's layout via the 1147 * <code>removeLayoutComponent</code> method. 1148 * 1149 * <p> 1150 * Note: If a component has been removed from a container that 1151 * had been displayed, {@link #validate} must be 1152 * called on that container to reflect changes. 1153 * If multiple components are being removed, you can improve 1154 * efficiency by calling {@link #validate} only once, 1155 * after all the components have been removed. 1156 * 1157 * @param index the index of the component to be removed 1158 * @throws ArrayIndexOutOfBoundsException if {@code index} is not in 1159 * range {@code [0, getComponentCount()-1]} 1160 * @see #add 1161 * @see #validate 1162 * @see #getComponentCount 1163 * @since JDK1.1 1164 */ 1165 public void remove(int index) { 1166 synchronized (getTreeLock()) { 1167 if (index < 0 || index >= component.size()) { 1168 throw new ArrayIndexOutOfBoundsException(index); 1169 } 1170 Component comp = component.get(index); 1171 if (peer != null) { 1172 comp.removeNotify(); 1173 } 1174 if (layoutMgr != null) { 1175 layoutMgr.removeLayoutComponent(comp); 1176 } 1177 1178 adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK, 1179 -comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK)); 1180 adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, 1181 -comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK)); 1182 adjustDescendants(-(comp.countHierarchyMembers())); 1183 1184 comp.parent = null; 1185 component.remove(index); 1186 comp.setGraphicsConfiguration(null); 1187 1188 invalidateIfValid(); 1189 if (containerListener != null || 1190 (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 || 1191 Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) { 1192 ContainerEvent e = new ContainerEvent(this, 1193 ContainerEvent.COMPONENT_REMOVED, 1194 comp); 1195 dispatchEvent(e); 1196 } 1197 1198 comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp, 1199 this, HierarchyEvent.PARENT_CHANGED, 1200 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK)); 1201 if (peer != null && layoutMgr == null && isVisible()) { 1202 updateCursorImmediately(); 1203 } 1204 } 1205 } 1206 1207 /** 1208 * Removes the specified component from this container. 1209 * This method also notifies the layout manager to remove the 1210 * component from this container's layout via the 1211 * <code>removeLayoutComponent</code> method. 1212 * 1213 * <p> 1214 * Note: If a component has been removed from a container that 1215 * had been displayed, {@link #validate} must be 1216 * called on that container to reflect changes. 1217 * If multiple components are being removed, you can improve 1218 * efficiency by calling {@link #validate} only once, 1219 * after all the components have been removed. 1220 * 1221 * @param comp the component to be removed 1222 * @see #add 1223 * @see #validate 1224 * @see #remove(int) 1225 */ 1226 public void remove(Component comp) { 1227 synchronized (getTreeLock()) { 1228 if (comp.parent == this) { 1229 int index = component.indexOf(comp); 1230 if (index >= 0) { 1231 remove(index); 1232 } 1233 } 1234 } 1235 } 1236 1237 /** 1238 * Removes all the components from this container. 1239 * This method also notifies the layout manager to remove the 1240 * components from this container's layout via the 1241 * <code>removeLayoutComponent</code> method. 1242 * @see #add 1243 * @see #remove 1244 */ 1245 public void removeAll() { 1246 synchronized (getTreeLock()) { 1247 adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK, 1248 -listeningChildren); 1249 adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, 1250 -listeningBoundsChildren); 1251 adjustDescendants(-descendantsCount); 1252 1253 while (!component.isEmpty()) { 1254 Component comp = component.remove(component.size()-1); 1255 1256 if (peer != null) { 1257 comp.removeNotify(); 1258 } 1259 if (layoutMgr != null) { 1260 layoutMgr.removeLayoutComponent(comp); 1261 } 1262 comp.parent = null; 1263 comp.setGraphicsConfiguration(null); 1264 if (containerListener != null || 1265 (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 || 1266 Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) { 1267 ContainerEvent e = new ContainerEvent(this, 1268 ContainerEvent.COMPONENT_REMOVED, 1269 comp); 1270 dispatchEvent(e); 1271 } 1272 1273 comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, 1274 comp, this, 1275 HierarchyEvent.PARENT_CHANGED, 1276 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK)); 1277 } 1278 if (peer != null && layoutMgr == null && isVisible()) { 1279 updateCursorImmediately(); 1280 } 1281 invalidateIfValid(); 1282 } 1283 } 1284 1285 // Should only be called while holding tree lock 1286 int numListening(long mask) { 1287 int superListening = super.numListening(mask); 1288 1289 if (mask == AWTEvent.HIERARCHY_EVENT_MASK) { 1290 if (eventLog.isLoggable(Level.FINE)) { 1291 // Verify listeningChildren is correct 1292 int sum = 0; 1293 for (Component comp : component) { 1294 sum += comp.numListening(mask); 1295 } 1296 if (listeningChildren != sum) { 1297 eventLog.log(Level.FINE, "Assertion (listeningChildren == sum) failed"); 1298 } 1299 } 1300 return listeningChildren + superListening; 1301 } else if (mask == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) { 1302 if (eventLog.isLoggable(Level.FINE)) { 1303 // Verify listeningBoundsChildren is correct 1304 int sum = 0; 1305 for (Component comp : component) { 1306 sum += comp.numListening(mask); 1307 } 1308 if (listeningBoundsChildren != sum) { 1309 eventLog.log(Level.FINE, "Assertion (listeningBoundsChildren == sum) failed"); 1310 } 1311 } 1312 return listeningBoundsChildren + superListening; 1313 } else { 1314 // assert false; 1315 if (eventLog.isLoggable(Level.FINE)) { 1316 eventLog.log(Level.FINE, "This code must never be reached"); 1317 } 1318 return superListening; 1319 } 1320 } 1321 1322 // Should only be called while holding tree lock 1323 void adjustListeningChildren(long mask, int num) { 1324 if (eventLog.isLoggable(Level.FINE)) { 1325 boolean toAssert = (mask == AWTEvent.HIERARCHY_EVENT_MASK || 1326 mask == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK || 1327 mask == (AWTEvent.HIERARCHY_EVENT_MASK | 1328 AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK)); 1329 if (!toAssert) { 1330 eventLog.log(Level.FINE, "Assertion failed"); 1331 } 1332 } 1333 1334 if (num == 0) 1335 return; 1336 1337 if ((mask & AWTEvent.HIERARCHY_EVENT_MASK) != 0) { 1338 listeningChildren += num; 1339 } 1340 if ((mask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0) { 1341 listeningBoundsChildren += num; 1342 } 1343 1344 adjustListeningChildrenOnParent(mask, num); 1345 } 1346 1347 // Should only be called while holding tree lock 1348 void adjustDescendants(int num) { 1349 if (num == 0) 1350 return; 1351 1352 descendantsCount += num; 1353 adjustDecendantsOnParent(num); 1354 } 1355 1356 // Should only be called while holding tree lock 1357 void adjustDecendantsOnParent(int num) { 1358 if (parent != null) { 1359 parent.adjustDescendants(num); 1360 } 1361 } 1362 1363 // Should only be called while holding tree lock 1364 int countHierarchyMembers() { 1365 if (log.isLoggable(Level.FINE)) { 1366 // Verify descendantsCount is correct 1367 int sum = 0; 1368 for (Component comp : component) { 1369 sum += comp.countHierarchyMembers(); 1370 } 1371 if (descendantsCount != sum) { 1372 log.log(Level.FINE, "Assertion (descendantsCount == sum) failed"); 1373 } 1374 } 1375 return descendantsCount + 1; 1376 } 1377 1378 private int getListenersCount(int id, boolean enabledOnToolkit) { 1379 checkTreeLock(); 1380 if (enabledOnToolkit) { 1381 return descendantsCount; 1382 } 1383 switch (id) { 1384 case HierarchyEvent.HIERARCHY_CHANGED: 1385 return listeningChildren; 1386 case HierarchyEvent.ANCESTOR_MOVED: 1387 case HierarchyEvent.ANCESTOR_RESIZED: 1388 return listeningBoundsChildren; 1389 default: 1390 return 0; 1391 } 1392 } 1393 1394 final int createHierarchyEvents(int id, Component changed, 1395 Container changedParent, long changeFlags, boolean enabledOnToolkit) 1396 { 1397 checkTreeLock(); 1398 int listeners = getListenersCount(id, enabledOnToolkit); 1399 1400 for (int count = listeners, i = 0; count > 0; i++) { 1401 count -= component.get(i).createHierarchyEvents(id, changed, 1402 changedParent, changeFlags, enabledOnToolkit); 1403 } 1404 return listeners + 1405 super.createHierarchyEvents(id, changed, changedParent, 1406 changeFlags, enabledOnToolkit); 1407 } 1408 1409 final void createChildHierarchyEvents(int id, long changeFlags, 1410 boolean enabledOnToolkit) 1411 { 1412 checkTreeLock(); 1413 if (component.isEmpty()) { 1414 return; 1415 } 1416 int listeners = getListenersCount(id, enabledOnToolkit); 1417 1418 for (int count = listeners, i = 0; count > 0; i++) { 1419 count -= component.get(i).createHierarchyEvents(id, this, parent, 1420 changeFlags, enabledOnToolkit); 1421 } 1422 } 1423 1424 /** 1425 * Gets the layout manager for this container. 1426 * @see #doLayout 1427 * @see #setLayout 1428 */ 1429 public LayoutManager getLayout() { 1430 return layoutMgr; 1431 } 1432 1433 /** 1434 * Sets the layout manager for this container. 1435 * @param mgr the specified layout manager 1436 * @see #doLayout 1437 * @see #getLayout 1438 */ 1439 public void setLayout(LayoutManager mgr) { 1440 layoutMgr = mgr; 1441 invalidateIfValid(); 1442 } 1443 1444 /** 1445 * Causes this container to lay out its components. Most programs 1446 * should not call this method directly, but should invoke 1447 * the <code>validate</code> method instead. 1448 * @see LayoutManager#layoutContainer 1449 * @see #setLayout 1450 * @see #validate 1451 * @since JDK1.1 1452 */ 1453 public void doLayout() { 1454 layout(); 1455 } 1456 1457 /** 1458 * @deprecated As of JDK version 1.1, 1459 * replaced by <code>doLayout()</code>. 1460 */ 1461 @Deprecated 1462 public void layout() { 1463 LayoutManager layoutMgr = this.layoutMgr; 1464 if (layoutMgr != null) { 1465 layoutMgr.layoutContainer(this); 1466 } 1467 } 1468 1469 /** 1470 * Invalidates the container. The container and all parents 1471 * above it are marked as needing to be laid out. This method can 1472 * be called often, so it needs to execute quickly. 1473 * 1474 * <p> If the {@code LayoutManager} installed on this container is 1475 * an instance of {@code LayoutManager2}, then 1476 * {@link LayoutManager2#invalidateLayout(Container)} is invoked on 1477 * it supplying this {@code Container} as the argument. 1478 * 1479 * @see #validate 1480 * @see #layout 1481 * @see LayoutManager 1482 * @see LayoutManager2#invalidateLayout(Container) 1483 */ 1484 public void invalidate() { 1485 LayoutManager layoutMgr = this.layoutMgr; 1486 if (layoutMgr instanceof LayoutManager2) { 1487 LayoutManager2 lm = (LayoutManager2) layoutMgr; 1488 lm.invalidateLayout(this); 1489 } 1490 super.invalidate(); 1491 } 1492 1493 /** 1494 * Validates this container and all of its subcomponents. 1495 * <p> 1496 * The <code>validate</code> method is used to cause a container 1497 * to lay out its subcomponents again. It should be invoked when 1498 * this container's subcomponents are modified (added to or 1499 * removed from the container, or layout-related information 1500 * changed) after the container has been displayed. 1501 * 1502 * <p>If this {@code Container} is not valid, this method invokes 1503 * the {@code validateTree} method and marks this {@code Container} 1504 * as valid. Otherwise, no action is performed. 1505 * 1506 * @see #add(java.awt.Component) 1507 * @see Component#invalidate 1508 * @see javax.swing.JComponent#revalidate() 1509 * @see #validateTree 1510 */ 1511 public void validate() { 1512 /* Avoid grabbing lock unless really necessary. */ 1513 if (!isValid()) { 1514 boolean updateCur = false; 1515 synchronized (getTreeLock()) { 1516 if (!isValid() && peer != null) { 1517 ContainerPeer p = null; 1518 if (peer instanceof ContainerPeer) { 1519 p = (ContainerPeer) peer; 1520 } 1521 if (p != null) { 1522 p.beginValidate(); 1523 } 1524 validateTree(); 1525 if (p != null) { 1526 p.endValidate(); 1527 updateCur = isVisible(); 1528 } 1529 } 1530 } 1531 if (updateCur) { 1532 updateCursorImmediately(); 1533 } 1534 } 1535 } 1536 1537 /** 1538 * Recursively descends the container tree and recomputes the 1539 * layout for any subtrees marked as needing it (those marked as 1540 * invalid). Synchronization should be provided by the method 1541 * that calls this one: <code>validate</code>. 1542 * 1543 * @see #doLayout 1544 * @see #validate 1545 */ 1546 protected void validateTree() { 1547 checkTreeLock(); 1548 if (!isValid()) { 1549 if (peer instanceof ContainerPeer) { 1550 ((ContainerPeer)peer).beginLayout(); 1551 } 1552 doLayout(); 1553 for (int i = 0; i < component.size(); i++) { 1554 Component comp = component.get(i); 1555 if ( (comp instanceof Container) 1556 && !(comp instanceof Window) 1557 && !comp.isValid()) { 1558 ((Container)comp).validateTree(); 1559 } else { 1560 comp.validate(); 1561 } 1562 } 1563 if (peer instanceof ContainerPeer) { 1564 ((ContainerPeer)peer).endLayout(); 1565 } 1566 } 1567 super.validate(); 1568 } 1569 1570 /** 1571 * Recursively descends the container tree and invalidates all 1572 * contained components. 1573 */ 1574 void invalidateTree() { 1575 synchronized (getTreeLock()) { 1576 for (int i = 0; i < component.size(); i++) { 1577 Component comp = component.get(i); 1578 if (comp instanceof Container) { 1579 ((Container)comp).invalidateTree(); 1580 } 1581 else { 1582 comp.invalidateIfValid(); 1583 } 1584 } 1585 invalidateIfValid(); 1586 } 1587 } 1588 1589 /** 1590 * Sets the font of this container. 1591 * @param f The font to become this container's font. 1592 * @see Component#getFont 1593 * @since JDK1.0 1594 */ 1595 public void setFont(Font f) { 1596 boolean shouldinvalidate = false; 1597 1598 Font oldfont = getFont(); 1599 super.setFont(f); 1600 Font newfont = getFont(); 1601 if (newfont != oldfont && (oldfont == null || 1602 !oldfont.equals(newfont))) { 1603 invalidateTree(); 1604 } 1605 } 1606 1607 /** 1608 * Returns the preferred size of this container. If the preferred size has 1609 * not been set explicitly by {@link Component#setPreferredSize(Dimension)} 1610 * and this {@code Container} has a {@code non-null} {@link LayoutManager}, 1611 * then {@link LayoutManager#preferredLayoutSize(Container)} 1612 * is used to calculate the preferred size. 1613 * 1614 * <p>Note: some implementations may cache the value returned from the 1615 * {@code LayoutManager}. Implementations that cache need not invoke 1616 * {@code preferredLayoutSize} on the {@code LayoutManager} every time 1617 * this method is invoked, rather the {@code LayoutManager} will only 1618 * be queried after the {@code Container} becomes invalid. 1619 * 1620 * @return an instance of <code>Dimension</code> that represents 1621 * the preferred size of this container. 1622 * @see #getMinimumSize 1623 * @see #getMaximumSize 1624 * @see #getLayout 1625 * @see LayoutManager#preferredLayoutSize(Container) 1626 * @see Component#getPreferredSize 1627 */ 1628 public Dimension getPreferredSize() { 1629 return preferredSize(); 1630 } 1631 1632 /** 1633 * @deprecated As of JDK version 1.1, 1634 * replaced by <code>getPreferredSize()</code>. 1635 */ 1636 @Deprecated 1637 public Dimension preferredSize() { 1638 /* Avoid grabbing the lock if a reasonable cached size value 1639 * is available. 1640 */ 1641 Dimension dim = prefSize; 1642 if (dim == null || !(isPreferredSizeSet() || isValid())) { 1643 synchronized (getTreeLock()) { 1644 prefSize = (layoutMgr != null) ? 1645 layoutMgr.preferredLayoutSize(this) : 1646 super.preferredSize(); 1647 dim = prefSize; 1648 } 1649 } 1650 if (dim != null){ 1651 return new Dimension(dim); 1652 } 1653 else{ 1654 return dim; 1655 } 1656 } 1657 1658 /** 1659 * Returns the minimum size of this container. If the minimum size has 1660 * not been set explicitly by {@link Component#setMinimumSize(Dimension)} 1661 * and this {@code Container} has a {@code non-null} {@link LayoutManager}, 1662 * then {@link LayoutManager#minimumLayoutSize(Container)} 1663 * is used to calculate the minimum size. 1664 * 1665 * <p>Note: some implementations may cache the value returned from the 1666 * {@code LayoutManager}. Implementations that cache need not invoke 1667 * {@code minimumLayoutSize} on the {@code LayoutManager} every time 1668 * this method is invoked, rather the {@code LayoutManager} will only 1669 * be queried after the {@code Container} becomes invalid. 1670 * 1671 * @return an instance of <code>Dimension</code> that represents 1672 * the minimum size of this container. 1673 * @see #getPreferredSize 1674 * @see #getMaximumSize 1675 * @see #getLayout 1676 * @see LayoutManager#minimumLayoutSize(Container) 1677 * @see Component#getMinimumSize 1678 * @since JDK1.1 1679 */ 1680 public Dimension getMinimumSize() { 1681 return minimumSize(); 1682 } 1683 1684 /** 1685 * @deprecated As of JDK version 1.1, 1686 * replaced by <code>getMinimumSize()</code>. 1687 */ 1688 @Deprecated 1689 public Dimension minimumSize() { 1690 /* Avoid grabbing the lock if a reasonable cached size value 1691 * is available. 1692 */ 1693 Dimension dim = minSize; 1694 if (dim == null || !(isMinimumSizeSet() || isValid())) { 1695 synchronized (getTreeLock()) { 1696 minSize = (layoutMgr != null) ? 1697 layoutMgr.minimumLayoutSize(this) : 1698 super.minimumSize(); 1699 dim = minSize; 1700 } 1701 } 1702 if (dim != null){ 1703 return new Dimension(dim); 1704 } 1705 else{ 1706 return dim; 1707 } 1708 } 1709 1710 /** 1711 * Returns the maximum size of this container. If the maximum size has 1712 * not been set explicitly by {@link Component#setMaximumSize(Dimension)} 1713 * and the {@link LayoutManager} installed on this {@code Container} 1714 * is an instance of {@link LayoutManager2}, then 1715 * {@link LayoutManager2#maximumLayoutSize(Container)} 1716 * is used to calculate the maximum size. 1717 * 1718 * <p>Note: some implementations may cache the value returned from the 1719 * {@code LayoutManager2}. Implementations that cache need not invoke 1720 * {@code maximumLayoutSize} on the {@code LayoutManager2} every time 1721 * this method is invoked, rather the {@code LayoutManager2} will only 1722 * be queried after the {@code Container} becomes invalid. 1723 * 1724 * @return an instance of <code>Dimension</code> that represents 1725 * the maximum size of this container. 1726 * @see #getPreferredSize 1727 * @see #getMinimumSize 1728 * @see #getLayout 1729 * @see LayoutManager2#maximumLayoutSize(Container) 1730 * @see Component#getMaximumSize 1731 */ 1732 public Dimension getMaximumSize() { 1733 /* Avoid grabbing the lock if a reasonable cached size value 1734 * is available. 1735 */ 1736 Dimension dim = maxSize; 1737 if (dim == null || !(isMaximumSizeSet() || isValid())) { 1738 synchronized (getTreeLock()) { 1739 if (layoutMgr instanceof LayoutManager2) { 1740 LayoutManager2 lm = (LayoutManager2) layoutMgr; 1741 maxSize = lm.maximumLayoutSize(this); 1742 } else { 1743 maxSize = super.getMaximumSize(); 1744 } 1745 dim = maxSize; 1746 } 1747 } 1748 if (dim != null){ 1749 return new Dimension(dim); 1750 } 1751 else{ 1752 return dim; 1753 } 1754 } 1755 1756 /** 1757 * Returns the alignment along the x axis. This specifies how 1758 * the component would like to be aligned relative to other 1759 * components. The value should be a number between 0 and 1 1760 * where 0 represents alignment along the origin, 1 is aligned 1761 * the furthest away from the origin, 0.5 is centered, etc. 1762 */ 1763 public float getAlignmentX() { 1764 float xAlign; 1765 if (layoutMgr instanceof LayoutManager2) { 1766 synchronized (getTreeLock()) { 1767 LayoutManager2 lm = (LayoutManager2) layoutMgr; 1768 xAlign = lm.getLayoutAlignmentX(this); 1769 } 1770 } else { 1771 xAlign = super.getAlignmentX(); 1772 } 1773 return xAlign; 1774 } 1775 1776 /** 1777 * Returns the alignment along the y axis. This specifies how 1778 * the component would like to be aligned relative to other 1779 * components. The value should be a number between 0 and 1 1780 * where 0 represents alignment along the origin, 1 is aligned 1781 * the furthest away from the origin, 0.5 is centered, etc. 1782 */ 1783 public float getAlignmentY() { 1784 float yAlign; 1785 if (layoutMgr instanceof LayoutManager2) { 1786 synchronized (getTreeLock()) { 1787 LayoutManager2 lm = (LayoutManager2) layoutMgr; 1788 yAlign = lm.getLayoutAlignmentY(this); 1789 } 1790 } else { 1791 yAlign = super.getAlignmentY(); 1792 } 1793 return yAlign; 1794 } 1795 1796 /** 1797 * Paints the container. This forwards the paint to any lightweight 1798 * components that are children of this container. If this method is 1799 * reimplemented, super.paint(g) should be called so that lightweight 1800 * components are properly rendered. If a child component is entirely 1801 * clipped by the current clipping setting in g, paint() will not be 1802 * forwarded to that child. 1803 * 1804 * @param g the specified Graphics window 1805 * @see Component#update(Graphics) 1806 */ 1807 public void paint(Graphics g) { 1808 if (isShowing()) { 1809 synchronized (this) { 1810 if (printing) { 1811 if (printingThreads.contains(Thread.currentThread())) { 1812 return; 1813 } 1814 } 1815 } 1816 1817 // The container is showing on screen and 1818 // this paint() is not called from print(). 1819 // Paint self and forward the paint to lightweight subcomponents. 1820 1821 // super.paint(); -- Don't bother, since it's a NOP. 1822 1823 GraphicsCallback.PaintCallback.getInstance(). 1824 runComponents(getComponentsSync(), g, GraphicsCallback.LIGHTWEIGHTS); 1825 } 1826 } 1827 1828 /** 1829 * Updates the container. This forwards the update to any lightweight 1830 * components that are children of this container. If this method is 1831 * reimplemented, super.update(g) should be called so that lightweight 1832 * components are properly rendered. If a child component is entirely 1833 * clipped by the current clipping setting in g, update() will not be 1834 * forwarded to that child. 1835 * 1836 * @param g the specified Graphics window 1837 * @see Component#update(Graphics) 1838 */ 1839 public void update(Graphics g) { 1840 if (isShowing()) { 1841 if (! (peer instanceof LightweightPeer)) { 1842 g.clearRect(0, 0, width, height); 1843 } 1844 paint(g); 1845 } 1846 } 1847 1848 /** 1849 * Prints the container. This forwards the print to any lightweight 1850 * components that are children of this container. If this method is 1851 * reimplemented, super.print(g) should be called so that lightweight 1852 * components are properly rendered. If a child component is entirely 1853 * clipped by the current clipping setting in g, print() will not be 1854 * forwarded to that child. 1855 * 1856 * @param g the specified Graphics window 1857 * @see Component#update(Graphics) 1858 */ 1859 public void print(Graphics g) { 1860 if (isShowing()) { 1861 Thread t = Thread.currentThread(); 1862 try { 1863 synchronized (this) { 1864 if (printingThreads == null) { 1865 printingThreads = new HashSet(); 1866 } 1867 printingThreads.add(t); 1868 printing = true; 1869 } 1870 super.print(g); // By default, Component.print() calls paint() 1871 } finally { 1872 synchronized (this) { 1873 printingThreads.remove(t); 1874 printing = !printingThreads.isEmpty(); 1875 } 1876 } 1877 1878 GraphicsCallback.PrintCallback.getInstance(). 1879 runComponents(getComponentsSync(), g, GraphicsCallback.LIGHTWEIGHTS); 1880 } 1881 } 1882 1883 /** 1884 * Paints each of the components in this container. 1885 * @param g the graphics context. 1886 * @see Component#paint 1887 * @see Component#paintAll 1888 */ 1889 public void paintComponents(Graphics g) { 1890 if (isShowing()) { 1891 GraphicsCallback.PaintAllCallback.getInstance(). 1892 runComponents(getComponentsSync(), g, GraphicsCallback.TWO_PASSES); 1893 } 1894 } 1895 1896 /** 1897 * Simulates the peer callbacks into java.awt for printing of 1898 * lightweight Containers. 1899 * @param g the graphics context to use for printing. 1900 * @see Component#printAll 1901 * @see #printComponents 1902 */ 1903 void lightweightPaint(Graphics g) { 1904 super.lightweightPaint(g); 1905 paintHeavyweightComponents(g); 1906 } 1907 1908 /** 1909 * Prints all the heavyweight subcomponents. 1910 */ 1911 void paintHeavyweightComponents(Graphics g) { 1912 if (isShowing()) { 1913 GraphicsCallback.PaintHeavyweightComponentsCallback.getInstance(). 1914 runComponents(getComponentsSync(), g, 1915 GraphicsCallback.LIGHTWEIGHTS | GraphicsCallback.HEAVYWEIGHTS); 1916 } 1917 } 1918 1919 /** 1920 * Prints each of the components in this container. 1921 * @param g the graphics context. 1922 * @see Component#print 1923 * @see Component#printAll 1924 */ 1925 public void printComponents(Graphics g) { 1926 if (isShowing()) { 1927 GraphicsCallback.PrintAllCallback.getInstance(). 1928 runComponents(getComponentsSync(), g, GraphicsCallback.TWO_PASSES); 1929 } 1930 } 1931 1932 /** 1933 * Simulates the peer callbacks into java.awt for printing of 1934 * lightweight Containers. 1935 * @param g the graphics context to use for printing. 1936 * @see Component#printAll 1937 * @see #printComponents 1938 */ 1939 void lightweightPrint(Graphics g) { 1940 super.lightweightPrint(g); 1941 printHeavyweightComponents(g); 1942 } 1943 1944 /** 1945 * Prints all the heavyweight subcomponents. 1946 */ 1947 void printHeavyweightComponents(Graphics g) { 1948 if (isShowing()) { 1949 GraphicsCallback.PrintHeavyweightComponentsCallback.getInstance(). 1950 runComponents(getComponentsSync(), g, 1951 GraphicsCallback.LIGHTWEIGHTS | GraphicsCallback.HEAVYWEIGHTS); 1952 } 1953 } 1954 1955 /** 1956 * Adds the specified container listener to receive container events 1957 * from this container. 1958 * If l is null, no exception is thrown and no action is performed. 1959 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" 1960 * >AWT Threading Issues</a> for details on AWT's threading model. 1961 * 1962 * @param l the container listener 1963 * 1964 * @see #removeContainerListener 1965 * @see #getContainerListeners 1966 */ 1967 public synchronized void addContainerListener(ContainerListener l) { 1968 if (l == null) { 1969 return; 1970 } 1971 containerListener = AWTEventMulticaster.add(containerListener, l); 1972 newEventsOnly = true; 1973 } 1974 1975 /** 1976 * Removes the specified container listener so it no longer receives 1977 * container events from this container. 1978 * If l is null, no exception is thrown and no action is performed. 1979 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" 1980 * >AWT Threading Issues</a> for details on AWT's threading model. 1981 * 1982 * @param l the container listener 1983 * 1984 * @see #addContainerListener 1985 * @see #getContainerListeners 1986 */ 1987 public synchronized void removeContainerListener(ContainerListener l) { 1988 if (l == null) { 1989 return; 1990 } 1991 containerListener = AWTEventMulticaster.remove(containerListener, l); 1992 } 1993 1994 /** 1995 * Returns an array of all the container listeners 1996 * registered on this container. 1997 * 1998 * @return all of this container's <code>ContainerListener</code>s 1999 * or an empty array if no container 2000 * listeners are currently registered 2001 * 2002 * @see #addContainerListener 2003 * @see #removeContainerListener 2004 * @since 1.4 2005 */ 2006 public synchronized ContainerListener[] getContainerListeners() { 2007 return (ContainerListener[]) (getListeners(ContainerListener.class)); 2008 } 2009 2010 /** 2011 * Returns an array of all the objects currently registered 2012 * as <code><em>Foo</em>Listener</code>s 2013 * upon this <code>Container</code>. 2014 * <code><em>Foo</em>Listener</code>s are registered using the 2015 * <code>add<em>Foo</em>Listener</code> method. 2016 * 2017 * <p> 2018 * You can specify the <code>listenerType</code> argument 2019 * with a class literal, such as 2020 * <code><em>Foo</em>Listener.class</code>. 2021 * For example, you can query a 2022 * <code>Container</code> <code>c</code> 2023 * for its container listeners with the following code: 2024 * 2025 * <pre>ContainerListener[] cls = (ContainerListener[])(c.getListeners(ContainerListener.class));</pre> 2026 * 2027 * If no such listeners exist, this method returns an empty array. 2028 * 2029 * @param listenerType the type of listeners requested; this parameter 2030 * should specify an interface that descends from 2031 * <code>java.util.EventListener</code> 2032 * @return an array of all objects registered as 2033 * <code><em>Foo</em>Listener</code>s on this container, 2034 * or an empty array if no such listeners have been added 2035 * @exception ClassCastException if <code>listenerType</code> 2036 * doesn't specify a class or interface that implements 2037 * <code>java.util.EventListener</code> 2038 * 2039 * @see #getContainerListeners 2040 * 2041 * @since 1.3 2042 */ 2043 public <T extends EventListener> T[] getListeners(Class<T> listenerType) { 2044 EventListener l = null; 2045 if (listenerType == ContainerListener.class) { 2046 l = containerListener; 2047 } else { 2048 return super.getListeners(listenerType); 2049 } 2050 return AWTEventMulticaster.getListeners(l, listenerType); 2051 } 2052 2053 // REMIND: remove when filtering is done at lower level 2054 boolean eventEnabled(AWTEvent e) { 2055 int id = e.getID(); 2056 2057 if (id == ContainerEvent.COMPONENT_ADDED || 2058 id == ContainerEvent.COMPONENT_REMOVED) { 2059 if ((eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 || 2060 containerListener != null) { 2061 return true; 2062 } 2063 return false; 2064 } 2065 return super.eventEnabled(e); 2066 } 2067 2068 /** 2069 * Processes events on this container. If the event is a 2070 * <code>ContainerEvent</code>, it invokes the 2071 * <code>processContainerEvent</code> method, else it invokes 2072 * its superclass's <code>processEvent</code>. 2073 * <p>Note that if the event parameter is <code>null</code> 2074 * the behavior is unspecified and may result in an 2075 * exception. 2076 * 2077 * @param e the event 2078 */ 2079 protected void processEvent(AWTEvent e) { 2080 if (e instanceof ContainerEvent) { 2081 processContainerEvent((ContainerEvent)e); 2082 return; 2083 } 2084 super.processEvent(e); 2085 } 2086 2087 /** 2088 * Processes container events occurring on this container by 2089 * dispatching them to any registered ContainerListener objects. 2090 * NOTE: This method will not be called unless container events 2091 * are enabled for this component; this happens when one of the 2092 * following occurs: 2093 * <ul> 2094 * <li>A ContainerListener object is registered via 2095 * <code>addContainerListener</code> 2096 * <li>Container events are enabled via <code>enableEvents</code> 2097 * </ul> 2098 * <p>Note that if the event parameter is <code>null</code> 2099 * the behavior is unspecified and may result in an 2100 * exception. 2101 * 2102 * @param e the container event 2103 * @see Component#enableEvents 2104 */ 2105 protected void processContainerEvent(ContainerEvent e) { 2106 ContainerListener listener = containerListener; 2107 if (listener != null) { 2108 switch(e.getID()) { 2109 case ContainerEvent.COMPONENT_ADDED: 2110 listener.componentAdded(e); 2111 break; 2112 case ContainerEvent.COMPONENT_REMOVED: 2113 listener.componentRemoved(e); 2114 break; 2115 } 2116 } 2117 } 2118 2119 /* 2120 * Dispatches an event to this component or one of its sub components. 2121 * Create ANCESTOR_RESIZED and ANCESTOR_MOVED events in response to 2122 * COMPONENT_RESIZED and COMPONENT_MOVED events. We have to do this 2123 * here instead of in processComponentEvent because ComponentEvents 2124 * may not be enabled for this Container. 2125 * @param e the event 2126 */ 2127 void dispatchEventImpl(AWTEvent e) { 2128 if ((dispatcher != null) && dispatcher.dispatchEvent(e)) { 2129 // event was sent to a lightweight component. The 2130 // native-produced event sent to the native container 2131 // must be properly disposed of by the peer, so it 2132 // gets forwarded. If the native host has been removed 2133 // as a result of the sending the lightweight event, 2134 // the peer reference will be null. 2135 e.consume(); 2136 if (peer != null) { 2137 peer.handleEvent(e); 2138 } 2139 return; 2140 } 2141 2142 super.dispatchEventImpl(e); 2143 2144 synchronized (getTreeLock()) { 2145 switch (e.getID()) { 2146 case ComponentEvent.COMPONENT_RESIZED: 2147 createChildHierarchyEvents(HierarchyEvent.ANCESTOR_RESIZED, 0, 2148 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK)); 2149 break; 2150 case ComponentEvent.COMPONENT_MOVED: 2151 createChildHierarchyEvents(HierarchyEvent.ANCESTOR_MOVED, 0, 2152 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK)); 2153 break; 2154 default: 2155 break; 2156 } 2157 } 2158 } 2159 2160 /* 2161 * Dispatches an event to this component, without trying to forward 2162 * it to any subcomponents 2163 * @param e the event 2164 */ 2165 void dispatchEventToSelf(AWTEvent e) { 2166 super.dispatchEventImpl(e); 2167 } 2168 2169 /** 2170 * Fetchs the top-most (deepest) lightweight component that is interested 2171 * in receiving mouse events. 2172 */ 2173 Component getMouseEventTarget(int x, int y, boolean includeSelf) { 2174 return getMouseEventTarget(x, y, includeSelf, 2175 MouseEventTargetFilter.FILTER, 2176 !SEARCH_HEAVYWEIGHTS); 2177 } 2178 2179 /** 2180 * Fetches the top-most (deepest) component to receive SunDropTargetEvents. 2181 */ 2182 Component getDropTargetEventTarget(int x, int y, boolean includeSelf) { 2183 return getMouseEventTarget(x, y, includeSelf, 2184 DropTargetEventTargetFilter.FILTER, 2185 SEARCH_HEAVYWEIGHTS); 2186 } 2187 2188 /** 2189 * A private version of getMouseEventTarget which has two additional 2190 * controllable behaviors. This method searches for the top-most 2191 * descendant of this container that contains the given coordinates 2192 * and is accepted by the given filter. The search will be constrained to 2193 * lightweight descendants if the last argument is <code>false</code>. 2194 * 2195 * @param filter EventTargetFilter instance to determine whether the 2196 * given component is a valid target for this event. 2197 * @param searchHeavyweights if <code>false</code>, the method 2198 * will bypass heavyweight components during the search. 2199 */ 2200 private Component getMouseEventTarget(int x, int y, boolean includeSelf, 2201 EventTargetFilter filter, 2202 boolean searchHeavyweights) { 2203 Component comp = null; 2204 if (searchHeavyweights) { 2205 comp = getMouseEventTargetImpl(x, y, includeSelf, filter, 2206 SEARCH_HEAVYWEIGHTS, 2207 searchHeavyweights); 2208 } 2209 2210 if (comp == null || comp == this) { 2211 comp = getMouseEventTargetImpl(x, y, includeSelf, filter, 2212 !SEARCH_HEAVYWEIGHTS, 2213 searchHeavyweights); 2214 } 2215 2216 return comp; 2217 } 2218 2219 /** 2220 * A private version of getMouseEventTarget which has three additional 2221 * controllable behaviors. This method searches for the top-most 2222 * descendant of this container that contains the given coordinates 2223 * and is accepted by the given filter. The search will be constrained to 2224 * descendants of only lightweight children or only heavyweight children 2225 * of this container depending on searchHeavyweightChildren. The search will 2226 * be constrained to only lightweight descendants of the searched children 2227 * of this container if searchHeavyweightDescendants is <code>false</code>. 2228 * 2229 * @param filter EventTargetFilter instance to determine whether the 2230 * selected component is a valid target for this event. 2231 * @param searchHeavyweightChildren if <code>true</code>, the method 2232 * will bypass immediate lightweight children during the search. 2233 * If <code>false</code>, the methods will bypass immediate 2234 * heavyweight children during the search. 2235 * @param searchHeavyweightDescendants if <code>false</code>, the method 2236 * will bypass heavyweight descendants which are not immediate 2237 * children during the search. If <code>true</code>, the method 2238 * will traverse both lightweight and heavyweight descendants during 2239 * the search. 2240 */ 2241 private Component getMouseEventTargetImpl(int x, int y, boolean includeSelf, 2242 EventTargetFilter filter, 2243 boolean searchHeavyweightChildren, 2244 boolean searchHeavyweightDescendants) { 2245 synchronized (getTreeLock()) { 2246 2247 for (int i = 0; i < component.size(); i++) { 2248 Component comp = component.get(i); 2249 if (comp != null && comp.visible && 2250 ((!searchHeavyweightChildren && 2251 comp.peer instanceof LightweightPeer) || 2252 (searchHeavyweightChildren && 2253 !(comp.peer instanceof LightweightPeer))) && 2254 comp.contains(x - comp.x, y - comp.y)) { 2255 2256 // found a component that intersects the point, see if there 2257 // is a deeper possibility. 2258 if (comp instanceof Container) { 2259 Container child = (Container) comp; 2260 Component deeper = child.getMouseEventTarget( 2261 x - child.x, 2262 y - child.y, 2263 includeSelf, 2264 filter, 2265 searchHeavyweightDescendants); 2266 if (deeper != null) { 2267 return deeper; 2268 } 2269 } else { 2270 if (filter.accept(comp)) { 2271 // there isn't a deeper target, but this component 2272 // is a target 2273 return comp; 2274 } 2275 } 2276 } 2277 } 2278 2279 boolean isPeerOK; 2280 boolean isMouseOverMe; 2281 2282 isPeerOK = (peer instanceof LightweightPeer) || includeSelf; 2283 isMouseOverMe = contains(x,y); 2284 2285 // didn't find a child target, return this component if it's 2286 // a possible target 2287 if (isMouseOverMe && isPeerOK && filter.accept(this)) { 2288 return this; 2289 } 2290 // no possible target 2291 return null; 2292 } 2293 } 2294 2295 static interface EventTargetFilter { 2296 boolean accept(final Component comp); 2297 } 2298 2299 static class MouseEventTargetFilter implements EventTargetFilter { 2300 static final EventTargetFilter FILTER = new MouseEventTargetFilter(); 2301 2302 private MouseEventTargetFilter() {} 2303 2304 public boolean accept(final Component comp) { 2305 return (comp.eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0 2306 || (comp.eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0 2307 || (comp.eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0 2308 || comp.mouseListener != null 2309 || comp.mouseMotionListener != null 2310 || comp.mouseWheelListener != null; 2311 } 2312 } 2313 2314 static class DropTargetEventTargetFilter implements EventTargetFilter { 2315 static final EventTargetFilter FILTER = new DropTargetEventTargetFilter(); 2316 2317 private DropTargetEventTargetFilter() {} 2318 2319 public boolean accept(final Component comp) { 2320 DropTarget dt = comp.getDropTarget(); 2321 return dt != null && dt.isActive(); 2322 } 2323 } 2324 2325 /** 2326 * This is called by lightweight components that want the containing 2327 * windowed parent to enable some kind of events on their behalf. 2328 * This is needed for events that are normally only dispatched to 2329 * windows to be accepted so that they can be forwarded downward to 2330 * the lightweight component that has enabled them. 2331 */ 2332 void proxyEnableEvents(long events) { 2333 if (peer instanceof LightweightPeer) { 2334 // this container is lightweight.... continue sending it 2335 // upward. 2336 if (parent != null) { 2337 parent.proxyEnableEvents(events); 2338 } 2339 } else { 2340 // This is a native container, so it needs to host 2341 // one of it's children. If this function is called before 2342 // a peer has been created we don't yet have a dispatcher 2343 // because it has not yet been determined if this instance 2344 // is lightweight. 2345 if (dispatcher != null) { 2346 dispatcher.enableEvents(events); 2347 } 2348 } 2349 } 2350 2351 /** 2352 * @deprecated As of JDK version 1.1, 2353 * replaced by <code>dispatchEvent(AWTEvent e)</code> 2354 */ 2355 @Deprecated 2356 public void deliverEvent(Event e) { 2357 Component comp = getComponentAt(e.x, e.y); 2358 if ((comp != null) && (comp != this)) { 2359 e.translate(-comp.x, -comp.y); 2360 comp.deliverEvent(e); 2361 } else { 2362 postEvent(e); 2363 } 2364 } 2365 2366 /** 2367 * Locates the component that contains the x,y position. The 2368 * top-most child component is returned in the case where there 2369 * is overlap in the components. This is determined by finding 2370 * the component closest to the index 0 that claims to contain 2371 * the given point via Component.contains(), except that Components 2372 * which have native peers take precedence over those which do not 2373 * (i.e., lightweight Components). 2374 * 2375 * @param x the <i>x</i> coordinate 2376 * @param y the <i>y</i> coordinate 2377 * @return null if the component does not contain the position. 2378 * If there is no child component at the requested point and the 2379 * point is within the bounds of the container the container itself 2380 * is returned; otherwise the top-most child is returned. 2381 * @see Component#contains 2382 * @since JDK1.1 2383 */ 2384 public Component getComponentAt(int x, int y) { 2385 return locate(x, y); 2386 } 2387 2388 /** 2389 * @deprecated As of JDK version 1.1, 2390 * replaced by <code>getComponentAt(int, int)</code>. 2391 */ 2392 @Deprecated 2393 public Component locate(int x, int y) { 2394 if (!contains(x, y)) { 2395 return null; 2396 } 2397 synchronized (getTreeLock()) { 2398 // Two passes: see comment in sun.awt.SunGraphicsCallback 2399 for (int i = 0; i < component.size(); i++) { 2400 Component comp = component.get(i); 2401 if (comp != null && 2402 !(comp.peer instanceof LightweightPeer)) { 2403 if (comp.contains(x - comp.x, y - comp.y)) { 2404 return comp; 2405 } 2406 } 2407 } 2408 for (int i = 0; i < component.size(); i++) { 2409 Component comp = component.get(i); 2410 if (comp != null && 2411 comp.peer instanceof LightweightPeer) { 2412 if (comp.contains(x - comp.x, y - comp.y)) { 2413 return comp; 2414 } 2415 } 2416 } 2417 } 2418 return this; 2419 } 2420 2421 /** 2422 * Gets the component that contains the specified point. 2423 * @param p the point. 2424 * @return returns the component that contains the point, 2425 * or <code>null</code> if the component does 2426 * not contain the point. 2427 * @see Component#contains 2428 * @since JDK1.1 2429 */ 2430 public Component getComponentAt(Point p) { 2431 return getComponentAt(p.x, p.y); 2432 } 2433 2434 /** 2435 * Returns the position of the mouse pointer in this <code>Container</code>'s 2436 * coordinate space if the <code>Container</code> is under the mouse pointer, 2437 * otherwise returns <code>null</code>. 2438 * This method is similar to {@link Component#getMousePosition()} with the exception 2439 * that it can take the <code>Container</code>'s children into account. 2440 * If <code>allowChildren</code> is <code>false</code>, this method will return 2441 * a non-null value only if the mouse pointer is above the <code>Container</code> 2442 * directly, not above the part obscured by children. 2443 * If <code>allowChildren</code> is <code>true</code>, this method returns 2444 * a non-null value if the mouse pointer is above <code>Container</code> or any 2445 * of its descendants. 2446 * 2447 * @exception HeadlessException if GraphicsEnvironment.isHeadless() returns true 2448 * @param allowChildren true if children should be taken into account 2449 * @see Component#getMousePosition 2450 * @return mouse coordinates relative to this <code>Component</code>, or null 2451 * @since 1.5 2452 */ 2453 public Point getMousePosition(boolean allowChildren) throws HeadlessException { 2454 if (GraphicsEnvironment.isHeadless()) { 2455 throw new HeadlessException(); 2456 } 2457 PointerInfo pi = (PointerInfo)java.security.AccessController.doPrivileged( 2458 new java.security.PrivilegedAction() { 2459 public Object run() { 2460 return MouseInfo.getPointerInfo(); 2461 } 2462 } 2463 ); 2464 synchronized (getTreeLock()) { 2465 Component inTheSameWindow = findUnderMouseInWindow(pi); 2466 if (isSameOrAncestorOf(inTheSameWindow, allowChildren)) { 2467 return pointRelativeToComponent(pi.getLocation()); 2468 } 2469 return null; 2470 } 2471 } 2472 2473 boolean isSameOrAncestorOf(Component comp, boolean allowChildren) { 2474 return this == comp || (allowChildren && isParentOf(comp)); 2475 } 2476 2477 /** 2478 * Locates the visible child component that contains the specified 2479 * position. The top-most child component is returned in the case 2480 * where there is overlap in the components. If the containing child 2481 * component is a Container, this method will continue searching for 2482 * the deepest nested child component. Components which are not 2483 * visible are ignored during the search.<p> 2484 * 2485 * The findComponentAt method is different from getComponentAt in 2486 * that getComponentAt only searches the Container's immediate 2487 * children; if the containing component is a Container, 2488 * findComponentAt will search that child to find a nested component. 2489 * 2490 * @param x the <i>x</i> coordinate 2491 * @param y the <i>y</i> coordinate 2492 * @return null if the component does not contain the position. 2493 * If there is no child component at the requested point and the 2494 * point is within the bounds of the container the container itself 2495 * is returned. 2496 * @see Component#contains 2497 * @see #getComponentAt 2498 * @since 1.2 2499 */ 2500 public Component findComponentAt(int x, int y) { 2501 return findComponentAt(x, y, true); 2502 } 2503 2504 /** 2505 * Private version of findComponentAt which has a controllable 2506 * behavior. Setting 'ignoreEnabled' to 'false' bypasses disabled 2507 * Components during the search. This behavior is used by the 2508 * lightweight cursor support in sun.awt.GlobalCursorManager. 2509 * The cursor code calls this function directly via native code. 2510 * 2511 * The addition of this feature is temporary, pending the 2512 * adoption of new, public API which exports this feature. 2513 */ 2514 final Component findComponentAt(int x, int y, boolean ignoreEnabled) { 2515 synchronized (getTreeLock()) { 2516 if (isRecursivelyVisible()){ 2517 return findComponentAtImpl(x, y, ignoreEnabled); 2518 } 2519 } 2520 return null; 2521 } 2522 2523 final Component findComponentAtImpl(int x, int y, boolean ignoreEnabled){ 2524 checkTreeLock(); 2525 2526 if (!(contains(x, y) && visible && (ignoreEnabled || enabled))) { 2527 return null; 2528 } 2529 2530 // Two passes: see comment in sun.awt.SunGraphicsCallback 2531 for (int i = 0; i < component.size(); i++) { 2532 Component comp = component.get(i); 2533 if (comp != null && 2534 !(comp.peer instanceof LightweightPeer)) { 2535 if (comp instanceof Container) { 2536 comp = ((Container)comp).findComponentAtImpl(x - comp.x, 2537 y - comp.y, 2538 ignoreEnabled); 2539 } else { 2540 comp = comp.locate(x - comp.x, y - comp.y); 2541 } 2542 if (comp != null && comp.visible && 2543 (ignoreEnabled || comp.enabled)) 2544 { 2545 return comp; 2546 } 2547 } 2548 } 2549 for (int i = 0; i < component.size(); i++) { 2550 Component comp = component.get(i); 2551 if (comp != null && 2552 comp.peer instanceof LightweightPeer) { 2553 if (comp instanceof Container) { 2554 comp = ((Container)comp).findComponentAtImpl(x - comp.x, 2555 y - comp.y, 2556 ignoreEnabled); 2557 } else { 2558 comp = comp.locate(x - comp.x, y - comp.y); 2559 } 2560 if (comp != null && comp.visible && 2561 (ignoreEnabled || comp.enabled)) 2562 { 2563 return comp; 2564 } 2565 } 2566 } 2567 2568 return this; 2569 } 2570 2571 /** 2572 * Locates the visible child component that contains the specified 2573 * point. The top-most child component is returned in the case 2574 * where there is overlap in the components. If the containing child 2575 * component is a Container, this method will continue searching for 2576 * the deepest nested child component. Components which are not 2577 * visible are ignored during the search.<p> 2578 * 2579 * The findComponentAt method is different from getComponentAt in 2580 * that getComponentAt only searches the Container's immediate 2581 * children; if the containing component is a Container, 2582 * findComponentAt will search that child to find a nested component. 2583 * 2584 * @param p the point. 2585 * @return null if the component does not contain the position. 2586 * If there is no child component at the requested point and the 2587 * point is within the bounds of the container the container itself 2588 * is returned. 2589 * @see Component#contains 2590 * @see #getComponentAt 2591 * @since 1.2 2592 */ 2593 public Component findComponentAt(Point p) { 2594 return findComponentAt(p.x, p.y); 2595 } 2596 2597 /** 2598 * Makes this Container displayable by connecting it to 2599 * a native screen resource. Making a container displayable will 2600 * cause all of its children to be made displayable. 2601 * This method is called internally by the toolkit and should 2602 * not be called directly by programs. 2603 * @see Component#isDisplayable 2604 * @see #removeNotify 2605 */ 2606 public void addNotify() { 2607 synchronized (getTreeLock()) { 2608 // addNotify() on the children may cause proxy event enabling 2609 // on this instance, so we first call super.addNotify() and 2610 // possibly create an lightweight event dispatcher before calling 2611 // addNotify() on the children which may be lightweight. 2612 super.addNotify(); 2613 if (! (peer instanceof LightweightPeer)) { 2614 dispatcher = new LightweightDispatcher(this); 2615 } 2616 2617 // We shouldn't use iterator because of the Swing menu 2618 // implementation specifics: 2619 // the menu is being assigned as a child to JLayeredPane 2620 // instead of particular component so always affect 2621 // collection of component if menu is becoming shown or hidden. 2622 for (int i = 0; i < component.size(); i++) { 2623 component.get(i).addNotify(); 2624 } 2625 } 2626 } 2627 2628 /** 2629 * Makes this Container undisplayable by removing its connection 2630 * to its native screen resource. Making a container undisplayable 2631 * will cause all of its children to be made undisplayable. 2632 * This method is called by the toolkit internally and should 2633 * not be called directly by programs. 2634 * @see Component#isDisplayable 2635 * @see #addNotify 2636 */ 2637 public void removeNotify() { 2638 synchronized (getTreeLock()) { 2639 // We shouldn't use iterator because of the Swing menu 2640 // implementation specifics: 2641 // the menu is being assigned as a child to JLayeredPane 2642 // instead of particular component so always affect 2643 // collection of component if menu is becoming shown or hidden. 2644 for (int i = component.size()-1 ; i >= 0 ; i--) { 2645 Component comp = component.get(i); 2646 if (comp != null) { 2647 // Fix for 6607170. 2648 // We want to suppress focus change on disposal 2649 // of the focused component. But because of focus 2650 // is asynchronous, we should suppress focus change 2651 // on every component in case it receives native focus 2652 // in the process of disposal. 2653 comp.setAutoFocusTransferOnDisposal(false); 2654 comp.removeNotify(); 2655 comp.setAutoFocusTransferOnDisposal(true); 2656 } 2657 } 2658 // If some of the children had focus before disposal then it still has. 2659 // Auto-transfer focus to the next (or previous) component if auto-transfer 2660 // is enabled. 2661 if (containsFocus() && KeyboardFocusManager.isAutoFocusTransferEnabledFor(this)) { 2662 if (!transferFocus(false)) { 2663 transferFocusBackward(true); 2664 } 2665 } 2666 if ( dispatcher != null ) { 2667 dispatcher.dispose(); 2668 dispatcher = null; 2669 } 2670 super.removeNotify(); 2671 } 2672 } 2673 2674 /** 2675 * Checks if the component is contained in the component hierarchy of 2676 * this container. 2677 * @param c the component 2678 * @return <code>true</code> if it is an ancestor; 2679 * <code>false</code> otherwise. 2680 * @since JDK1.1 2681 */ 2682 public boolean isAncestorOf(Component c) { 2683 Container p; 2684 if (c == null || ((p = c.getParent()) == null)) { 2685 return false; 2686 } 2687 while (p != null) { 2688 if (p == this) { 2689 return true; 2690 } 2691 p = p.getParent(); 2692 } 2693 return false; 2694 } 2695 2696 /* 2697 * The following code was added to support modal JInternalFrames 2698 * Unfortunately this code has to be added here so that we can get access to 2699 * some private AWT classes like SequencedEvent. 2700 * 2701 * The native container of the LW component has this field set 2702 * to tell it that it should block Mouse events for all LW 2703 * children except for the modal component. 2704 * 2705 * In the case of nested Modal components, we store the previous 2706 * modal component in the new modal components value of modalComp; 2707 */ 2708 2709 transient Component modalComp; 2710 transient AppContext modalAppContext; 2711 2712 private void startLWModal() { 2713 // Store the app context on which this component is being shown. 2714 // Event dispatch thread of this app context will be sleeping until 2715 // we wake it by any event from hideAndDisposeHandler(). 2716 modalAppContext = AppContext.getAppContext(); 2717 2718 // keep the KeyEvents from being dispatched 2719 // until the focus has been transfered 2720 long time = Toolkit.getEventQueue().getMostRecentEventTime(); 2721 Component predictedFocusOwner = (Component.isInstanceOf(this, "javax.swing.JInternalFrame")) ? ((javax.swing.JInternalFrame)(this)).getMostRecentFocusOwner() : null; 2722 if (predictedFocusOwner != null) { 2723 KeyboardFocusManager.getCurrentKeyboardFocusManager(). 2724 enqueueKeyEvents(time, predictedFocusOwner); 2725 } 2726 // We have two mechanisms for blocking: 1. If we're on the 2727 // EventDispatchThread, start a new event pump. 2. If we're 2728 // on any other thread, call wait() on the treelock. 2729 final Container nativeContainer; 2730 synchronized (getTreeLock()) { 2731 nativeContainer = getHeavyweightContainer(); 2732 if (nativeContainer.modalComp != null) { 2733 this.modalComp = nativeContainer.modalComp; 2734 nativeContainer.modalComp = this; 2735 return; 2736 } 2737 else { 2738 nativeContainer.modalComp = this; 2739 } 2740 } 2741 2742 Runnable pumpEventsForHierarchy = new Runnable() { 2743 public void run() { 2744 EventDispatchThread dispatchThread = 2745 (EventDispatchThread)Thread.currentThread(); 2746 dispatchThread.pumpEventsForHierarchy( 2747 new Conditional() { 2748 public boolean evaluate() { 2749 return ((windowClosingException == null) && (nativeContainer.modalComp != null)) ; 2750 } 2751 }, Container.this); 2752 } 2753 }; 2754 2755 if (EventQueue.isDispatchThread()) { 2756 SequencedEvent currentSequencedEvent = 2757 KeyboardFocusManager.getCurrentKeyboardFocusManager(). 2758 getCurrentSequencedEvent(); 2759 if (currentSequencedEvent != null) { 2760 currentSequencedEvent.dispose(); 2761 } 2762 2763 pumpEventsForHierarchy.run(); 2764 } else { 2765 synchronized (getTreeLock()) { 2766 Toolkit.getEventQueue(). 2767 postEvent(new PeerEvent(this, 2768 pumpEventsForHierarchy, 2769 PeerEvent.PRIORITY_EVENT)); 2770 while ((windowClosingException == null) && 2771 (nativeContainer.modalComp != null)) 2772 { 2773 try { 2774 getTreeLock().wait(); 2775 } catch (InterruptedException e) { 2776 break; 2777 } 2778 } 2779 } 2780 } 2781 if (windowClosingException != null) { 2782 windowClosingException.fillInStackTrace(); 2783 throw windowClosingException; 2784 } 2785 if (predictedFocusOwner != null) { 2786 KeyboardFocusManager.getCurrentKeyboardFocusManager(). 2787 dequeueKeyEvents(time, predictedFocusOwner); 2788 } 2789 } 2790 2791 private void stopLWModal() { 2792 synchronized (getTreeLock()) { 2793 if (modalAppContext != null) { 2794 Container nativeContainer = getHeavyweightContainer(); 2795 if(nativeContainer != null) { 2796 if (this.modalComp != null) { 2797 nativeContainer.modalComp = this.modalComp; 2798 this.modalComp = null; 2799 return; 2800 } 2801 else { 2802 nativeContainer.modalComp = null; 2803 } 2804 } 2805 // Wake up event dispatch thread on which the dialog was 2806 // initially shown 2807 SunToolkit.postEvent(modalAppContext, 2808 new PeerEvent(this, 2809 new WakingRunnable(), 2810 PeerEvent.PRIORITY_EVENT)); 2811 } 2812 EventQueue.invokeLater(new WakingRunnable()); 2813 getTreeLock().notifyAll(); 2814 } 2815 } 2816 2817 final static class WakingRunnable implements Runnable { 2818 public void run() { 2819 } 2820 } 2821 2822 /* End of JOptionPane support code */ 2823 2824 /** 2825 * Returns a string representing the state of this <code>Container</code>. 2826 * This method is intended to be used only for debugging purposes, and the 2827 * content and format of the returned string may vary between 2828 * implementations. The returned string may be empty but may not be 2829 * <code>null</code>. 2830 * 2831 * @return the parameter string of this container 2832 */ 2833 protected String paramString() { 2834 String str = super.paramString(); 2835 LayoutManager layoutMgr = this.layoutMgr; 2836 if (layoutMgr != null) { 2837 str += ",layout=" + layoutMgr.getClass().getName(); 2838 } 2839 return str; 2840 } 2841 2842 /** 2843 * Prints a listing of this container to the specified output 2844 * stream. The listing starts at the specified indentation. 2845 * <p> 2846 * The immediate children of the container are printed with 2847 * an indentation of <code>indent+1</code>. The children 2848 * of those children are printed at <code>indent+2</code> 2849 * and so on. 2850 * 2851 * @param out a print stream 2852 * @param indent the number of spaces to indent 2853 * @see Component#list(java.io.PrintStream, int) 2854 * @since JDK1.0 2855 */ 2856 public void list(PrintStream out, int indent) { 2857 super.list(out, indent); 2858 synchronized(getTreeLock()) { 2859 for (int i = 0; i < component.size(); i++) { 2860 Component comp = component.get(i); 2861 if (comp != null) { 2862 comp.list(out, indent+1); 2863 } 2864 } 2865 } 2866 } 2867 2868 /** 2869 * Prints out a list, starting at the specified indentation, 2870 * to the specified print writer. 2871 * <p> 2872 * The immediate children of the container are printed with 2873 * an indentation of <code>indent+1</code>. The children 2874 * of those children are printed at <code>indent+2</code> 2875 * and so on. 2876 * 2877 * @param out a print writer 2878 * @param indent the number of spaces to indent 2879 * @see Component#list(java.io.PrintWriter, int) 2880 * @since JDK1.1 2881 */ 2882 public void list(PrintWriter out, int indent) { 2883 super.list(out, indent); 2884 synchronized(getTreeLock()) { 2885 for (int i = 0; i < component.size(); i++) { 2886 Component comp = component.get(i); 2887 if (comp != null) { 2888 comp.list(out, indent+1); 2889 } 2890 } 2891 } 2892 } 2893 2894 /** 2895 * Sets the focus traversal keys for a given traversal operation for this 2896 * Container. 2897 * <p> 2898 * The default values for a Container's focus traversal keys are 2899 * implementation-dependent. Sun recommends that all implementations for a 2900 * particular native platform use the same default values. The 2901 * recommendations for Windows and Unix are listed below. These 2902 * recommendations are used in the Sun AWT implementations. 2903 * 2904 * <table border=1 summary="Recommended default values for a Container's focus traversal keys"> 2905 * <tr> 2906 * <th>Identifier</th> 2907 * <th>Meaning</th> 2908 * <th>Default</th> 2909 * </tr> 2910 * <tr> 2911 * <td>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</td> 2912 * <td>Normal forward keyboard traversal</td> 2913 * <td>TAB on KEY_PRESSED, CTRL-TAB on KEY_PRESSED</td> 2914 * </tr> 2915 * <tr> 2916 * <td>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</td> 2917 * <td>Normal reverse keyboard traversal</td> 2918 * <td>SHIFT-TAB on KEY_PRESSED, CTRL-SHIFT-TAB on KEY_PRESSED</td> 2919 * </tr> 2920 * <tr> 2921 * <td>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</td> 2922 * <td>Go up one focus traversal cycle</td> 2923 * <td>none</td> 2924 * </tr> 2925 * <tr> 2926 * <td>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS<td> 2927 * <td>Go down one focus traversal cycle</td> 2928 * <td>none</td> 2929 * </tr> 2930 * </table> 2931 * 2932 * To disable a traversal key, use an empty Set; Collections.EMPTY_SET is 2933 * recommended. 2934 * <p> 2935 * Using the AWTKeyStroke API, client code can specify on which of two 2936 * specific KeyEvents, KEY_PRESSED or KEY_RELEASED, the focus traversal 2937 * operation will occur. Regardless of which KeyEvent is specified, 2938 * however, all KeyEvents related to the focus traversal key, including the 2939 * associated KEY_TYPED event, will be consumed, and will not be dispatched 2940 * to any Container. It is a runtime error to specify a KEY_TYPED event as 2941 * mapping to a focus traversal operation, or to map the same event to 2942 * multiple default focus traversal operations. 2943 * <p> 2944 * If a value of null is specified for the Set, this Container inherits the 2945 * Set from its parent. If all ancestors of this Container have null 2946 * specified for the Set, then the current KeyboardFocusManager's default 2947 * Set is used. 2948 * 2949 * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, 2950 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, 2951 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or 2952 * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS 2953 * @param keystrokes the Set of AWTKeyStroke for the specified operation 2954 * @see #getFocusTraversalKeys 2955 * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS 2956 * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS 2957 * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS 2958 * @see KeyboardFocusManager#DOWN_CYCLE_TRAVERSAL_KEYS 2959 * @throws IllegalArgumentException if id is not one of 2960 * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, 2961 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, 2962 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or 2963 * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS, or if keystrokes 2964 * contains null, or if any Object in keystrokes is not an 2965 * AWTKeyStroke, or if any keystroke represents a KEY_TYPED event, 2966 * or if any keystroke already maps to another focus traversal 2967 * operation for this Container 2968 * @since 1.4 2969 * @beaninfo 2970 * bound: true 2971 */ 2972 public void setFocusTraversalKeys(int id, 2973 Set<? extends AWTKeyStroke> keystrokes) 2974 { 2975 if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) { 2976 throw new IllegalArgumentException("invalid focus traversal key identifier"); 2977 } 2978 2979 // Don't call super.setFocusTraversalKey. The Component parameter check 2980 // does not allow DOWN_CYCLE_TRAVERSAL_KEYS, but we do. 2981 setFocusTraversalKeys_NoIDCheck(id, keystrokes); 2982 } 2983 2984 /** 2985 * Returns the Set of focus traversal keys for a given traversal operation 2986 * for this Container. (See 2987 * <code>setFocusTraversalKeys</code> for a full description of each key.) 2988 * <p> 2989 * If a Set of traversal keys has not been explicitly defined for this 2990 * Container, then this Container's parent's Set is returned. If no Set 2991 * has been explicitly defined for any of this Container's ancestors, then 2992 * the current KeyboardFocusManager's default Set is returned. 2993 * 2994 * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, 2995 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, 2996 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or 2997 * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS 2998 * @return the Set of AWTKeyStrokes for the specified operation. The Set 2999 * will be unmodifiable, and may be empty. null will never be 3000 * returned. 3001 * @see #setFocusTraversalKeys 3002 * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS 3003 * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS 3004 * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS 3005 * @see KeyboardFocusManager#DOWN_CYCLE_TRAVERSAL_KEYS 3006 * @throws IllegalArgumentException if id is not one of 3007 * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, 3008 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, 3009 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or 3010 * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS 3011 * @since 1.4 3012 */ 3013 public Set<AWTKeyStroke> getFocusTraversalKeys(int id) { 3014 if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) { 3015 throw new IllegalArgumentException("invalid focus traversal key identifier"); 3016 } 3017 3018 // Don't call super.getFocusTraversalKey. The Component parameter check 3019 // does not allow DOWN_CYCLE_TRAVERSAL_KEY, but we do. 3020 return getFocusTraversalKeys_NoIDCheck(id); 3021 } 3022 3023 /** 3024 * Returns whether the Set of focus traversal keys for the given focus 3025 * traversal operation has been explicitly defined for this Container. If 3026 * this method returns <code>false</code>, this Container is inheriting the 3027 * Set from an ancestor, or from the current KeyboardFocusManager. 3028 * 3029 * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, 3030 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, 3031 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or 3032 * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS 3033 * @return <code>true</code> if the the Set of focus traversal keys for the 3034 * given focus traversal operation has been explicitly defined for 3035 * this Component; <code>false</code> otherwise. 3036 * @throws IllegalArgumentException if id is not one of 3037 * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, 3038 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, 3039 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or 3040 * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS 3041 * @since 1.4 3042 */ 3043 public boolean areFocusTraversalKeysSet(int id) { 3044 if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) { 3045 throw new IllegalArgumentException("invalid focus traversal key identifier"); 3046 } 3047 3048 return (focusTraversalKeys != null && focusTraversalKeys[id] != null); 3049 } 3050 3051 /** 3052 * Returns whether the specified Container is the focus cycle root of this 3053 * Container's focus traversal cycle. Each focus traversal cycle has only 3054 * a single focus cycle root and each Container which is not a focus cycle 3055 * root belongs to only a single focus traversal cycle. Containers which 3056 * are focus cycle roots belong to two cycles: one rooted at the Container 3057 * itself, and one rooted at the Container's nearest focus-cycle-root 3058 * ancestor. This method will return <code>true</code> for both such 3059 * Containers in this case. 3060 * 3061 * @param container the Container to be tested 3062 * @return <code>true</code> if the specified Container is a focus-cycle- 3063 * root of this Container; <code>false</code> otherwise 3064 * @see #isFocusCycleRoot() 3065 * @since 1.4 3066 */ 3067 public boolean isFocusCycleRoot(Container container) { 3068 if (isFocusCycleRoot() && container == this) { 3069 return true; 3070 } else { 3071 return super.isFocusCycleRoot(container); 3072 } 3073 } 3074 3075 private Container findTraversalRoot() { 3076 // I potentially have two roots, myself and my root parent 3077 // If I am the current root, then use me 3078 // If none of my parents are roots, then use me 3079 // If my root parent is the current root, then use my root parent 3080 // If neither I nor my root parent is the current root, then 3081 // use my root parent (a guess) 3082 3083 Container currentFocusCycleRoot = KeyboardFocusManager. 3084 getCurrentKeyboardFocusManager().getCurrentFocusCycleRoot(); 3085 Container root; 3086 3087 if (currentFocusCycleRoot == this) { 3088 root = this; 3089 } else { 3090 root = getFocusCycleRootAncestor(); 3091 if (root == null) { 3092 root = this; 3093 } 3094 } 3095 3096 if (root != currentFocusCycleRoot) { 3097 KeyboardFocusManager.getCurrentKeyboardFocusManager(). 3098 setGlobalCurrentFocusCycleRoot(root); 3099 } 3100 return root; 3101 } 3102 3103 final boolean containsFocus() { 3104 final Component focusOwner = KeyboardFocusManager. 3105 getCurrentKeyboardFocusManager().getFocusOwner(); 3106 return isParentOf(focusOwner); 3107 } 3108 3109 /** 3110 * Check if this component is the child of this container or its children. 3111 * Note: this function acquires treeLock 3112 * Note: this function traverses children tree only in one Window. 3113 * @param comp a component in test, must not be null 3114 */ 3115 private boolean isParentOf(Component comp) { 3116 synchronized(getTreeLock()) { 3117 while (comp != null && comp != this && !(comp instanceof Window)) { 3118 comp = comp.getParent(); 3119 } 3120 return (comp == this); 3121 } 3122 } 3123 3124 void clearMostRecentFocusOwnerOnHide() { 3125 boolean reset = false; 3126 Window window = null; 3127 3128 synchronized (getTreeLock()) { 3129 window = getContainingWindow(); 3130 if (window != null) { 3131 Component comp = KeyboardFocusManager.getMostRecentFocusOwner(window); 3132 reset = ((comp == this) || isParentOf(comp)); 3133 // This synchronized should always be the second in a pair 3134 // (tree lock, KeyboardFocusManager.class) 3135 synchronized(KeyboardFocusManager.class) { 3136 Component storedComp = window.getTemporaryLostComponent(); 3137 if (isParentOf(storedComp) || storedComp == this) { 3138 window.setTemporaryLostComponent(null); 3139 } 3140 } 3141 } 3142 } 3143 3144 if (reset) { 3145 KeyboardFocusManager.setMostRecentFocusOwner(window, null); 3146 } 3147 } 3148 3149 void clearCurrentFocusCycleRootOnHide() { 3150 KeyboardFocusManager kfm = 3151 KeyboardFocusManager.getCurrentKeyboardFocusManager(); 3152 Container cont = kfm.getCurrentFocusCycleRoot(); 3153 3154 if (cont == this || isParentOf(cont)) { 3155 kfm.setGlobalCurrentFocusCycleRoot(null); 3156 } 3157 } 3158 3159 final Container getTraversalRoot() { 3160 if (isFocusCycleRoot()) { 3161 return findTraversalRoot(); 3162 } 3163 3164 return super.getTraversalRoot(); 3165 } 3166 3167 /** 3168 * Sets the focus traversal policy that will manage keyboard traversal of 3169 * this Container's children, if this Container is a focus cycle root. If 3170 * the argument is null, this Container inherits its policy from its focus- 3171 * cycle-root ancestor. If the argument is non-null, this policy will be 3172 * inherited by all focus-cycle-root children that have no keyboard- 3173 * traversal policy of their own (as will, recursively, their focus-cycle- 3174 * root children). 3175 * <p> 3176 * If this Container is not a focus cycle root, the policy will be 3177 * remembered, but will not be used or inherited by this or any other 3178 * Containers until this Container is made a focus cycle root. 3179 * 3180 * @param policy the new focus traversal policy for this Container 3181 * @see #getFocusTraversalPolicy 3182 * @see #setFocusCycleRoot 3183 * @see #isFocusCycleRoot 3184 * @since 1.4 3185 * @beaninfo 3186 * bound: true 3187 */ 3188 public void setFocusTraversalPolicy(FocusTraversalPolicy policy) { 3189 FocusTraversalPolicy oldPolicy; 3190 synchronized (this) { 3191 oldPolicy = this.focusTraversalPolicy; 3192 this.focusTraversalPolicy = policy; 3193 } 3194 firePropertyChange("focusTraversalPolicy", oldPolicy, policy); 3195 } 3196 3197 /** 3198 * Returns the focus traversal policy that will manage keyboard traversal 3199 * of this Container's children, or null if this Container is not a focus 3200 * cycle root. If no traversal policy has been explicitly set for this 3201 * Container, then this Container's focus-cycle-root ancestor's policy is 3202 * returned. 3203 * 3204 * @return this Container's focus traversal policy, or null if this 3205 * Container is not a focus cycle root. 3206 * @see #setFocusTraversalPolicy 3207 * @see #setFocusCycleRoot 3208 * @see #isFocusCycleRoot 3209 * @since 1.4 3210 */ 3211 public FocusTraversalPolicy getFocusTraversalPolicy() { 3212 if (!isFocusTraversalPolicyProvider() && !isFocusCycleRoot()) { 3213 return null; 3214 } 3215 3216 FocusTraversalPolicy policy = this.focusTraversalPolicy; 3217 if (policy != null) { 3218 return policy; 3219 } 3220 3221 Container rootAncestor = getFocusCycleRootAncestor(); 3222 if (rootAncestor != null) { 3223 return rootAncestor.getFocusTraversalPolicy(); 3224 } else { 3225 return KeyboardFocusManager.getCurrentKeyboardFocusManager(). 3226 getDefaultFocusTraversalPolicy(); 3227 } 3228 } 3229 3230 /** 3231 * Returns whether the focus traversal policy has been explicitly set for 3232 * this Container. If this method returns <code>false</code>, this 3233 * Container will inherit its focus traversal policy from an ancestor. 3234 * 3235 * @return <code>true</code> if the focus traversal policy has been 3236 * explicitly set for this Container; <code>false</code> otherwise. 3237 * @since 1.4 3238 */ 3239 public boolean isFocusTraversalPolicySet() { 3240 return (focusTraversalPolicy != null); 3241 } 3242 3243 /** 3244 * Sets whether this Container is the root of a focus traversal cycle. Once 3245 * focus enters a traversal cycle, typically it cannot leave it via focus 3246 * traversal unless one of the up- or down-cycle keys is pressed. Normal 3247 * traversal is limited to this Container, and all of this Container's 3248 * descendants that are not descendants of inferior focus cycle roots. Note 3249 * that a FocusTraversalPolicy may bend these restrictions, however. For 3250 * example, ContainerOrderFocusTraversalPolicy supports implicit down-cycle 3251 * traversal. 3252 * <p> 3253 * The alternative way to specify the traversal order of this Container's 3254 * children is to make this Container a 3255 * <a href="doc-files/FocusSpec.html#FocusTraversalPolicyProviders">focus traversal policy provider</a>. 3256 * 3257 * @param focusCycleRoot indicates whether this Container is the root of a 3258 * focus traversal cycle 3259 * @see #isFocusCycleRoot() 3260 * @see #setFocusTraversalPolicy 3261 * @see #getFocusTraversalPolicy 3262 * @see ContainerOrderFocusTraversalPolicy 3263 * @see #setFocusTraversalPolicyProvider 3264 * @since 1.4 3265 * @beaninfo 3266 * bound: true 3267 */ 3268 public void setFocusCycleRoot(boolean focusCycleRoot) { 3269 boolean oldFocusCycleRoot; 3270 synchronized (this) { 3271 oldFocusCycleRoot = this.focusCycleRoot; 3272 this.focusCycleRoot = focusCycleRoot; 3273 } 3274 firePropertyChange("focusCycleRoot", oldFocusCycleRoot, 3275 focusCycleRoot); 3276 } 3277 3278 /** 3279 * Returns whether this Container is the root of a focus traversal cycle. 3280 * Once focus enters a traversal cycle, typically it cannot leave it via 3281 * focus traversal unless one of the up- or down-cycle keys is pressed. 3282 * Normal traversal is limited to this Container, and all of this 3283 * Container's descendants that are not descendants of inferior focus 3284 * cycle roots. Note that a FocusTraversalPolicy may bend these 3285 * restrictions, however. For example, ContainerOrderFocusTraversalPolicy 3286 * supports implicit down-cycle traversal. 3287 * 3288 * @return whether this Container is the root of a focus traversal cycle 3289 * @see #setFocusCycleRoot 3290 * @see #setFocusTraversalPolicy 3291 * @see #getFocusTraversalPolicy 3292 * @see ContainerOrderFocusTraversalPolicy 3293 * @since 1.4 3294 */ 3295 public boolean isFocusCycleRoot() { 3296 return focusCycleRoot; 3297 } 3298 3299 /** 3300 * Sets whether this container will be used to provide focus 3301 * traversal policy. Container with this property as 3302 * <code>true</code> will be used to acquire focus traversal policy 3303 * instead of closest focus cycle root ancestor. 3304 * @param provider indicates whether this container will be used to 3305 * provide focus traversal policy 3306 * @see #setFocusTraversalPolicy 3307 * @see #getFocusTraversalPolicy 3308 * @see #isFocusTraversalPolicyProvider 3309 * @since 1.5 3310 * @beaninfo 3311 * bound: true 3312 */ 3313 public final void setFocusTraversalPolicyProvider(boolean provider) { 3314 boolean oldProvider; 3315 synchronized(this) { 3316 oldProvider = focusTraversalPolicyProvider; 3317 focusTraversalPolicyProvider = provider; 3318 } 3319 firePropertyChange("focusTraversalPolicyProvider", oldProvider, provider); 3320 } 3321 3322 /** 3323 * Returns whether this container provides focus traversal 3324 * policy. If this property is set to <code>true</code> then when 3325 * keyboard focus manager searches container hierarchy for focus 3326 * traversal policy and encounters this container before any other 3327 * container with this property as true or focus cycle roots then 3328 * its focus traversal policy will be used instead of focus cycle 3329 * root's policy. 3330 * @see #setFocusTraversalPolicy 3331 * @see #getFocusTraversalPolicy 3332 * @see #setFocusCycleRoot 3333 * @see #setFocusTraversalPolicyProvider 3334 * @return <code>true</code> if this container provides focus traversal 3335 * policy, <code>false</code> otherwise 3336 * @since 1.5 3337 * @beaninfo 3338 * bound: true 3339 */ 3340 public final boolean isFocusTraversalPolicyProvider() { 3341 return focusTraversalPolicyProvider; 3342 } 3343 3344 /** 3345 * Transfers the focus down one focus traversal cycle. If this Container is 3346 * a focus cycle root, then the focus owner is set to this Container's 3347 * default Component to focus, and the current focus cycle root is set to 3348 * this Container. If this Container is not a focus cycle root, then no 3349 * focus traversal operation occurs. 3350 * 3351 * @see Component#requestFocus() 3352 * @see #isFocusCycleRoot 3353 * @see #setFocusCycleRoot 3354 * @since 1.4 3355 */ 3356 public void transferFocusDownCycle() { 3357 if (isFocusCycleRoot()) { 3358 KeyboardFocusManager.getCurrentKeyboardFocusManager(). 3359 setGlobalCurrentFocusCycleRoot(this); 3360 Component toFocus = getFocusTraversalPolicy(). 3361 getDefaultComponent(this); 3362 if (toFocus != null) { 3363 toFocus.requestFocus(CausedFocusEvent.Cause.TRAVERSAL_DOWN); 3364 } 3365 } 3366 } 3367 3368 void preProcessKeyEvent(KeyEvent e) { 3369 Container parent = this.parent; 3370 if (parent != null) { 3371 parent.preProcessKeyEvent(e); 3372 } 3373 } 3374 3375 void postProcessKeyEvent(KeyEvent e) { 3376 Container parent = this.parent; 3377 if (parent != null) { 3378 parent.postProcessKeyEvent(e); 3379 } 3380 } 3381 3382 boolean postsOldMouseEvents() { 3383 return true; 3384 } 3385 3386 /** 3387 * Sets the <code>ComponentOrientation</code> property of this container 3388 * and all components contained within it. 3389 * 3390 * @param o the new component orientation of this container and 3391 * the components contained within it. 3392 * @exception NullPointerException if <code>orientation</code> is null. 3393 * @see Component#setComponentOrientation 3394 * @see Component#getComponentOrientation 3395 * @since 1.4 3396 */ 3397 public void applyComponentOrientation(ComponentOrientation o) { 3398 super.applyComponentOrientation(o); 3399 synchronized (getTreeLock()) { 3400 for (int i = 0; i < component.size(); i++) { 3401 Component comp = component.get(i); 3402 comp.applyComponentOrientation(o); 3403 } 3404 } 3405 } 3406 3407 /** 3408 * Adds a PropertyChangeListener to the listener list. The listener is 3409 * registered for all bound properties of this class, including the 3410 * following: 3411 * <ul> 3412 * <li>this Container's font ("font")</li> 3413 * <li>this Container's background color ("background")</li> 3414 * <li>this Container's foreground color ("foreground")</li> 3415 * <li>this Container's focusability ("focusable")</li> 3416 * <li>this Container's focus traversal keys enabled state 3417 * ("focusTraversalKeysEnabled")</li> 3418 * <li>this Container's Set of FORWARD_TRAVERSAL_KEYS 3419 * ("forwardFocusTraversalKeys")</li> 3420 * <li>this Container's Set of BACKWARD_TRAVERSAL_KEYS 3421 * ("backwardFocusTraversalKeys")</li> 3422 * <li>this Container's Set of UP_CYCLE_TRAVERSAL_KEYS 3423 * ("upCycleFocusTraversalKeys")</li> 3424 * <li>this Container's Set of DOWN_CYCLE_TRAVERSAL_KEYS 3425 * ("downCycleFocusTraversalKeys")</li> 3426 * <li>this Container's focus traversal policy ("focusTraversalPolicy") 3427 * </li> 3428 * <li>this Container's focus-cycle-root state ("focusCycleRoot")</li> 3429 * </ul> 3430 * Note that if this Container is inheriting a bound property, then no 3431 * event will be fired in response to a change in the inherited property. 3432 * <p> 3433 * If listener is null, no exception is thrown and no action is performed. 3434 * 3435 * @param listener the PropertyChangeListener to be added 3436 * 3437 * @see Component#removePropertyChangeListener 3438 * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener) 3439 */ 3440 public void addPropertyChangeListener(PropertyChangeListener listener) { 3441 super.addPropertyChangeListener(listener); 3442 } 3443 3444 /** 3445 * Adds a PropertyChangeListener to the listener list for a specific 3446 * property. The specified property may be user-defined, or one of the 3447 * following defaults: 3448 * <ul> 3449 * <li>this Container's font ("font")</li> 3450 * <li>this Container's background color ("background")</li> 3451 * <li>this Container's foreground color ("foreground")</li> 3452 * <li>this Container's focusability ("focusable")</li> 3453 * <li>this Container's focus traversal keys enabled state 3454 * ("focusTraversalKeysEnabled")</li> 3455 * <li>this Container's Set of FORWARD_TRAVERSAL_KEYS 3456 * ("forwardFocusTraversalKeys")</li> 3457 * <li>this Container's Set of BACKWARD_TRAVERSAL_KEYS 3458 * ("backwardFocusTraversalKeys")</li> 3459 * <li>this Container's Set of UP_CYCLE_TRAVERSAL_KEYS 3460 * ("upCycleFocusTraversalKeys")</li> 3461 * <li>this Container's Set of DOWN_CYCLE_TRAVERSAL_KEYS 3462 * ("downCycleFocusTraversalKeys")</li> 3463 * <li>this Container's focus traversal policy ("focusTraversalPolicy") 3464 * </li> 3465 * <li>this Container's focus-cycle-root state ("focusCycleRoot")</li> 3466 * <li>this Container's focus-traversal-policy-provider state("focusTraversalPolicyProvider")</li> 3467 * <li>this Container's focus-traversal-policy-provider state("focusTraversalPolicyProvider")</li> 3468 * </ul> 3469 * Note that if this Container is inheriting a bound property, then no 3470 * event will be fired in response to a change in the inherited property. 3471 * <p> 3472 * If listener is null, no exception is thrown and no action is performed. 3473 * 3474 * @param propertyName one of the property names listed above 3475 * @param listener the PropertyChangeListener to be added 3476 * 3477 * @see #addPropertyChangeListener(java.beans.PropertyChangeListener) 3478 * @see Component#removePropertyChangeListener 3479 */ 3480 public void addPropertyChangeListener(String propertyName, 3481 PropertyChangeListener listener) { 3482 super.addPropertyChangeListener(propertyName, listener); 3483 } 3484 3485 // Serialization support. A Container is responsible for restoring the 3486 // parent fields of its component children. 3487 3488 /** 3489 * Container Serial Data Version. 3490 */ 3491 private int containerSerializedDataVersion = 1; 3492 3493 /** 3494 * Serializes this <code>Container</code> to the specified 3495 * <code>ObjectOutputStream</code>. 3496 * <ul> 3497 * <li>Writes default serializable fields to the stream.</li> 3498 * <li>Writes a list of serializable ContainerListener(s) as optional 3499 * data. The non-serializable ContainerListner(s) are detected and 3500 * no attempt is made to serialize them.</li> 3501 * <li>Write this Container's FocusTraversalPolicy if and only if it 3502 * is Serializable; otherwise, <code>null</code> is written.</li> 3503 * </ul> 3504 * 3505 * @param s the <code>ObjectOutputStream</code> to write 3506 * @serialData <code>null</code> terminated sequence of 0 or more pairs; 3507 * the pair consists of a <code>String</code> and <code>Object</code>; 3508 * the <code>String</code> indicates the type of object and 3509 * is one of the following: 3510 * <code>containerListenerK</code> indicating an 3511 * <code>ContainerListener</code> object; 3512 * the <code>Container</code>'s <code>FocusTraversalPolicy</code>, 3513 * or <code>null</code> 3514 * 3515 * @see AWTEventMulticaster#save(java.io.ObjectOutputStream, java.lang.String, java.util.EventListener) 3516 * @see Container#containerListenerK 3517 * @see #readObject(ObjectInputStream) 3518 */ 3519 private void writeObject(ObjectOutputStream s) throws IOException { 3520 ObjectOutputStream.PutField f = s.putFields(); 3521 f.put("ncomponents", component.size()); 3522 f.put("component", getComponentsSync()); 3523 f.put("layoutMgr", layoutMgr); 3524 f.put("dispatcher", dispatcher); 3525 f.put("maxSize", maxSize); 3526 f.put("focusCycleRoot", focusCycleRoot); 3527 f.put("containerSerializedDataVersion", containerSerializedDataVersion); 3528 f.put("focusTraversalPolicyProvider", focusTraversalPolicyProvider); 3529 s.writeFields(); 3530 3531 AWTEventMulticaster.save(s, containerListenerK, containerListener); 3532 s.writeObject(null); 3533 3534 if (focusTraversalPolicy instanceof java.io.Serializable) { 3535 s.writeObject(focusTraversalPolicy); 3536 } else { 3537 s.writeObject(null); 3538 } 3539 } 3540 3541 /** 3542 * Deserializes this <code>Container</code> from the specified 3543 * <code>ObjectInputStream</code>. 3544 * <ul> 3545 * <li>Reads default serializable fields from the stream.</li> 3546 * <li>Reads a list of serializable ContainerListener(s) as optional 3547 * data. If the list is null, no Listeners are installed.</li> 3548 * <li>Reads this Container's FocusTraversalPolicy, which may be null, 3549 * as optional data.</li> 3550 * </ul> 3551 * 3552 * @param s the <code>ObjectInputStream</code> to read 3553 * @serial 3554 * @see #addContainerListener 3555 * @see #writeObject(ObjectOutputStream) 3556 */ 3557 private void readObject(ObjectInputStream s) 3558 throws ClassNotFoundException, IOException 3559 { 3560 ObjectInputStream.GetField f = s.readFields(); 3561 Component [] tmpComponent = (Component[])f.get("component", EMPTY_ARRAY); 3562 int ncomponents = (Integer) f.get("ncomponents", 0); 3563 component = new java.util.ArrayList<Component>(ncomponents); 3564 for (int i = 0; i < ncomponents; ++i) { 3565 component.add(tmpComponent[i]); 3566 } 3567 layoutMgr = (LayoutManager)f.get("layoutMgr", null); 3568 dispatcher = (LightweightDispatcher)f.get("dispatcher", null); 3569 // Old stream. Doesn't contain maxSize among Component's fields. 3570 if (maxSize == null) { 3571 maxSize = (Dimension)f.get("maxSize", null); 3572 } 3573 focusCycleRoot = f.get("focusCycleRoot", false); 3574 containerSerializedDataVersion = f.get("containerSerializedDataVersion", 1); 3575 focusTraversalPolicyProvider = f.get("focusTraversalPolicyProvider", false); 3576 java.util.List<Component> component = this.component; 3577 for(Component comp : component) { 3578 comp.parent = this; 3579 adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK, 3580 comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK)); 3581 adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, 3582 comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK)); 3583 adjustDescendants(comp.countHierarchyMembers()); 3584 } 3585 3586 Object keyOrNull; 3587 while(null != (keyOrNull = s.readObject())) { 3588 String key = ((String)keyOrNull).intern(); 3589 3590 if (containerListenerK == key) { 3591 addContainerListener((ContainerListener)(s.readObject())); 3592 } else { 3593 // skip value for unrecognized key 3594 s.readObject(); 3595 } 3596 } 3597 3598 try { 3599 Object policy = s.readObject(); 3600 if (policy instanceof FocusTraversalPolicy) { 3601 focusTraversalPolicy = (FocusTraversalPolicy)policy; 3602 } 3603 } catch (java.io.OptionalDataException e) { 3604 // JDK 1.1/1.2/1.3 instances will not have this optional data. 3605 // e.eof will be true to indicate that there is no more data 3606 // available for this object. If e.eof is not true, throw the 3607 // exception as it might have been caused by reasons unrelated to 3608 // focusTraversalPolicy. 3609 3610 if (!e.eof) { 3611 throw e; 3612 } 3613 } 3614 } 3615 3616 /* 3617 * --- Accessibility Support --- 3618 */ 3619 3620 /** 3621 * Inner class of Container used to provide default support for 3622 * accessibility. This class is not meant to be used directly by 3623 * application developers, but is instead meant only to be 3624 * subclassed by container developers. 3625 * <p> 3626 * The class used to obtain the accessible role for this object, 3627 * as well as implementing many of the methods in the 3628 * AccessibleContainer interface. 3629 * @since 1.3 3630 */ 3631 protected class AccessibleAWTContainer extends AccessibleAWTComponent { 3632 3633 /** 3634 * JDK1.3 serialVersionUID 3635 */ 3636 private static final long serialVersionUID = 5081320404842566097L; 3637 3638 /** 3639 * Returns the number of accessible children in the object. If all 3640 * of the children of this object implement <code>Accessible</code>, 3641 * then this method should return the number of children of this object. 3642 * 3643 * @return the number of accessible children in the object 3644 */ 3645 public int getAccessibleChildrenCount() { 3646 return Container.this.getAccessibleChildrenCount(); 3647 } 3648 3649 /** 3650 * Returns the nth <code>Accessible</code> child of the object. 3651 * 3652 * @param i zero-based index of child 3653 * @return the nth <code>Accessible</code> child of the object 3654 */ 3655 public Accessible getAccessibleChild(int i) { 3656 return Container.this.getAccessibleChild(i); 3657 } 3658 3659 /** 3660 * Returns the <code>Accessible</code> child, if one exists, 3661 * contained at the local coordinate <code>Point</code>. 3662 * 3663 * @param p the point defining the top-left corner of the 3664 * <code>Accessible</code>, given in the coordinate space 3665 * of the object's parent 3666 * @return the <code>Accessible</code>, if it exists, 3667 * at the specified location; else <code>null</code> 3668 */ 3669 public Accessible getAccessibleAt(Point p) { 3670 return Container.this.getAccessibleAt(p); 3671 } 3672 3673 protected ContainerListener accessibleContainerHandler = null; 3674 3675 /** 3676 * Fire <code>PropertyChange</code> listener, if one is registered, 3677 * when children are added or removed. 3678 * @since 1.3 3679 */ 3680 protected class AccessibleContainerHandler 3681 implements ContainerListener { 3682 public void componentAdded(ContainerEvent e) { 3683 Component c = e.getChild(); 3684 if (c != null && c instanceof Accessible) { 3685 AccessibleAWTContainer.this.firePropertyChange( 3686 AccessibleContext.ACCESSIBLE_CHILD_PROPERTY, 3687 null, ((Accessible) c).getAccessibleContext()); 3688 } 3689 } 3690 public void componentRemoved(ContainerEvent e) { 3691 Component c = e.getChild(); 3692 if (c != null && c instanceof Accessible) { 3693 AccessibleAWTContainer.this.firePropertyChange( 3694 AccessibleContext.ACCESSIBLE_CHILD_PROPERTY, 3695 ((Accessible) c).getAccessibleContext(), null); 3696 } 3697 } 3698 } 3699 3700 /** 3701 * Adds a PropertyChangeListener to the listener list. 3702 * 3703 * @param listener the PropertyChangeListener to be added 3704 */ 3705 public void addPropertyChangeListener(PropertyChangeListener listener) { 3706 if (accessibleContainerHandler == null) { 3707 accessibleContainerHandler = new AccessibleContainerHandler(); 3708 Container.this.addContainerListener(accessibleContainerHandler); 3709 } 3710 super.addPropertyChangeListener(listener); 3711 } 3712 3713 } // inner class AccessibleAWTContainer 3714 3715 /** 3716 * Returns the <code>Accessible</code> child contained at the local 3717 * coordinate <code>Point</code>, if one exists. Otherwise 3718 * returns <code>null</code>. 3719 * 3720 * @param p the point defining the top-left corner of the 3721 * <code>Accessible</code>, given in the coordinate space 3722 * of the object's parent 3723 * @return the <code>Accessible</code> at the specified location, 3724 * if it exists; otherwise <code>null</code> 3725 */ 3726 Accessible getAccessibleAt(Point p) { 3727 synchronized (getTreeLock()) { 3728 if (this instanceof Accessible) { 3729 Accessible a = (Accessible)this; 3730 AccessibleContext ac = a.getAccessibleContext(); 3731 if (ac != null) { 3732 AccessibleComponent acmp; 3733 Point location; 3734 int nchildren = ac.getAccessibleChildrenCount(); 3735 for (int i=0; i < nchildren; i++) { 3736 a = ac.getAccessibleChild(i); 3737 if ((a != null)) { 3738 ac = a.getAccessibleContext(); 3739 if (ac != null) { 3740 acmp = ac.getAccessibleComponent(); 3741 if ((acmp != null) && (acmp.isShowing())) { 3742 location = acmp.getLocation(); 3743 Point np = new Point(p.x-location.x, 3744 p.y-location.y); 3745 if (acmp.contains(np)){ 3746 return a; 3747 } 3748 } 3749 } 3750 } 3751 } 3752 } 3753 return (Accessible)this; 3754 } else { 3755 Component ret = this; 3756 if (!this.contains(p.x,p.y)) { 3757 ret = null; 3758 } else { 3759 int ncomponents = this.getComponentCount(); 3760 for (int i=0; i < ncomponents; i++) { 3761 Component comp = this.getComponent(i); 3762 if ((comp != null) && comp.isShowing()) { 3763 Point location = comp.getLocation(); 3764 if (comp.contains(p.x-location.x,p.y-location.y)) { 3765 ret = comp; 3766 } 3767 } 3768 } 3769 } 3770 if (ret instanceof Accessible) { 3771 return (Accessible) ret; 3772 } 3773 } 3774 return null; 3775 } 3776 } 3777 3778 /** 3779 * Returns the number of accessible children in the object. If all 3780 * of the children of this object implement <code>Accessible</code>, 3781 * then this method should return the number of children of this object. 3782 * 3783 * @return the number of accessible children in the object 3784 */ 3785 int getAccessibleChildrenCount() { 3786 synchronized (getTreeLock()) { 3787 int count = 0; 3788 Component[] children = this.getComponents(); 3789 for (int i = 0; i < children.length; i++) { 3790 if (children[i] instanceof Accessible) { 3791 count++; 3792 } 3793 } 3794 return count; 3795 } 3796 } 3797 3798 /** 3799 * Returns the nth <code>Accessible</code> child of the object. 3800 * 3801 * @param i zero-based index of child 3802 * @return the nth <code>Accessible</code> child of the object 3803 */ 3804 Accessible getAccessibleChild(int i) { 3805 synchronized (getTreeLock()) { 3806 Component[] children = this.getComponents(); 3807 int count = 0; 3808 for (int j = 0; j < children.length; j++) { 3809 if (children[j] instanceof Accessible) { 3810 if (count == i) { 3811 return (Accessible) children[j]; 3812 } else { 3813 count++; 3814 } 3815 } 3816 } 3817 return null; 3818 } 3819 } 3820 3821 // ************************** MIXING CODE ******************************* 3822 3823 final void increaseComponentCount(Component c) { 3824 synchronized (getTreeLock()) { 3825 if (!c.isDisplayable()) { 3826 throw new IllegalStateException( 3827 "Peer does not exist while invoking the increaseComponentCount() method" 3828 ); 3829 } 3830 3831 int addHW = 0; 3832 int addLW = 0; 3833 3834 if (c instanceof Container) { 3835 addLW = ((Container)c).numOfLWComponents; 3836 addHW = ((Container)c).numOfHWComponents; 3837 } 3838 if (c.isLightweight()) { 3839 addLW++; 3840 } else { 3841 addHW++; 3842 } 3843 3844 for (Container cont = this; cont != null; cont = cont.getContainer()) { 3845 cont.numOfLWComponents += addLW; 3846 cont.numOfHWComponents += addHW; 3847 } 3848 } 3849 } 3850 3851 final void decreaseComponentCount(Component c) { 3852 synchronized (getTreeLock()) { 3853 if (!c.isDisplayable()) { 3854 throw new IllegalStateException( 3855 "Peer does not exist while invoking the decreaseComponentCount() method" 3856 ); 3857 } 3858 3859 int subHW = 0; 3860 int subLW = 0; 3861 3862 if (c instanceof Container) { 3863 subLW = ((Container)c).numOfLWComponents; 3864 subHW = ((Container)c).numOfHWComponents; 3865 } 3866 if (c.isLightweight()) { 3867 subLW++; 3868 } else { 3869 subHW++; 3870 } 3871 3872 for (Container cont = this; cont != null; cont = cont.getContainer()) { 3873 cont.numOfLWComponents -= subLW; 3874 cont.numOfHWComponents -= subHW; 3875 } 3876 } 3877 } 3878 3879 private int getTopmostComponentIndex() { 3880 checkTreeLock(); 3881 if (getComponentCount() > 0) { 3882 return 0; 3883 } 3884 return -1; 3885 } 3886 3887 private int getBottommostComponentIndex() { 3888 checkTreeLock(); 3889 if (getComponentCount() > 0) { 3890 return getComponentCount() - 1; 3891 } 3892 return -1; 3893 } 3894 3895 /* 3896 * This method is overriden to handle opaque children in non-opaque 3897 * containers. 3898 */ 3899 @Override 3900 final Region getOpaqueShape() { 3901 checkTreeLock(); 3902 if (isLightweight() && isNonOpaqueForMixing() 3903 && hasLightweightDescendants()) 3904 { 3905 Region s = Region.EMPTY_REGION; 3906 for (int index = 0; index < getComponentCount(); index++) { 3907 Component c = getComponent(index); 3908 if (c.isLightweight() && c.isShowing()) { 3909 s = s.getUnion(c.getOpaqueShape()); 3910 } 3911 } 3912 return s.getIntersection(getNormalShape()); 3913 } 3914 return super.getOpaqueShape(); 3915 } 3916 3917 final void recursiveSubtractAndApplyShape(Region shape) { 3918 recursiveSubtractAndApplyShape(shape, getTopmostComponentIndex(), getBottommostComponentIndex()); 3919 } 3920 3921 final void recursiveSubtractAndApplyShape(Region shape, int fromZorder) { 3922 recursiveSubtractAndApplyShape(shape, fromZorder, getBottommostComponentIndex()); 3923 } 3924 3925 final void recursiveSubtractAndApplyShape(Region shape, int fromZorder, int toZorder) { 3926 checkTreeLock(); 3927 if (mixingLog.isLoggable(Level.FINE)) { 3928 mixingLog.fine("this = " + this + 3929 "; shape=" + shape + "; fromZ=" + fromZorder + "; toZ=" + toZorder); 3930 } 3931 if (fromZorder == -1) { 3932 return; 3933 } 3934 if (shape.isEmpty()) { 3935 return; 3936 } 3937 // An invalid container with not-null layout should be ignored 3938 // by the mixing code, the container will be validated later 3939 // and the mixing code will be executed later. 3940 if (getLayout() != null && !isValid()) { 3941 return; 3942 } 3943 for (int index = fromZorder; index <= toZorder; index++) { 3944 Component comp = getComponent(index); 3945 if (!comp.isLightweight()) { 3946 comp.subtractAndApplyShape(shape); 3947 } else if (comp instanceof Container && 3948 ((Container)comp).hasHeavyweightDescendants() && comp.isShowing()) { 3949 ((Container)comp).recursiveSubtractAndApplyShape(shape); 3950 } 3951 } 3952 } 3953 3954 final void recursiveApplyCurrentShape() { 3955 recursiveApplyCurrentShape(getTopmostComponentIndex(), getBottommostComponentIndex()); 3956 } 3957 3958 final void recursiveApplyCurrentShape(int fromZorder) { 3959 recursiveApplyCurrentShape(fromZorder, getBottommostComponentIndex()); 3960 } 3961 3962 final void recursiveApplyCurrentShape(int fromZorder, int toZorder) { 3963 checkTreeLock(); 3964 if (mixingLog.isLoggable(Level.FINE)) { 3965 mixingLog.fine("this = " + this + 3966 "; fromZ=" + fromZorder + "; toZ=" + toZorder); 3967 } 3968 if (fromZorder == -1) { 3969 return; 3970 } 3971 // An invalid container with not-null layout should be ignored 3972 // by the mixing code, the container will be validated later 3973 // and the mixing code will be executed later. 3974 if (getLayout() != null && !isValid()) { 3975 return; 3976 } 3977 for (int index = fromZorder; index <= toZorder; index++) { 3978 Component comp = getComponent(index); 3979 if (!comp.isLightweight()) { 3980 comp.applyCurrentShape(); 3981 } 3982 if (comp instanceof Container && 3983 ((Container)comp).hasHeavyweightDescendants()) { 3984 ((Container)comp).recursiveApplyCurrentShape(); 3985 } 3986 } 3987 } 3988 3989 private void recursiveShowHeavyweightChildren() { 3990 if (!hasHeavyweightDescendants() || !isVisible()) { 3991 return; 3992 } 3993 for (int index = 0; index < getComponentCount(); index++) { 3994 Component comp = getComponent(index); 3995 if (comp.isLightweight()) { 3996 if (comp instanceof Container) { 3997 ((Container)comp).recursiveShowHeavyweightChildren(); 3998 } 3999 } else { 4000 if (comp.isVisible()) { 4001 ComponentPeer peer = comp.getPeer(); 4002 if (peer != null) { 4003 peer.setVisible(true); 4004 } 4005 } 4006 } 4007 } 4008 } 4009 4010 private void recursiveHideHeavyweightChildren() { 4011 if (!hasHeavyweightDescendants()) { 4012 return; 4013 } 4014 for (int index = 0; index < getComponentCount(); index++) { 4015 Component comp = getComponent(index); 4016 if (comp.isLightweight()) { 4017 if (comp instanceof Container) { 4018 ((Container)comp).recursiveHideHeavyweightChildren(); 4019 } 4020 } else { 4021 if (comp.isVisible()) { 4022 ComponentPeer peer = comp.getPeer(); 4023 if (peer != null) { 4024 peer.setVisible(false); 4025 } 4026 } 4027 } 4028 } 4029 } 4030 4031 private void recursiveRelocateHeavyweightChildren(Point origin) { 4032 for (int index = 0; index < getComponentCount(); index++) { 4033 Component comp = getComponent(index); 4034 if (comp.isLightweight()) { 4035 if (comp instanceof Container && 4036 ((Container)comp).hasHeavyweightDescendants()) 4037 { 4038 final Point newOrigin = new Point(origin); 4039 newOrigin.translate(comp.getX(), comp.getY()); 4040 ((Container)comp).recursiveRelocateHeavyweightChildren(newOrigin); 4041 } 4042 } else { 4043 ComponentPeer peer = comp.getPeer(); 4044 if (peer != null) { 4045 peer.setBounds(origin.x + comp.getX(), origin.y + comp.getY(), 4046 comp.getWidth(), comp.getHeight(), 4047 ComponentPeer.SET_LOCATION); 4048 } 4049 } 4050 } 4051 } 4052 4053 /* 4054 * Consider the heavyweight container hides or shows the HW descendants 4055 * automatically. Therefore we care of LW containers' visibility only. 4056 */ 4057 private boolean isRecursivelyVisibleUpToHeavyweightContainer() { 4058 if (!isLightweight()) { 4059 return true; 4060 } 4061 return isVisible() && (getContainer() == null || 4062 getContainer().isRecursivelyVisibleUpToHeavyweightContainer()); 4063 } 4064 4065 @Override 4066 void mixOnShowing() { 4067 synchronized (getTreeLock()) { 4068 if (mixingLog.isLoggable(Level.FINE)) { 4069 mixingLog.fine("this = " + this); 4070 } 4071 4072 if (!isMixingNeeded()) { 4073 return; 4074 } 4075 4076 boolean isLightweight = isLightweight(); 4077 4078 if (isLightweight && isRecursivelyVisibleUpToHeavyweightContainer()) { 4079 recursiveShowHeavyweightChildren(); 4080 } 4081 4082 if (!isLightweight || (isLightweight && hasHeavyweightDescendants())) { 4083 recursiveApplyCurrentShape(); 4084 } 4085 4086 super.mixOnShowing(); 4087 } 4088 } 4089 4090 @Override 4091 void mixOnHiding(boolean isLightweight) { 4092 synchronized (getTreeLock()) { 4093 if (mixingLog.isLoggable(Level.FINE)) { 4094 mixingLog.fine("this = " + this + 4095 "; isLightweight=" + isLightweight); 4096 } 4097 if (isLightweight) { 4098 recursiveHideHeavyweightChildren(); 4099 } 4100 super.mixOnHiding(isLightweight); 4101 } 4102 } 4103 4104 @Override 4105 void mixOnReshaping() { 4106 synchronized (getTreeLock()) { 4107 if (mixingLog.isLoggable(Level.FINE)) { 4108 mixingLog.fine("this = " + this); 4109 } 4110 4111 boolean isMixingNeeded = isMixingNeeded(); 4112 4113 if (isLightweight() && hasHeavyweightDescendants()) { 4114 final Point origin = new Point(getX(), getY()); 4115 for (Container cont = getContainer(); 4116 cont != null && cont.isLightweight(); 4117 cont = cont.getContainer()) 4118 { 4119 origin.translate(cont.getX(), cont.getY()); 4120 } 4121 4122 recursiveRelocateHeavyweightChildren(origin); 4123 4124 if (!isMixingNeeded) { 4125 return; 4126 } 4127 4128 recursiveApplyCurrentShape(); 4129 } 4130 4131 if (!isMixingNeeded) { 4132 return; 4133 } 4134 4135 super.mixOnReshaping(); 4136 } 4137 } 4138 4139 @Override 4140 void mixOnZOrderChanging(int oldZorder, int newZorder) { 4141 synchronized (getTreeLock()) { 4142 if (mixingLog.isLoggable(Level.FINE)) { 4143 mixingLog.fine("this = " + this + 4144 "; oldZ=" + oldZorder + "; newZ=" + newZorder); 4145 } 4146 4147 if (!isMixingNeeded()) { 4148 return; 4149 } 4150 4151 boolean becameHigher = newZorder < oldZorder; 4152 4153 if (becameHigher && isLightweight() && hasHeavyweightDescendants()) { 4154 recursiveApplyCurrentShape(); 4155 } 4156 super.mixOnZOrderChanging(oldZorder, newZorder); 4157 } 4158 } 4159 4160 @Override 4161 void mixOnValidating() { 4162 synchronized (getTreeLock()) { 4163 if (mixingLog.isLoggable(Level.FINE)) { 4164 mixingLog.fine("this = " + this); 4165 } 4166 4167 if (!isMixingNeeded()) { 4168 return; 4169 } 4170 4171 if (hasHeavyweightDescendants()) { 4172 recursiveApplyCurrentShape(); 4173 } 4174 4175 if (isLightweight() && isNonOpaqueForMixing()) { 4176 subtractAndApplyShapeBelowMe(); 4177 } 4178 4179 super.mixOnValidating(); 4180 } 4181 } 4182 4183 // ****************** END OF MIXING CODE ******************************** 4184 } 4185 4186 4187 /** 4188 * Class to manage the dispatching of MouseEvents to the lightweight descendants 4189 * and SunDropTargetEvents to both lightweight and heavyweight descendants 4190 * contained by a native container. 4191 * 4192 * NOTE: the class name is not appropriate anymore, but we cannot change it 4193 * because we must keep serialization compatibility. 4194 * 4195 * @author Timothy Prinzing 4196 */ 4197 class LightweightDispatcher implements java.io.Serializable, AWTEventListener { 4198 4199 /* 4200 * JDK 1.1 serialVersionUID 4201 */ 4202 private static final long serialVersionUID = 5184291520170872969L; 4203 /* 4204 * Our own mouse event for when we're dragged over from another hw 4205 * container 4206 */ 4207 private static final int LWD_MOUSE_DRAGGED_OVER = 1500; 4208 4209 private static final Logger eventLog = Logger.getLogger("java.awt.event.LightweightDispatcher"); 4210 4211 LightweightDispatcher(Container nativeContainer) { 4212 this.nativeContainer = nativeContainer; 4213 mouseEventTarget = null; 4214 eventMask = 0; 4215 } 4216 4217 /* 4218 * Clean up any resources allocated when dispatcher was created; 4219 * should be called from Container.removeNotify 4220 */ 4221 void dispose() { 4222 //System.out.println("Disposing lw dispatcher"); 4223 stopListeningForOtherDrags(); 4224 mouseEventTarget = null; 4225 } 4226 4227 /** 4228 * Enables events to subcomponents. 4229 */ 4230 void enableEvents(long events) { 4231 eventMask |= events; 4232 } 4233 4234 /** 4235 * Dispatches an event to a sub-component if necessary, and 4236 * returns whether or not the event was forwarded to a 4237 * sub-component. 4238 * 4239 * @param e the event 4240 */ 4241 boolean dispatchEvent(AWTEvent e) { 4242 boolean ret = false; 4243 4244 /* 4245 * Fix for BugTraq Id 4389284. 4246 * Dispatch SunDropTargetEvents regardless of eventMask value. 4247 * Do not update cursor on dispatching SunDropTargetEvents. 4248 */ 4249 if (e instanceof SunDropTargetEvent) { 4250 4251 SunDropTargetEvent sdde = (SunDropTargetEvent) e; 4252 ret = processDropTargetEvent(sdde); 4253 4254 } else { 4255 if (e instanceof MouseEvent && (eventMask & MOUSE_MASK) != 0) { 4256 MouseEvent me = (MouseEvent) e; 4257 ret = processMouseEvent(me); 4258 } 4259 4260 if (e.getID() == MouseEvent.MOUSE_MOVED) { 4261 nativeContainer.updateCursorImmediately(); 4262 } 4263 } 4264 4265 return ret; 4266 } 4267 4268 /* This method effectively returns whether or not a mouse button was down 4269 * just BEFORE the event happened. A better method name might be 4270 * wasAMouseButtonDownBeforeThisEvent(). 4271 */ 4272 private boolean isMouseGrab(MouseEvent e) { 4273 int modifiers = e.getModifiersEx(); 4274 4275 if(e.getID() == MouseEvent.MOUSE_PRESSED 4276 || e.getID() == MouseEvent.MOUSE_RELEASED) 4277 { 4278 switch (e.getButton()) { 4279 case MouseEvent.BUTTON1: 4280 modifiers ^= InputEvent.BUTTON1_DOWN_MASK; 4281 break; 4282 case MouseEvent.BUTTON2: 4283 modifiers ^= InputEvent.BUTTON2_DOWN_MASK; 4284 break; 4285 case MouseEvent.BUTTON3: 4286 modifiers ^= InputEvent.BUTTON3_DOWN_MASK; 4287 break; 4288 } 4289 } 4290 /* modifiers now as just before event */ 4291 return ((modifiers & (InputEvent.BUTTON1_DOWN_MASK 4292 | InputEvent.BUTTON2_DOWN_MASK 4293 | InputEvent.BUTTON3_DOWN_MASK)) != 0); 4294 } 4295 4296 /** 4297 * This method attempts to distribute a mouse event to a lightweight 4298 * component. It tries to avoid doing any unnecessary probes down 4299 * into the component tree to minimize the overhead of determining 4300 * where to route the event, since mouse movement events tend to 4301 * come in large and frequent amounts. 4302 */ 4303 private boolean processMouseEvent(MouseEvent e) { 4304 int id = e.getID(); 4305 Component mouseOver = // sensitive to mouse events 4306 nativeContainer.getMouseEventTarget(e.getX(), e.getY(), 4307 Container.INCLUDE_SELF); 4308 4309 trackMouseEnterExit(mouseOver, e); 4310 4311 // 4508327 : MOUSE_CLICKED should only go to the recipient of 4312 // the accompanying MOUSE_PRESSED, so don't reset mouseEventTarget on a 4313 // MOUSE_CLICKED. 4314 if (!isMouseGrab(e) && id != MouseEvent.MOUSE_CLICKED) { 4315 mouseEventTarget = (mouseOver != nativeContainer) ? mouseOver: null; 4316 } 4317 4318 if (mouseEventTarget != null) { 4319 switch (id) { 4320 case MouseEvent.MOUSE_ENTERED: 4321 case MouseEvent.MOUSE_EXITED: 4322 break; 4323 case MouseEvent.MOUSE_PRESSED: 4324 retargetMouseEvent(mouseEventTarget, id, e); 4325 break; 4326 case MouseEvent.MOUSE_RELEASED: 4327 retargetMouseEvent(mouseEventTarget, id, e); 4328 break; 4329 case MouseEvent.MOUSE_CLICKED: 4330 // 4508327: MOUSE_CLICKED should never be dispatched to a Component 4331 // other than that which received the MOUSE_PRESSED event. If the 4332 // mouse is now over a different Component, don't dispatch the event. 4333 // The previous fix for a similar problem was associated with bug 4334 // 4155217. 4335 if (mouseOver == mouseEventTarget) { 4336 retargetMouseEvent(mouseOver, id, e); 4337 } 4338 break; 4339 case MouseEvent.MOUSE_MOVED: 4340 retargetMouseEvent(mouseEventTarget, id, e); 4341 break; 4342 case MouseEvent.MOUSE_DRAGGED: 4343 if (isMouseGrab(e)) { 4344 retargetMouseEvent(mouseEventTarget, id, e); 4345 } 4346 break; 4347 case MouseEvent.MOUSE_WHEEL: 4348 // This may send it somewhere that doesn't have MouseWheelEvents 4349 // enabled. In this case, Component.dispatchEventImpl() will 4350 // retarget the event to a parent that DOES have the events enabled. 4351 if (eventLog.isLoggable(Level.FINEST) && (mouseOver != null)) { 4352 eventLog.log(Level.FINEST, "retargeting mouse wheel to " + 4353 mouseOver.getName() + ", " + 4354 mouseOver.getClass()); 4355 } 4356 retargetMouseEvent(mouseOver, id, e); 4357 break; 4358 } 4359 e.consume(); 4360 } 4361 return e.isConsumed(); 4362 } 4363 4364 private boolean processDropTargetEvent(SunDropTargetEvent e) { 4365 int id = e.getID(); 4366 int x = e.getX(); 4367 int y = e.getY(); 4368 4369 /* 4370 * Fix for BugTraq ID 4395290. 4371 * It is possible that SunDropTargetEvent's Point is outside of the 4372 * native container bounds. In this case we truncate coordinates. 4373 */ 4374 if (!nativeContainer.contains(x, y)) { 4375 final Dimension d = nativeContainer.getSize(); 4376 if (d.width <= x) { 4377 x = d.width - 1; 4378 } else if (x < 0) { 4379 x = 0; 4380 } 4381 if (d.height <= y) { 4382 y = d.height - 1; 4383 } else if (y < 0) { 4384 y = 0; 4385 } 4386 } 4387 Component mouseOver = // not necessarily sensitive to mouse events 4388 nativeContainer.getDropTargetEventTarget(x, y, 4389 Container.INCLUDE_SELF); 4390 trackMouseEnterExit(mouseOver, e); 4391 4392 if (mouseOver != nativeContainer && mouseOver != null) { 4393 switch (id) { 4394 case SunDropTargetEvent.MOUSE_ENTERED: 4395 case SunDropTargetEvent.MOUSE_EXITED: 4396 break; 4397 default: 4398 retargetMouseEvent(mouseOver, id, e); 4399 e.consume(); 4400 break; 4401 } 4402 } 4403 return e.isConsumed(); 4404 } 4405 4406 /* 4407 * Generates enter/exit events as mouse moves over lw components 4408 * @param targetOver Target mouse is over (including native container) 4409 * @param e Mouse event in native container 4410 */ 4411 private void trackMouseEnterExit(Component targetOver, MouseEvent e) { 4412 Component targetEnter = null; 4413 int id = e.getID(); 4414 4415 if (e instanceof SunDropTargetEvent && 4416 id == MouseEvent.MOUSE_ENTERED && 4417 isMouseInNativeContainer == true) { 4418 // This can happen if a lightweight component which initiated the 4419 // drag has an associated drop target. MOUSE_ENTERED comes when the 4420 // mouse is in the native container already. To propagate this event 4421 // properly we should null out targetLastEntered. 4422 targetLastEntered = null; 4423 } else if ( id != MouseEvent.MOUSE_EXITED && 4424 id != MouseEvent.MOUSE_DRAGGED && 4425 id != LWD_MOUSE_DRAGGED_OVER && 4426 isMouseInNativeContainer == false ) { 4427 // any event but an exit or drag means we're in the native container 4428 isMouseInNativeContainer = true; 4429 startListeningForOtherDrags(); 4430 } else if ( id == MouseEvent.MOUSE_EXITED ) { 4431 isMouseInNativeContainer = false; 4432 stopListeningForOtherDrags(); 4433 } 4434 4435 if (isMouseInNativeContainer) { 4436 targetEnter = targetOver; 4437 } 4438 4439 if (targetLastEntered == targetEnter) { 4440 return; 4441 } 4442 4443 if (targetLastEntered != null) { 4444 retargetMouseEvent(targetLastEntered, MouseEvent.MOUSE_EXITED, e); 4445 } 4446 if (id == MouseEvent.MOUSE_EXITED) { 4447 // consume native exit event if we generate one 4448 e.consume(); 4449 } 4450 4451 if (targetEnter != null) { 4452 retargetMouseEvent(targetEnter, MouseEvent.MOUSE_ENTERED, e); 4453 } 4454 if (id == MouseEvent.MOUSE_ENTERED) { 4455 // consume native enter event if we generate one 4456 e.consume(); 4457 } 4458 4459 targetLastEntered = targetEnter; 4460 } 4461 4462 /* 4463 * Listens to global mouse drag events so even drags originating 4464 * from other heavyweight containers will generate enter/exit 4465 * events in this container 4466 */ 4467 private void startListeningForOtherDrags() { 4468 //System.out.println("Adding AWTEventListener"); 4469 java.security.AccessController.doPrivileged( 4470 new java.security.PrivilegedAction() { 4471 public Object run() { 4472 nativeContainer.getToolkit().addAWTEventListener( 4473 LightweightDispatcher.this, 4474 AWTEvent.MOUSE_EVENT_MASK | 4475 AWTEvent.MOUSE_MOTION_EVENT_MASK); 4476 return null; 4477 } 4478 } 4479 ); 4480 } 4481 4482 private void stopListeningForOtherDrags() { 4483 //System.out.println("Removing AWTEventListener"); 4484 java.security.AccessController.doPrivileged( 4485 new java.security.PrivilegedAction() { 4486 public Object run() { 4487 nativeContainer.getToolkit().removeAWTEventListener(LightweightDispatcher.this); 4488 return null; 4489 } 4490 } 4491 ); 4492 } 4493 4494 /* 4495 * (Implementation of AWTEventListener) 4496 * Listen for drag events posted in other hw components so we can 4497 * track enter/exit regardless of where a drag originated 4498 */ 4499 public void eventDispatched(AWTEvent e) { 4500 boolean isForeignDrag = (e instanceof MouseEvent) && 4501 !(e instanceof SunDropTargetEvent) && 4502 (e.id == MouseEvent.MOUSE_DRAGGED) && 4503 (e.getSource() != nativeContainer); 4504 4505 if (!isForeignDrag) { 4506 // only interested in drags from other hw components 4507 return; 4508 } 4509 4510 MouseEvent srcEvent = (MouseEvent)e; 4511 MouseEvent me; 4512 4513 synchronized (nativeContainer.getTreeLock()) { 4514 Component srcComponent = srcEvent.getComponent(); 4515 4516 // component may have disappeared since drag event posted 4517 // (i.e. Swing hierarchical menus) 4518 if ( !srcComponent.isShowing() ) { 4519 return; 4520 } 4521 4522 // see 5083555 4523 // check if srcComponent is in any modal blocked window 4524 Component c = nativeContainer; 4525 while ((c != null) && !(c instanceof Window)) { 4526 c = c.getParent_NoClientCode(); 4527 } 4528 if ((c == null) || ((Window)c).isModalBlocked()) { 4529 return; 4530 } 4531 4532 // 4533 // create an internal 'dragged-over' event indicating 4534 // we are being dragged over from another hw component 4535 // 4536 me = new MouseEvent(nativeContainer, 4537 LWD_MOUSE_DRAGGED_OVER, 4538 srcEvent.getWhen(), 4539 srcEvent.getModifiersEx() | srcEvent.getModifiers(), 4540 srcEvent.getX(), 4541 srcEvent.getY(), 4542 srcEvent.getXOnScreen(), 4543 srcEvent.getYOnScreen(), 4544 srcEvent.getClickCount(), 4545 srcEvent.isPopupTrigger(), 4546 srcEvent.getButton()); 4547 ((AWTEvent)srcEvent).copyPrivateDataInto(me); 4548 // translate coordinates to this native container 4549 final Point ptSrcOrigin = srcComponent.getLocationOnScreen(); 4550 4551 if (AppContext.getAppContext() != nativeContainer.appContext) { 4552 final MouseEvent mouseEvent = me; 4553 Runnable r = new Runnable() { 4554 public void run() { 4555 if (!nativeContainer.isShowing() ) { 4556 return; 4557 } 4558 4559 Point ptDstOrigin = nativeContainer.getLocationOnScreen(); 4560 mouseEvent.translatePoint(ptSrcOrigin.x - ptDstOrigin.x, 4561 ptSrcOrigin.y - ptDstOrigin.y ); 4562 Component targetOver = 4563 nativeContainer.getMouseEventTarget(mouseEvent.getX(), 4564 mouseEvent.getY(), 4565 Container.INCLUDE_SELF); 4566 trackMouseEnterExit(targetOver, mouseEvent); 4567 } 4568 }; 4569 SunToolkit.executeOnEventHandlerThread(nativeContainer, r); 4570 return; 4571 } else { 4572 if (!nativeContainer.isShowing() ) { 4573 return; 4574 } 4575 4576 Point ptDstOrigin = nativeContainer.getLocationOnScreen(); 4577 me.translatePoint( ptSrcOrigin.x - ptDstOrigin.x, ptSrcOrigin.y - ptDstOrigin.y ); 4578 } 4579 } 4580 //System.out.println("Track event: " + me); 4581 // feed the 'dragged-over' event directly to the enter/exit 4582 // code (not a real event so don't pass it to dispatchEvent) 4583 Component targetOver = 4584 nativeContainer.getMouseEventTarget(me.getX(), me.getY(), 4585 Container.INCLUDE_SELF); 4586 trackMouseEnterExit(targetOver, me); 4587 } 4588 4589 /** 4590 * Sends a mouse event to the current mouse event recipient using 4591 * the given event (sent to the windowed host) as a srcEvent. If 4592 * the mouse event target is still in the component tree, the 4593 * coordinates of the event are translated to those of the target. 4594 * If the target has been removed, we don't bother to send the 4595 * message. 4596 */ 4597 void retargetMouseEvent(Component target, int id, MouseEvent e) { 4598 if (target == null) { 4599 return; // mouse is over another hw component or target is disabled 4600 } 4601 4602 int x = e.getX(), y = e.getY(); 4603 Component component; 4604 4605 for(component = target; 4606 component != null && component != nativeContainer; 4607 component = component.getParent()) { 4608 x -= component.x; 4609 y -= component.y; 4610 } 4611 MouseEvent retargeted; 4612 if (component != null) { 4613 if (e instanceof SunDropTargetEvent) { 4614 retargeted = new SunDropTargetEvent(target, 4615 id, 4616 x, 4617 y, 4618 ((SunDropTargetEvent)e).getDispatcher()); 4619 } else if (id == MouseEvent.MOUSE_WHEEL) { 4620 retargeted = new MouseWheelEvent(target, 4621 id, 4622 e.getWhen(), 4623 e.getModifiersEx() | e.getModifiers(), 4624 x, 4625 y, 4626 e.getXOnScreen(), 4627 e.getYOnScreen(), 4628 e.getClickCount(), 4629 e.isPopupTrigger(), 4630 ((MouseWheelEvent)e).getScrollType(), 4631 ((MouseWheelEvent)e).getScrollAmount(), 4632 ((MouseWheelEvent)e).getWheelRotation(), 4633 ((MouseWheelEvent)e).getPreciseWheelRotation()); 4634 } 4635 else { 4636 retargeted = new MouseEvent(target, 4637 id, 4638 e.getWhen(), 4639 e.getModifiersEx() | e.getModifiers(), 4640 x, 4641 y, 4642 e.getXOnScreen(), 4643 e.getYOnScreen(), 4644 e.getClickCount(), 4645 e.isPopupTrigger(), 4646 e.getButton()); 4647 } 4648 4649 ((AWTEvent)e).copyPrivateDataInto(retargeted); 4650 4651 if (target == nativeContainer) { 4652 // avoid recursively calling LightweightDispatcher... 4653 ((Container)target).dispatchEventToSelf(retargeted); 4654 } else { 4655 assert AppContext.getAppContext() == target.appContext; 4656 4657 if (nativeContainer.modalComp != null) { 4658 if (((Container)nativeContainer.modalComp).isAncestorOf(target)) { 4659 target.dispatchEvent(retargeted); 4660 } else { 4661 e.consume(); 4662 } 4663 } else { 4664 target.dispatchEvent(retargeted); 4665 } 4666 } 4667 } 4668 } 4669 4670 // --- member variables ------------------------------- 4671 4672 /** 4673 * The windowed container that might be hosting events for 4674 * subcomponents. 4675 */ 4676 private Container nativeContainer; 4677 4678 /** 4679 * This variable is not used, but kept for serialization compatibility 4680 */ 4681 private Component focus; 4682 4683 /** 4684 * The current subcomponent being hosted by this windowed 4685 * component that has events being forwarded to it. If this 4686 * is null, there are currently no events being forwarded to 4687 * a subcomponent. 4688 */ 4689 private transient Component mouseEventTarget; 4690 4691 /** 4692 * The last component entered 4693 */ 4694 private transient Component targetLastEntered; 4695 4696 /** 4697 * Is the mouse over the native container 4698 */ 4699 private transient boolean isMouseInNativeContainer = false; 4700 4701 /** 4702 * This variable is not used, but kept for serialization compatibility 4703 */ 4704 private Cursor nativeCursor; 4705 4706 /** 4707 * The event mask for contained lightweight components. Lightweight 4708 * components need a windowed container to host window-related 4709 * events. This separate mask indicates events that have been 4710 * requested by contained lightweight components without effecting 4711 * the mask of the windowed component itself. 4712 */ 4713 private long eventMask; 4714 4715 /** 4716 * The kind of events routed to lightweight components from windowed 4717 * hosts. 4718 */ 4719 private static final long PROXY_EVENT_MASK = 4720 AWTEvent.FOCUS_EVENT_MASK | 4721 AWTEvent.KEY_EVENT_MASK | 4722 AWTEvent.MOUSE_EVENT_MASK | 4723 AWTEvent.MOUSE_MOTION_EVENT_MASK | 4724 AWTEvent.MOUSE_WHEEL_EVENT_MASK; 4725 4726 private static final long MOUSE_MASK = 4727 AWTEvent.MOUSE_EVENT_MASK | 4728 AWTEvent.MOUSE_MOTION_EVENT_MASK | 4729 AWTEvent.MOUSE_WHEEL_EVENT_MASK; 4730 }