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