Frames | No Frames |
1: /* Container.java -- parent container class in AWT 2: Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 2006 3: Free Software Foundation 4: 5: This file is part of GNU Classpath. 6: 7: GNU Classpath is free software; you can redistribute it and/or modify 8: it under the terms of the GNU General Public License as published by 9: the Free Software Foundation; either version 2, or (at your option) 10: any later version. 11: 12: GNU Classpath is distributed in the hope that it will be useful, but 13: WITHOUT ANY WARRANTY; without even the implied warranty of 14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15: General Public License for more details. 16: 17: You should have received a copy of the GNU General Public License 18: along with GNU Classpath; see the file COPYING. If not, write to the 19: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20: 02110-1301 USA. 21: 22: Linking this library statically or dynamically with other modules is 23: making a combined work based on this library. Thus, the terms and 24: conditions of the GNU General Public License cover the whole 25: combination. 26: 27: As a special exception, the copyright holders of this library give you 28: permission to link this library with independent modules to produce an 29: executable, regardless of the license terms of these independent 30: modules, and to copy and distribute the resulting executable under 31: terms of your choice, provided that you also meet, for each linked 32: independent module, the terms and conditions of the license of that 33: module. An independent module is a module which is not derived from 34: or based on this library. If you modify this library, you may extend 35: this exception to your version of the library, but you are not 36: obligated to do so. If you do not wish to do so, delete this 37: exception statement from your version. */ 38: 39: 40: package java.awt; 41: 42: import gnu.java.lang.CPStringBuilder; 43: 44: import java.awt.event.ContainerEvent; 45: import java.awt.event.ContainerListener; 46: import java.awt.event.HierarchyEvent; 47: import java.awt.event.KeyEvent; 48: import java.awt.event.MouseEvent; 49: import java.awt.peer.ComponentPeer; 50: import java.awt.peer.ContainerPeer; 51: import java.awt.peer.LightweightPeer; 52: import java.beans.PropertyChangeListener; 53: import java.io.IOException; 54: import java.io.ObjectInputStream; 55: import java.io.ObjectOutputStream; 56: import java.io.PrintStream; 57: import java.io.PrintWriter; 58: import java.io.Serializable; 59: import java.util.Collections; 60: import java.util.EventListener; 61: import java.util.HashSet; 62: import java.util.Iterator; 63: import java.util.Set; 64: 65: import javax.accessibility.Accessible; 66: 67: /** 68: * A generic window toolkit object that acts as a container for other objects. 69: * Components are tracked in a list, and new elements are at the end of the 70: * list or bottom of the stacking order. 71: * 72: * @author original author unknown 73: * @author Eric Blake (ebb9@email.byu.edu) 74: * @author Andrew John Hughes (gnu_andrew@member.fsf.org) 75: * 76: * @since 1.0 77: * 78: * @status still missing 1.4 support, some generics from 1.5 79: */ 80: public class Container extends Component 81: { 82: /** 83: * Compatible with JDK 1.0+. 84: */ 85: private static final long serialVersionUID = 4613797578919906343L; 86: 87: /* Serialized fields from the serialization spec. */ 88: int ncomponents; 89: Component[] component; 90: LayoutManager layoutMgr; 91: 92: /** 93: * @since 1.4 94: */ 95: boolean focusCycleRoot; 96: 97: /** 98: * Indicates if this container provides a focus traversal policy. 99: * 100: * @since 1.5 101: */ 102: private boolean focusTraversalPolicyProvider; 103: 104: int containerSerializedDataVersion; 105: 106: /* Anything else is non-serializable, and should be declared "transient". */ 107: transient ContainerListener containerListener; 108: 109: /** The focus traversal policy that determines how focus is 110: transferred between this Container and its children. */ 111: private FocusTraversalPolicy focusTraversalPolicy; 112: 113: /** 114: * The focus traversal keys, if not inherited from the parent or default 115: * keyboard manager. These sets will contain only AWTKeyStrokes that 116: * represent press and release events to use as focus control. 117: * 118: * @see #getFocusTraversalKeys(int) 119: * @see #setFocusTraversalKeys(int, Set) 120: * @since 1.4 121: */ 122: transient Set[] focusTraversalKeys; 123: 124: /** 125: * Default constructor for subclasses. 126: */ 127: public Container() 128: { 129: // Nothing to do here. 130: } 131: 132: /** 133: * Returns the number of components in this container. 134: * 135: * @return The number of components in this container. 136: */ 137: public int getComponentCount() 138: { 139: return countComponents (); 140: } 141: 142: /** 143: * Returns the number of components in this container. 144: * 145: * @return The number of components in this container. 146: * 147: * @deprecated use {@link #getComponentCount()} instead 148: */ 149: public int countComponents() 150: { 151: return ncomponents; 152: } 153: 154: /** 155: * Returns the component at the specified index. 156: * 157: * @param n The index of the component to retrieve. 158: * 159: * @return The requested component. 160: * 161: * @throws ArrayIndexOutOfBoundsException If the specified index is invalid 162: */ 163: public Component getComponent(int n) 164: { 165: synchronized (getTreeLock ()) 166: { 167: if (n < 0 || n >= ncomponents) 168: throw new ArrayIndexOutOfBoundsException("no such component"); 169: 170: return component[n]; 171: } 172: } 173: 174: /** 175: * Returns an array of the components in this container. 176: * 177: * @return The components in this container. 178: */ 179: public Component[] getComponents() 180: { 181: synchronized (getTreeLock ()) 182: { 183: Component[] result = new Component[ncomponents]; 184: 185: if (ncomponents > 0) 186: System.arraycopy(component, 0, result, 0, ncomponents); 187: 188: return result; 189: } 190: } 191: 192: /** 193: * Returns the insets for this container, which is the space used for 194: * borders, the margin, etc. 195: * 196: * @return The insets for this container. 197: */ 198: public Insets getInsets() 199: { 200: return insets (); 201: } 202: 203: /** 204: * Returns the insets for this container, which is the space used for 205: * borders, the margin, etc. 206: * 207: * @return The insets for this container. 208: * @deprecated use {@link #getInsets()} instead 209: */ 210: public Insets insets() 211: { 212: Insets i; 213: if (peer == null || peer instanceof LightweightPeer) 214: i = new Insets (0, 0, 0, 0); 215: else 216: i = ((ContainerPeer) peer).getInsets (); 217: return i; 218: } 219: 220: /** 221: * Adds the specified component to this container at the end of the 222: * component list. 223: * 224: * @param comp The component to add to the container. 225: * 226: * @return The same component that was added. 227: */ 228: public Component add(Component comp) 229: { 230: addImpl(comp, null, -1); 231: return comp; 232: } 233: 234: /** 235: * Adds the specified component to the container at the end of the 236: * component list. This method should not be used. Instead, use 237: * <code>add(Component, Object)</code>. 238: * 239: * @param name The name of the component to be added. 240: * @param comp The component to be added. 241: * 242: * @return The same component that was added. 243: * 244: * @see #add(Component,Object) 245: */ 246: public Component add(String name, Component comp) 247: { 248: addImpl(comp, name, -1); 249: return comp; 250: } 251: 252: /** 253: * Adds the specified component to this container at the specified index 254: * in the component list. 255: * 256: * @param comp The component to be added. 257: * @param index The index in the component list to insert this child 258: * at, or -1 to add at the end of the list. 259: * 260: * @return The same component that was added. 261: * 262: * @throws ArrayIndexOutOfBoundsException If the specified index is invalid. 263: */ 264: public Component add(Component comp, int index) 265: { 266: addImpl(comp, null, index); 267: return comp; 268: } 269: 270: /** 271: * Adds the specified component to this container at the end of the 272: * component list. The layout manager will use the specified constraints 273: * when laying out this component. 274: * 275: * @param comp The component to be added to this container. 276: * @param constraints The layout constraints for this component. 277: */ 278: public void add(Component comp, Object constraints) 279: { 280: addImpl(comp, constraints, -1); 281: } 282: 283: /** 284: * Adds the specified component to this container at the specified index 285: * in the component list. The layout manager will use the specified 286: * constraints when layout out this component. 287: * 288: * @param comp The component to be added. 289: * @param constraints The layout constraints for this component. 290: * @param index The index in the component list to insert this child 291: * at, or -1 to add at the end of the list. 292: * 293: * @throws ArrayIndexOutOfBoundsException If the specified index is invalid. 294: */ 295: public void add(Component comp, Object constraints, int index) 296: { 297: addImpl(comp, constraints, index); 298: } 299: 300: /** 301: * This method is called by all the <code>add()</code> methods to perform 302: * the actual adding of the component. Subclasses who wish to perform 303: * their own processing when a component is added should override this 304: * method. Any subclass doing this must call the superclass version of 305: * this method in order to ensure proper functioning of the container. 306: * 307: * @param comp The component to be added. 308: * @param constraints The layout constraints for this component, or 309: * <code>null</code> if there are no constraints. 310: * @param index The index in the component list to insert this child 311: * at, or -1 to add at the end of the list. 312: * 313: * @throws ArrayIndexOutOfBoundsException If the specified index is invalid. 314: */ 315: protected void addImpl(Component comp, Object constraints, int index) 316: { 317: synchronized (getTreeLock ()) 318: { 319: if (index > ncomponents 320: || (index < 0 && index != -1) 321: || comp instanceof Window 322: || (comp instanceof Container 323: && ((Container) comp).isAncestorOf(this))) 324: throw new IllegalArgumentException(); 325: 326: // Reparent component, and make sure component is instantiated if 327: // we are. 328: if (comp.parent != null) 329: comp.parent.remove(comp); 330: 331: if (component == null) 332: component = new Component[4]; // FIXME, better initial size? 333: 334: // This isn't the most efficient implementation. We could do less 335: // copying when growing the array. It probably doesn't matter. 336: if (ncomponents >= component.length) 337: { 338: int nl = component.length * 2; 339: Component[] c = new Component[nl]; 340: System.arraycopy(component, 0, c, 0, ncomponents); 341: component = c; 342: } 343: 344: if (index == -1) 345: component[ncomponents++] = comp; 346: else 347: { 348: System.arraycopy(component, index, component, index + 1, 349: ncomponents - index); 350: component[index] = comp; 351: ++ncomponents; 352: } 353: 354: // Give the new component a parent. 355: comp.parent = this; 356: 357: // Update the counter for Hierarchy(Bounds)Listeners. 358: int childHierarchyListeners = comp.numHierarchyListeners; 359: if (childHierarchyListeners > 0) 360: updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK, 361: childHierarchyListeners); 362: int childHierarchyBoundsListeners = comp.numHierarchyBoundsListeners; 363: if (childHierarchyBoundsListeners > 0) 364: updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, 365: childHierarchyListeners); 366: 367: // Invalidate the layout of this container. 368: if (valid) 369: invalidate(); 370: 371: // Create the peer _after_ the component has been added, so that 372: // the peer gets to know about the component hierarchy. 373: if (peer != null) 374: { 375: // Notify the component that it has a new parent. 376: comp.addNotify(); 377: } 378: 379: // Notify the layout manager. 380: if (layoutMgr != null) 381: { 382: // If we have a LayoutManager2 the constraints are "real", 383: // otherwise they are the "name" of the Component to add. 384: if (layoutMgr instanceof LayoutManager2) 385: { 386: LayoutManager2 lm2 = (LayoutManager2) layoutMgr; 387: lm2.addLayoutComponent(comp, constraints); 388: } 389: else if (constraints instanceof String) 390: layoutMgr.addLayoutComponent((String) constraints, comp); 391: else 392: layoutMgr.addLayoutComponent("", comp); 393: } 394: 395: // We previously only sent an event when this container is showing. 396: // Also, the event was posted to the event queue. A Mauve test shows 397: // that this event is not delivered using the event queue and it is 398: // also sent when the container is not showing. 399: if (containerListener != null 400: || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0) 401: { 402: ContainerEvent ce = new ContainerEvent(this, 403: ContainerEvent.COMPONENT_ADDED, 404: comp); 405: dispatchEvent(ce); 406: } 407: 408: // Notify hierarchy listeners. 409: comp.fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, comp, 410: this, HierarchyEvent.PARENT_CHANGED); 411: } 412: } 413: 414: /** 415: * Removes the component at the specified index from this container. 416: * 417: * @param index The index of the component to remove. 418: */ 419: public void remove(int index) 420: { 421: synchronized (getTreeLock ()) 422: { 423: if (index < 0 || index >= ncomponents) 424: throw new ArrayIndexOutOfBoundsException(); 425: 426: Component r = component[index]; 427: if (peer != null) 428: r.removeNotify(); 429: 430: if (layoutMgr != null) 431: layoutMgr.removeLayoutComponent(r); 432: 433: // Update the counter for Hierarchy(Bounds)Listeners. 434: int childHierarchyListeners = r.numHierarchyListeners; 435: if (childHierarchyListeners > 0) 436: updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK, 437: -childHierarchyListeners); 438: int childHierarchyBoundsListeners = r.numHierarchyBoundsListeners; 439: if (childHierarchyBoundsListeners > 0) 440: updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, 441: -childHierarchyListeners); 442: 443: r.parent = null; 444: 445: System.arraycopy(component, index + 1, component, index, 446: ncomponents - index - 1); 447: component[--ncomponents] = null; 448: 449: if (valid) 450: invalidate(); 451: 452: if (containerListener != null 453: || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0) 454: { 455: // Post event to notify of removing the component. 456: ContainerEvent ce = new ContainerEvent(this, 457: ContainerEvent.COMPONENT_REMOVED, 458: r); 459: dispatchEvent(ce); 460: } 461: 462: // Notify hierarchy listeners. 463: r.fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, r, 464: this, HierarchyEvent.PARENT_CHANGED); 465: } 466: } 467: 468: /** 469: * Removes the specified component from this container. 470: * 471: * @param comp The component to remove from this container. 472: */ 473: public void remove(Component comp) 474: { 475: synchronized (getTreeLock ()) 476: { 477: for (int i = 0; i < ncomponents; ++i) 478: { 479: if (component[i] == comp) 480: { 481: remove(i); 482: break; 483: } 484: } 485: } 486: } 487: 488: /** 489: * Removes all components from this container. 490: */ 491: public void removeAll() 492: { 493: synchronized (getTreeLock ()) 494: { 495: // In order to allow the same bad tricks to be used as in RI 496: // this code has to stay exactly that way: In a real-life app 497: // a Container subclass implemented its own vector for 498: // subcomponents, supplied additional addXYZ() methods 499: // and overrode remove(int) and removeAll (the latter calling 500: // super.removeAll() ). 501: // By doing it this way, user code cannot prevent the correct 502: // removal of components. 503: while (ncomponents > 0) 504: { 505: ncomponents--; 506: Component r = component[ncomponents]; 507: component[ncomponents] = null; 508: 509: if (peer != null) 510: r.removeNotify(); 511: 512: if (layoutMgr != null) 513: layoutMgr.removeLayoutComponent(r); 514: 515: r.parent = null; 516: 517: // Send ContainerEvent if necessary. 518: if (containerListener != null 519: || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0) 520: { 521: // Post event to notify of removing the component. 522: ContainerEvent ce 523: = new ContainerEvent(this, 524: ContainerEvent.COMPONENT_REMOVED, 525: r); 526: dispatchEvent(ce); 527: } 528: 529: // Update the counter for Hierarchy(Bounds)Listeners. 530: int childHierarchyListeners = r.numHierarchyListeners; 531: if (childHierarchyListeners > 0) 532: updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK, 533: -childHierarchyListeners); 534: int childHierarchyBoundsListeners = r.numHierarchyBoundsListeners; 535: if (childHierarchyBoundsListeners > 0) 536: updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, 537: -childHierarchyListeners); 538: 539: 540: // Send HierarchyEvent if necessary. 541: fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, r, this, 542: HierarchyEvent.PARENT_CHANGED); 543: 544: } 545: 546: if (valid) 547: invalidate(); 548: } 549: } 550: 551: /** 552: * Returns the current layout manager for this container. 553: * 554: * @return The layout manager for this container. 555: */ 556: public LayoutManager getLayout() 557: { 558: return layoutMgr; 559: } 560: 561: /** 562: * Sets the layout manager for this container to the specified layout 563: * manager. 564: * 565: * @param mgr The new layout manager for this container. 566: */ 567: public void setLayout(LayoutManager mgr) 568: { 569: layoutMgr = mgr; 570: if (valid) 571: invalidate(); 572: } 573: 574: /** 575: * Layout the components in this container. 576: */ 577: public void doLayout() 578: { 579: layout (); 580: } 581: 582: /** 583: * Layout the components in this container. 584: * 585: * @deprecated use {@link #doLayout()} instead 586: */ 587: public void layout() 588: { 589: if (layoutMgr != null) 590: layoutMgr.layoutContainer (this); 591: } 592: 593: /** 594: * Invalidates this container to indicate that it (and all parent 595: * containers) need to be laid out. 596: */ 597: public void invalidate() 598: { 599: super.invalidate(); 600: if (layoutMgr != null && layoutMgr instanceof LayoutManager2) 601: { 602: LayoutManager2 lm2 = (LayoutManager2) layoutMgr; 603: lm2.invalidateLayout(this); 604: } 605: } 606: 607: /** 608: * Re-lays out the components in this container. 609: */ 610: public void validate() 611: { 612: ComponentPeer p = peer; 613: if (! valid && p != null) 614: { 615: ContainerPeer cPeer = null; 616: if (p instanceof ContainerPeer) 617: cPeer = (ContainerPeer) peer; 618: synchronized (getTreeLock ()) 619: { 620: if (cPeer != null) 621: cPeer.beginValidate(); 622: validateTree(); 623: valid = true; 624: if (cPeer != null) 625: cPeer.endValidate(); 626: } 627: } 628: } 629: 630: /** 631: * Recursively invalidates the container tree. 632: */ 633: private final void invalidateTree() 634: { 635: synchronized (getTreeLock()) 636: { 637: for (int i = 0; i < ncomponents; i++) 638: { 639: Component comp = component[i]; 640: if (comp instanceof Container) 641: ((Container) comp).invalidateTree(); 642: else if (comp.valid) 643: comp.invalidate(); 644: } 645: if (valid) 646: invalidate(); 647: } 648: } 649: 650: /** 651: * Recursively validates the container tree, recomputing any invalid 652: * layouts. 653: */ 654: protected void validateTree() 655: { 656: if (!valid) 657: { 658: ContainerPeer cPeer = null; 659: if (peer instanceof ContainerPeer) 660: { 661: cPeer = (ContainerPeer) peer; 662: cPeer.beginLayout(); 663: } 664: 665: doLayout (); 666: for (int i = 0; i < ncomponents; ++i) 667: { 668: Component comp = component[i]; 669: 670: if (comp instanceof Container && ! (comp instanceof Window) 671: && ! comp.valid) 672: { 673: ((Container) comp).validateTree(); 674: } 675: else 676: { 677: comp.validate(); 678: } 679: } 680: 681: if (cPeer != null) 682: { 683: cPeer = (ContainerPeer) peer; 684: cPeer.endLayout(); 685: } 686: } 687: 688: /* children will call invalidate() when they are layed out. It 689: is therefore important that valid is not set to true 690: until after the children have been layed out. */ 691: valid = true; 692: 693: } 694: 695: public void setFont(Font f) 696: { 697: Font oldFont = getFont(); 698: super.setFont(f); 699: Font newFont = getFont(); 700: if (newFont != oldFont && (oldFont == null || ! oldFont.equals(newFont))) 701: { 702: invalidateTree(); 703: } 704: } 705: 706: /** 707: * Returns the preferred size of this container. 708: * 709: * @return The preferred size of this container. 710: */ 711: public Dimension getPreferredSize() 712: { 713: return preferredSize (); 714: } 715: 716: /** 717: * Returns the preferred size of this container. 718: * 719: * @return The preferred size of this container. 720: * 721: * @deprecated use {@link #getPreferredSize()} instead 722: */ 723: public Dimension preferredSize() 724: { 725: Dimension size = prefSize; 726: // Try to return cached value if possible. 727: if (size == null || !(prefSizeSet || valid)) 728: { 729: // Need to lock here. 730: synchronized (getTreeLock()) 731: { 732: LayoutManager l = layoutMgr; 733: if (l != null) 734: prefSize = l.preferredLayoutSize(this); 735: else 736: prefSize = super.preferredSizeImpl(); 737: size = prefSize; 738: } 739: } 740: if (size != null) 741: return new Dimension(size); 742: else 743: return size; 744: } 745: 746: /** 747: * Returns the minimum size of this container. 748: * 749: * @return The minimum size of this container. 750: */ 751: public Dimension getMinimumSize() 752: { 753: return minimumSize (); 754: } 755: 756: /** 757: * Returns the minimum size of this container. 758: * 759: * @return The minimum size of this container. 760: * 761: * @deprecated use {@link #getMinimumSize()} instead 762: */ 763: public Dimension minimumSize() 764: { 765: Dimension size = minSize; 766: // Try to return cached value if possible. 767: if (size == null || !(minSizeSet || valid)) 768: { 769: // Need to lock here. 770: synchronized (getTreeLock()) 771: { 772: LayoutManager l = layoutMgr; 773: if (l != null) 774: minSize = l.minimumLayoutSize(this); 775: else 776: minSize = super.minimumSizeImpl(); 777: size = minSize; 778: } 779: } 780: if (size != null) 781: return new Dimension(size); 782: else 783: return size; 784: } 785: 786: /** 787: * Returns the maximum size of this container. 788: * 789: * @return The maximum size of this container. 790: */ 791: public Dimension getMaximumSize() 792: { 793: Dimension size = maxSize; 794: // Try to return cached value if possible. 795: if (size == null || !(maxSizeSet || valid)) 796: { 797: // Need to lock here. 798: synchronized (getTreeLock()) 799: { 800: LayoutManager l = layoutMgr; 801: if (l instanceof LayoutManager2) 802: maxSize = ((LayoutManager2) l).maximumLayoutSize(this); 803: else { 804: maxSize = super.maximumSizeImpl(); 805: } 806: size = maxSize; 807: } 808: } 809: if (size != null) 810: return new Dimension(size); 811: else 812: return size; 813: } 814: 815: /** 816: * Returns the preferred alignment along the X axis. This is a value 817: * between 0 and 1 where 0 represents alignment flush left and 818: * 1 means alignment flush right, and 0.5 means centered. 819: * 820: * @return The preferred alignment along the X axis. 821: */ 822: public float getAlignmentX() 823: { 824: LayoutManager layout = getLayout(); 825: float alignmentX = 0.0F; 826: if (layout != null && layout instanceof LayoutManager2) 827: { 828: synchronized (getTreeLock()) 829: { 830: LayoutManager2 lm2 = (LayoutManager2) layout; 831: alignmentX = lm2.getLayoutAlignmentX(this); 832: } 833: } 834: else 835: alignmentX = super.getAlignmentX(); 836: return alignmentX; 837: } 838: 839: /** 840: * Returns the preferred alignment along the Y axis. This is a value 841: * between 0 and 1 where 0 represents alignment flush top and 842: * 1 means alignment flush bottom, and 0.5 means centered. 843: * 844: * @return The preferred alignment along the Y axis. 845: */ 846: public float getAlignmentY() 847: { 848: LayoutManager layout = getLayout(); 849: float alignmentY = 0.0F; 850: if (layout != null && layout instanceof LayoutManager2) 851: { 852: synchronized (getTreeLock()) 853: { 854: LayoutManager2 lm2 = (LayoutManager2) layout; 855: alignmentY = lm2.getLayoutAlignmentY(this); 856: } 857: } 858: else 859: alignmentY = super.getAlignmentY(); 860: return alignmentY; 861: } 862: 863: /** 864: * Paints this container. The implementation of this method in this 865: * class forwards to any lightweight components in this container. If 866: * this method is subclassed, this method should still be invoked as 867: * a superclass method so that lightweight components are properly 868: * drawn. 869: * 870: * @param g - The graphics context for this paint job. 871: */ 872: public void paint(Graphics g) 873: { 874: if (isShowing()) 875: { 876: visitChildren(g, GfxPaintVisitor.INSTANCE, true); 877: } 878: } 879: 880: /** 881: * Updates this container. The implementation of this method in this 882: * class forwards to any lightweight components in this container. If 883: * this method is subclassed, this method should still be invoked as 884: * a superclass method so that lightweight components are properly 885: * drawn. 886: * 887: * @param g The graphics context for this update. 888: * 889: * @specnote The specification suggests that this method forwards the 890: * update() call to all its lightweight children. Tests show 891: * that this is not done either in the JDK. The exact behaviour 892: * seems to be that the background is cleared in heavyweight 893: * Containers, and all other containers 894: * directly call paint(), causing the (lightweight) children to 895: * be painted. 896: */ 897: public void update(Graphics g) 898: { 899: // It seems that the JDK clears the background of containers like Panel 900: // and Window (within this method) but not of 'plain' Containers or 901: // JComponents. This could 902: // lead to the assumption that it only clears heavyweight containers. 903: // However that is not quite true. In a test with a custom Container 904: // that overrides isLightweight() to return false, the background is 905: // also not cleared. So we do a check on !(peer instanceof LightweightPeer) 906: // instead. 907: if (isShowing()) 908: { 909: ComponentPeer p = peer; 910: if (! (p instanceof LightweightPeer)) 911: { 912: g.clearRect(0, 0, getWidth(), getHeight()); 913: } 914: paint(g); 915: } 916: } 917: 918: /** 919: * Prints this container. The implementation of this method in this 920: * class forwards to any lightweight components in this container. If 921: * this method is subclassed, this method should still be invoked as 922: * a superclass method so that lightweight components are properly 923: * drawn. 924: * 925: * @param g The graphics context for this print job. 926: */ 927: public void print(Graphics g) 928: { 929: super.print(g); 930: visitChildren(g, GfxPrintVisitor.INSTANCE, true); 931: } 932: 933: /** 934: * Paints all of the components in this container. 935: * 936: * @param g The graphics context for this paint job. 937: */ 938: public void paintComponents(Graphics g) 939: { 940: if (isShowing()) 941: visitChildren(g, GfxPaintAllVisitor.INSTANCE, false); 942: } 943: 944: /** 945: * Prints all of the components in this container. 946: * 947: * @param g The graphics context for this print job. 948: */ 949: public void printComponents(Graphics g) 950: { 951: super.paint(g); 952: visitChildren(g, GfxPrintAllVisitor.INSTANCE, true); 953: } 954: 955: /** 956: * Adds the specified container listener to this object's list of 957: * container listeners. 958: * 959: * @param listener The listener to add. 960: */ 961: public synchronized void addContainerListener(ContainerListener listener) 962: { 963: if (listener != null) 964: { 965: containerListener = AWTEventMulticaster.add(containerListener, 966: listener); 967: newEventsOnly = true; 968: } 969: } 970: 971: /** 972: * Removes the specified container listener from this object's list of 973: * container listeners. 974: * 975: * @param listener The listener to remove. 976: */ 977: public synchronized void removeContainerListener(ContainerListener listener) 978: { 979: containerListener = AWTEventMulticaster.remove(containerListener, listener); 980: } 981: 982: /** 983: * @since 1.4 984: */ 985: public synchronized ContainerListener[] getContainerListeners() 986: { 987: return (ContainerListener[]) 988: AWTEventMulticaster.getListeners(containerListener, 989: ContainerListener.class); 990: } 991: 992: /** 993: * Returns all registered {@link EventListener}s of the given 994: * <code>listenerType</code>. 995: * 996: * @param listenerType the class of listeners to filter (<code>null</code> 997: * not permitted). 998: * 999: * @return An array of registered listeners. 1000: * 1001: * @throws ClassCastException if <code>listenerType</code> does not implement 1002: * the {@link EventListener} interface. 1003: * @throws NullPointerException if <code>listenerType</code> is 1004: * <code>null</code>. 1005: * 1006: * @see #getContainerListeners() 1007: * 1008: * @since 1.3 1009: */ 1010: public <T extends EventListener> T[] getListeners(Class<T> listenerType) 1011: { 1012: if (listenerType == ContainerListener.class) 1013: return (T[]) getContainerListeners(); 1014: return super.getListeners(listenerType); 1015: } 1016: 1017: /** 1018: * Processes the specified event. This method calls 1019: * <code>processContainerEvent()</code> if this method is a 1020: * <code>ContainerEvent</code>, otherwise it calls the superclass 1021: * method. 1022: * 1023: * @param e The event to be processed. 1024: */ 1025: protected void processEvent(AWTEvent e) 1026: { 1027: if (e instanceof ContainerEvent) 1028: processContainerEvent((ContainerEvent) e); 1029: else 1030: super.processEvent(e); 1031: } 1032: 1033: /** 1034: * Called when a container event occurs if container events are enabled. 1035: * This method calls any registered listeners. 1036: * 1037: * @param e The event that occurred. 1038: */ 1039: protected void processContainerEvent(ContainerEvent e) 1040: { 1041: if (containerListener == null) 1042: return; 1043: switch (e.id) 1044: { 1045: case ContainerEvent.COMPONENT_ADDED: 1046: containerListener.componentAdded(e); 1047: break; 1048: 1049: case ContainerEvent.COMPONENT_REMOVED: 1050: containerListener.componentRemoved(e); 1051: break; 1052: } 1053: } 1054: 1055: /** 1056: * AWT 1.0 event processor. 1057: * 1058: * @param e The event that occurred. 1059: * 1060: * @deprecated use {@link #dispatchEvent(AWTEvent)} instead 1061: */ 1062: public void deliverEvent(Event e) 1063: { 1064: if (!handleEvent (e)) 1065: { 1066: synchronized (getTreeLock ()) 1067: { 1068: Component parent = getParent (); 1069: 1070: if (parent != null) 1071: parent.deliverEvent (e); 1072: } 1073: } 1074: } 1075: 1076: /** 1077: * Returns the component located at the specified point. This is done 1078: * by checking whether or not a child component claims to contain this 1079: * point. The first child component that does is returned. If no 1080: * child component claims the point, the container itself is returned, 1081: * unless the point does not exist within this container, in which 1082: * case <code>null</code> is returned. 1083: * 1084: * When components overlap, the first component is returned. The component 1085: * that is closest to (x, y), containing that location, is returned. 1086: * Heavyweight components take precedence of lightweight components. 1087: * 1088: * This function does not ignore invisible components. If there is an invisible 1089: * component at (x,y), it will be returned. 1090: * 1091: * @param x The X coordinate of the point. 1092: * @param y The Y coordinate of the point. 1093: * 1094: * @return The component containing the specified point, or 1095: * <code>null</code> if there is no such point. 1096: */ 1097: public Component getComponentAt(int x, int y) 1098: { 1099: return locate (x, y); 1100: } 1101: 1102: /** 1103: * Returns the mouse pointer position relative to this Container's 1104: * top-left corner. If allowChildren is false, the mouse pointer 1105: * must be directly over this container. If allowChildren is true, 1106: * the mouse pointer may be over this container or any of its 1107: * descendents. 1108: * 1109: * @param allowChildren true to allow descendents, false if pointer 1110: * must be directly over Container. 1111: * 1112: * @return relative mouse pointer position 1113: * 1114: * @throws HeadlessException if in a headless environment 1115: */ 1116: public Point getMousePosition(boolean allowChildren) throws HeadlessException 1117: { 1118: return super.getMousePositionHelper(allowChildren); 1119: } 1120: 1121: boolean mouseOverComponent(Component component, boolean allowChildren) 1122: { 1123: if (allowChildren) 1124: return isAncestorOf(component); 1125: else 1126: return component == this; 1127: } 1128: 1129: /** 1130: * Returns the component located at the specified point. This is done 1131: * by checking whether or not a child component claims to contain this 1132: * point. The first child component that does is returned. If no 1133: * child component claims the point, the container itself is returned, 1134: * unless the point does not exist within this container, in which 1135: * case <code>null</code> is returned. 1136: * 1137: * When components overlap, the first component is returned. The component 1138: * that is closest to (x, y), containing that location, is returned. 1139: * Heavyweight components take precedence of lightweight components. 1140: * 1141: * This function does not ignore invisible components. If there is an invisible 1142: * component at (x,y), it will be returned. 1143: * 1144: * @param x The x position of the point to return the component at. 1145: * @param y The y position of the point to return the component at. 1146: * 1147: * @return The component containing the specified point, or <code>null</code> 1148: * if there is no such point. 1149: * 1150: * @deprecated use {@link #getComponentAt(int, int)} instead 1151: */ 1152: public Component locate(int x, int y) 1153: { 1154: synchronized (getTreeLock ()) 1155: { 1156: if (!contains (x, y)) 1157: return null; 1158: 1159: // First find the component closest to (x,y) that is a heavyweight. 1160: for (int i = 0; i < ncomponents; ++i) 1161: { 1162: Component comp = component[i]; 1163: int x2 = x - comp.x; 1164: int y2 = y - comp.y; 1165: if (comp.contains (x2, y2) && !comp.isLightweight()) 1166: return comp; 1167: } 1168: 1169: // if a heavyweight component is not found, look for a lightweight 1170: // closest to (x,y). 1171: for (int i = 0; i < ncomponents; ++i) 1172: { 1173: Component comp = component[i]; 1174: int x2 = x - comp.x; 1175: int y2 = y - comp.y; 1176: if (comp.contains (x2, y2) && comp.isLightweight()) 1177: return comp; 1178: } 1179: 1180: return this; 1181: } 1182: } 1183: 1184: /** 1185: * Returns the component located at the specified point. This is done 1186: * by checking whether or not a child component claims to contain this 1187: * point. The first child component that does is returned. If no 1188: * child component claims the point, the container itself is returned, 1189: * unless the point does not exist within this container, in which 1190: * case <code>null</code> is returned. 1191: * 1192: * The top-most child component is returned in the case where components overlap. 1193: * This is determined by finding the component closest to (x,y) and contains 1194: * that location. Heavyweight components take precedence of lightweight components. 1195: * 1196: * This function does not ignore invisible components. If there is an invisible 1197: * component at (x,y), it will be returned. 1198: * 1199: * @param p The point to return the component at. 1200: * @return The component containing the specified point, or <code>null</code> 1201: * if there is no such point. 1202: */ 1203: public Component getComponentAt(Point p) 1204: { 1205: return getComponentAt (p.x, p.y); 1206: } 1207: 1208: /** 1209: * Locates the visible child component that contains the specified position. 1210: * The top-most child component is returned in the case where there is overlap 1211: * in the components. If the containing child component is a Container, 1212: * this method will continue searching for the deepest nested child 1213: * component. Components which are not visible are ignored during the search. 1214: * 1215: * findComponentAt differs from getComponentAt, because it recursively 1216: * searches a Container's children. 1217: * 1218: * @param x - x coordinate 1219: * @param y - y coordinate 1220: * @return null if the component does not contain the position. 1221: * If there is no child component at the requested point and the point is 1222: * within the bounds of the container the container itself is returned. 1223: */ 1224: public Component findComponentAt(int x, int y) 1225: { 1226: synchronized (getTreeLock ()) 1227: { 1228: if (! contains(x, y)) 1229: return null; 1230: 1231: for (int i = 0; i < ncomponents; ++i) 1232: { 1233: // Ignore invisible children... 1234: if (!component[i].isVisible()) 1235: continue; 1236: 1237: int x2 = x - component[i].x; 1238: int y2 = y - component[i].y; 1239: // We don't do the contains() check right away because 1240: // findComponentAt would redundantly do it first thing. 1241: if (component[i] instanceof Container) 1242: { 1243: Container k = (Container) component[i]; 1244: Component r = k.findComponentAt(x2, y2); 1245: if (r != null) 1246: return r; 1247: } 1248: else if (component[i].contains(x2, y2)) 1249: return component[i]; 1250: } 1251: 1252: return this; 1253: } 1254: } 1255: 1256: /** 1257: * Locates the visible child component that contains the specified position. 1258: * The top-most child component is returned in the case where there is overlap 1259: * in the components. If the containing child component is a Container, 1260: * this method will continue searching for the deepest nested child 1261: * component. Components which are not visible are ignored during the search. 1262: * 1263: * findComponentAt differs from getComponentAt, because it recursively 1264: * searches a Container's children. 1265: * 1266: * @param p - the component's location 1267: * @return null if the component does not contain the position. 1268: * If there is no child component at the requested point and the point is 1269: * within the bounds of the container the container itself is returned. 1270: */ 1271: public Component findComponentAt(Point p) 1272: { 1273: return findComponentAt(p.x, p.y); 1274: } 1275: 1276: /** 1277: * Called when this container is added to another container to inform it 1278: * to create its peer. Peers for any child components will also be 1279: * created. 1280: */ 1281: public void addNotify() 1282: { 1283: synchronized (getTreeLock()) 1284: { 1285: super.addNotify(); 1286: addNotifyContainerChildren(); 1287: } 1288: } 1289: 1290: /** 1291: * Called when this container is removed from its parent container to 1292: * inform it to destroy its peer. This causes the peers of all child 1293: * component to be destroyed as well. 1294: */ 1295: public void removeNotify() 1296: { 1297: synchronized (getTreeLock ()) 1298: { 1299: int ncomps = ncomponents; 1300: Component[] comps = component; 1301: for (int i = ncomps - 1; i >= 0; --i) 1302: { 1303: Component comp = comps[i]; 1304: if (comp != null) 1305: comp.removeNotify(); 1306: } 1307: super.removeNotify(); 1308: } 1309: } 1310: 1311: /** 1312: * Tests whether or not the specified component is contained within 1313: * this components subtree. 1314: * 1315: * @param comp The component to test. 1316: * 1317: * @return <code>true</code> if this container is an ancestor of the 1318: * specified component, <code>false</code> otherwise. 1319: */ 1320: public boolean isAncestorOf(Component comp) 1321: { 1322: synchronized (getTreeLock ()) 1323: { 1324: while (true) 1325: { 1326: if (comp == null) 1327: return false; 1328: comp = comp.getParent(); 1329: if (comp == this) 1330: return true; 1331: } 1332: } 1333: } 1334: 1335: /** 1336: * Returns a string representing the state of this container for 1337: * debugging purposes. 1338: * 1339: * @return A string representing the state of this container. 1340: */ 1341: protected String paramString() 1342: { 1343: if (layoutMgr == null) 1344: return super.paramString(); 1345: 1346: CPStringBuilder sb = new CPStringBuilder(); 1347: sb.append(super.paramString()); 1348: sb.append(",layout="); 1349: sb.append(layoutMgr.getClass().getName()); 1350: return sb.toString(); 1351: } 1352: 1353: /** 1354: * Writes a listing of this container to the specified stream starting 1355: * at the specified indentation point. 1356: * 1357: * @param out The <code>PrintStream</code> to write to. 1358: * @param indent The indentation point. 1359: */ 1360: public void list(PrintStream out, int indent) 1361: { 1362: synchronized (getTreeLock ()) 1363: { 1364: super.list(out, indent); 1365: for (int i = 0; i < ncomponents; ++i) 1366: component[i].list(out, indent + 2); 1367: } 1368: } 1369: 1370: /** 1371: * Writes a listing of this container to the specified stream starting 1372: * at the specified indentation point. 1373: * 1374: * @param out The <code>PrintWriter</code> to write to. 1375: * @param indent The indentation point. 1376: */ 1377: public void list(PrintWriter out, int indent) 1378: { 1379: synchronized (getTreeLock ()) 1380: { 1381: super.list(out, indent); 1382: for (int i = 0; i < ncomponents; ++i) 1383: component[i].list(out, indent + 2); 1384: } 1385: } 1386: 1387: /** 1388: * Sets the focus traversal keys for a given traversal operation for this 1389: * Container. 1390: * 1391: * @exception IllegalArgumentException If id is not one of 1392: * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, 1393: * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, 1394: * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, 1395: * or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS, 1396: * or if keystrokes contains null, or if any Object in keystrokes is not an 1397: * AWTKeyStroke, or if any keystroke represents a KEY_TYPED event, or if any 1398: * keystroke already maps to another focus traversal operation for this 1399: * Container. 1400: * 1401: * @since 1.4 1402: */ 1403: public void setFocusTraversalKeys(int id, 1404: Set<? extends AWTKeyStroke> keystrokes) 1405: { 1406: if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS && 1407: id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS && 1408: id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS && 1409: id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS) 1410: throw new IllegalArgumentException (); 1411: 1412: if (keystrokes == null) 1413: { 1414: Container parent = getParent (); 1415: 1416: while (parent != null) 1417: { 1418: if (parent.areFocusTraversalKeysSet (id)) 1419: { 1420: keystrokes = parent.getFocusTraversalKeys (id); 1421: break; 1422: } 1423: parent = parent.getParent (); 1424: } 1425: 1426: if (keystrokes == null) 1427: keystrokes = KeyboardFocusManager.getCurrentKeyboardFocusManager (). 1428: getDefaultFocusTraversalKeys (id); 1429: } 1430: 1431: Set sa; 1432: Set sb; 1433: Set sc; 1434: String name; 1435: switch (id) 1436: { 1437: case KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS: 1438: sa = getFocusTraversalKeys 1439: (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS); 1440: sb = getFocusTraversalKeys 1441: (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS); 1442: sc = getFocusTraversalKeys 1443: (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS); 1444: name = "forwardFocusTraversalKeys"; 1445: break; 1446: case KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS: 1447: sa = getFocusTraversalKeys 1448: (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS); 1449: sb = getFocusTraversalKeys 1450: (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS); 1451: sc = getFocusTraversalKeys 1452: (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS); 1453: name = "backwardFocusTraversalKeys"; 1454: break; 1455: case KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS: 1456: sa = getFocusTraversalKeys 1457: (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS); 1458: sb = getFocusTraversalKeys 1459: (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS); 1460: sc = getFocusTraversalKeys 1461: (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS); 1462: name = "upCycleFocusTraversalKeys"; 1463: break; 1464: case KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS: 1465: sa = getFocusTraversalKeys 1466: (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS); 1467: sb = getFocusTraversalKeys 1468: (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS); 1469: sc = getFocusTraversalKeys 1470: (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS); 1471: name = "downCycleFocusTraversalKeys"; 1472: break; 1473: default: 1474: throw new IllegalArgumentException (); 1475: } 1476: 1477: int i = keystrokes.size (); 1478: Iterator iter = keystrokes.iterator (); 1479: 1480: while (--i >= 0) 1481: { 1482: Object o = iter.next (); 1483: if (!(o instanceof AWTKeyStroke) 1484: || sa.contains (o) || sb.contains (o) || sc.contains (o) 1485: || ((AWTKeyStroke) o).keyCode == KeyEvent.VK_UNDEFINED) 1486: throw new IllegalArgumentException (); 1487: } 1488: 1489: if (focusTraversalKeys == null) 1490: focusTraversalKeys = new Set[4]; 1491: 1492: keystrokes = 1493: Collections.unmodifiableSet(new HashSet<AWTKeyStroke>(keystrokes)); 1494: firePropertyChange (name, focusTraversalKeys[id], keystrokes); 1495: 1496: focusTraversalKeys[id] = keystrokes; 1497: } 1498: 1499: /** 1500: * Returns the Set of focus traversal keys for a given traversal operation for 1501: * this Container. 1502: * 1503: * @exception IllegalArgumentException If id is not one of 1504: * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, 1505: * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, 1506: * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, 1507: * or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS. 1508: * 1509: * @since 1.4 1510: */ 1511: public Set<AWTKeyStroke> getFocusTraversalKeys (int id) 1512: { 1513: if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS && 1514: id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS && 1515: id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS && 1516: id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS) 1517: throw new IllegalArgumentException (); 1518: 1519: Set s = null; 1520: 1521: if (focusTraversalKeys != null) 1522: s = focusTraversalKeys[id]; 1523: 1524: if (s == null && parent != null) 1525: s = parent.getFocusTraversalKeys (id); 1526: 1527: return s == null ? (KeyboardFocusManager.getCurrentKeyboardFocusManager() 1528: .getDefaultFocusTraversalKeys(id)) : s; 1529: } 1530: 1531: /** 1532: * Returns whether the Set of focus traversal keys for the given focus 1533: * traversal operation has been explicitly defined for this Container. 1534: * If this method returns false, this Container is inheriting the Set from 1535: * an ancestor, or from the current KeyboardFocusManager. 1536: * 1537: * @exception IllegalArgumentException If id is not one of 1538: * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, 1539: * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, 1540: * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, 1541: * or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS. 1542: * 1543: * @since 1.4 1544: */ 1545: public boolean areFocusTraversalKeysSet (int id) 1546: { 1547: if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS && 1548: id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS && 1549: id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS && 1550: id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS) 1551: throw new IllegalArgumentException (); 1552: 1553: return focusTraversalKeys != null && focusTraversalKeys[id] != null; 1554: } 1555: 1556: /** 1557: * Check whether the given Container is the focus cycle root of this 1558: * Container's focus traversal cycle. If this Container is a focus 1559: * cycle root itself, then it will be in two different focus cycles 1560: * -- it's own, and that of its ancestor focus cycle root's. In 1561: * that case, if <code>c</code> is either of those containers, this 1562: * method will return true. 1563: * 1564: * @param c the candidate Container 1565: * 1566: * @return true if c is the focus cycle root of the focus traversal 1567: * cycle to which this Container belongs, false otherwise 1568: * 1569: * @since 1.4 1570: */ 1571: public boolean isFocusCycleRoot (Container c) 1572: { 1573: if (this == c 1574: && isFocusCycleRoot ()) 1575: return true; 1576: 1577: Container ancestor = getFocusCycleRootAncestor (); 1578: 1579: if (c == ancestor) 1580: return true; 1581: 1582: return false; 1583: } 1584: 1585: /** 1586: * If this Container is a focus cycle root, set the focus traversal 1587: * policy that determines the focus traversal order for its 1588: * children. If non-null, this policy will be inherited by all 1589: * inferior focus cycle roots. If <code>policy</code> is null, this 1590: * Container will inherit its policy from the closest ancestor focus 1591: * cycle root that's had its policy set. 1592: * 1593: * @param policy the new focus traversal policy for this Container or null 1594: * 1595: * @since 1.4 1596: */ 1597: public void setFocusTraversalPolicy (FocusTraversalPolicy policy) 1598: { 1599: focusTraversalPolicy = policy; 1600: } 1601: 1602: /** 1603: * Return the focus traversal policy that determines the focus 1604: * traversal order for this Container's children. This method 1605: * returns null if this Container is not a focus cycle root. If the 1606: * focus traversal policy has not been set explicitly, then this 1607: * method will return an ancestor focus cycle root's policy instead. 1608: * 1609: * @return this Container's focus traversal policy or null 1610: * 1611: * @since 1.4 1612: */ 1613: public FocusTraversalPolicy getFocusTraversalPolicy () 1614: { 1615: if (!isFocusCycleRoot ()) 1616: return null; 1617: 1618: if (focusTraversalPolicy == null) 1619: { 1620: Container ancestor = getFocusCycleRootAncestor (); 1621: 1622: if (ancestor != this && ancestor != null) 1623: return ancestor.getFocusTraversalPolicy (); 1624: else 1625: { 1626: KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager (); 1627: 1628: return manager.getDefaultFocusTraversalPolicy (); 1629: } 1630: } 1631: else 1632: return focusTraversalPolicy; 1633: } 1634: 1635: /** 1636: * Check whether this Container's focus traversal policy has been 1637: * explicitly set. If it has not, then this Container will inherit 1638: * its focus traversal policy from one of its ancestor focus cycle 1639: * roots. 1640: * 1641: * @return true if focus traversal policy is set, false otherwise 1642: */ 1643: public boolean isFocusTraversalPolicySet () 1644: { 1645: return focusTraversalPolicy == null; 1646: } 1647: 1648: /** 1649: * Set whether or not this Container is the root of a focus 1650: * traversal cycle. This Container's focus traversal policy 1651: * determines the order of focus traversal. Some policies prevent 1652: * the focus from being transferred between two traversal cycles 1653: * until an up or down traversal operation is performed. In that 1654: * case, normal traversal (not up or down) is limited to this 1655: * Container and all of this Container's descendents that are not 1656: * descendents of inferior focus cycle roots. In the default case 1657: * however, ContainerOrderFocusTraversalPolicy is in effect, and it 1658: * supports implicit down-cycle traversal operations. 1659: * 1660: * @param focusCycleRoot true if this is a focus cycle root, false otherwise 1661: * 1662: * @since 1.4 1663: */ 1664: public void setFocusCycleRoot (boolean focusCycleRoot) 1665: { 1666: this.focusCycleRoot = focusCycleRoot; 1667: } 1668: 1669: /** 1670: * Set to <code>true</code> if this container provides a focus traversal 1671: * policy, <code>false</code> when the root container's focus 1672: * traversal policy should be used. 1673: * 1674: * @return <code>true</code> if this container provides a focus traversal 1675: * policy, <code>false</code> when the root container's focus 1676: * traversal policy should be used 1677: * 1678: * @see #setFocusTraversalPolicyProvider(boolean) 1679: * 1680: * @since 1.5 1681: */ 1682: public final boolean isFocusTraversalPolicyProvider() 1683: { 1684: return focusTraversalPolicyProvider; 1685: } 1686: 1687: /** 1688: * Set to <code>true</code> if this container provides a focus traversal 1689: * policy, <code>false</code> when the root container's focus 1690: * traversal policy should be used. 1691: * 1692: * @param b <code>true</code> if this container provides a focus traversal 1693: * policy, <code>false</code> when the root container's focus 1694: * traversal policy should be used 1695: * 1696: * @see #isFocusTraversalPolicyProvider() 1697: * 1698: * @since 1.5 1699: */ 1700: public final void setFocusTraversalPolicyProvider(boolean b) 1701: { 1702: focusTraversalPolicyProvider = b; 1703: } 1704: 1705: /** 1706: * Check whether this Container is a focus cycle root. 1707: * 1708: * @return true if this is a focus cycle root, false otherwise 1709: * 1710: * @since 1.4 1711: */ 1712: public boolean isFocusCycleRoot () 1713: { 1714: return focusCycleRoot; 1715: } 1716: 1717: /** 1718: * Transfer focus down one focus traversal cycle. If this Container 1719: * is a focus cycle root, then its default component becomes the 1720: * focus owner, and this Container becomes the current focus cycle 1721: * root. No traversal will occur if this Container is not a focus 1722: * cycle root. 1723: * 1724: * @since 1.4 1725: */ 1726: public void transferFocusDownCycle () 1727: { 1728: if (isFocusCycleRoot()) 1729: { 1730: KeyboardFocusManager fm = 1731: KeyboardFocusManager.getCurrentKeyboardFocusManager(); 1732: fm.setGlobalCurrentFocusCycleRoot(this); 1733: FocusTraversalPolicy policy = getFocusTraversalPolicy(); 1734: Component defaultComponent = policy.getDefaultComponent(this); 1735: if (defaultComponent != null) 1736: defaultComponent.requestFocus(); 1737: } 1738: } 1739: 1740: /** 1741: * Sets the ComponentOrientation property of this container and all components 1742: * contained within it. 1743: * 1744: * @exception NullPointerException If orientation is null 1745: * 1746: * @since 1.4 1747: */ 1748: public void applyComponentOrientation (ComponentOrientation orientation) 1749: { 1750: if (orientation == null) 1751: throw new NullPointerException(); 1752: 1753: setComponentOrientation(orientation); 1754: for (int i = 0; i < ncomponents; i++) 1755: { 1756: if (component[i] instanceof Container) 1757: ((Container) component[i]).applyComponentOrientation(orientation); 1758: else 1759: component[i].setComponentOrientation(orientation); 1760: } 1761: } 1762: 1763: public void addPropertyChangeListener (PropertyChangeListener listener) 1764: { 1765: // TODO: Why is this overridden? 1766: super.addPropertyChangeListener(listener); 1767: } 1768: 1769: public void addPropertyChangeListener (String propertyName, 1770: PropertyChangeListener listener) 1771: { 1772: // TODO: Why is this overridden? 1773: super.addPropertyChangeListener(propertyName, listener); 1774: } 1775: 1776: 1777: /** 1778: * Sets the Z ordering for the component <code>comp</code> to 1779: * <code>index</code>. Components with lower Z order paint above components 1780: * with higher Z order. 1781: * 1782: * @param comp the component for which to change the Z ordering 1783: * @param index the index to set 1784: * 1785: * @throws NullPointerException if <code>comp == null</code> 1786: * @throws IllegalArgumentException if comp is an ancestor of this container 1787: * @throws IllegalArgumentException if <code>index</code> is not in 1788: * <code>[0, getComponentCount()]</code> for moving between 1789: * containers or <code>[0, getComponentCount() - 1]</code> for moving 1790: * inside this container 1791: * @throws IllegalArgumentException if <code>comp == this</code> 1792: * @throws IllegalArgumentException if <code>comp</code> is a 1793: * <code>Window</code> 1794: * 1795: * @see #getComponentZOrder(Component) 1796: * 1797: * @since 1.5 1798: */ 1799: public final void setComponentZOrder(Component comp, int index) 1800: { 1801: if (comp == null) 1802: throw new NullPointerException("comp must not be null"); 1803: if (comp instanceof Container && ((Container) comp).isAncestorOf(this)) 1804: throw new IllegalArgumentException("comp must not be an ancestor of " 1805: + "this"); 1806: if (comp instanceof Window) 1807: throw new IllegalArgumentException("comp must not be a Window"); 1808: 1809: if (comp == this) 1810: throw new IllegalArgumentException("cannot add component to itself"); 1811: 1812: synchronized (getTreeLock()) 1813: { 1814: // FIXME: Implement reparenting. 1815: if ( comp.getParent() != this) 1816: throw new AssertionError("Reparenting is not implemented yet"); 1817: else 1818: { 1819: // Find current component index. 1820: int currentIndex = getComponentZOrder(comp); 1821: if (currentIndex < index) 1822: { 1823: System.arraycopy(component, currentIndex + 1, component, 1824: currentIndex, index - currentIndex); 1825: } 1826: else 1827: { 1828: System.arraycopy(component, index, component, index + 1, 1829: currentIndex - index); 1830: } 1831: component[index] = comp; 1832: } 1833: } 1834: } 1835: 1836: /** 1837: * Returns the Z ordering index of <code>comp</code>. If <code>comp</code> 1838: * is not a child component of this Container, this returns <code>-1</code>. 1839: * 1840: * @param comp the component for which to query the Z ordering 1841: * 1842: * @return the Z ordering index of <code>comp</code> or <code>-1</code> if 1843: * <code>comp</code> is not a child of this Container 1844: * 1845: * @see #setComponentZOrder(Component, int) 1846: * 1847: * @since 1.5 1848: */ 1849: public final int getComponentZOrder(Component comp) 1850: { 1851: synchronized (getTreeLock()) 1852: { 1853: int index = -1; 1854: if (component != null) 1855: { 1856: for (int i = 0; i < ncomponents; i++) 1857: { 1858: if (component[i] == comp) 1859: { 1860: index = i; 1861: break; 1862: } 1863: } 1864: } 1865: return index; 1866: } 1867: } 1868: 1869: // Hidden helper methods. 1870: 1871: /** 1872: * Perform a graphics operation on the children of this container. 1873: * For each applicable child, the visitChild() method will be called 1874: * to perform the graphics operation. 1875: * 1876: * @param gfx The graphics object that will be used to derive new 1877: * graphics objects for the children. 1878: * 1879: * @param visitor Object encapsulating the graphics operation that 1880: * should be performed. 1881: * 1882: * @param lightweightOnly If true, only lightweight components will 1883: * be visited. 1884: */ 1885: private void visitChildren(Graphics gfx, GfxVisitor visitor, 1886: boolean lightweightOnly) 1887: { 1888: synchronized (getTreeLock()) 1889: { 1890: for (int i = ncomponents - 1; i >= 0; --i) 1891: { 1892: Component comp = component[i]; 1893: boolean applicable = comp.isVisible() 1894: && (comp.isLightweight() || ! lightweightOnly); 1895: 1896: if (applicable) 1897: visitChild(gfx, visitor, comp); 1898: } 1899: } 1900: } 1901: 1902: /** 1903: * Perform a graphics operation on a child. A translated and clipped 1904: * graphics object will be created, and the visit() method of the 1905: * visitor will be called to perform the operation. 1906: * 1907: * @param gfx The graphics object that will be used to derive new 1908: * graphics objects for the child. 1909: * 1910: * @param visitor Object encapsulating the graphics operation that 1911: * should be performed. 1912: * 1913: * @param comp The child component that should be visited. 1914: */ 1915: private void visitChild(Graphics gfx, GfxVisitor visitor, 1916: Component comp) 1917: { 1918: Rectangle bounds = comp.getBounds(); 1919: 1920: if(!gfx.hitClip(bounds.x,bounds.y, bounds.width, bounds.height)) 1921: return; 1922: Graphics g2 = gfx.create(bounds.x, bounds.y, bounds.width, 1923: bounds.height); 1924: try 1925: { 1926: g2.setFont(comp.getFont()); 1927: visitor.visit(comp, g2); 1928: } 1929: finally 1930: { 1931: g2.dispose(); 1932: } 1933: } 1934: 1935: /** 1936: * Overridden to dispatch events to lightweight descendents. 1937: * 1938: * @param e the event to dispatch. 1939: */ 1940: void dispatchEventImpl(AWTEvent e) 1941: { 1942: LightweightDispatcher dispatcher = LightweightDispatcher.getInstance(); 1943: if (! isLightweight() && dispatcher.dispatchEvent(e)) 1944: { 1945: // Some lightweight descendent got this event dispatched. Consume 1946: // it and let the peer handle it. 1947: e.consume(); 1948: ComponentPeer p = peer; 1949: if (p != null) 1950: p.handleEvent(e); 1951: } 1952: else 1953: { 1954: super.dispatchEventImpl(e); 1955: } 1956: } 1957: 1958: /** 1959: * This is called by the lightweight dispatcher to avoid recursivly 1960: * calling into the lightweight dispatcher. 1961: * 1962: * @param e the event to dispatch 1963: * 1964: * @see LightweightDispatcher#redispatch(MouseEvent, Component, int) 1965: */ 1966: void dispatchNoLightweight(AWTEvent e) 1967: { 1968: super.dispatchEventImpl(e); 1969: } 1970: 1971: /** 1972: * Tests if this container has an interest in the given event id. 1973: * 1974: * @param eventId The event id to check. 1975: * 1976: * @return <code>true</code> if a listener for the event id exists or 1977: * if the eventMask is set for the event id. 1978: * 1979: * @see java.awt.Component#eventTypeEnabled(int) 1980: */ 1981: boolean eventTypeEnabled(int eventId) 1982: { 1983: if(eventId <= ContainerEvent.CONTAINER_LAST 1984: && eventId >= ContainerEvent.CONTAINER_FIRST) 1985: return containerListener != null 1986: || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0; 1987: else 1988: return super.eventTypeEnabled(eventId); 1989: } 1990: 1991: // This is used to implement Component.transferFocus. 1992: Component findNextFocusComponent(Component child) 1993: { 1994: synchronized (getTreeLock ()) 1995: { 1996: int start, end; 1997: if (child != null) 1998: { 1999: for (start = 0; start < ncomponents; ++start) 2000: { 2001: if (component[start] == child) 2002: break; 2003: } 2004: end = start; 2005: // This special case lets us be sure to terminate. 2006: if (end == 0) 2007: end = ncomponents; 2008: ++start; 2009: } 2010: else 2011: { 2012: start = 0; 2013: end = ncomponents; 2014: } 2015: 2016: for (int j = start; j != end; ++j) 2017: { 2018: if (j >= ncomponents) 2019: { 2020: // The JCL says that we should wrap here. However, that 2021: // seems wrong. To me it seems that focus order should be 2022: // global within in given window. So instead if we reach 2023: // the end we try to look in our parent, if we have one. 2024: if (parent != null) 2025: return parent.findNextFocusComponent(this); 2026: j -= ncomponents; 2027: } 2028: if (component[j] instanceof Container) 2029: { 2030: Component c = component[j]; 2031: c = c.findNextFocusComponent(null); 2032: if (c != null) 2033: return c; 2034: } 2035: else if (component[j].isFocusTraversable()) 2036: return component[j]; 2037: } 2038: 2039: return null; 2040: } 2041: } 2042: 2043: /** 2044: * Fires hierarchy events to the children of this container and this 2045: * container itself. This overrides {@link Component#fireHierarchyEvent} 2046: * in order to forward this event to all children. 2047: */ 2048: void fireHierarchyEvent(int id, Component changed, Container parent, 2049: long flags) 2050: { 2051: // Only propagate event if there is actually a listener waiting for it. 2052: if ((id == HierarchyEvent.HIERARCHY_CHANGED && numHierarchyListeners > 0) 2053: || ((id == HierarchyEvent.ANCESTOR_MOVED 2054: || id == HierarchyEvent.ANCESTOR_RESIZED) 2055: && numHierarchyBoundsListeners > 0)) 2056: { 2057: for (int i = 0; i < ncomponents; i++) 2058: component[i].fireHierarchyEvent(id, changed, parent, flags); 2059: super.fireHierarchyEvent(id, changed, parent, flags); 2060: } 2061: } 2062: 2063: /** 2064: * Adjusts the number of hierarchy listeners of this container and all of 2065: * its parents. This is called by the add/remove listener methods and 2066: * structure changing methods in Container. 2067: * 2068: * @param type the type, either {@link AWTEvent#HIERARCHY_BOUNDS_EVENT_MASK} 2069: * or {@link AWTEvent#HIERARCHY_EVENT_MASK} 2070: * @param delta the number of listeners added or removed 2071: */ 2072: void updateHierarchyListenerCount(long type, int delta) 2073: { 2074: if (type == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) 2075: numHierarchyBoundsListeners += delta; 2076: else if (type == AWTEvent.HIERARCHY_EVENT_MASK) 2077: numHierarchyListeners += delta; 2078: else 2079: assert false : "Should not reach here"; 2080: 2081: if (parent != null) 2082: parent.updateHierarchyListenerCount(type, delta); 2083: } 2084: 2085: /** 2086: * Notifies interested listeners about resizing or moving the container. 2087: * This performs the super behaviour (sending component events) and 2088: * additionally notifies any hierarchy bounds listeners on child components. 2089: * 2090: * @param resized true if the component has been resized, false otherwise 2091: * @param moved true if the component has been moved, false otherwise 2092: */ 2093: void notifyReshape(boolean resized, boolean moved) 2094: { 2095: // Notify component listeners. 2096: super.notifyReshape(resized, moved); 2097: 2098: if (ncomponents > 0) 2099: { 2100: // Notify hierarchy bounds listeners. 2101: if (resized) 2102: { 2103: for (int i = 0; i < getComponentCount(); i++) 2104: { 2105: Component child = getComponent(i); 2106: child.fireHierarchyEvent(HierarchyEvent.ANCESTOR_RESIZED, 2107: this, parent, 0); 2108: } 2109: } 2110: if (moved) 2111: { 2112: for (int i = 0; i < getComponentCount(); i++) 2113: { 2114: Component child = getComponent(i); 2115: child.fireHierarchyEvent(HierarchyEvent.ANCESTOR_MOVED, 2116: this, parent, 0); 2117: } 2118: } 2119: } 2120: } 2121: 2122: private void addNotifyContainerChildren() 2123: { 2124: synchronized (getTreeLock ()) 2125: { 2126: for (int i = ncomponents; --i >= 0; ) 2127: { 2128: component[i].addNotify(); 2129: } 2130: } 2131: } 2132: 2133: /** 2134: * Deserialize this Container: 2135: * <ol> 2136: * <li>Read from the stream the default serializable fields.</li> 2137: * <li>Read a list of serializable ContainerListeners as optional 2138: * data. If the list is null, no listeners will be registered.</li> 2139: * <li>Read this Container's FocusTraversalPolicy as optional data. 2140: * If this is null, then this Container will use a 2141: * DefaultFocusTraversalPolicy.</li> 2142: * </ol> 2143: * 2144: * @param s the stream to read from 2145: * @throws ClassNotFoundException if deserialization fails 2146: * @throws IOException if the stream fails 2147: */ 2148: private void readObject (ObjectInputStream s) 2149: throws ClassNotFoundException, IOException 2150: { 2151: s.defaultReadObject (); 2152: String key = (String) s.readObject (); 2153: while (key != null) 2154: { 2155: Object object = s.readObject (); 2156: if ("containerL".equals (key)) 2157: addContainerListener((ContainerListener) object); 2158: // FIXME: under what key is the focus traversal policy stored? 2159: else if ("focusTraversalPolicy".equals (key)) 2160: setFocusTraversalPolicy ((FocusTraversalPolicy) object); 2161: 2162: key = (String) s.readObject(); 2163: } 2164: } 2165: 2166: /** 2167: * Serialize this Container: 2168: * <ol> 2169: * <li>Write to the stream the default serializable fields.</li> 2170: * <li>Write the list of serializable ContainerListeners as optional 2171: * data.</li> 2172: * <li>Write this Container's FocusTraversalPolicy as optional data.</li> 2173: * </ol> 2174: * 2175: * @param s the stream to write to 2176: * @throws IOException if the stream fails 2177: */ 2178: private void writeObject (ObjectOutputStream s) throws IOException 2179: { 2180: s.defaultWriteObject (); 2181: AWTEventMulticaster.save (s, "containerL", containerListener); 2182: if (focusTraversalPolicy instanceof Serializable) 2183: s.writeObject (focusTraversalPolicy); 2184: else 2185: s.writeObject (null); 2186: } 2187: 2188: // Nested classes. 2189: 2190: /* The following classes are used in concert with the 2191: visitChildren() method to implement all the graphics operations 2192: that requires traversal of the containment hierarchy. */ 2193: 2194: abstract static class GfxVisitor 2195: { 2196: public abstract void visit(Component c, Graphics gfx); 2197: } 2198: 2199: static class GfxPaintVisitor extends GfxVisitor 2200: { 2201: public static final GfxVisitor INSTANCE = new GfxPaintVisitor(); 2202: 2203: public void visit(Component c, Graphics gfx) 2204: { 2205: c.paint(gfx); 2206: } 2207: } 2208: 2209: static class GfxPrintVisitor extends GfxVisitor 2210: { 2211: public static final GfxVisitor INSTANCE = new GfxPrintVisitor(); 2212: 2213: public void visit(Component c, Graphics gfx) 2214: { 2215: c.print(gfx); 2216: } 2217: } 2218: 2219: static class GfxPaintAllVisitor extends GfxVisitor 2220: { 2221: public static final GfxVisitor INSTANCE = new GfxPaintAllVisitor(); 2222: 2223: public void visit(Component c, Graphics gfx) 2224: { 2225: c.paintAll(gfx); 2226: } 2227: } 2228: 2229: static class GfxPrintAllVisitor extends GfxVisitor 2230: { 2231: public static final GfxVisitor INSTANCE = new GfxPrintAllVisitor(); 2232: 2233: public void visit(Component c, Graphics gfx) 2234: { 2235: c.printAll(gfx); 2236: } 2237: } 2238: 2239: /** 2240: * This class provides accessibility support for subclasses of container. 2241: * 2242: * @author Eric Blake (ebb9@email.byu.edu) 2243: * 2244: * @since 1.3 2245: */ 2246: protected class AccessibleAWTContainer extends AccessibleAWTComponent 2247: { 2248: /** 2249: * Compatible with JDK 1.4+. 2250: */ 2251: private static final long serialVersionUID = 5081320404842566097L; 2252: 2253: /** 2254: * The handler to fire PropertyChange when children are added or removed. 2255: * 2256: * @serial the handler for property changes 2257: */ 2258: protected ContainerListener accessibleContainerHandler 2259: = new AccessibleContainerHandler(); 2260: 2261: /** 2262: * The default constructor. 2263: */ 2264: protected AccessibleAWTContainer() 2265: { 2266: Container.this.addContainerListener(accessibleContainerHandler); 2267: } 2268: 2269: /** 2270: * Return the number of accessible children of the containing accessible 2271: * object (at most the total number of its children). 2272: * 2273: * @return the number of accessible children 2274: */ 2275: public int getAccessibleChildrenCount() 2276: { 2277: synchronized (getTreeLock ()) 2278: { 2279: int count = 0; 2280: int i = component == null ? 0 : component.length; 2281: while (--i >= 0) 2282: if (component[i] instanceof Accessible) 2283: count++; 2284: return count; 2285: } 2286: } 2287: 2288: /** 2289: * Return the nth accessible child of the containing accessible object. 2290: * 2291: * @param i the child to grab, zero-based 2292: * @return the accessible child, or null 2293: */ 2294: public Accessible getAccessibleChild(int i) 2295: { 2296: synchronized (getTreeLock ()) 2297: { 2298: if (component == null) 2299: return null; 2300: int index = -1; 2301: while (i >= 0 && ++index < component.length) 2302: if (component[index] instanceof Accessible) 2303: i--; 2304: if (i < 0) 2305: return (Accessible) component[index]; 2306: return null; 2307: } 2308: } 2309: 2310: /** 2311: * Return the accessible child located at point (in the parent's 2312: * coordinates), if one exists. 2313: * 2314: * @param p the point to look at 2315: * 2316: * @return an accessible object at that point, or null 2317: * 2318: * @throws NullPointerException if p is null 2319: */ 2320: public Accessible getAccessibleAt(Point p) 2321: { 2322: Component c = getComponentAt(p.x, p.y); 2323: return c != Container.this && c instanceof Accessible ? (Accessible) c 2324: : null; 2325: } 2326: 2327: /** 2328: * This class fires a <code>PropertyChange</code> listener, if registered, 2329: * when children are added or removed from the enclosing accessible object. 2330: * 2331: * @author Eric Blake (ebb9@email.byu.edu) 2332: * 2333: * @since 1.3 2334: */ 2335: protected class AccessibleContainerHandler implements ContainerListener 2336: { 2337: /** 2338: * Default constructor. 2339: */ 2340: protected AccessibleContainerHandler() 2341: { 2342: // Nothing to do here. 2343: } 2344: 2345: /** 2346: * Fired when a component is added; forwards to the PropertyChange 2347: * listener. 2348: * 2349: * @param e the container event for adding 2350: */ 2351: public void componentAdded(ContainerEvent e) 2352: { 2353: AccessibleAWTContainer.this.firePropertyChange 2354: (ACCESSIBLE_CHILD_PROPERTY, null, e.getChild()); 2355: } 2356: 2357: /** 2358: * Fired when a component is removed; forwards to the PropertyChange 2359: * listener. 2360: * 2361: * @param e the container event for removing 2362: */ 2363: public void componentRemoved(ContainerEvent e) 2364: { 2365: AccessibleAWTContainer.this.firePropertyChange 2366: (ACCESSIBLE_CHILD_PROPERTY, e.getChild(), null); 2367: } 2368: } // class AccessibleContainerHandler 2369: } // class AccessibleAWTContainer 2370: } // class Container