166 // True if there is at least one thread that's printing this component
167 private transient boolean printing = false;
168
169 transient ContainerListener containerListener;
170
171 /* HierarchyListener and HierarchyBoundsListener support */
172 transient int listeningChildren;
173 transient int listeningBoundsChildren;
174 transient int descendantsCount;
175
176 /* Non-opaque window support -- see Window.setLayersOpaque */
177 transient Color preserveBackgroundColor = null;
178
179 /**
180 * JDK 1.1 serialVersionUID
181 */
182 private static final long serialVersionUID = 4613797578919906343L;
183
184 /**
185 * A constant which toggles one of the controllable behaviors
186 * of <code>getMouseEventTarget</code>. It is used to specify whether
187 * the method can return the Container on which it is originally called
188 * in case if none of its children are the current mouse event targets.
189 *
190 * @see #getMouseEventTarget(int, int, boolean)
191 */
192 static final boolean INCLUDE_SELF = true;
193
194 /**
195 * A constant which toggles one of the controllable behaviors
196 * of <code>getMouseEventTarget</code>. It is used to specify whether
197 * the method should search only lightweight components.
198 *
199 * @see #getMouseEventTarget(int, int, boolean)
200 */
201 static final boolean SEARCH_HEAVYWEIGHTS = true;
202
203 /*
204 * Number of HW or LW components in this container (including
205 * all descendant containers).
206 */
207 private transient int numOfHWComponents = 0;
208 private transient int numOfLWComponents = 0;
209
210 private static final PlatformLogger mixingLog = PlatformLogger.getLogger("java.awt.mixing.Container");
211
212 /**
213 * @serialField ncomponents int
214 * The number of components in this container.
215 * This value can be null.
216 * @serialField component Component[]
367 // This functionality is implemented in a package-private method
368 // to insure that it cannot be overridden by client subclasses.
369 // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
370 final Component[] getComponents_NoClientCode() {
371 return component.toArray(EMPTY_ARRAY);
372 }
373
374 /*
375 * Wrapper for getComponents() method with a proper synchronization.
376 */
377 Component[] getComponentsSync() {
378 synchronized (getTreeLock()) {
379 return getComponents();
380 }
381 }
382
383 /**
384 * Determines the insets of this container, which indicate the size
385 * of the container's border.
386 * <p>
387 * A <code>Frame</code> object, for example, has a top inset that
388 * corresponds to the height of the frame's title bar.
389 * @return the insets of this container.
390 * @see Insets
391 * @see LayoutManager
392 * @since 1.1
393 */
394 public Insets getInsets() {
395 return insets();
396 }
397
398 /**
399 * Returns the insets for this container.
400 *
401 * @deprecated As of JDK version 1.1,
402 * replaced by <code>getInsets()</code>.
403 * @return the insets for this container
404 */
405 @Deprecated
406 public Insets insets() {
407 ComponentPeer peer = this.peer;
408 if (peer instanceof ContainerPeer) {
409 ContainerPeer cpeer = (ContainerPeer)peer;
410 return (Insets)cpeer.getInsets().clone();
411 }
412 return new Insets(0, 0, 0, 0);
413 }
414
415 /**
416 * Appends the specified component to the end of this container.
417 * This is a convenience method for {@link #addImpl}.
418 * <p>
419 * This method changes layout-related information, and therefore,
420 * invalidates the component hierarchy. If the container has already been
421 * displayed, the hierarchy must be validated thereafter in order to
422 * display the added component.
423 *
424 * @param comp the component to be added
425 * @exception NullPointerException if {@code comp} is {@code null}
426 * @see #addImpl
427 * @see #invalidate
428 * @see #validate
429 * @see javax.swing.JComponent#revalidate()
430 * @return the component argument
431 */
432 public Component add(Component comp) {
433 addImpl(comp, null, -1);
434 return comp;
435 }
436
437 /**
438 * Adds the specified component to this container.
439 * This is a convenience method for {@link #addImpl}.
440 * <p>
441 * This method is obsolete as of 1.1. Please use the
442 * method <code>add(Component, Object)</code> instead.
443 * <p>
444 * This method changes layout-related information, and therefore,
445 * invalidates the component hierarchy. If the container has already been
446 * displayed, the hierarchy must be validated thereafter in order to
447 * display the added component.
448 *
449 * @param name the name of the component to be added
450 * @param comp the component to be added
451 * @return the component added
452 * @exception NullPointerException if {@code comp} is {@code null}
453 * @see #add(Component, Object)
454 * @see #invalidate
455 */
456 public Component add(String name, Component comp) {
457 addImpl(comp, name, -1);
458 return comp;
459 }
460
461 /**
462 * Adds the specified component to this container at the given
463 * position.
464 * This is a convenience method for {@link #addImpl}.
465 * <p>
466 * This method changes layout-related information, and therefore,
467 * invalidates the component hierarchy. If the container has already been
468 * displayed, the hierarchy must be validated thereafter in order to
469 * display the added component.
470 *
471 *
472 * @param comp the component to be added
473 * @param index the position at which to insert the component,
474 * or <code>-1</code> to append the component to the end
475 * @exception NullPointerException if {@code comp} is {@code null}
476 * @exception IllegalArgumentException if {@code index} is invalid (see
477 * {@link #addImpl} for details)
478 * @return the component <code>comp</code>
479 * @see #addImpl
480 * @see #remove
481 * @see #invalidate
482 * @see #validate
483 * @see javax.swing.JComponent#revalidate()
484 */
485 public Component add(Component comp, int index) {
486 addImpl(comp, null, index);
487 return comp;
488 }
489
490 /**
491 * Checks that the component
492 * isn't supposed to be added into itself.
493 */
494 private void checkAddToSelf(Component comp){
495 if (comp instanceof Container) {
496 for (Container cn = this; cn != null; cn=cn.parent) {
497 if (cn == comp) {
498 throw new IllegalArgumentException("adding container's parent to itself");
515 * Checks : index in bounds of container's size,
516 * comp is not one of this container's parents,
517 * and comp is not a window.
518 * Comp and container must be on the same GraphicsDevice.
519 * if comp is container, all sub-components must be on
520 * same GraphicsDevice.
521 *
522 * @since 1.5
523 */
524 private void checkAdding(Component comp, int index) {
525 checkTreeLock();
526
527 GraphicsConfiguration thisGC = getGraphicsConfiguration();
528
529 if (index > component.size() || index < 0) {
530 throw new IllegalArgumentException("illegal component position");
531 }
532 if (comp.parent == this) {
533 if (index == component.size()) {
534 throw new IllegalArgumentException("illegal component position " +
535 index + " should be less then " + component.size());
536 }
537 }
538 checkAddToSelf(comp);
539 checkNotAWindow(comp);
540
541 Window thisTopLevel = getContainingWindow();
542 Window compTopLevel = comp.getContainingWindow();
543 if (thisTopLevel != compTopLevel) {
544 throw new IllegalArgumentException("component and container should be in the same top-level window");
545 }
546 if (thisGC != null) {
547 comp.checkGD(thisGC.getDevice().getIDstring());
548 }
549 }
550
551 /**
552 * Removes component comp from this container without making unnecessary changes
553 * and generating unnecessary events. This function intended to perform optimized
554 * remove, for example, if newParent and current parent are the same it just changes
555 * index without calling removeNotify.
717 // is quite rare. If we ever need to save the peers, we'll have to slightly change the
718 // addDelicately() method in order to handle such LW containers recursively, reparenting
719 // each HW descendant independently.
720 return !comp.peer.isReparentSupported();
721 } else {
722 return false;
723 }
724 }
725
726 /**
727 * Moves the specified component to the specified z-order index in
728 * the container. The z-order determines the order that components
729 * are painted; the component with the highest z-order paints first
730 * and the component with the lowest z-order paints last.
731 * Where components overlap, the component with the lower
732 * z-order paints over the component with the higher z-order.
733 * <p>
734 * If the component is a child of some other container, it is
735 * removed from that container before being added to this container.
736 * The important difference between this method and
737 * <code>java.awt.Container.add(Component, int)</code> is that this method
738 * doesn't call <code>removeNotify</code> on the component while
739 * removing it from its previous container unless necessary and when
740 * allowed by the underlying native windowing system. This way, if the
741 * component has the keyboard focus, it maintains the focus when
742 * moved to the new position.
743 * <p>
744 * This property is guaranteed to apply only to lightweight
745 * non-<code>Container</code> components.
746 * <p>
747 * This method changes layout-related information, and therefore,
748 * invalidates the component hierarchy.
749 * <p>
750 * <b>Note</b>: Not all platforms support changing the z-order of
751 * heavyweight components from one container into another without
752 * the call to <code>removeNotify</code>. There is no way to detect
753 * whether a platform supports this, so developers shouldn't make
754 * any assumptions.
755 *
756 * @param comp the component to be moved
757 * @param index the position in the container's list to
758 * insert the component, where <code>getComponentCount()</code>
759 * appends to the end
760 * @exception NullPointerException if <code>comp</code> is
761 * <code>null</code>
762 * @exception IllegalArgumentException if <code>comp</code> is one of the
763 * container's parents
764 * @exception IllegalArgumentException if <code>index</code> is not in
765 * the range <code>[0, getComponentCount()]</code> for moving
766 * between containers, or not in the range
767 * <code>[0, getComponentCount()-1]</code> for moving inside
768 * a container
769 * @exception IllegalArgumentException if adding a container to itself
770 * @exception IllegalArgumentException if adding a <code>Window</code>
771 * to a container
772 * @see #getComponentZOrder(java.awt.Component)
773 * @see #invalidate
774 * @since 1.5
775 */
776 public void setComponentZOrder(Component comp, int index) {
777 synchronized (getTreeLock()) {
778 // Store parent because remove will clear it
779 Container curParent = comp.parent;
780 int oldZindex = getComponentZOrder(comp);
781
782 if (curParent == this && index == oldZindex) {
783 return;
784 }
785 checkAdding(comp, index);
786
787 boolean peerRecreated = (curParent != null) ?
788 curParent.removeDelicately(comp, this, index) : false;
789
790 addDelicately(comp, curParent, index);
932 }
933 } else {
934 comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
935 this, HierarchyEvent.HIERARCHY_CHANGED,
936 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
937 }
938
939 if (peer != null && layoutMgr == null && isVisible()) {
940 updateCursorImmediately();
941 }
942 }
943
944 /**
945 * Returns the z-order index of the component inside the container.
946 * The higher a component is in the z-order hierarchy, the lower
947 * its index. The component with the lowest z-order index is
948 * painted last, above all other child components.
949 *
950 * @param comp the component being queried
951 * @return the z-order index of the component; otherwise
952 * returns -1 if the component is <code>null</code>
953 * or doesn't belong to the container
954 * @see #setComponentZOrder(java.awt.Component, int)
955 * @since 1.5
956 */
957 public int getComponentZOrder(Component comp) {
958 if (comp == null) {
959 return -1;
960 }
961 synchronized(getTreeLock()) {
962 // Quick check - container should be immediate parent of the component
963 if (comp.parent != this) {
964 return -1;
965 }
966 return component.indexOf(comp);
967 }
968 }
969
970 /**
971 * Adds the specified component to the end of this container.
972 * Also notifies the layout manager to add the component to
993 public void add(Component comp, Object constraints) {
994 addImpl(comp, constraints, -1);
995 }
996
997 /**
998 * Adds the specified component to this container with the specified
999 * constraints at the specified index. Also notifies the layout
1000 * manager to add the component to the this container's layout using
1001 * the specified constraints object.
1002 * This is a convenience method for {@link #addImpl}.
1003 * <p>
1004 * This method changes layout-related information, and therefore,
1005 * invalidates the component hierarchy. If the container has already been
1006 * displayed, the hierarchy must be validated thereafter in order to
1007 * display the added component.
1008 *
1009 *
1010 * @param comp the component to be added
1011 * @param constraints an object expressing layout constraints for this
1012 * @param index the position in the container's list at which to insert
1013 * the component; <code>-1</code> means insert at the end
1014 * component
1015 * @exception NullPointerException if {@code comp} is {@code null}
1016 * @exception IllegalArgumentException if {@code index} is invalid (see
1017 * {@link #addImpl} for details)
1018 * @see #addImpl
1019 * @see #invalidate
1020 * @see #validate
1021 * @see javax.swing.JComponent#revalidate()
1022 * @see #remove
1023 * @see LayoutManager
1024 */
1025 public void add(Component comp, Object constraints, int index) {
1026 addImpl(comp, constraints, index);
1027 }
1028
1029 /**
1030 * Adds the specified component to this container at the specified
1031 * index. This method also notifies the layout manager to add
1032 * the component to this container's layout using the specified
1033 * constraints object via the <code>addLayoutComponent</code>
1034 * method.
1035 * <p>
1036 * The constraints are
1037 * defined by the particular layout manager being used. For
1038 * example, the <code>BorderLayout</code> class defines five
1039 * constraints: <code>BorderLayout.NORTH</code>,
1040 * <code>BorderLayout.SOUTH</code>, <code>BorderLayout.EAST</code>,
1041 * <code>BorderLayout.WEST</code>, and <code>BorderLayout.CENTER</code>.
1042 * <p>
1043 * The <code>GridBagLayout</code> class requires a
1044 * <code>GridBagConstraints</code> object. Failure to pass
1045 * the correct type of constraints object results in an
1046 * <code>IllegalArgumentException</code>.
1047 * <p>
1048 * If the current layout manager implements {@code LayoutManager2}, then
1049 * {@link LayoutManager2#addLayoutComponent(Component,Object)} is invoked on
1050 * it. If the current layout manager does not implement
1051 * {@code LayoutManager2}, and constraints is a {@code String}, then
1052 * {@link LayoutManager#addLayoutComponent(String,Component)} is invoked on it.
1053 * <p>
1054 * If the component is not an ancestor of this container and has a non-null
1055 * parent, it is removed from its current parent before it is added to this
1056 * container.
1057 * <p>
1058 * This is the method to override if a program needs to track
1059 * every add request to a container as all other add methods defer
1060 * to this one. An overriding method should
1061 * usually include a call to the superclass's version of the method:
1062 *
1063 * <blockquote>
1064 * <code>super.addImpl(comp, constraints, index)</code>
1065 * </blockquote>
1066 * <p>
1067 * This method changes layout-related information, and therefore,
1068 * invalidates the component hierarchy. If the container has already been
1069 * displayed, the hierarchy must be validated thereafter in order to
1070 * display the added component.
1071 *
1072 * @param comp the component to be added
1073 * @param constraints an object expressing layout constraints
1074 * for this component
1075 * @param index the position in the container's list at which to
1076 * insert the component, where <code>-1</code>
1077 * means append to the end
1078 * @exception IllegalArgumentException if {@code index} is invalid;
1079 * if {@code comp} is a child of this container, the valid
1080 * range is {@code [-1, getComponentCount()-1]}; if component is
1081 * not a child of this container, the valid range is
1082 * {@code [-1, getComponentCount()]}
1083 *
1084 * @exception IllegalArgumentException if {@code comp} is an ancestor of
1085 * this container
1086 * @exception IllegalArgumentException if adding a window to a container
1087 * @exception NullPointerException if {@code comp} is {@code null}
1088 * @see #add(Component)
1089 * @see #add(Component, int)
1090 * @see #add(Component, java.lang.Object)
1091 * @see #invalidate
1092 * @see LayoutManager
1093 * @see LayoutManager2
1094 * @since 1.1
1095 */
1096 protected void addImpl(Component comp, Object constraints, int index) {
1179 ret |= comp.updateGraphicsData(gc);
1180 }
1181 }
1182 return ret;
1183 }
1184
1185 /**
1186 * Checks that all Components that this Container contains are on
1187 * the same GraphicsDevice as this Container. If not, throws an
1188 * IllegalArgumentException.
1189 */
1190 void checkGD(String stringID) {
1191 for (Component comp : component) {
1192 if (comp != null) {
1193 comp.checkGD(stringID);
1194 }
1195 }
1196 }
1197
1198 /**
1199 * Removes the component, specified by <code>index</code>,
1200 * from this container.
1201 * This method also notifies the layout manager to remove the
1202 * component from this container's layout via the
1203 * <code>removeLayoutComponent</code> method.
1204 * <p>
1205 * This method changes layout-related information, and therefore,
1206 * invalidates the component hierarchy. If the container has already been
1207 * displayed, the hierarchy must be validated thereafter in order to
1208 * reflect the changes.
1209 *
1210 *
1211 * @param index the index of the component to be removed
1212 * @throws ArrayIndexOutOfBoundsException if {@code index} is not in
1213 * range {@code [0, getComponentCount()-1]}
1214 * @see #add
1215 * @see #invalidate
1216 * @see #validate
1217 * @see #getComponentCount
1218 * @since 1.1
1219 */
1220 public void remove(int index) {
1221 synchronized (getTreeLock()) {
1222 if (index < 0 || index >= component.size()) {
1223 throw new ArrayIndexOutOfBoundsException(index);
1246 Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
1247 ContainerEvent e = new ContainerEvent(this,
1248 ContainerEvent.COMPONENT_REMOVED,
1249 comp);
1250 dispatchEvent(e);
1251 }
1252
1253 comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
1254 this, HierarchyEvent.PARENT_CHANGED,
1255 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
1256 if (peer != null && layoutMgr == null && isVisible()) {
1257 updateCursorImmediately();
1258 }
1259 }
1260 }
1261
1262 /**
1263 * Removes the specified component from this container.
1264 * This method also notifies the layout manager to remove the
1265 * component from this container's layout via the
1266 * <code>removeLayoutComponent</code> method.
1267 * <p>
1268 * This method changes layout-related information, and therefore,
1269 * invalidates the component hierarchy. If the container has already been
1270 * displayed, the hierarchy must be validated thereafter in order to
1271 * reflect the changes.
1272 *
1273 * @param comp the component to be removed
1274 * @throws NullPointerException if {@code comp} is {@code null}
1275 * @see #add
1276 * @see #invalidate
1277 * @see #validate
1278 * @see #remove(int)
1279 */
1280 public void remove(Component comp) {
1281 synchronized (getTreeLock()) {
1282 if (comp.parent == this) {
1283 int index = component.indexOf(comp);
1284 if (index >= 0) {
1285 remove(index);
1286 }
1287 }
1288 }
1289 }
1290
1291 /**
1292 * Removes all the components from this container.
1293 * This method also notifies the layout manager to remove the
1294 * components from this container's layout via the
1295 * <code>removeLayoutComponent</code> method.
1296 * <p>
1297 * This method changes layout-related information, and therefore,
1298 * invalidates the component hierarchy. If the container has already been
1299 * displayed, the hierarchy must be validated thereafter in order to
1300 * reflect the changes.
1301 *
1302 * @see #add
1303 * @see #remove
1304 * @see #invalidate
1305 */
1306 public void removeAll() {
1307 synchronized (getTreeLock()) {
1308 adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
1309 -listeningChildren);
1310 adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
1311 -listeningBoundsChildren);
1312 adjustDescendants(-descendantsCount);
1313
1314 while (!component.isEmpty()) {
1315 Component comp = component.remove(component.size()-1);
1495
1496 /**
1497 * Sets the layout manager for this container.
1498 * <p>
1499 * This method changes layout-related information, and therefore,
1500 * invalidates the component hierarchy.
1501 *
1502 * @param mgr the specified layout manager
1503 * @see #doLayout
1504 * @see #getLayout
1505 * @see #invalidate
1506 */
1507 public void setLayout(LayoutManager mgr) {
1508 layoutMgr = mgr;
1509 invalidateIfValid();
1510 }
1511
1512 /**
1513 * Causes this container to lay out its components. Most programs
1514 * should not call this method directly, but should invoke
1515 * the <code>validate</code> method instead.
1516 * @see LayoutManager#layoutContainer
1517 * @see #setLayout
1518 * @see #validate
1519 * @since 1.1
1520 */
1521 public void doLayout() {
1522 layout();
1523 }
1524
1525 /**
1526 * @deprecated As of JDK version 1.1,
1527 * replaced by <code>doLayout()</code>.
1528 */
1529 @Deprecated
1530 public void layout() {
1531 LayoutManager layoutMgr = this.layoutMgr;
1532 if (layoutMgr != null) {
1533 layoutMgr.layoutContainer(this);
1534 }
1535 }
1536
1537 /**
1538 * Indicates if this container is a <i>validate root</i>.
1539 * <p>
1540 * Layout-related changes, such as bounds of the validate root descendants,
1541 * do not affect the layout of the validate root parent. This peculiarity
1542 * enables the {@code invalidate()} method to stop invalidating the
1543 * component hierarchy when the method encounters a validate root. However,
1544 * to preserve backward compatibility this new optimized behavior is
1545 * enabled only when the {@code java.awt.smartInvalidate} system property
1546 * value is set to {@code true}.
1547 * <p>
1686 boolean updateCur = false;
1687 synchronized (getTreeLock()) {
1688 descendUnconditionallyWhenValidating = true;
1689
1690 validate();
1691 if (peer instanceof ContainerPeer) {
1692 updateCur = isVisible();
1693 }
1694
1695 descendUnconditionallyWhenValidating = false;
1696 }
1697 if (updateCur) {
1698 updateCursorImmediately();
1699 }
1700 }
1701
1702 /**
1703 * Recursively descends the container tree and recomputes the
1704 * layout for any subtrees marked as needing it (those marked as
1705 * invalid). Synchronization should be provided by the method
1706 * that calls this one: <code>validate</code>.
1707 *
1708 * @see #doLayout
1709 * @see #validate
1710 */
1711 protected void validateTree() {
1712 checkTreeLock();
1713 if (!isValid() || descendUnconditionallyWhenValidating) {
1714 if (peer instanceof ContainerPeer) {
1715 ((ContainerPeer)peer).beginLayout();
1716 }
1717 if (!isValid()) {
1718 doLayout();
1719 }
1720 for (int i = 0; i < component.size(); i++) {
1721 Component comp = component.get(i);
1722 if ( (comp instanceof Container)
1723 && !(comp instanceof Window)
1724 && (!comp.isValid() ||
1725 descendUnconditionallyWhenValidating))
1726 {
1774 Font newfont = getFont();
1775 if (newfont != oldfont && (oldfont == null ||
1776 !oldfont.equals(newfont))) {
1777 invalidateTree();
1778 }
1779 }
1780
1781 /**
1782 * Returns the preferred size of this container. If the preferred size has
1783 * not been set explicitly by {@link Component#setPreferredSize(Dimension)}
1784 * and this {@code Container} has a {@code non-null} {@link LayoutManager},
1785 * then {@link LayoutManager#preferredLayoutSize(Container)}
1786 * is used to calculate the preferred size.
1787 *
1788 * <p>Note: some implementations may cache the value returned from the
1789 * {@code LayoutManager}. Implementations that cache need not invoke
1790 * {@code preferredLayoutSize} on the {@code LayoutManager} every time
1791 * this method is invoked, rather the {@code LayoutManager} will only
1792 * be queried after the {@code Container} becomes invalid.
1793 *
1794 * @return an instance of <code>Dimension</code> that represents
1795 * the preferred size of this container.
1796 * @see #getMinimumSize
1797 * @see #getMaximumSize
1798 * @see #getLayout
1799 * @see LayoutManager#preferredLayoutSize(Container)
1800 * @see Component#getPreferredSize
1801 */
1802 public Dimension getPreferredSize() {
1803 return preferredSize();
1804 }
1805
1806 /**
1807 * @deprecated As of JDK version 1.1,
1808 * replaced by <code>getPreferredSize()</code>.
1809 */
1810 @Deprecated
1811 public Dimension preferredSize() {
1812 /* Avoid grabbing the lock if a reasonable cached size value
1813 * is available.
1814 */
1815 Dimension dim = prefSize;
1816 if (dim == null || !(isPreferredSizeSet() || isValid())) {
1817 synchronized (getTreeLock()) {
1818 prefSize = (layoutMgr != null) ?
1819 layoutMgr.preferredLayoutSize(this) :
1820 super.preferredSize();
1821 dim = prefSize;
1822 }
1823 }
1824 if (dim != null){
1825 return new Dimension(dim);
1826 }
1827 else{
1828 return dim;
1829 }
1830 }
1831
1832 /**
1833 * Returns the minimum size of this container. If the minimum size has
1834 * not been set explicitly by {@link Component#setMinimumSize(Dimension)}
1835 * and this {@code Container} has a {@code non-null} {@link LayoutManager},
1836 * then {@link LayoutManager#minimumLayoutSize(Container)}
1837 * is used to calculate the minimum size.
1838 *
1839 * <p>Note: some implementations may cache the value returned from the
1840 * {@code LayoutManager}. Implementations that cache need not invoke
1841 * {@code minimumLayoutSize} on the {@code LayoutManager} every time
1842 * this method is invoked, rather the {@code LayoutManager} will only
1843 * be queried after the {@code Container} becomes invalid.
1844 *
1845 * @return an instance of <code>Dimension</code> that represents
1846 * the minimum size of this container.
1847 * @see #getPreferredSize
1848 * @see #getMaximumSize
1849 * @see #getLayout
1850 * @see LayoutManager#minimumLayoutSize(Container)
1851 * @see Component#getMinimumSize
1852 * @since 1.1
1853 */
1854 public Dimension getMinimumSize() {
1855 return minimumSize();
1856 }
1857
1858 /**
1859 * @deprecated As of JDK version 1.1,
1860 * replaced by <code>getMinimumSize()</code>.
1861 */
1862 @Deprecated
1863 public Dimension minimumSize() {
1864 /* Avoid grabbing the lock if a reasonable cached size value
1865 * is available.
1866 */
1867 Dimension dim = minSize;
1868 if (dim == null || !(isMinimumSizeSet() || isValid())) {
1869 synchronized (getTreeLock()) {
1870 minSize = (layoutMgr != null) ?
1871 layoutMgr.minimumLayoutSize(this) :
1872 super.minimumSize();
1873 dim = minSize;
1874 }
1875 }
1876 if (dim != null){
1877 return new Dimension(dim);
1878 }
1879 else{
1880 return dim;
1881 }
1882 }
1883
1884 /**
1885 * Returns the maximum size of this container. If the maximum size has
1886 * not been set explicitly by {@link Component#setMaximumSize(Dimension)}
1887 * and the {@link LayoutManager} installed on this {@code Container}
1888 * is an instance of {@link LayoutManager2}, then
1889 * {@link LayoutManager2#maximumLayoutSize(Container)}
1890 * is used to calculate the maximum size.
1891 *
1892 * <p>Note: some implementations may cache the value returned from the
1893 * {@code LayoutManager2}. Implementations that cache need not invoke
1894 * {@code maximumLayoutSize} on the {@code LayoutManager2} every time
1895 * this method is invoked, rather the {@code LayoutManager2} will only
1896 * be queried after the {@code Container} becomes invalid.
1897 *
1898 * @return an instance of <code>Dimension</code> that represents
1899 * the maximum size of this container.
1900 * @see #getPreferredSize
1901 * @see #getMinimumSize
1902 * @see #getLayout
1903 * @see LayoutManager2#maximumLayoutSize(Container)
1904 * @see Component#getMaximumSize
1905 */
1906 public Dimension getMaximumSize() {
1907 /* Avoid grabbing the lock if a reasonable cached size value
1908 * is available.
1909 */
1910 Dimension dim = maxSize;
1911 if (dim == null || !(isMaximumSizeSet() || isValid())) {
1912 synchronized (getTreeLock()) {
1913 if (layoutMgr instanceof LayoutManager2) {
1914 LayoutManager2 lm = (LayoutManager2) layoutMgr;
1915 maxSize = lm.maximumLayoutSize(this);
1916 } else {
1917 maxSize = super.getMaximumSize();
1918 }
2152 * If l is null, no exception is thrown and no action is performed.
2153 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
2154 * >AWT Threading Issues</a> for details on AWT's threading model.
2155 *
2156 * @param l the container listener
2157 *
2158 * @see #addContainerListener
2159 * @see #getContainerListeners
2160 */
2161 public synchronized void removeContainerListener(ContainerListener l) {
2162 if (l == null) {
2163 return;
2164 }
2165 containerListener = AWTEventMulticaster.remove(containerListener, l);
2166 }
2167
2168 /**
2169 * Returns an array of all the container listeners
2170 * registered on this container.
2171 *
2172 * @return all of this container's <code>ContainerListener</code>s
2173 * or an empty array if no container
2174 * listeners are currently registered
2175 *
2176 * @see #addContainerListener
2177 * @see #removeContainerListener
2178 * @since 1.4
2179 */
2180 public synchronized ContainerListener[] getContainerListeners() {
2181 return getListeners(ContainerListener.class);
2182 }
2183
2184 /**
2185 * Returns an array of all the objects currently registered
2186 * as <code><em>Foo</em>Listener</code>s
2187 * upon this <code>Container</code>.
2188 * <code><em>Foo</em>Listener</code>s are registered using the
2189 * <code>add<em>Foo</em>Listener</code> method.
2190 *
2191 * <p>
2192 * You can specify the <code>listenerType</code> argument
2193 * with a class literal, such as
2194 * <code><em>Foo</em>Listener.class</code>.
2195 * For example, you can query a
2196 * <code>Container</code> <code>c</code>
2197 * for its container listeners with the following code:
2198 *
2199 * <pre>ContainerListener[] cls = (ContainerListener[])(c.getListeners(ContainerListener.class));</pre>
2200 *
2201 * If no such listeners exist, this method returns an empty array.
2202 *
2203 * @param listenerType the type of listeners requested; this parameter
2204 * should specify an interface that descends from
2205 * <code>java.util.EventListener</code>
2206 * @return an array of all objects registered as
2207 * <code><em>Foo</em>Listener</code>s on this container,
2208 * or an empty array if no such listeners have been added
2209 * @exception ClassCastException if <code>listenerType</code>
2210 * doesn't specify a class or interface that implements
2211 * <code>java.util.EventListener</code>
2212 * @exception NullPointerException if {@code listenerType} is {@code null}
2213 *
2214 * @see #getContainerListeners
2215 *
2216 * @since 1.3
2217 */
2218 public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
2219 EventListener l = null;
2220 if (listenerType == ContainerListener.class) {
2221 l = containerListener;
2222 } else {
2223 return super.getListeners(listenerType);
2224 }
2225 return AWTEventMulticaster.getListeners(l, listenerType);
2226 }
2227
2228 // REMIND: remove when filtering is done at lower level
2229 boolean eventEnabled(AWTEvent e) {
2230 int id = e.getID();
2231
2232 if (id == ContainerEvent.COMPONENT_ADDED ||
2233 id == ContainerEvent.COMPONENT_REMOVED) {
2234 if ((eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
2235 containerListener != null) {
2236 return true;
2237 }
2238 return false;
2239 }
2240 return super.eventEnabled(e);
2241 }
2242
2243 /**
2244 * Processes events on this container. If the event is a
2245 * <code>ContainerEvent</code>, it invokes the
2246 * <code>processContainerEvent</code> method, else it invokes
2247 * its superclass's <code>processEvent</code>.
2248 * <p>Note that if the event parameter is <code>null</code>
2249 * the behavior is unspecified and may result in an
2250 * exception.
2251 *
2252 * @param e the event
2253 */
2254 protected void processEvent(AWTEvent e) {
2255 if (e instanceof ContainerEvent) {
2256 processContainerEvent((ContainerEvent)e);
2257 return;
2258 }
2259 super.processEvent(e);
2260 }
2261
2262 /**
2263 * Processes container events occurring on this container by
2264 * dispatching them to any registered ContainerListener objects.
2265 * NOTE: This method will not be called unless container events
2266 * are enabled for this component; this happens when one of the
2267 * following occurs:
2268 * <ul>
2269 * <li>A ContainerListener object is registered via
2270 * <code>addContainerListener</code>
2271 * <li>Container events are enabled via <code>enableEvents</code>
2272 * </ul>
2273 * <p>Note that if the event parameter is <code>null</code>
2274 * the behavior is unspecified and may result in an
2275 * exception.
2276 *
2277 * @param e the container event
2278 * @see Component#enableEvents
2279 */
2280 protected void processContainerEvent(ContainerEvent e) {
2281 ContainerListener listener = containerListener;
2282 if (listener != null) {
2283 switch(e.getID()) {
2284 case ContainerEvent.COMPONENT_ADDED:
2285 listener.componentAdded(e);
2286 break;
2287 case ContainerEvent.COMPONENT_REMOVED:
2288 listener.componentRemoved(e);
2289 break;
2290 }
2291 }
2292 }
2293
2348 Component getMouseEventTarget(int x, int y, boolean includeSelf) {
2349 return getMouseEventTarget(x, y, includeSelf,
2350 MouseEventTargetFilter.FILTER,
2351 !SEARCH_HEAVYWEIGHTS);
2352 }
2353
2354 /**
2355 * Fetches the top-most (deepest) component to receive SunDropTargetEvents.
2356 */
2357 Component getDropTargetEventTarget(int x, int y, boolean includeSelf) {
2358 return getMouseEventTarget(x, y, includeSelf,
2359 DropTargetEventTargetFilter.FILTER,
2360 SEARCH_HEAVYWEIGHTS);
2361 }
2362
2363 /**
2364 * A private version of getMouseEventTarget which has two additional
2365 * controllable behaviors. This method searches for the top-most
2366 * descendant of this container that contains the given coordinates
2367 * and is accepted by the given filter. The search will be constrained to
2368 * lightweight descendants if the last argument is <code>false</code>.
2369 *
2370 * @param filter EventTargetFilter instance to determine whether the
2371 * given component is a valid target for this event.
2372 * @param searchHeavyweights if <code>false</code>, the method
2373 * will bypass heavyweight components during the search.
2374 */
2375 private Component getMouseEventTarget(int x, int y, boolean includeSelf,
2376 EventTargetFilter filter,
2377 boolean searchHeavyweights) {
2378 Component comp = null;
2379 if (searchHeavyweights) {
2380 comp = getMouseEventTargetImpl(x, y, includeSelf, filter,
2381 SEARCH_HEAVYWEIGHTS,
2382 searchHeavyweights);
2383 }
2384
2385 if (comp == null || comp == this) {
2386 comp = getMouseEventTargetImpl(x, y, includeSelf, filter,
2387 !SEARCH_HEAVYWEIGHTS,
2388 searchHeavyweights);
2389 }
2390
2391 return comp;
2392 }
2393
2394 /**
2395 * A private version of getMouseEventTarget which has three additional
2396 * controllable behaviors. This method searches for the top-most
2397 * descendant of this container that contains the given coordinates
2398 * and is accepted by the given filter. The search will be constrained to
2399 * descendants of only lightweight children or only heavyweight children
2400 * of this container depending on searchHeavyweightChildren. The search will
2401 * be constrained to only lightweight descendants of the searched children
2402 * of this container if searchHeavyweightDescendants is <code>false</code>.
2403 *
2404 * @param filter EventTargetFilter instance to determine whether the
2405 * selected component is a valid target for this event.
2406 * @param searchHeavyweightChildren if <code>true</code>, the method
2407 * will bypass immediate lightweight children during the search.
2408 * If <code>false</code>, the methods will bypass immediate
2409 * heavyweight children during the search.
2410 * @param searchHeavyweightDescendants if <code>false</code>, the method
2411 * will bypass heavyweight descendants which are not immediate
2412 * children during the search. If <code>true</code>, the method
2413 * will traverse both lightweight and heavyweight descendants during
2414 * the search.
2415 */
2416 private Component getMouseEventTargetImpl(int x, int y, boolean includeSelf,
2417 EventTargetFilter filter,
2418 boolean searchHeavyweightChildren,
2419 boolean searchHeavyweightDescendants) {
2420 synchronized (getTreeLock()) {
2421
2422 for (int i = 0; i < component.size(); i++) {
2423 Component comp = component.get(i);
2424 if (comp != null && comp.visible &&
2425 ((!searchHeavyweightChildren &&
2426 comp.peer instanceof LightweightPeer) ||
2427 (searchHeavyweightChildren &&
2428 !(comp.peer instanceof LightweightPeer))) &&
2429 comp.contains(x - comp.x, y - comp.y)) {
2430
2431 // found a component that intersects the point, see if there
2432 // is a deeper possibility.
2508 if (peer instanceof LightweightPeer) {
2509 // this container is lightweight.... continue sending it
2510 // upward.
2511 if (parent != null) {
2512 parent.proxyEnableEvents(events);
2513 }
2514 } else {
2515 // This is a native container, so it needs to host
2516 // one of it's children. If this function is called before
2517 // a peer has been created we don't yet have a dispatcher
2518 // because it has not yet been determined if this instance
2519 // is lightweight.
2520 if (dispatcher != null) {
2521 dispatcher.enableEvents(events);
2522 }
2523 }
2524 }
2525
2526 /**
2527 * @deprecated As of JDK version 1.1,
2528 * replaced by <code>dispatchEvent(AWTEvent e)</code>
2529 */
2530 @Deprecated
2531 public void deliverEvent(Event e) {
2532 Component comp = getComponentAt(e.x, e.y);
2533 if ((comp != null) && (comp != this)) {
2534 e.translate(-comp.x, -comp.y);
2535 comp.deliverEvent(e);
2536 } else {
2537 postEvent(e);
2538 }
2539 }
2540
2541 /**
2542 * Locates the component that contains the x,y position. The
2543 * top-most child component is returned in the case where there
2544 * is overlap in the components. This is determined by finding
2545 * the component closest to the index 0 that claims to contain
2546 * the given point via Component.contains(), except that Components
2547 * which have native peers take precedence over those which do not
2548 * (i.e., lightweight Components).
2549 *
2550 * @param x the <i>x</i> coordinate
2551 * @param y the <i>y</i> coordinate
2552 * @return null if the component does not contain the position.
2553 * If there is no child component at the requested point and the
2554 * point is within the bounds of the container the container itself
2555 * is returned; otherwise the top-most child is returned.
2556 * @see Component#contains
2557 * @since 1.1
2558 */
2559 public Component getComponentAt(int x, int y) {
2560 return locate(x, y);
2561 }
2562
2563 /**
2564 * @deprecated As of JDK version 1.1,
2565 * replaced by <code>getComponentAt(int, int)</code>.
2566 */
2567 @Deprecated
2568 public Component locate(int x, int y) {
2569 if (!contains(x, y)) {
2570 return null;
2571 }
2572 Component lightweight = null;
2573 synchronized (getTreeLock()) {
2574 // Optimized version of two passes:
2575 // see comment in sun.awt.SunGraphicsCallback
2576 for (final Component comp : component) {
2577 if (comp.contains(x - comp.x, y - comp.y)) {
2578 if (!comp.isLightweight()) {
2579 // return heavyweight component as soon as possible
2580 return comp;
2581 }
2582 if (lightweight == null) {
2583 // save and return later the first lightweight component
2584 lightweight = comp;
2585 }
2586 }
2587 }
2588 }
2589 return lightweight != null ? lightweight : this;
2590 }
2591
2592 /**
2593 * Gets the component that contains the specified point.
2594 * @param p the point.
2595 * @return returns the component that contains the point,
2596 * or <code>null</code> if the component does
2597 * not contain the point.
2598 * @see Component#contains
2599 * @since 1.1
2600 */
2601 public Component getComponentAt(Point p) {
2602 return getComponentAt(p.x, p.y);
2603 }
2604
2605 /**
2606 * Returns the position of the mouse pointer in this <code>Container</code>'s
2607 * coordinate space if the <code>Container</code> is under the mouse pointer,
2608 * otherwise returns <code>null</code>.
2609 * This method is similar to {@link Component#getMousePosition()} with the exception
2610 * that it can take the <code>Container</code>'s children into account.
2611 * If <code>allowChildren</code> is <code>false</code>, this method will return
2612 * a non-null value only if the mouse pointer is above the <code>Container</code>
2613 * directly, not above the part obscured by children.
2614 * If <code>allowChildren</code> is <code>true</code>, this method returns
2615 * a non-null value if the mouse pointer is above <code>Container</code> or any
2616 * of its descendants.
2617 *
2618 * @exception HeadlessException if GraphicsEnvironment.isHeadless() returns true
2619 * @param allowChildren true if children should be taken into account
2620 * @see Component#getMousePosition
2621 * @return mouse coordinates relative to this <code>Component</code>, or null
2622 * @since 1.5
2623 */
2624 public Point getMousePosition(boolean allowChildren) throws HeadlessException {
2625 if (GraphicsEnvironment.isHeadless()) {
2626 throw new HeadlessException();
2627 }
2628 PointerInfo pi = java.security.AccessController.doPrivileged(
2629 new java.security.PrivilegedAction<PointerInfo>() {
2630 public PointerInfo run() {
2631 return MouseInfo.getPointerInfo();
2632 }
2633 }
2634 );
2635 synchronized (getTreeLock()) {
2636 Component inTheSameWindow = findUnderMouseInWindow(pi);
2637 if (isSameOrAncestorOf(inTheSameWindow, allowChildren)) {
2638 return pointRelativeToComponent(pi.getLocation());
2639 }
2640 return null;
2641 }
2831 // If some of the children had focus before disposal then it still has.
2832 // Auto-transfer focus to the next (or previous) component if auto-transfer
2833 // is enabled.
2834 if (containsFocus() && KeyboardFocusManager.isAutoFocusTransferEnabledFor(this)) {
2835 if (!transferFocus(false)) {
2836 transferFocusBackward(true);
2837 }
2838 }
2839 if ( dispatcher != null ) {
2840 dispatcher.dispose();
2841 dispatcher = null;
2842 }
2843 super.removeNotify();
2844 }
2845 }
2846
2847 /**
2848 * Checks if the component is contained in the component hierarchy of
2849 * this container.
2850 * @param c the component
2851 * @return <code>true</code> if it is an ancestor;
2852 * <code>false</code> otherwise.
2853 * @since 1.1
2854 */
2855 public boolean isAncestorOf(Component c) {
2856 Container p;
2857 if (c == null || ((p = c.getParent()) == null)) {
2858 return false;
2859 }
2860 while (p != null) {
2861 if (p == this) {
2862 return true;
2863 }
2864 p = p.getParent();
2865 }
2866 return false;
2867 }
2868
2869 /*
2870 * The following code was added to support modal JInternalFrames
2871 * Unfortunately this code has to be added here so that we can get access to
2872 * some private AWT classes like SequencedEvent.
2966 // Wake up event dispatch thread on which the dialog was
2967 // initially shown
2968 SunToolkit.postEvent(modalAppContext,
2969 new PeerEvent(this,
2970 new WakingRunnable(),
2971 PeerEvent.PRIORITY_EVENT));
2972 }
2973 EventQueue.invokeLater(new WakingRunnable());
2974 getTreeLock().notifyAll();
2975 }
2976 }
2977
2978 static final class WakingRunnable implements Runnable {
2979 public void run() {
2980 }
2981 }
2982
2983 /* End of JOptionPane support code */
2984
2985 /**
2986 * Returns a string representing the state of this <code>Container</code>.
2987 * This method is intended to be used only for debugging purposes, and the
2988 * content and format of the returned string may vary between
2989 * implementations. The returned string may be empty but may not be
2990 * <code>null</code>.
2991 *
2992 * @return the parameter string of this container
2993 */
2994 protected String paramString() {
2995 String str = super.paramString();
2996 LayoutManager layoutMgr = this.layoutMgr;
2997 if (layoutMgr != null) {
2998 str += ",layout=" + layoutMgr.getClass().getName();
2999 }
3000 return str;
3001 }
3002
3003 /**
3004 * Prints a listing of this container to the specified output
3005 * stream. The listing starts at the specified indentation.
3006 * <p>
3007 * The immediate children of the container are printed with
3008 * an indentation of <code>indent+1</code>. The children
3009 * of those children are printed at <code>indent+2</code>
3010 * and so on.
3011 *
3012 * @param out a print stream
3013 * @param indent the number of spaces to indent
3014 * @throws NullPointerException if {@code out} is {@code null}
3015 * @see Component#list(java.io.PrintStream, int)
3016 * @since 1.0
3017 */
3018 public void list(PrintStream out, int indent) {
3019 super.list(out, indent);
3020 synchronized(getTreeLock()) {
3021 for (int i = 0; i < component.size(); i++) {
3022 Component comp = component.get(i);
3023 if (comp != null) {
3024 comp.list(out, indent+1);
3025 }
3026 }
3027 }
3028 }
3029
3030 /**
3031 * Prints out a list, starting at the specified indentation,
3032 * to the specified print writer.
3033 * <p>
3034 * The immediate children of the container are printed with
3035 * an indentation of <code>indent+1</code>. The children
3036 * of those children are printed at <code>indent+2</code>
3037 * and so on.
3038 *
3039 * @param out a print writer
3040 * @param indent the number of spaces to indent
3041 * @throws NullPointerException if {@code out} is {@code null}
3042 * @see Component#list(java.io.PrintWriter, int)
3043 * @since 1.1
3044 */
3045 public void list(PrintWriter out, int indent) {
3046 super.list(out, indent);
3047 synchronized(getTreeLock()) {
3048 for (int i = 0; i < component.size(); i++) {
3049 Component comp = component.get(i);
3050 if (comp != null) {
3051 comp.list(out, indent+1);
3052 }
3053 }
3054 }
3055 }
3056
3132 * operation for this Container
3133 * @since 1.4
3134 * @beaninfo
3135 * bound: true
3136 */
3137 public void setFocusTraversalKeys(int id,
3138 Set<? extends AWTKeyStroke> keystrokes)
3139 {
3140 if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {
3141 throw new IllegalArgumentException("invalid focus traversal key identifier");
3142 }
3143
3144 // Don't call super.setFocusTraversalKey. The Component parameter check
3145 // does not allow DOWN_CYCLE_TRAVERSAL_KEYS, but we do.
3146 setFocusTraversalKeys_NoIDCheck(id, keystrokes);
3147 }
3148
3149 /**
3150 * Returns the Set of focus traversal keys for a given traversal operation
3151 * for this Container. (See
3152 * <code>setFocusTraversalKeys</code> for a full description of each key.)
3153 * <p>
3154 * If a Set of traversal keys has not been explicitly defined for this
3155 * Container, then this Container's parent's Set is returned. If no Set
3156 * has been explicitly defined for any of this Container's ancestors, then
3157 * the current KeyboardFocusManager's default Set is returned.
3158 *
3159 * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
3160 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
3161 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
3162 * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
3163 * @return the Set of AWTKeyStrokes for the specified operation. The Set
3164 * will be unmodifiable, and may be empty. null will never be
3165 * returned.
3166 * @see #setFocusTraversalKeys
3167 * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
3168 * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
3169 * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
3170 * @see KeyboardFocusManager#DOWN_CYCLE_TRAVERSAL_KEYS
3171 * @throws IllegalArgumentException if id is not one of
3172 * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
3173 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
3174 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
3175 * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
3176 * @since 1.4
3177 */
3178 public Set<AWTKeyStroke> getFocusTraversalKeys(int id) {
3179 if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {
3180 throw new IllegalArgumentException("invalid focus traversal key identifier");
3181 }
3182
3183 // Don't call super.getFocusTraversalKey. The Component parameter check
3184 // does not allow DOWN_CYCLE_TRAVERSAL_KEY, but we do.
3185 return getFocusTraversalKeys_NoIDCheck(id);
3186 }
3187
3188 /**
3189 * Returns whether the Set of focus traversal keys for the given focus
3190 * traversal operation has been explicitly defined for this Container. If
3191 * this method returns <code>false</code>, this Container is inheriting the
3192 * Set from an ancestor, or from the current KeyboardFocusManager.
3193 *
3194 * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
3195 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
3196 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
3197 * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
3198 * @return <code>true</code> if the Set of focus traversal keys for the
3199 * given focus traversal operation has been explicitly defined for
3200 * this Component; <code>false</code> otherwise.
3201 * @throws IllegalArgumentException if id is not one of
3202 * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
3203 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
3204 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
3205 * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
3206 * @since 1.4
3207 */
3208 public boolean areFocusTraversalKeysSet(int id) {
3209 if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {
3210 throw new IllegalArgumentException("invalid focus traversal key identifier");
3211 }
3212
3213 return (focusTraversalKeys != null && focusTraversalKeys[id] != null);
3214 }
3215
3216 /**
3217 * Returns whether the specified Container is the focus cycle root of this
3218 * Container's focus traversal cycle. Each focus traversal cycle has only
3219 * a single focus cycle root and each Container which is not a focus cycle
3220 * root belongs to only a single focus traversal cycle. Containers which
3221 * are focus cycle roots belong to two cycles: one rooted at the Container
3222 * itself, and one rooted at the Container's nearest focus-cycle-root
3223 * ancestor. This method will return <code>true</code> for both such
3224 * Containers in this case.
3225 *
3226 * @param container the Container to be tested
3227 * @return <code>true</code> if the specified Container is a focus-cycle-
3228 * root of this Container; <code>false</code> otherwise
3229 * @see #isFocusCycleRoot()
3230 * @since 1.4
3231 */
3232 public boolean isFocusCycleRoot(Container container) {
3233 if (isFocusCycleRoot() && container == this) {
3234 return true;
3235 } else {
3236 return super.isFocusCycleRoot(container);
3237 }
3238 }
3239
3240 private Container findTraversalRoot() {
3241 // I potentially have two roots, myself and my root parent
3242 // If I am the current root, then use me
3243 // If none of my parents are roots, then use me
3244 // If my root parent is the current root, then use my root parent
3245 // If neither I nor my root parent is the current root, then
3246 // use my root parent (a guess)
3247
3248 Container currentFocusCycleRoot = KeyboardFocusManager.
3377 if (!isFocusTraversalPolicyProvider() && !isFocusCycleRoot()) {
3378 return null;
3379 }
3380
3381 FocusTraversalPolicy policy = this.focusTraversalPolicy;
3382 if (policy != null) {
3383 return policy;
3384 }
3385
3386 Container rootAncestor = getFocusCycleRootAncestor();
3387 if (rootAncestor != null) {
3388 return rootAncestor.getFocusTraversalPolicy();
3389 } else {
3390 return KeyboardFocusManager.getCurrentKeyboardFocusManager().
3391 getDefaultFocusTraversalPolicy();
3392 }
3393 }
3394
3395 /**
3396 * Returns whether the focus traversal policy has been explicitly set for
3397 * this Container. If this method returns <code>false</code>, this
3398 * Container will inherit its focus traversal policy from an ancestor.
3399 *
3400 * @return <code>true</code> if the focus traversal policy has been
3401 * explicitly set for this Container; <code>false</code> otherwise.
3402 * @since 1.4
3403 */
3404 public boolean isFocusTraversalPolicySet() {
3405 return (focusTraversalPolicy != null);
3406 }
3407
3408 /**
3409 * Sets whether this Container is the root of a focus traversal cycle. Once
3410 * focus enters a traversal cycle, typically it cannot leave it via focus
3411 * traversal unless one of the up- or down-cycle keys is pressed. Normal
3412 * traversal is limited to this Container, and all of this Container's
3413 * descendants that are not descendants of inferior focus cycle roots. Note
3414 * that a FocusTraversalPolicy may bend these restrictions, however. For
3415 * example, ContainerOrderFocusTraversalPolicy supports implicit down-cycle
3416 * traversal.
3417 * <p>
3418 * The alternative way to specify the traversal order of this Container's
3419 * children is to make this Container a
3420 * <a href="doc-files/FocusSpec.html#FocusTraversalPolicyProviders">focus traversal policy provider</a>.
3421 *
3447 * Normal traversal is limited to this Container, and all of this
3448 * Container's descendants that are not descendants of inferior focus
3449 * cycle roots. Note that a FocusTraversalPolicy may bend these
3450 * restrictions, however. For example, ContainerOrderFocusTraversalPolicy
3451 * supports implicit down-cycle traversal.
3452 *
3453 * @return whether this Container is the root of a focus traversal cycle
3454 * @see #setFocusCycleRoot
3455 * @see #setFocusTraversalPolicy
3456 * @see #getFocusTraversalPolicy
3457 * @see ContainerOrderFocusTraversalPolicy
3458 * @since 1.4
3459 */
3460 public boolean isFocusCycleRoot() {
3461 return focusCycleRoot;
3462 }
3463
3464 /**
3465 * Sets whether this container will be used to provide focus
3466 * traversal policy. Container with this property as
3467 * <code>true</code> will be used to acquire focus traversal policy
3468 * instead of closest focus cycle root ancestor.
3469 * @param provider indicates whether this container will be used to
3470 * provide focus traversal policy
3471 * @see #setFocusTraversalPolicy
3472 * @see #getFocusTraversalPolicy
3473 * @see #isFocusTraversalPolicyProvider
3474 * @since 1.5
3475 * @beaninfo
3476 * bound: true
3477 */
3478 public final void setFocusTraversalPolicyProvider(boolean provider) {
3479 boolean oldProvider;
3480 synchronized(this) {
3481 oldProvider = focusTraversalPolicyProvider;
3482 focusTraversalPolicyProvider = provider;
3483 }
3484 firePropertyChange("focusTraversalPolicyProvider", oldProvider, provider);
3485 }
3486
3487 /**
3488 * Returns whether this container provides focus traversal
3489 * policy. If this property is set to <code>true</code> then when
3490 * keyboard focus manager searches container hierarchy for focus
3491 * traversal policy and encounters this container before any other
3492 * container with this property as true or focus cycle roots then
3493 * its focus traversal policy will be used instead of focus cycle
3494 * root's policy.
3495 * @see #setFocusTraversalPolicy
3496 * @see #getFocusTraversalPolicy
3497 * @see #setFocusCycleRoot
3498 * @see #setFocusTraversalPolicyProvider
3499 * @return <code>true</code> if this container provides focus traversal
3500 * policy, <code>false</code> otherwise
3501 * @since 1.5
3502 * @beaninfo
3503 * bound: true
3504 */
3505 public final boolean isFocusTraversalPolicyProvider() {
3506 return focusTraversalPolicyProvider;
3507 }
3508
3509 /**
3510 * Transfers the focus down one focus traversal cycle. If this Container is
3511 * a focus cycle root, then the focus owner is set to this Container's
3512 * default Component to focus, and the current focus cycle root is set to
3513 * this Container. If this Container is not a focus cycle root, then no
3514 * focus traversal operation occurs.
3515 *
3516 * @see Component#requestFocus()
3517 * @see #isFocusCycleRoot
3518 * @see #setFocusCycleRoot
3519 * @since 1.4
3520 */
3532
3533 void preProcessKeyEvent(KeyEvent e) {
3534 Container parent = this.parent;
3535 if (parent != null) {
3536 parent.preProcessKeyEvent(e);
3537 }
3538 }
3539
3540 void postProcessKeyEvent(KeyEvent e) {
3541 Container parent = this.parent;
3542 if (parent != null) {
3543 parent.postProcessKeyEvent(e);
3544 }
3545 }
3546
3547 boolean postsOldMouseEvents() {
3548 return true;
3549 }
3550
3551 /**
3552 * Sets the <code>ComponentOrientation</code> property of this container
3553 * and all components contained within it.
3554 * <p>
3555 * This method changes layout-related information, and therefore,
3556 * invalidates the component hierarchy.
3557 *
3558 * @param o the new component orientation of this container and
3559 * the components contained within it.
3560 * @exception NullPointerException if <code>orientation</code> is null.
3561 * @see Component#setComponentOrientation
3562 * @see Component#getComponentOrientation
3563 * @see #invalidate
3564 * @since 1.4
3565 */
3566 public void applyComponentOrientation(ComponentOrientation o) {
3567 super.applyComponentOrientation(o);
3568 synchronized (getTreeLock()) {
3569 for (int i = 0; i < component.size(); i++) {
3570 Component comp = component.get(i);
3571 comp.applyComponentOrientation(o);
3572 }
3573 }
3574 }
3575
3576 /**
3577 * Adds a PropertyChangeListener to the listener list. The listener is
3578 * registered for all bound properties of this class, including the
3579 * following:
3580 * <ul>
3643 * @param propertyName one of the property names listed above
3644 * @param listener the PropertyChangeListener to be added
3645 *
3646 * @see #addPropertyChangeListener(java.beans.PropertyChangeListener)
3647 * @see Component#removePropertyChangeListener
3648 */
3649 public void addPropertyChangeListener(String propertyName,
3650 PropertyChangeListener listener) {
3651 super.addPropertyChangeListener(propertyName, listener);
3652 }
3653
3654 // Serialization support. A Container is responsible for restoring the
3655 // parent fields of its component children.
3656
3657 /**
3658 * Container Serial Data Version.
3659 */
3660 private int containerSerializedDataVersion = 1;
3661
3662 /**
3663 * Serializes this <code>Container</code> to the specified
3664 * <code>ObjectOutputStream</code>.
3665 * <ul>
3666 * <li>Writes default serializable fields to the stream.</li>
3667 * <li>Writes a list of serializable ContainerListener(s) as optional
3668 * data. The non-serializable ContainerListener(s) are detected and
3669 * no attempt is made to serialize them.</li>
3670 * <li>Write this Container's FocusTraversalPolicy if and only if it
3671 * is Serializable; otherwise, <code>null</code> is written.</li>
3672 * </ul>
3673 *
3674 * @param s the <code>ObjectOutputStream</code> to write
3675 * @serialData <code>null</code> terminated sequence of 0 or more pairs;
3676 * the pair consists of a <code>String</code> and <code>Object</code>;
3677 * the <code>String</code> indicates the type of object and
3678 * is one of the following:
3679 * <code>containerListenerK</code> indicating an
3680 * <code>ContainerListener</code> object;
3681 * the <code>Container</code>'s <code>FocusTraversalPolicy</code>,
3682 * or <code>null</code>
3683 *
3684 * @see AWTEventMulticaster#save(java.io.ObjectOutputStream, java.lang.String, java.util.EventListener)
3685 * @see Container#containerListenerK
3686 * @see #readObject(ObjectInputStream)
3687 */
3688 private void writeObject(ObjectOutputStream s) throws IOException {
3689 ObjectOutputStream.PutField f = s.putFields();
3690 f.put("ncomponents", component.size());
3691 f.put("component", component.toArray(EMPTY_ARRAY));
3692 f.put("layoutMgr", layoutMgr);
3693 f.put("dispatcher", dispatcher);
3694 f.put("maxSize", maxSize);
3695 f.put("focusCycleRoot", focusCycleRoot);
3696 f.put("containerSerializedDataVersion", containerSerializedDataVersion);
3697 f.put("focusTraversalPolicyProvider", focusTraversalPolicyProvider);
3698 s.writeFields();
3699
3700 AWTEventMulticaster.save(s, containerListenerK, containerListener);
3701 s.writeObject(null);
3702
3703 if (focusTraversalPolicy instanceof java.io.Serializable) {
3704 s.writeObject(focusTraversalPolicy);
3705 } else {
3706 s.writeObject(null);
3707 }
3708 }
3709
3710 /**
3711 * Deserializes this <code>Container</code> from the specified
3712 * <code>ObjectInputStream</code>.
3713 * <ul>
3714 * <li>Reads default serializable fields from the stream.</li>
3715 * <li>Reads a list of serializable ContainerListener(s) as optional
3716 * data. If the list is null, no Listeners are installed.</li>
3717 * <li>Reads this Container's FocusTraversalPolicy, which may be null,
3718 * as optional data.</li>
3719 * </ul>
3720 *
3721 * @param s the <code>ObjectInputStream</code> to read
3722 * @serial
3723 * @see #addContainerListener
3724 * @see #writeObject(ObjectOutputStream)
3725 */
3726 private void readObject(ObjectInputStream s)
3727 throws ClassNotFoundException, IOException
3728 {
3729 ObjectInputStream.GetField f = s.readFields();
3730 Component [] tmpComponent = (Component[])f.get("component", EMPTY_ARRAY);
3731 int ncomponents = (Integer) f.get("ncomponents", 0);
3732 component = new java.util.ArrayList<Component>(ncomponents);
3733 for (int i = 0; i < ncomponents; ++i) {
3734 component.add(tmpComponent[i]);
3735 }
3736 layoutMgr = (LayoutManager)f.get("layoutMgr", null);
3737 dispatcher = (LightweightDispatcher)f.get("dispatcher", null);
3738 // Old stream. Doesn't contain maxSize among Component's fields.
3739 if (maxSize == null) {
3740 maxSize = (Dimension)f.get("maxSize", null);
3741 }
3789 /**
3790 * Inner class of Container used to provide default support for
3791 * accessibility. This class is not meant to be used directly by
3792 * application developers, but is instead meant only to be
3793 * subclassed by container developers.
3794 * <p>
3795 * The class used to obtain the accessible role for this object,
3796 * as well as implementing many of the methods in the
3797 * AccessibleContainer interface.
3798 * @since 1.3
3799 */
3800 protected class AccessibleAWTContainer extends AccessibleAWTComponent {
3801
3802 /**
3803 * JDK1.3 serialVersionUID
3804 */
3805 private static final long serialVersionUID = 5081320404842566097L;
3806
3807 /**
3808 * Returns the number of accessible children in the object. If all
3809 * of the children of this object implement <code>Accessible</code>,
3810 * then this method should return the number of children of this object.
3811 *
3812 * @return the number of accessible children in the object
3813 */
3814 public int getAccessibleChildrenCount() {
3815 return Container.this.getAccessibleChildrenCount();
3816 }
3817
3818 /**
3819 * Returns the nth <code>Accessible</code> child of the object.
3820 *
3821 * @param i zero-based index of child
3822 * @return the nth <code>Accessible</code> child of the object
3823 */
3824 public Accessible getAccessibleChild(int i) {
3825 return Container.this.getAccessibleChild(i);
3826 }
3827
3828 /**
3829 * Returns the <code>Accessible</code> child, if one exists,
3830 * contained at the local coordinate <code>Point</code>.
3831 *
3832 * @param p the point defining the top-left corner of the
3833 * <code>Accessible</code>, given in the coordinate space
3834 * of the object's parent
3835 * @return the <code>Accessible</code>, if it exists,
3836 * at the specified location; else <code>null</code>
3837 */
3838 public Accessible getAccessibleAt(Point p) {
3839 return Container.this.getAccessibleAt(p);
3840 }
3841
3842 /**
3843 * Number of PropertyChangeListener objects registered. It's used
3844 * to add/remove ContainerListener to track target Container's state.
3845 */
3846 private transient volatile int propertyListenersCount = 0;
3847
3848 /**
3849 * The handler to fire {@code PropertyChange}
3850 * when children are added or removed
3851 */
3852 protected ContainerListener accessibleContainerHandler = null;
3853
3854 /**
3855 * Fire <code>PropertyChange</code> listener, if one is registered,
3856 * when children are added or removed.
3857 * @since 1.3
3858 */
3859 protected class AccessibleContainerHandler
3860 implements ContainerListener {
3861 public void componentAdded(ContainerEvent e) {
3862 Component c = e.getChild();
3863 if (c != null && c instanceof Accessible) {
3864 AccessibleAWTContainer.this.firePropertyChange(
3865 AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
3866 null, ((Accessible) c).getAccessibleContext());
3867 }
3868 }
3869 public void componentRemoved(ContainerEvent e) {
3870 Component c = e.getChild();
3871 if (c != null && c instanceof Accessible) {
3872 AccessibleAWTContainer.this.firePropertyChange(
3873 AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
3874 ((Accessible) c).getAccessibleContext(), null);
3875 }
3891 super.addPropertyChangeListener(listener);
3892 }
3893
3894 /**
3895 * Remove a PropertyChangeListener from the listener list.
3896 * This removes a PropertyChangeListener that was registered
3897 * for all properties.
3898 *
3899 * @param listener the PropertyChangeListener to be removed
3900 */
3901 public void removePropertyChangeListener(PropertyChangeListener listener) {
3902 if (--propertyListenersCount == 0) {
3903 Container.this.removeContainerListener(accessibleContainerHandler);
3904 }
3905 super.removePropertyChangeListener(listener);
3906 }
3907
3908 } // inner class AccessibleAWTContainer
3909
3910 /**
3911 * Returns the <code>Accessible</code> child contained at the local
3912 * coordinate <code>Point</code>, if one exists. Otherwise
3913 * returns <code>null</code>.
3914 *
3915 * @param p the point defining the top-left corner of the
3916 * <code>Accessible</code>, given in the coordinate space
3917 * of the object's parent
3918 * @return the <code>Accessible</code> at the specified location,
3919 * if it exists; otherwise <code>null</code>
3920 */
3921 Accessible getAccessibleAt(Point p) {
3922 synchronized (getTreeLock()) {
3923 if (this instanceof Accessible) {
3924 Accessible a = (Accessible)this;
3925 AccessibleContext ac = a.getAccessibleContext();
3926 if (ac != null) {
3927 AccessibleComponent acmp;
3928 Point location;
3929 int nchildren = ac.getAccessibleChildrenCount();
3930 for (int i=0; i < nchildren; i++) {
3931 a = ac.getAccessibleChild(i);
3932 if ((a != null)) {
3933 ac = a.getAccessibleContext();
3934 if (ac != null) {
3935 acmp = ac.getAccessibleComponent();
3936 if ((acmp != null) && (acmp.isShowing())) {
3937 location = acmp.getLocation();
3938 Point np = new Point(p.x-location.x,
3939 p.y-location.y);
3955 for (int i=0; i < ncomponents; i++) {
3956 Component comp = this.getComponent(i);
3957 if ((comp != null) && comp.isShowing()) {
3958 Point location = comp.getLocation();
3959 if (comp.contains(p.x-location.x,p.y-location.y)) {
3960 ret = comp;
3961 }
3962 }
3963 }
3964 }
3965 if (ret instanceof Accessible) {
3966 return (Accessible) ret;
3967 }
3968 }
3969 return null;
3970 }
3971 }
3972
3973 /**
3974 * Returns the number of accessible children in the object. If all
3975 * of the children of this object implement <code>Accessible</code>,
3976 * then this method should return the number of children of this object.
3977 *
3978 * @return the number of accessible children in the object
3979 */
3980 int getAccessibleChildrenCount() {
3981 synchronized (getTreeLock()) {
3982 int count = 0;
3983 Component[] children = this.getComponents();
3984 for (int i = 0; i < children.length; i++) {
3985 if (children[i] instanceof Accessible) {
3986 count++;
3987 }
3988 }
3989 return count;
3990 }
3991 }
3992
3993 /**
3994 * Returns the nth <code>Accessible</code> child of the object.
3995 *
3996 * @param i zero-based index of child
3997 * @return the nth <code>Accessible</code> child of the object
3998 */
3999 Accessible getAccessibleChild(int i) {
4000 synchronized (getTreeLock()) {
4001 Component[] children = this.getComponents();
4002 int count = 0;
4003 for (int j = 0; j < children.length; j++) {
4004 if (children[j] instanceof Accessible) {
4005 if (count == i) {
4006 return (Accessible) children[j];
4007 } else {
4008 count++;
4009 }
4010 }
4011 }
4012 return null;
4013 }
4014 }
4015
4016 // ************************** MIXING CODE *******************************
4017
|
166 // True if there is at least one thread that's printing this component
167 private transient boolean printing = false;
168
169 transient ContainerListener containerListener;
170
171 /* HierarchyListener and HierarchyBoundsListener support */
172 transient int listeningChildren;
173 transient int listeningBoundsChildren;
174 transient int descendantsCount;
175
176 /* Non-opaque window support -- see Window.setLayersOpaque */
177 transient Color preserveBackgroundColor = null;
178
179 /**
180 * JDK 1.1 serialVersionUID
181 */
182 private static final long serialVersionUID = 4613797578919906343L;
183
184 /**
185 * A constant which toggles one of the controllable behaviors
186 * of {@code getMouseEventTarget}. It is used to specify whether
187 * the method can return the Container on which it is originally called
188 * in case if none of its children are the current mouse event targets.
189 *
190 * @see #getMouseEventTarget(int, int, boolean)
191 */
192 static final boolean INCLUDE_SELF = true;
193
194 /**
195 * A constant which toggles one of the controllable behaviors
196 * of {@code getMouseEventTarget}. It is used to specify whether
197 * the method should search only lightweight components.
198 *
199 * @see #getMouseEventTarget(int, int, boolean)
200 */
201 static final boolean SEARCH_HEAVYWEIGHTS = true;
202
203 /*
204 * Number of HW or LW components in this container (including
205 * all descendant containers).
206 */
207 private transient int numOfHWComponents = 0;
208 private transient int numOfLWComponents = 0;
209
210 private static final PlatformLogger mixingLog = PlatformLogger.getLogger("java.awt.mixing.Container");
211
212 /**
213 * @serialField ncomponents int
214 * The number of components in this container.
215 * This value can be null.
216 * @serialField component Component[]
367 // This functionality is implemented in a package-private method
368 // to insure that it cannot be overridden by client subclasses.
369 // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
370 final Component[] getComponents_NoClientCode() {
371 return component.toArray(EMPTY_ARRAY);
372 }
373
374 /*
375 * Wrapper for getComponents() method with a proper synchronization.
376 */
377 Component[] getComponentsSync() {
378 synchronized (getTreeLock()) {
379 return getComponents();
380 }
381 }
382
383 /**
384 * Determines the insets of this container, which indicate the size
385 * of the container's border.
386 * <p>
387 * A {@code Frame} object, for example, has a top inset that
388 * corresponds to the height of the frame's title bar.
389 * @return the insets of this container.
390 * @see Insets
391 * @see LayoutManager
392 * @since 1.1
393 */
394 public Insets getInsets() {
395 return insets();
396 }
397
398 /**
399 * Returns the insets for this container.
400 *
401 * @deprecated As of JDK version 1.1,
402 * replaced by {@code getInsets()}.
403 * @return the insets for this container
404 */
405 @Deprecated
406 public Insets insets() {
407 ComponentPeer peer = this.peer;
408 if (peer instanceof ContainerPeer) {
409 ContainerPeer cpeer = (ContainerPeer)peer;
410 return (Insets)cpeer.getInsets().clone();
411 }
412 return new Insets(0, 0, 0, 0);
413 }
414
415 /**
416 * Appends the specified component to the end of this container.
417 * This is a convenience method for {@link #addImpl}.
418 * <p>
419 * This method changes layout-related information, and therefore,
420 * invalidates the component hierarchy. If the container has already been
421 * displayed, the hierarchy must be validated thereafter in order to
422 * display the added component.
423 *
424 * @param comp the component to be added
425 * @exception NullPointerException if {@code comp} is {@code null}
426 * @see #addImpl
427 * @see #invalidate
428 * @see #validate
429 * @see javax.swing.JComponent#revalidate()
430 * @return the component argument
431 */
432 public Component add(Component comp) {
433 addImpl(comp, null, -1);
434 return comp;
435 }
436
437 /**
438 * Adds the specified component to this container.
439 * This is a convenience method for {@link #addImpl}.
440 * <p>
441 * This method is obsolete as of 1.1. Please use the
442 * method {@code add(Component, Object)} instead.
443 * <p>
444 * This method changes layout-related information, and therefore,
445 * invalidates the component hierarchy. If the container has already been
446 * displayed, the hierarchy must be validated thereafter in order to
447 * display the added component.
448 *
449 * @param name the name of the component to be added
450 * @param comp the component to be added
451 * @return the component added
452 * @exception NullPointerException if {@code comp} is {@code null}
453 * @see #add(Component, Object)
454 * @see #invalidate
455 */
456 public Component add(String name, Component comp) {
457 addImpl(comp, name, -1);
458 return comp;
459 }
460
461 /**
462 * Adds the specified component to this container at the given
463 * position.
464 * This is a convenience method for {@link #addImpl}.
465 * <p>
466 * This method changes layout-related information, and therefore,
467 * invalidates the component hierarchy. If the container has already been
468 * displayed, the hierarchy must be validated thereafter in order to
469 * display the added component.
470 *
471 *
472 * @param comp the component to be added
473 * @param index the position at which to insert the component,
474 * or {@code -1} to append the component to the end
475 * @exception NullPointerException if {@code comp} is {@code null}
476 * @exception IllegalArgumentException if {@code index} is invalid (see
477 * {@link #addImpl} for details)
478 * @return the component {@code comp}
479 * @see #addImpl
480 * @see #remove
481 * @see #invalidate
482 * @see #validate
483 * @see javax.swing.JComponent#revalidate()
484 */
485 public Component add(Component comp, int index) {
486 addImpl(comp, null, index);
487 return comp;
488 }
489
490 /**
491 * Checks that the component
492 * isn't supposed to be added into itself.
493 */
494 private void checkAddToSelf(Component comp){
495 if (comp instanceof Container) {
496 for (Container cn = this; cn != null; cn=cn.parent) {
497 if (cn == comp) {
498 throw new IllegalArgumentException("adding container's parent to itself");
515 * Checks : index in bounds of container's size,
516 * comp is not one of this container's parents,
517 * and comp is not a window.
518 * Comp and container must be on the same GraphicsDevice.
519 * if comp is container, all sub-components must be on
520 * same GraphicsDevice.
521 *
522 * @since 1.5
523 */
524 private void checkAdding(Component comp, int index) {
525 checkTreeLock();
526
527 GraphicsConfiguration thisGC = getGraphicsConfiguration();
528
529 if (index > component.size() || index < 0) {
530 throw new IllegalArgumentException("illegal component position");
531 }
532 if (comp.parent == this) {
533 if (index == component.size()) {
534 throw new IllegalArgumentException("illegal component position " +
535 index + " should be less than " + component.size());
536 }
537 }
538 checkAddToSelf(comp);
539 checkNotAWindow(comp);
540
541 Window thisTopLevel = getContainingWindow();
542 Window compTopLevel = comp.getContainingWindow();
543 if (thisTopLevel != compTopLevel) {
544 throw new IllegalArgumentException("component and container should be in the same top-level window");
545 }
546 if (thisGC != null) {
547 comp.checkGD(thisGC.getDevice().getIDstring());
548 }
549 }
550
551 /**
552 * Removes component comp from this container without making unnecessary changes
553 * and generating unnecessary events. This function intended to perform optimized
554 * remove, for example, if newParent and current parent are the same it just changes
555 * index without calling removeNotify.
717 // is quite rare. If we ever need to save the peers, we'll have to slightly change the
718 // addDelicately() method in order to handle such LW containers recursively, reparenting
719 // each HW descendant independently.
720 return !comp.peer.isReparentSupported();
721 } else {
722 return false;
723 }
724 }
725
726 /**
727 * Moves the specified component to the specified z-order index in
728 * the container. The z-order determines the order that components
729 * are painted; the component with the highest z-order paints first
730 * and the component with the lowest z-order paints last.
731 * Where components overlap, the component with the lower
732 * z-order paints over the component with the higher z-order.
733 * <p>
734 * If the component is a child of some other container, it is
735 * removed from that container before being added to this container.
736 * The important difference between this method and
737 * {@code java.awt.Container.add(Component, int)} is that this method
738 * doesn't call {@code removeNotify} on the component while
739 * removing it from its previous container unless necessary and when
740 * allowed by the underlying native windowing system. This way, if the
741 * component has the keyboard focus, it maintains the focus when
742 * moved to the new position.
743 * <p>
744 * This property is guaranteed to apply only to lightweight
745 * non-{@code Container} components.
746 * <p>
747 * This method changes layout-related information, and therefore,
748 * invalidates the component hierarchy.
749 * <p>
750 * <b>Note</b>: Not all platforms support changing the z-order of
751 * heavyweight components from one container into another without
752 * the call to {@code removeNotify}. There is no way to detect
753 * whether a platform supports this, so developers shouldn't make
754 * any assumptions.
755 *
756 * @param comp the component to be moved
757 * @param index the position in the container's list to
758 * insert the component, where {@code getComponentCount()}
759 * appends to the end
760 * @exception NullPointerException if {@code comp} is
761 * {@code null}
762 * @exception IllegalArgumentException if {@code comp} is one of the
763 * container's parents
764 * @exception IllegalArgumentException if {@code index} is not in
765 * the range {@code [0, getComponentCount()]} for moving
766 * between containers, or not in the range
767 * {@code [0, getComponentCount()-1]} for moving inside
768 * a container
769 * @exception IllegalArgumentException if adding a container to itself
770 * @exception IllegalArgumentException if adding a {@code Window}
771 * to a container
772 * @see #getComponentZOrder(java.awt.Component)
773 * @see #invalidate
774 * @since 1.5
775 */
776 public void setComponentZOrder(Component comp, int index) {
777 synchronized (getTreeLock()) {
778 // Store parent because remove will clear it
779 Container curParent = comp.parent;
780 int oldZindex = getComponentZOrder(comp);
781
782 if (curParent == this && index == oldZindex) {
783 return;
784 }
785 checkAdding(comp, index);
786
787 boolean peerRecreated = (curParent != null) ?
788 curParent.removeDelicately(comp, this, index) : false;
789
790 addDelicately(comp, curParent, index);
932 }
933 } else {
934 comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
935 this, HierarchyEvent.HIERARCHY_CHANGED,
936 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
937 }
938
939 if (peer != null && layoutMgr == null && isVisible()) {
940 updateCursorImmediately();
941 }
942 }
943
944 /**
945 * Returns the z-order index of the component inside the container.
946 * The higher a component is in the z-order hierarchy, the lower
947 * its index. The component with the lowest z-order index is
948 * painted last, above all other child components.
949 *
950 * @param comp the component being queried
951 * @return the z-order index of the component; otherwise
952 * returns -1 if the component is {@code null}
953 * or doesn't belong to the container
954 * @see #setComponentZOrder(java.awt.Component, int)
955 * @since 1.5
956 */
957 public int getComponentZOrder(Component comp) {
958 if (comp == null) {
959 return -1;
960 }
961 synchronized(getTreeLock()) {
962 // Quick check - container should be immediate parent of the component
963 if (comp.parent != this) {
964 return -1;
965 }
966 return component.indexOf(comp);
967 }
968 }
969
970 /**
971 * Adds the specified component to the end of this container.
972 * Also notifies the layout manager to add the component to
993 public void add(Component comp, Object constraints) {
994 addImpl(comp, constraints, -1);
995 }
996
997 /**
998 * Adds the specified component to this container with the specified
999 * constraints at the specified index. Also notifies the layout
1000 * manager to add the component to the this container's layout using
1001 * the specified constraints object.
1002 * This is a convenience method for {@link #addImpl}.
1003 * <p>
1004 * This method changes layout-related information, and therefore,
1005 * invalidates the component hierarchy. If the container has already been
1006 * displayed, the hierarchy must be validated thereafter in order to
1007 * display the added component.
1008 *
1009 *
1010 * @param comp the component to be added
1011 * @param constraints an object expressing layout constraints for this
1012 * @param index the position in the container's list at which to insert
1013 * the component; {@code -1} means insert at the end
1014 * component
1015 * @exception NullPointerException if {@code comp} is {@code null}
1016 * @exception IllegalArgumentException if {@code index} is invalid (see
1017 * {@link #addImpl} for details)
1018 * @see #addImpl
1019 * @see #invalidate
1020 * @see #validate
1021 * @see javax.swing.JComponent#revalidate()
1022 * @see #remove
1023 * @see LayoutManager
1024 */
1025 public void add(Component comp, Object constraints, int index) {
1026 addImpl(comp, constraints, index);
1027 }
1028
1029 /**
1030 * Adds the specified component to this container at the specified
1031 * index. This method also notifies the layout manager to add
1032 * the component to this container's layout using the specified
1033 * constraints object via the {@code addLayoutComponent}
1034 * method.
1035 * <p>
1036 * The constraints are
1037 * defined by the particular layout manager being used. For
1038 * example, the {@code BorderLayout} class defines five
1039 * constraints: {@code BorderLayout.NORTH},
1040 * {@code BorderLayout.SOUTH}, {@code BorderLayout.EAST},
1041 * {@code BorderLayout.WEST}, and {@code BorderLayout.CENTER}.
1042 * <p>
1043 * The {@code GridBagLayout} class requires a
1044 * {@code GridBagConstraints} object. Failure to pass
1045 * the correct type of constraints object results in an
1046 * {@code IllegalArgumentException}.
1047 * <p>
1048 * If the current layout manager implements {@code LayoutManager2}, then
1049 * {@link LayoutManager2#addLayoutComponent(Component,Object)} is invoked on
1050 * it. If the current layout manager does not implement
1051 * {@code LayoutManager2}, and constraints is a {@code String}, then
1052 * {@link LayoutManager#addLayoutComponent(String,Component)} is invoked on it.
1053 * <p>
1054 * If the component is not an ancestor of this container and has a non-null
1055 * parent, it is removed from its current parent before it is added to this
1056 * container.
1057 * <p>
1058 * This is the method to override if a program needs to track
1059 * every add request to a container as all other add methods defer
1060 * to this one. An overriding method should
1061 * usually include a call to the superclass's version of the method:
1062 *
1063 * <blockquote>
1064 * {@code super.addImpl(comp, constraints, index)}
1065 * </blockquote>
1066 * <p>
1067 * This method changes layout-related information, and therefore,
1068 * invalidates the component hierarchy. If the container has already been
1069 * displayed, the hierarchy must be validated thereafter in order to
1070 * display the added component.
1071 *
1072 * @param comp the component to be added
1073 * @param constraints an object expressing layout constraints
1074 * for this component
1075 * @param index the position in the container's list at which to
1076 * insert the component, where {@code -1}
1077 * means append to the end
1078 * @exception IllegalArgumentException if {@code index} is invalid;
1079 * if {@code comp} is a child of this container, the valid
1080 * range is {@code [-1, getComponentCount()-1]}; if component is
1081 * not a child of this container, the valid range is
1082 * {@code [-1, getComponentCount()]}
1083 *
1084 * @exception IllegalArgumentException if {@code comp} is an ancestor of
1085 * this container
1086 * @exception IllegalArgumentException if adding a window to a container
1087 * @exception NullPointerException if {@code comp} is {@code null}
1088 * @see #add(Component)
1089 * @see #add(Component, int)
1090 * @see #add(Component, java.lang.Object)
1091 * @see #invalidate
1092 * @see LayoutManager
1093 * @see LayoutManager2
1094 * @since 1.1
1095 */
1096 protected void addImpl(Component comp, Object constraints, int index) {
1179 ret |= comp.updateGraphicsData(gc);
1180 }
1181 }
1182 return ret;
1183 }
1184
1185 /**
1186 * Checks that all Components that this Container contains are on
1187 * the same GraphicsDevice as this Container. If not, throws an
1188 * IllegalArgumentException.
1189 */
1190 void checkGD(String stringID) {
1191 for (Component comp : component) {
1192 if (comp != null) {
1193 comp.checkGD(stringID);
1194 }
1195 }
1196 }
1197
1198 /**
1199 * Removes the component, specified by {@code index},
1200 * from this container.
1201 * This method also notifies the layout manager to remove the
1202 * component from this container's layout via the
1203 * {@code removeLayoutComponent} method.
1204 * <p>
1205 * This method changes layout-related information, and therefore,
1206 * invalidates the component hierarchy. If the container has already been
1207 * displayed, the hierarchy must be validated thereafter in order to
1208 * reflect the changes.
1209 *
1210 *
1211 * @param index the index of the component to be removed
1212 * @throws ArrayIndexOutOfBoundsException if {@code index} is not in
1213 * range {@code [0, getComponentCount()-1]}
1214 * @see #add
1215 * @see #invalidate
1216 * @see #validate
1217 * @see #getComponentCount
1218 * @since 1.1
1219 */
1220 public void remove(int index) {
1221 synchronized (getTreeLock()) {
1222 if (index < 0 || index >= component.size()) {
1223 throw new ArrayIndexOutOfBoundsException(index);
1246 Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
1247 ContainerEvent e = new ContainerEvent(this,
1248 ContainerEvent.COMPONENT_REMOVED,
1249 comp);
1250 dispatchEvent(e);
1251 }
1252
1253 comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
1254 this, HierarchyEvent.PARENT_CHANGED,
1255 Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
1256 if (peer != null && layoutMgr == null && isVisible()) {
1257 updateCursorImmediately();
1258 }
1259 }
1260 }
1261
1262 /**
1263 * Removes the specified component from this container.
1264 * This method also notifies the layout manager to remove the
1265 * component from this container's layout via the
1266 * {@code removeLayoutComponent} method.
1267 * <p>
1268 * This method changes layout-related information, and therefore,
1269 * invalidates the component hierarchy. If the container has already been
1270 * displayed, the hierarchy must be validated thereafter in order to
1271 * reflect the changes.
1272 *
1273 * @param comp the component to be removed
1274 * @throws NullPointerException if {@code comp} is {@code null}
1275 * @see #add
1276 * @see #invalidate
1277 * @see #validate
1278 * @see #remove(int)
1279 */
1280 public void remove(Component comp) {
1281 synchronized (getTreeLock()) {
1282 if (comp.parent == this) {
1283 int index = component.indexOf(comp);
1284 if (index >= 0) {
1285 remove(index);
1286 }
1287 }
1288 }
1289 }
1290
1291 /**
1292 * Removes all the components from this container.
1293 * This method also notifies the layout manager to remove the
1294 * components from this container's layout via the
1295 * {@code removeLayoutComponent} method.
1296 * <p>
1297 * This method changes layout-related information, and therefore,
1298 * invalidates the component hierarchy. If the container has already been
1299 * displayed, the hierarchy must be validated thereafter in order to
1300 * reflect the changes.
1301 *
1302 * @see #add
1303 * @see #remove
1304 * @see #invalidate
1305 */
1306 public void removeAll() {
1307 synchronized (getTreeLock()) {
1308 adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
1309 -listeningChildren);
1310 adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
1311 -listeningBoundsChildren);
1312 adjustDescendants(-descendantsCount);
1313
1314 while (!component.isEmpty()) {
1315 Component comp = component.remove(component.size()-1);
1495
1496 /**
1497 * Sets the layout manager for this container.
1498 * <p>
1499 * This method changes layout-related information, and therefore,
1500 * invalidates the component hierarchy.
1501 *
1502 * @param mgr the specified layout manager
1503 * @see #doLayout
1504 * @see #getLayout
1505 * @see #invalidate
1506 */
1507 public void setLayout(LayoutManager mgr) {
1508 layoutMgr = mgr;
1509 invalidateIfValid();
1510 }
1511
1512 /**
1513 * Causes this container to lay out its components. Most programs
1514 * should not call this method directly, but should invoke
1515 * the {@code validate} method instead.
1516 * @see LayoutManager#layoutContainer
1517 * @see #setLayout
1518 * @see #validate
1519 * @since 1.1
1520 */
1521 public void doLayout() {
1522 layout();
1523 }
1524
1525 /**
1526 * @deprecated As of JDK version 1.1,
1527 * replaced by {@code doLayout()}.
1528 */
1529 @Deprecated
1530 public void layout() {
1531 LayoutManager layoutMgr = this.layoutMgr;
1532 if (layoutMgr != null) {
1533 layoutMgr.layoutContainer(this);
1534 }
1535 }
1536
1537 /**
1538 * Indicates if this container is a <i>validate root</i>.
1539 * <p>
1540 * Layout-related changes, such as bounds of the validate root descendants,
1541 * do not affect the layout of the validate root parent. This peculiarity
1542 * enables the {@code invalidate()} method to stop invalidating the
1543 * component hierarchy when the method encounters a validate root. However,
1544 * to preserve backward compatibility this new optimized behavior is
1545 * enabled only when the {@code java.awt.smartInvalidate} system property
1546 * value is set to {@code true}.
1547 * <p>
1686 boolean updateCur = false;
1687 synchronized (getTreeLock()) {
1688 descendUnconditionallyWhenValidating = true;
1689
1690 validate();
1691 if (peer instanceof ContainerPeer) {
1692 updateCur = isVisible();
1693 }
1694
1695 descendUnconditionallyWhenValidating = false;
1696 }
1697 if (updateCur) {
1698 updateCursorImmediately();
1699 }
1700 }
1701
1702 /**
1703 * Recursively descends the container tree and recomputes the
1704 * layout for any subtrees marked as needing it (those marked as
1705 * invalid). Synchronization should be provided by the method
1706 * that calls this one: {@code validate}.
1707 *
1708 * @see #doLayout
1709 * @see #validate
1710 */
1711 protected void validateTree() {
1712 checkTreeLock();
1713 if (!isValid() || descendUnconditionallyWhenValidating) {
1714 if (peer instanceof ContainerPeer) {
1715 ((ContainerPeer)peer).beginLayout();
1716 }
1717 if (!isValid()) {
1718 doLayout();
1719 }
1720 for (int i = 0; i < component.size(); i++) {
1721 Component comp = component.get(i);
1722 if ( (comp instanceof Container)
1723 && !(comp instanceof Window)
1724 && (!comp.isValid() ||
1725 descendUnconditionallyWhenValidating))
1726 {
1774 Font newfont = getFont();
1775 if (newfont != oldfont && (oldfont == null ||
1776 !oldfont.equals(newfont))) {
1777 invalidateTree();
1778 }
1779 }
1780
1781 /**
1782 * Returns the preferred size of this container. If the preferred size has
1783 * not been set explicitly by {@link Component#setPreferredSize(Dimension)}
1784 * and this {@code Container} has a {@code non-null} {@link LayoutManager},
1785 * then {@link LayoutManager#preferredLayoutSize(Container)}
1786 * is used to calculate the preferred size.
1787 *
1788 * <p>Note: some implementations may cache the value returned from the
1789 * {@code LayoutManager}. Implementations that cache need not invoke
1790 * {@code preferredLayoutSize} on the {@code LayoutManager} every time
1791 * this method is invoked, rather the {@code LayoutManager} will only
1792 * be queried after the {@code Container} becomes invalid.
1793 *
1794 * @return an instance of {@code Dimension} that represents
1795 * the preferred size of this container.
1796 * @see #getMinimumSize
1797 * @see #getMaximumSize
1798 * @see #getLayout
1799 * @see LayoutManager#preferredLayoutSize(Container)
1800 * @see Component#getPreferredSize
1801 */
1802 public Dimension getPreferredSize() {
1803 return preferredSize();
1804 }
1805
1806 /**
1807 * @deprecated As of JDK version 1.1,
1808 * replaced by {@code getPreferredSize()}.
1809 */
1810 @Deprecated
1811 public Dimension preferredSize() {
1812 /* Avoid grabbing the lock if a reasonable cached size value
1813 * is available.
1814 */
1815 Dimension dim = prefSize;
1816 if (dim == null || !(isPreferredSizeSet() || isValid())) {
1817 synchronized (getTreeLock()) {
1818 prefSize = (layoutMgr != null) ?
1819 layoutMgr.preferredLayoutSize(this) :
1820 super.preferredSize();
1821 dim = prefSize;
1822 }
1823 }
1824 if (dim != null){
1825 return new Dimension(dim);
1826 }
1827 else{
1828 return dim;
1829 }
1830 }
1831
1832 /**
1833 * Returns the minimum size of this container. If the minimum size has
1834 * not been set explicitly by {@link Component#setMinimumSize(Dimension)}
1835 * and this {@code Container} has a {@code non-null} {@link LayoutManager},
1836 * then {@link LayoutManager#minimumLayoutSize(Container)}
1837 * is used to calculate the minimum size.
1838 *
1839 * <p>Note: some implementations may cache the value returned from the
1840 * {@code LayoutManager}. Implementations that cache need not invoke
1841 * {@code minimumLayoutSize} on the {@code LayoutManager} every time
1842 * this method is invoked, rather the {@code LayoutManager} will only
1843 * be queried after the {@code Container} becomes invalid.
1844 *
1845 * @return an instance of {@code Dimension} that represents
1846 * the minimum size of this container.
1847 * @see #getPreferredSize
1848 * @see #getMaximumSize
1849 * @see #getLayout
1850 * @see LayoutManager#minimumLayoutSize(Container)
1851 * @see Component#getMinimumSize
1852 * @since 1.1
1853 */
1854 public Dimension getMinimumSize() {
1855 return minimumSize();
1856 }
1857
1858 /**
1859 * @deprecated As of JDK version 1.1,
1860 * replaced by {@code getMinimumSize()}.
1861 */
1862 @Deprecated
1863 public Dimension minimumSize() {
1864 /* Avoid grabbing the lock if a reasonable cached size value
1865 * is available.
1866 */
1867 Dimension dim = minSize;
1868 if (dim == null || !(isMinimumSizeSet() || isValid())) {
1869 synchronized (getTreeLock()) {
1870 minSize = (layoutMgr != null) ?
1871 layoutMgr.minimumLayoutSize(this) :
1872 super.minimumSize();
1873 dim = minSize;
1874 }
1875 }
1876 if (dim != null){
1877 return new Dimension(dim);
1878 }
1879 else{
1880 return dim;
1881 }
1882 }
1883
1884 /**
1885 * Returns the maximum size of this container. If the maximum size has
1886 * not been set explicitly by {@link Component#setMaximumSize(Dimension)}
1887 * and the {@link LayoutManager} installed on this {@code Container}
1888 * is an instance of {@link LayoutManager2}, then
1889 * {@link LayoutManager2#maximumLayoutSize(Container)}
1890 * is used to calculate the maximum size.
1891 *
1892 * <p>Note: some implementations may cache the value returned from the
1893 * {@code LayoutManager2}. Implementations that cache need not invoke
1894 * {@code maximumLayoutSize} on the {@code LayoutManager2} every time
1895 * this method is invoked, rather the {@code LayoutManager2} will only
1896 * be queried after the {@code Container} becomes invalid.
1897 *
1898 * @return an instance of {@code Dimension} that represents
1899 * the maximum size of this container.
1900 * @see #getPreferredSize
1901 * @see #getMinimumSize
1902 * @see #getLayout
1903 * @see LayoutManager2#maximumLayoutSize(Container)
1904 * @see Component#getMaximumSize
1905 */
1906 public Dimension getMaximumSize() {
1907 /* Avoid grabbing the lock if a reasonable cached size value
1908 * is available.
1909 */
1910 Dimension dim = maxSize;
1911 if (dim == null || !(isMaximumSizeSet() || isValid())) {
1912 synchronized (getTreeLock()) {
1913 if (layoutMgr instanceof LayoutManager2) {
1914 LayoutManager2 lm = (LayoutManager2) layoutMgr;
1915 maxSize = lm.maximumLayoutSize(this);
1916 } else {
1917 maxSize = super.getMaximumSize();
1918 }
2152 * If l is null, no exception is thrown and no action is performed.
2153 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
2154 * >AWT Threading Issues</a> for details on AWT's threading model.
2155 *
2156 * @param l the container listener
2157 *
2158 * @see #addContainerListener
2159 * @see #getContainerListeners
2160 */
2161 public synchronized void removeContainerListener(ContainerListener l) {
2162 if (l == null) {
2163 return;
2164 }
2165 containerListener = AWTEventMulticaster.remove(containerListener, l);
2166 }
2167
2168 /**
2169 * Returns an array of all the container listeners
2170 * registered on this container.
2171 *
2172 * @return all of this container's {@code ContainerListener}s
2173 * or an empty array if no container
2174 * listeners are currently registered
2175 *
2176 * @see #addContainerListener
2177 * @see #removeContainerListener
2178 * @since 1.4
2179 */
2180 public synchronized ContainerListener[] getContainerListeners() {
2181 return getListeners(ContainerListener.class);
2182 }
2183
2184 /**
2185 * Returns an array of all the objects currently registered
2186 * as <code><em>Foo</em>Listener</code>s
2187 * upon this {@code Container}.
2188 * <code><em>Foo</em>Listener</code>s are registered using the
2189 * <code>add<em>Foo</em>Listener</code> method.
2190 *
2191 * <p>
2192 * You can specify the {@code listenerType} argument
2193 * with a class literal, such as
2194 * <code><em>Foo</em>Listener.class</code>.
2195 * For example, you can query a
2196 * {@code Container c}
2197 * for its container listeners with the following code:
2198 *
2199 * <pre>ContainerListener[] cls = (ContainerListener[])(c.getListeners(ContainerListener.class));</pre>
2200 *
2201 * If no such listeners exist, this method returns an empty array.
2202 *
2203 * @param listenerType the type of listeners requested; this parameter
2204 * should specify an interface that descends from
2205 * {@code java.util.EventListener}
2206 * @return an array of all objects registered as
2207 * <code><em>Foo</em>Listener</code>s on this container,
2208 * or an empty array if no such listeners have been added
2209 * @exception ClassCastException if {@code listenerType}
2210 * doesn't specify a class or interface that implements
2211 * {@code java.util.EventListener}
2212 * @exception NullPointerException if {@code listenerType} is {@code null}
2213 *
2214 * @see #getContainerListeners
2215 *
2216 * @since 1.3
2217 */
2218 public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
2219 EventListener l = null;
2220 if (listenerType == ContainerListener.class) {
2221 l = containerListener;
2222 } else {
2223 return super.getListeners(listenerType);
2224 }
2225 return AWTEventMulticaster.getListeners(l, listenerType);
2226 }
2227
2228 // REMIND: remove when filtering is done at lower level
2229 boolean eventEnabled(AWTEvent e) {
2230 int id = e.getID();
2231
2232 if (id == ContainerEvent.COMPONENT_ADDED ||
2233 id == ContainerEvent.COMPONENT_REMOVED) {
2234 if ((eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
2235 containerListener != null) {
2236 return true;
2237 }
2238 return false;
2239 }
2240 return super.eventEnabled(e);
2241 }
2242
2243 /**
2244 * Processes events on this container. If the event is a
2245 * {@code ContainerEvent}, it invokes the
2246 * {@code processContainerEvent} method, else it invokes
2247 * its superclass's {@code processEvent}.
2248 * <p>Note that if the event parameter is {@code null}
2249 * the behavior is unspecified and may result in an
2250 * exception.
2251 *
2252 * @param e the event
2253 */
2254 protected void processEvent(AWTEvent e) {
2255 if (e instanceof ContainerEvent) {
2256 processContainerEvent((ContainerEvent)e);
2257 return;
2258 }
2259 super.processEvent(e);
2260 }
2261
2262 /**
2263 * Processes container events occurring on this container by
2264 * dispatching them to any registered ContainerListener objects.
2265 * NOTE: This method will not be called unless container events
2266 * are enabled for this component; this happens when one of the
2267 * following occurs:
2268 * <ul>
2269 * <li>A ContainerListener object is registered via
2270 * {@code addContainerListener}
2271 * <li>Container events are enabled via {@code enableEvents}
2272 * </ul>
2273 * <p>Note that if the event parameter is {@code null}
2274 * the behavior is unspecified and may result in an
2275 * exception.
2276 *
2277 * @param e the container event
2278 * @see Component#enableEvents
2279 */
2280 protected void processContainerEvent(ContainerEvent e) {
2281 ContainerListener listener = containerListener;
2282 if (listener != null) {
2283 switch(e.getID()) {
2284 case ContainerEvent.COMPONENT_ADDED:
2285 listener.componentAdded(e);
2286 break;
2287 case ContainerEvent.COMPONENT_REMOVED:
2288 listener.componentRemoved(e);
2289 break;
2290 }
2291 }
2292 }
2293
2348 Component getMouseEventTarget(int x, int y, boolean includeSelf) {
2349 return getMouseEventTarget(x, y, includeSelf,
2350 MouseEventTargetFilter.FILTER,
2351 !SEARCH_HEAVYWEIGHTS);
2352 }
2353
2354 /**
2355 * Fetches the top-most (deepest) component to receive SunDropTargetEvents.
2356 */
2357 Component getDropTargetEventTarget(int x, int y, boolean includeSelf) {
2358 return getMouseEventTarget(x, y, includeSelf,
2359 DropTargetEventTargetFilter.FILTER,
2360 SEARCH_HEAVYWEIGHTS);
2361 }
2362
2363 /**
2364 * A private version of getMouseEventTarget which has two additional
2365 * controllable behaviors. This method searches for the top-most
2366 * descendant of this container that contains the given coordinates
2367 * and is accepted by the given filter. The search will be constrained to
2368 * lightweight descendants if the last argument is {@code false}.
2369 *
2370 * @param filter EventTargetFilter instance to determine whether the
2371 * given component is a valid target for this event.
2372 * @param searchHeavyweights if {@code false}, the method
2373 * will bypass heavyweight components during the search.
2374 */
2375 private Component getMouseEventTarget(int x, int y, boolean includeSelf,
2376 EventTargetFilter filter,
2377 boolean searchHeavyweights) {
2378 Component comp = null;
2379 if (searchHeavyweights) {
2380 comp = getMouseEventTargetImpl(x, y, includeSelf, filter,
2381 SEARCH_HEAVYWEIGHTS,
2382 searchHeavyweights);
2383 }
2384
2385 if (comp == null || comp == this) {
2386 comp = getMouseEventTargetImpl(x, y, includeSelf, filter,
2387 !SEARCH_HEAVYWEIGHTS,
2388 searchHeavyweights);
2389 }
2390
2391 return comp;
2392 }
2393
2394 /**
2395 * A private version of getMouseEventTarget which has three additional
2396 * controllable behaviors. This method searches for the top-most
2397 * descendant of this container that contains the given coordinates
2398 * and is accepted by the given filter. The search will be constrained to
2399 * descendants of only lightweight children or only heavyweight children
2400 * of this container depending on searchHeavyweightChildren. The search will
2401 * be constrained to only lightweight descendants of the searched children
2402 * of this container if searchHeavyweightDescendants is {@code false}.
2403 *
2404 * @param filter EventTargetFilter instance to determine whether the
2405 * selected component is a valid target for this event.
2406 * @param searchHeavyweightChildren if {@code true}, the method
2407 * will bypass immediate lightweight children during the search.
2408 * If {@code false}, the methods will bypass immediate
2409 * heavyweight children during the search.
2410 * @param searchHeavyweightDescendants if {@code false}, the method
2411 * will bypass heavyweight descendants which are not immediate
2412 * children during the search. If {@code true}, the method
2413 * will traverse both lightweight and heavyweight descendants during
2414 * the search.
2415 */
2416 private Component getMouseEventTargetImpl(int x, int y, boolean includeSelf,
2417 EventTargetFilter filter,
2418 boolean searchHeavyweightChildren,
2419 boolean searchHeavyweightDescendants) {
2420 synchronized (getTreeLock()) {
2421
2422 for (int i = 0; i < component.size(); i++) {
2423 Component comp = component.get(i);
2424 if (comp != null && comp.visible &&
2425 ((!searchHeavyweightChildren &&
2426 comp.peer instanceof LightweightPeer) ||
2427 (searchHeavyweightChildren &&
2428 !(comp.peer instanceof LightweightPeer))) &&
2429 comp.contains(x - comp.x, y - comp.y)) {
2430
2431 // found a component that intersects the point, see if there
2432 // is a deeper possibility.
2508 if (peer instanceof LightweightPeer) {
2509 // this container is lightweight.... continue sending it
2510 // upward.
2511 if (parent != null) {
2512 parent.proxyEnableEvents(events);
2513 }
2514 } else {
2515 // This is a native container, so it needs to host
2516 // one of it's children. If this function is called before
2517 // a peer has been created we don't yet have a dispatcher
2518 // because it has not yet been determined if this instance
2519 // is lightweight.
2520 if (dispatcher != null) {
2521 dispatcher.enableEvents(events);
2522 }
2523 }
2524 }
2525
2526 /**
2527 * @deprecated As of JDK version 1.1,
2528 * replaced by {@code dispatchEvent(AWTEvent e)}
2529 */
2530 @Deprecated
2531 public void deliverEvent(Event e) {
2532 Component comp = getComponentAt(e.x, e.y);
2533 if ((comp != null) && (comp != this)) {
2534 e.translate(-comp.x, -comp.y);
2535 comp.deliverEvent(e);
2536 } else {
2537 postEvent(e);
2538 }
2539 }
2540
2541 /**
2542 * Locates the component that contains the x,y position. The
2543 * top-most child component is returned in the case where there
2544 * is overlap in the components. This is determined by finding
2545 * the component closest to the index 0 that claims to contain
2546 * the given point via Component.contains(), except that Components
2547 * which have native peers take precedence over those which do not
2548 * (i.e., lightweight Components).
2549 *
2550 * @param x the <i>x</i> coordinate
2551 * @param y the <i>y</i> coordinate
2552 * @return null if the component does not contain the position.
2553 * If there is no child component at the requested point and the
2554 * point is within the bounds of the container the container itself
2555 * is returned; otherwise the top-most child is returned.
2556 * @see Component#contains
2557 * @since 1.1
2558 */
2559 public Component getComponentAt(int x, int y) {
2560 return locate(x, y);
2561 }
2562
2563 /**
2564 * @deprecated As of JDK version 1.1,
2565 * replaced by {@code getComponentAt(int, int)}.
2566 */
2567 @Deprecated
2568 public Component locate(int x, int y) {
2569 if (!contains(x, y)) {
2570 return null;
2571 }
2572 Component lightweight = null;
2573 synchronized (getTreeLock()) {
2574 // Optimized version of two passes:
2575 // see comment in sun.awt.SunGraphicsCallback
2576 for (final Component comp : component) {
2577 if (comp.contains(x - comp.x, y - comp.y)) {
2578 if (!comp.isLightweight()) {
2579 // return heavyweight component as soon as possible
2580 return comp;
2581 }
2582 if (lightweight == null) {
2583 // save and return later the first lightweight component
2584 lightweight = comp;
2585 }
2586 }
2587 }
2588 }
2589 return lightweight != null ? lightweight : this;
2590 }
2591
2592 /**
2593 * Gets the component that contains the specified point.
2594 * @param p the point.
2595 * @return returns the component that contains the point,
2596 * or {@code null} if the component does
2597 * not contain the point.
2598 * @see Component#contains
2599 * @since 1.1
2600 */
2601 public Component getComponentAt(Point p) {
2602 return getComponentAt(p.x, p.y);
2603 }
2604
2605 /**
2606 * Returns the position of the mouse pointer in this {@code Container}'s
2607 * coordinate space if the {@code Container} is under the mouse pointer,
2608 * otherwise returns {@code null}.
2609 * This method is similar to {@link Component#getMousePosition()} with the exception
2610 * that it can take the {@code Container}'s children into account.
2611 * If {@code allowChildren} is {@code false}, this method will return
2612 * a non-null value only if the mouse pointer is above the {@code Container}
2613 * directly, not above the part obscured by children.
2614 * If {@code allowChildren} is {@code true}, this method returns
2615 * a non-null value if the mouse pointer is above {@code Container} or any
2616 * of its descendants.
2617 *
2618 * @exception HeadlessException if GraphicsEnvironment.isHeadless() returns true
2619 * @param allowChildren true if children should be taken into account
2620 * @see Component#getMousePosition
2621 * @return mouse coordinates relative to this {@code Component}, or null
2622 * @since 1.5
2623 */
2624 public Point getMousePosition(boolean allowChildren) throws HeadlessException {
2625 if (GraphicsEnvironment.isHeadless()) {
2626 throw new HeadlessException();
2627 }
2628 PointerInfo pi = java.security.AccessController.doPrivileged(
2629 new java.security.PrivilegedAction<PointerInfo>() {
2630 public PointerInfo run() {
2631 return MouseInfo.getPointerInfo();
2632 }
2633 }
2634 );
2635 synchronized (getTreeLock()) {
2636 Component inTheSameWindow = findUnderMouseInWindow(pi);
2637 if (isSameOrAncestorOf(inTheSameWindow, allowChildren)) {
2638 return pointRelativeToComponent(pi.getLocation());
2639 }
2640 return null;
2641 }
2831 // If some of the children had focus before disposal then it still has.
2832 // Auto-transfer focus to the next (or previous) component if auto-transfer
2833 // is enabled.
2834 if (containsFocus() && KeyboardFocusManager.isAutoFocusTransferEnabledFor(this)) {
2835 if (!transferFocus(false)) {
2836 transferFocusBackward(true);
2837 }
2838 }
2839 if ( dispatcher != null ) {
2840 dispatcher.dispose();
2841 dispatcher = null;
2842 }
2843 super.removeNotify();
2844 }
2845 }
2846
2847 /**
2848 * Checks if the component is contained in the component hierarchy of
2849 * this container.
2850 * @param c the component
2851 * @return {@code true} if it is an ancestor;
2852 * {@code false} otherwise.
2853 * @since 1.1
2854 */
2855 public boolean isAncestorOf(Component c) {
2856 Container p;
2857 if (c == null || ((p = c.getParent()) == null)) {
2858 return false;
2859 }
2860 while (p != null) {
2861 if (p == this) {
2862 return true;
2863 }
2864 p = p.getParent();
2865 }
2866 return false;
2867 }
2868
2869 /*
2870 * The following code was added to support modal JInternalFrames
2871 * Unfortunately this code has to be added here so that we can get access to
2872 * some private AWT classes like SequencedEvent.
2966 // Wake up event dispatch thread on which the dialog was
2967 // initially shown
2968 SunToolkit.postEvent(modalAppContext,
2969 new PeerEvent(this,
2970 new WakingRunnable(),
2971 PeerEvent.PRIORITY_EVENT));
2972 }
2973 EventQueue.invokeLater(new WakingRunnable());
2974 getTreeLock().notifyAll();
2975 }
2976 }
2977
2978 static final class WakingRunnable implements Runnable {
2979 public void run() {
2980 }
2981 }
2982
2983 /* End of JOptionPane support code */
2984
2985 /**
2986 * Returns a string representing the state of this {@code Container}.
2987 * This method is intended to be used only for debugging purposes, and the
2988 * content and format of the returned string may vary between
2989 * implementations. The returned string may be empty but may not be
2990 * {@code null}.
2991 *
2992 * @return the parameter string of this container
2993 */
2994 protected String paramString() {
2995 String str = super.paramString();
2996 LayoutManager layoutMgr = this.layoutMgr;
2997 if (layoutMgr != null) {
2998 str += ",layout=" + layoutMgr.getClass().getName();
2999 }
3000 return str;
3001 }
3002
3003 /**
3004 * Prints a listing of this container to the specified output
3005 * stream. The listing starts at the specified indentation.
3006 * <p>
3007 * The immediate children of the container are printed with
3008 * an indentation of {@code indent+1}. The children
3009 * of those children are printed at {@code indent+2}
3010 * and so on.
3011 *
3012 * @param out a print stream
3013 * @param indent the number of spaces to indent
3014 * @throws NullPointerException if {@code out} is {@code null}
3015 * @see Component#list(java.io.PrintStream, int)
3016 * @since 1.0
3017 */
3018 public void list(PrintStream out, int indent) {
3019 super.list(out, indent);
3020 synchronized(getTreeLock()) {
3021 for (int i = 0; i < component.size(); i++) {
3022 Component comp = component.get(i);
3023 if (comp != null) {
3024 comp.list(out, indent+1);
3025 }
3026 }
3027 }
3028 }
3029
3030 /**
3031 * Prints out a list, starting at the specified indentation,
3032 * to the specified print writer.
3033 * <p>
3034 * The immediate children of the container are printed with
3035 * an indentation of {@code indent+1}. The children
3036 * of those children are printed at {@code indent+2}
3037 * and so on.
3038 *
3039 * @param out a print writer
3040 * @param indent the number of spaces to indent
3041 * @throws NullPointerException if {@code out} is {@code null}
3042 * @see Component#list(java.io.PrintWriter, int)
3043 * @since 1.1
3044 */
3045 public void list(PrintWriter out, int indent) {
3046 super.list(out, indent);
3047 synchronized(getTreeLock()) {
3048 for (int i = 0; i < component.size(); i++) {
3049 Component comp = component.get(i);
3050 if (comp != null) {
3051 comp.list(out, indent+1);
3052 }
3053 }
3054 }
3055 }
3056
3132 * operation for this Container
3133 * @since 1.4
3134 * @beaninfo
3135 * bound: true
3136 */
3137 public void setFocusTraversalKeys(int id,
3138 Set<? extends AWTKeyStroke> keystrokes)
3139 {
3140 if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {
3141 throw new IllegalArgumentException("invalid focus traversal key identifier");
3142 }
3143
3144 // Don't call super.setFocusTraversalKey. The Component parameter check
3145 // does not allow DOWN_CYCLE_TRAVERSAL_KEYS, but we do.
3146 setFocusTraversalKeys_NoIDCheck(id, keystrokes);
3147 }
3148
3149 /**
3150 * Returns the Set of focus traversal keys for a given traversal operation
3151 * for this Container. (See
3152 * {@code setFocusTraversalKeys} for a full description of each key.)
3153 * <p>
3154 * If a Set of traversal keys has not been explicitly defined for this
3155 * Container, then this Container's parent's Set is returned. If no Set
3156 * has been explicitly defined for any of this Container's ancestors, then
3157 * the current KeyboardFocusManager's default Set is returned.
3158 *
3159 * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
3160 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
3161 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
3162 * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
3163 * @return the Set of AWTKeyStrokes for the specified operation. The Set
3164 * will be unmodifiable, and may be empty. null will never be
3165 * returned.
3166 * @see #setFocusTraversalKeys
3167 * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
3168 * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
3169 * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
3170 * @see KeyboardFocusManager#DOWN_CYCLE_TRAVERSAL_KEYS
3171 * @throws IllegalArgumentException if id is not one of
3172 * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
3173 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
3174 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
3175 * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
3176 * @since 1.4
3177 */
3178 public Set<AWTKeyStroke> getFocusTraversalKeys(int id) {
3179 if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {
3180 throw new IllegalArgumentException("invalid focus traversal key identifier");
3181 }
3182
3183 // Don't call super.getFocusTraversalKey. The Component parameter check
3184 // does not allow DOWN_CYCLE_TRAVERSAL_KEY, but we do.
3185 return getFocusTraversalKeys_NoIDCheck(id);
3186 }
3187
3188 /**
3189 * Returns whether the Set of focus traversal keys for the given focus
3190 * traversal operation has been explicitly defined for this Container. If
3191 * this method returns {@code false}, this Container is inheriting the
3192 * Set from an ancestor, or from the current KeyboardFocusManager.
3193 *
3194 * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
3195 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
3196 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
3197 * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
3198 * @return {@code true} if the Set of focus traversal keys for the
3199 * given focus traversal operation has been explicitly defined for
3200 * this Component; {@code false} otherwise.
3201 * @throws IllegalArgumentException if id is not one of
3202 * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
3203 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
3204 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
3205 * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
3206 * @since 1.4
3207 */
3208 public boolean areFocusTraversalKeysSet(int id) {
3209 if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {
3210 throw new IllegalArgumentException("invalid focus traversal key identifier");
3211 }
3212
3213 return (focusTraversalKeys != null && focusTraversalKeys[id] != null);
3214 }
3215
3216 /**
3217 * Returns whether the specified Container is the focus cycle root of this
3218 * Container's focus traversal cycle. Each focus traversal cycle has only
3219 * a single focus cycle root and each Container which is not a focus cycle
3220 * root belongs to only a single focus traversal cycle. Containers which
3221 * are focus cycle roots belong to two cycles: one rooted at the Container
3222 * itself, and one rooted at the Container's nearest focus-cycle-root
3223 * ancestor. This method will return {@code true} for both such
3224 * Containers in this case.
3225 *
3226 * @param container the Container to be tested
3227 * @return {@code true} if the specified Container is a focus-cycle-
3228 * root of this Container; {@code false} otherwise
3229 * @see #isFocusCycleRoot()
3230 * @since 1.4
3231 */
3232 public boolean isFocusCycleRoot(Container container) {
3233 if (isFocusCycleRoot() && container == this) {
3234 return true;
3235 } else {
3236 return super.isFocusCycleRoot(container);
3237 }
3238 }
3239
3240 private Container findTraversalRoot() {
3241 // I potentially have two roots, myself and my root parent
3242 // If I am the current root, then use me
3243 // If none of my parents are roots, then use me
3244 // If my root parent is the current root, then use my root parent
3245 // If neither I nor my root parent is the current root, then
3246 // use my root parent (a guess)
3247
3248 Container currentFocusCycleRoot = KeyboardFocusManager.
3377 if (!isFocusTraversalPolicyProvider() && !isFocusCycleRoot()) {
3378 return null;
3379 }
3380
3381 FocusTraversalPolicy policy = this.focusTraversalPolicy;
3382 if (policy != null) {
3383 return policy;
3384 }
3385
3386 Container rootAncestor = getFocusCycleRootAncestor();
3387 if (rootAncestor != null) {
3388 return rootAncestor.getFocusTraversalPolicy();
3389 } else {
3390 return KeyboardFocusManager.getCurrentKeyboardFocusManager().
3391 getDefaultFocusTraversalPolicy();
3392 }
3393 }
3394
3395 /**
3396 * Returns whether the focus traversal policy has been explicitly set for
3397 * this Container. If this method returns {@code false}, this
3398 * Container will inherit its focus traversal policy from an ancestor.
3399 *
3400 * @return {@code true} if the focus traversal policy has been
3401 * explicitly set for this Container; {@code false} otherwise.
3402 * @since 1.4
3403 */
3404 public boolean isFocusTraversalPolicySet() {
3405 return (focusTraversalPolicy != null);
3406 }
3407
3408 /**
3409 * Sets whether this Container is the root of a focus traversal cycle. Once
3410 * focus enters a traversal cycle, typically it cannot leave it via focus
3411 * traversal unless one of the up- or down-cycle keys is pressed. Normal
3412 * traversal is limited to this Container, and all of this Container's
3413 * descendants that are not descendants of inferior focus cycle roots. Note
3414 * that a FocusTraversalPolicy may bend these restrictions, however. For
3415 * example, ContainerOrderFocusTraversalPolicy supports implicit down-cycle
3416 * traversal.
3417 * <p>
3418 * The alternative way to specify the traversal order of this Container's
3419 * children is to make this Container a
3420 * <a href="doc-files/FocusSpec.html#FocusTraversalPolicyProviders">focus traversal policy provider</a>.
3421 *
3447 * Normal traversal is limited to this Container, and all of this
3448 * Container's descendants that are not descendants of inferior focus
3449 * cycle roots. Note that a FocusTraversalPolicy may bend these
3450 * restrictions, however. For example, ContainerOrderFocusTraversalPolicy
3451 * supports implicit down-cycle traversal.
3452 *
3453 * @return whether this Container is the root of a focus traversal cycle
3454 * @see #setFocusCycleRoot
3455 * @see #setFocusTraversalPolicy
3456 * @see #getFocusTraversalPolicy
3457 * @see ContainerOrderFocusTraversalPolicy
3458 * @since 1.4
3459 */
3460 public boolean isFocusCycleRoot() {
3461 return focusCycleRoot;
3462 }
3463
3464 /**
3465 * Sets whether this container will be used to provide focus
3466 * traversal policy. Container with this property as
3467 * {@code true} will be used to acquire focus traversal policy
3468 * instead of closest focus cycle root ancestor.
3469 * @param provider indicates whether this container will be used to
3470 * provide focus traversal policy
3471 * @see #setFocusTraversalPolicy
3472 * @see #getFocusTraversalPolicy
3473 * @see #isFocusTraversalPolicyProvider
3474 * @since 1.5
3475 * @beaninfo
3476 * bound: true
3477 */
3478 public final void setFocusTraversalPolicyProvider(boolean provider) {
3479 boolean oldProvider;
3480 synchronized(this) {
3481 oldProvider = focusTraversalPolicyProvider;
3482 focusTraversalPolicyProvider = provider;
3483 }
3484 firePropertyChange("focusTraversalPolicyProvider", oldProvider, provider);
3485 }
3486
3487 /**
3488 * Returns whether this container provides focus traversal
3489 * policy. If this property is set to {@code true} then when
3490 * keyboard focus manager searches container hierarchy for focus
3491 * traversal policy and encounters this container before any other
3492 * container with this property as true or focus cycle roots then
3493 * its focus traversal policy will be used instead of focus cycle
3494 * root's policy.
3495 * @see #setFocusTraversalPolicy
3496 * @see #getFocusTraversalPolicy
3497 * @see #setFocusCycleRoot
3498 * @see #setFocusTraversalPolicyProvider
3499 * @return {@code true} if this container provides focus traversal
3500 * policy, {@code false} otherwise
3501 * @since 1.5
3502 * @beaninfo
3503 * bound: true
3504 */
3505 public final boolean isFocusTraversalPolicyProvider() {
3506 return focusTraversalPolicyProvider;
3507 }
3508
3509 /**
3510 * Transfers the focus down one focus traversal cycle. If this Container is
3511 * a focus cycle root, then the focus owner is set to this Container's
3512 * default Component to focus, and the current focus cycle root is set to
3513 * this Container. If this Container is not a focus cycle root, then no
3514 * focus traversal operation occurs.
3515 *
3516 * @see Component#requestFocus()
3517 * @see #isFocusCycleRoot
3518 * @see #setFocusCycleRoot
3519 * @since 1.4
3520 */
3532
3533 void preProcessKeyEvent(KeyEvent e) {
3534 Container parent = this.parent;
3535 if (parent != null) {
3536 parent.preProcessKeyEvent(e);
3537 }
3538 }
3539
3540 void postProcessKeyEvent(KeyEvent e) {
3541 Container parent = this.parent;
3542 if (parent != null) {
3543 parent.postProcessKeyEvent(e);
3544 }
3545 }
3546
3547 boolean postsOldMouseEvents() {
3548 return true;
3549 }
3550
3551 /**
3552 * Sets the {@code ComponentOrientation} property of this container
3553 * and all components contained within it.
3554 * <p>
3555 * This method changes layout-related information, and therefore,
3556 * invalidates the component hierarchy.
3557 *
3558 * @param o the new component orientation of this container and
3559 * the components contained within it.
3560 * @exception NullPointerException if {@code orientation} is null.
3561 * @see Component#setComponentOrientation
3562 * @see Component#getComponentOrientation
3563 * @see #invalidate
3564 * @since 1.4
3565 */
3566 public void applyComponentOrientation(ComponentOrientation o) {
3567 super.applyComponentOrientation(o);
3568 synchronized (getTreeLock()) {
3569 for (int i = 0; i < component.size(); i++) {
3570 Component comp = component.get(i);
3571 comp.applyComponentOrientation(o);
3572 }
3573 }
3574 }
3575
3576 /**
3577 * Adds a PropertyChangeListener to the listener list. The listener is
3578 * registered for all bound properties of this class, including the
3579 * following:
3580 * <ul>
3643 * @param propertyName one of the property names listed above
3644 * @param listener the PropertyChangeListener to be added
3645 *
3646 * @see #addPropertyChangeListener(java.beans.PropertyChangeListener)
3647 * @see Component#removePropertyChangeListener
3648 */
3649 public void addPropertyChangeListener(String propertyName,
3650 PropertyChangeListener listener) {
3651 super.addPropertyChangeListener(propertyName, listener);
3652 }
3653
3654 // Serialization support. A Container is responsible for restoring the
3655 // parent fields of its component children.
3656
3657 /**
3658 * Container Serial Data Version.
3659 */
3660 private int containerSerializedDataVersion = 1;
3661
3662 /**
3663 * Serializes this {@code Container} to the specified
3664 * {@code ObjectOutputStream}.
3665 * <ul>
3666 * <li>Writes default serializable fields to the stream.</li>
3667 * <li>Writes a list of serializable ContainerListener(s) as optional
3668 * data. The non-serializable ContainerListener(s) are detected and
3669 * no attempt is made to serialize them.</li>
3670 * <li>Write this Container's FocusTraversalPolicy if and only if it
3671 * is Serializable; otherwise, {@code null} is written.</li>
3672 * </ul>
3673 *
3674 * @param s the {@code ObjectOutputStream} to write
3675 * @serialData {@code null} terminated sequence of 0 or more pairs;
3676 * the pair consists of a {@code String} and {@code Object};
3677 * the {@code String} indicates the type of object and
3678 * is one of the following:
3679 * {@code containerListenerK} indicating an
3680 * {@code ContainerListener} object;
3681 * the {@code Container}'s {@code FocusTraversalPolicy},
3682 * or {@code null}
3683 *
3684 * @see AWTEventMulticaster#save(java.io.ObjectOutputStream, java.lang.String, java.util.EventListener)
3685 * @see Container#containerListenerK
3686 * @see #readObject(ObjectInputStream)
3687 */
3688 private void writeObject(ObjectOutputStream s) throws IOException {
3689 ObjectOutputStream.PutField f = s.putFields();
3690 f.put("ncomponents", component.size());
3691 f.put("component", component.toArray(EMPTY_ARRAY));
3692 f.put("layoutMgr", layoutMgr);
3693 f.put("dispatcher", dispatcher);
3694 f.put("maxSize", maxSize);
3695 f.put("focusCycleRoot", focusCycleRoot);
3696 f.put("containerSerializedDataVersion", containerSerializedDataVersion);
3697 f.put("focusTraversalPolicyProvider", focusTraversalPolicyProvider);
3698 s.writeFields();
3699
3700 AWTEventMulticaster.save(s, containerListenerK, containerListener);
3701 s.writeObject(null);
3702
3703 if (focusTraversalPolicy instanceof java.io.Serializable) {
3704 s.writeObject(focusTraversalPolicy);
3705 } else {
3706 s.writeObject(null);
3707 }
3708 }
3709
3710 /**
3711 * Deserializes this {@code Container} from the specified
3712 * {@code ObjectInputStream}.
3713 * <ul>
3714 * <li>Reads default serializable fields from the stream.</li>
3715 * <li>Reads a list of serializable ContainerListener(s) as optional
3716 * data. If the list is null, no Listeners are installed.</li>
3717 * <li>Reads this Container's FocusTraversalPolicy, which may be null,
3718 * as optional data.</li>
3719 * </ul>
3720 *
3721 * @param s the {@code ObjectInputStream} to read
3722 * @serial
3723 * @see #addContainerListener
3724 * @see #writeObject(ObjectOutputStream)
3725 */
3726 private void readObject(ObjectInputStream s)
3727 throws ClassNotFoundException, IOException
3728 {
3729 ObjectInputStream.GetField f = s.readFields();
3730 Component [] tmpComponent = (Component[])f.get("component", EMPTY_ARRAY);
3731 int ncomponents = (Integer) f.get("ncomponents", 0);
3732 component = new java.util.ArrayList<Component>(ncomponents);
3733 for (int i = 0; i < ncomponents; ++i) {
3734 component.add(tmpComponent[i]);
3735 }
3736 layoutMgr = (LayoutManager)f.get("layoutMgr", null);
3737 dispatcher = (LightweightDispatcher)f.get("dispatcher", null);
3738 // Old stream. Doesn't contain maxSize among Component's fields.
3739 if (maxSize == null) {
3740 maxSize = (Dimension)f.get("maxSize", null);
3741 }
3789 /**
3790 * Inner class of Container used to provide default support for
3791 * accessibility. This class is not meant to be used directly by
3792 * application developers, but is instead meant only to be
3793 * subclassed by container developers.
3794 * <p>
3795 * The class used to obtain the accessible role for this object,
3796 * as well as implementing many of the methods in the
3797 * AccessibleContainer interface.
3798 * @since 1.3
3799 */
3800 protected class AccessibleAWTContainer extends AccessibleAWTComponent {
3801
3802 /**
3803 * JDK1.3 serialVersionUID
3804 */
3805 private static final long serialVersionUID = 5081320404842566097L;
3806
3807 /**
3808 * Returns the number of accessible children in the object. If all
3809 * of the children of this object implement {@code Accessible},
3810 * then this method should return the number of children of this object.
3811 *
3812 * @return the number of accessible children in the object
3813 */
3814 public int getAccessibleChildrenCount() {
3815 return Container.this.getAccessibleChildrenCount();
3816 }
3817
3818 /**
3819 * Returns the nth {@code Accessible} child of the object.
3820 *
3821 * @param i zero-based index of child
3822 * @return the nth {@code Accessible} child of the object
3823 */
3824 public Accessible getAccessibleChild(int i) {
3825 return Container.this.getAccessibleChild(i);
3826 }
3827
3828 /**
3829 * Returns the {@code Accessible} child, if one exists,
3830 * contained at the local coordinate {@code Point}.
3831 *
3832 * @param p the point defining the top-left corner of the
3833 * {@code Accessible}, given in the coordinate space
3834 * of the object's parent
3835 * @return the {@code Accessible}, if it exists,
3836 * at the specified location; else {@code null}
3837 */
3838 public Accessible getAccessibleAt(Point p) {
3839 return Container.this.getAccessibleAt(p);
3840 }
3841
3842 /**
3843 * Number of PropertyChangeListener objects registered. It's used
3844 * to add/remove ContainerListener to track target Container's state.
3845 */
3846 private transient volatile int propertyListenersCount = 0;
3847
3848 /**
3849 * The handler to fire {@code PropertyChange}
3850 * when children are added or removed
3851 */
3852 protected ContainerListener accessibleContainerHandler = null;
3853
3854 /**
3855 * Fire {@code PropertyChange} listener, if one is registered,
3856 * when children are added or removed.
3857 * @since 1.3
3858 */
3859 protected class AccessibleContainerHandler
3860 implements ContainerListener {
3861 public void componentAdded(ContainerEvent e) {
3862 Component c = e.getChild();
3863 if (c != null && c instanceof Accessible) {
3864 AccessibleAWTContainer.this.firePropertyChange(
3865 AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
3866 null, ((Accessible) c).getAccessibleContext());
3867 }
3868 }
3869 public void componentRemoved(ContainerEvent e) {
3870 Component c = e.getChild();
3871 if (c != null && c instanceof Accessible) {
3872 AccessibleAWTContainer.this.firePropertyChange(
3873 AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
3874 ((Accessible) c).getAccessibleContext(), null);
3875 }
3891 super.addPropertyChangeListener(listener);
3892 }
3893
3894 /**
3895 * Remove a PropertyChangeListener from the listener list.
3896 * This removes a PropertyChangeListener that was registered
3897 * for all properties.
3898 *
3899 * @param listener the PropertyChangeListener to be removed
3900 */
3901 public void removePropertyChangeListener(PropertyChangeListener listener) {
3902 if (--propertyListenersCount == 0) {
3903 Container.this.removeContainerListener(accessibleContainerHandler);
3904 }
3905 super.removePropertyChangeListener(listener);
3906 }
3907
3908 } // inner class AccessibleAWTContainer
3909
3910 /**
3911 * Returns the {@code Accessible} child contained at the local
3912 * coordinate {@code Point}, if one exists. Otherwise
3913 * returns {@code null}.
3914 *
3915 * @param p the point defining the top-left corner of the
3916 * {@code Accessible}, given in the coordinate space
3917 * of the object's parent
3918 * @return the {@code Accessible} at the specified location,
3919 * if it exists; otherwise {@code null}
3920 */
3921 Accessible getAccessibleAt(Point p) {
3922 synchronized (getTreeLock()) {
3923 if (this instanceof Accessible) {
3924 Accessible a = (Accessible)this;
3925 AccessibleContext ac = a.getAccessibleContext();
3926 if (ac != null) {
3927 AccessibleComponent acmp;
3928 Point location;
3929 int nchildren = ac.getAccessibleChildrenCount();
3930 for (int i=0; i < nchildren; i++) {
3931 a = ac.getAccessibleChild(i);
3932 if ((a != null)) {
3933 ac = a.getAccessibleContext();
3934 if (ac != null) {
3935 acmp = ac.getAccessibleComponent();
3936 if ((acmp != null) && (acmp.isShowing())) {
3937 location = acmp.getLocation();
3938 Point np = new Point(p.x-location.x,
3939 p.y-location.y);
3955 for (int i=0; i < ncomponents; i++) {
3956 Component comp = this.getComponent(i);
3957 if ((comp != null) && comp.isShowing()) {
3958 Point location = comp.getLocation();
3959 if (comp.contains(p.x-location.x,p.y-location.y)) {
3960 ret = comp;
3961 }
3962 }
3963 }
3964 }
3965 if (ret instanceof Accessible) {
3966 return (Accessible) ret;
3967 }
3968 }
3969 return null;
3970 }
3971 }
3972
3973 /**
3974 * Returns the number of accessible children in the object. If all
3975 * of the children of this object implement {@code Accessible},
3976 * then this method should return the number of children of this object.
3977 *
3978 * @return the number of accessible children in the object
3979 */
3980 int getAccessibleChildrenCount() {
3981 synchronized (getTreeLock()) {
3982 int count = 0;
3983 Component[] children = this.getComponents();
3984 for (int i = 0; i < children.length; i++) {
3985 if (children[i] instanceof Accessible) {
3986 count++;
3987 }
3988 }
3989 return count;
3990 }
3991 }
3992
3993 /**
3994 * Returns the nth {@code Accessible} child of the object.
3995 *
3996 * @param i zero-based index of child
3997 * @return the nth {@code Accessible} child of the object
3998 */
3999 Accessible getAccessibleChild(int i) {
4000 synchronized (getTreeLock()) {
4001 Component[] children = this.getComponents();
4002 int count = 0;
4003 for (int j = 0; j < children.length; j++) {
4004 if (children[j] instanceof Accessible) {
4005 if (count == i) {
4006 return (Accessible) children[j];
4007 } else {
4008 count++;
4009 }
4010 }
4011 }
4012 return null;
4013 }
4014 }
4015
4016 // ************************** MIXING CODE *******************************
4017
|