0001: /*
0002: * @(#)Container.java 1.14 06/10/10
0003: *
0004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
0005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
0006: *
0007: * This program is free software; you can redistribute it and/or
0008: * modify it under the terms of the GNU General Public License version
0009: * 2 only, as published by the Free Software Foundation.
0010: *
0011: * This program is distributed in the hope that it will be useful, but
0012: * WITHOUT ANY WARRANTY; without even the implied warranty of
0013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0014: * General Public License version 2 for more details (a copy is
0015: * included at /legal/license.txt).
0016: *
0017: * You should have received a copy of the GNU General Public License
0018: * version 2 along with this work; if not, write to the Free Software
0019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0020: * 02110-1301 USA
0021: *
0022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
0023: * Clara, CA 95054 or visit www.sun.com if you need additional
0024: * information or have any questions.
0025: *
0026: */
0027: package java.awt;
0028:
0029: import java.io.PrintStream;
0030: import java.io.PrintWriter;
0031: import java.awt.event.*;
0032: import java.io.ObjectOutputStream;
0033: import java.io.ObjectInputStream;
0034: import java.io.IOException;
0035:
0036: /**
0037: * A generic Abstract Window Toolkit(AWT) container object is a component
0038: * that can contain other AWT components.
0039: * <p>
0040: * Components added to a container are tracked in a list. The order
0041: * of the list will define the components' front-to-back stacking order
0042: * within the container. If no index is specified when adding a
0043: * component to a container, it will be added to the end of the list
0044: * (and hence to the bottom of the stacking order).
0045: * @version 1.9, 08/19/02
0046: * @author Nicholas Allen
0047: * @see java.awt.Container#add(java.awt.Component, int)
0048: * @see java.awt.Container#getComponent(int)
0049: * @see java.awt.LayoutManager
0050: * @since JDK1.0
0051: */
0052: public class Container extends Component {
0053: /**
0054: * The number of components in this container.
0055: */
0056: int ncomponents;
0057: /**
0058: * The components in this container.
0059: */
0060: Component component[] = new Component[4];
0061: /**
0062: * Layout manager for this container.
0063: */
0064: LayoutManager layoutMgr;
0065: /**
0066: * Event router for lightweight components. If this container
0067: * is native, this dispatcher takes care of forwarding and
0068: * retargeting the events to lightweight components contained
0069: * (if any).
0070: */
0071: //private LightweightDispatcher dispatcher;
0072: /** Internal, cached size information */
0073: private Dimension maxSize;
0074: transient ContainerListener containerListener;
0075: /*
0076: * JDK 1.1 serialVersionUID
0077: */
0078: private static final long serialVersionUID = 4613797578919906343L;
0079:
0080: /**
0081: * Constructs a new Container. Containers can be extended directly,
0082: * but are lightweight in this case and must be contained by a parent
0083: * somewhere higher up in the component tree that is native.
0084: * (such as Frame for example).
0085: */
0086: public Container() {
0087: }
0088:
0089: /**
0090: * Gets the number of components in this panel.
0091: * @return the number of components in this panel.
0092: * @see java.awt.Container#getComponent
0093: * @since JDK1.1
0094: */
0095: public int getComponentCount() {
0096: return countComponents();
0097: }
0098:
0099: /**
0100: * @deprecated As of JDK version 1.1,
0101: * replaced by getComponentCount().
0102: */
0103: public int countComponents() {
0104: return ncomponents;
0105: }
0106:
0107: /**
0108: * Gets the nth component in this container.
0109: * @param n the index of the component to get.
0110: * @return the n<sup>th</sup> component in this container.
0111: * @exception ArrayIndexOutOfBoundsException
0112: * if the n<sup>th</sup> value does not exist.
0113: * @since JDK1.0
0114: */
0115: public Component getComponent(int n) {
0116: synchronized (getTreeLock()) {
0117: if ((n < 0) || (n >= ncomponents)) {
0118: throw new ArrayIndexOutOfBoundsException(
0119: "No such child: " + n);
0120: }
0121: return component[n];
0122: }
0123: }
0124:
0125: /**
0126: * Gets all the components in this container.
0127: * @return an array of all the components in this container.
0128: * @since JDK1.0
0129: */
0130: public Component[] getComponents() {
0131: synchronized (getTreeLock()) {
0132: Component list[] = new Component[ncomponents];
0133: System.arraycopy(component, 0, list, 0, ncomponents);
0134: return list;
0135: }
0136: }
0137:
0138: /**
0139: * Determines the insets of this container, which indicate the size
0140: * of the container's border.
0141: * <p>
0142: * A <code>Frame</code> object, for example, has a top inset that
0143: * corresponds to the height of the frame's title bar.
0144: * @return the insets of this container.
0145: * @see java.awt.Insets
0146: * @see java.awt.LayoutManager
0147: * @since JDK1.1
0148: */
0149: public Insets getInsets() {
0150: return insets();
0151: }
0152:
0153: /**
0154: * @deprecated As of JDK version 1.1,
0155: * replaced by <code>getInsets()</code>.
0156: */
0157: public Insets insets() {
0158: return new Insets(0, 0, 0, 0);
0159: }
0160:
0161: /**
0162: * Adds the specified component to the end of this container.
0163: * @param comp the component to be added.
0164: * @return the component argument.
0165: * @since JDK1.0
0166: */
0167: public Component add(Component comp) {
0168: addImpl(comp, null, -1);
0169: return comp;
0170: }
0171:
0172: /**
0173: * Adds the specified component to this container.
0174: * It is strongly advised to use the 1.1 method, add(Component, Object),
0175: * in place of this method.
0176: */
0177: public Component add(String name, Component comp) {
0178: addImpl(comp, name, -1);
0179: return comp;
0180: }
0181:
0182: /**
0183: * Adds the specified component to this container at the given
0184: * position.
0185: * @param comp the component to be added.
0186: * @param index the position at which to insert the component,
0187: * or <code>-1</code> to insert the component at the end.
0188: * @return the component <code>comp</code>
0189: * @see #remove
0190: * @since JDK1.0
0191: */
0192: public Component add(Component comp, int index) {
0193: addImpl(comp, null, index);
0194: return comp;
0195: }
0196:
0197: /**
0198: * Adds the specified component to the end of this container.
0199: * Also notifies the layout manager to add the component to
0200: * this container's layout using the specified constraints object.
0201: * @param comp the component to be added
0202: * @param constraints an object expressing
0203: * layout contraints for this component
0204: * @see java.awt.LayoutManager
0205: * @since JDK1.1
0206: */
0207: public void add(Component comp, Object constraints) {
0208: addImpl(comp, constraints, -1);
0209: }
0210:
0211: /**
0212: * Adds the specified component to this container with the specified
0213: * constraints at the specified index. Also notifies the layout
0214: * manager to add the component to the this container's layout using
0215: * the specified constraints object.
0216: * @param comp the component to be added
0217: * @param constraints an object expressing layout contraints for this
0218: * @param index the position in the container's list at which to insert
0219: * the component. -1 means insert at the end.
0220: * component
0221: * @see #remove
0222: * @see LayoutManager
0223: */
0224: public void add(Component comp, Object constraints, int index) {
0225: addImpl(comp, constraints, index);
0226: }
0227:
0228: /**
0229: * Adds the specified component to this container at the specified
0230: * index. This method also notifies the layout manager to add
0231: * the component to this container's layout using the specified
0232: * constraints object.
0233: * <p>
0234: * This is the method to override if a program needs to track
0235: * every add request to a container. An overriding method should
0236: * usually include a call to the superclass's version of the method:
0237: * <p>
0238: * <blockquote>
0239: * <code>super.addImpl(comp, constraints, index)</code>
0240: * </blockquote>
0241: * <p>
0242: * @param comp the component to be added.
0243: * @param constraints an object expressing layout contraints
0244: * for this component.
0245: * @param index the position in the container's list at which to
0246: * insert the component, where <code>-1</code>
0247: * means insert at the end.
0248: * @see java.awt.Container#add(java.awt.Component)
0249: * @see java.awt.Container#add(java.awt.Component, int)
0250: * @see java.awt.Container#add(java.awt.Component, java.lang.Object)
0251: * @see java.awt.LayoutManager
0252: * @since JDK1.1
0253: */
0254: protected void addImpl(Component comp, Object constraints, int index) {
0255: synchronized (getTreeLock()) {
0256: /* Check for correct arguments: index in bounds,
0257: * comp cannot be one of this container's parents,
0258: * and comp cannot be a window.
0259: */
0260: if (index > ncomponents || (index < 0 && index != -1)) {
0261: throw new IllegalArgumentException(
0262: "illegal component position");
0263: }
0264: if (comp instanceof Container) {
0265: for (Container cn = this ; cn != null; cn = cn.parent) {
0266: if (cn == comp) {
0267: throw new IllegalArgumentException(
0268: "adding container's parent to itself");
0269: }
0270: }
0271: }
0272: if (comp instanceof Window) {
0273: throw new IllegalArgumentException(
0274: "adding a window to a container");
0275: }
0276: /* Reparent the component and tidy up the tree's state. */
0277: if (comp.parent != null) {
0278: comp.parent.remove(comp);
0279: }
0280: /* Add component to list; allocate new array if necessary. */
0281: if (ncomponents == component.length) {
0282: Component newcomponents[] = new Component[ncomponents * 2];
0283: System.arraycopy(component, 0, newcomponents, 0,
0284: ncomponents);
0285: component = newcomponents;
0286: }
0287: if (index == ncomponents || index == -1) {
0288: component[ncomponents++] = comp;
0289: } else {
0290: System.arraycopy(component, index, component,
0291: index + 1, ncomponents - index);
0292: component[index] = comp;
0293: ncomponents++;
0294: }
0295: comp.parent = this ;
0296: if (valid) {
0297: invalidate();
0298: }
0299: // If the xwindow is created for this container then create X window
0300: // for added component.
0301:
0302: if (xwindow != null) {
0303: if (index == -1)
0304: index = ncomponents - 1;
0305: // Java stacks components from front to back but X stacks windows
0306: // the other way round. If we added the component to the start then
0307: // we can just create the X window for the component as it will be
0308: // on top. Otherwise, we need to recreate the X windows in reverse
0309: // order to ensure they match the stacking order of the components.
0310:
0311: if (index == 0)
0312: comp.addNotify();
0313: else {
0314: for (int i = 0; i < index; i++)
0315: component[i].removeNotify();
0316: for (int i = index; i >= 0; i--) {
0317: Component c = component[i];
0318: if (c.isLightweightWhenDisplayable())
0319: component[i].addNotify();
0320: }
0321: // Heavyweight components must exist on top of lightweight ones.
0322:
0323: for (int i = index; i >= 0; i--) {
0324: Component c = component[i];
0325: if (!c.isLightweightWhenDisplayable())
0326: component[i].addNotify();
0327: }
0328: }
0329: }
0330: /* Notify the layout manager of the added component. */
0331: if (layoutMgr != null) {
0332: if (layoutMgr instanceof LayoutManager2) {
0333: ((LayoutManager2) layoutMgr).addLayoutComponent(
0334: comp, constraints);
0335: } else if (constraints instanceof String) {
0336: layoutMgr.addLayoutComponent((String) constraints,
0337: comp);
0338: }
0339: }
0340: if (containerListener != null
0341: || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0) {
0342: ContainerEvent e = new ContainerEvent(this ,
0343: ContainerEvent.COMPONENT_ADDED, comp);
0344: processEvent(e);
0345: }
0346: }
0347: }
0348:
0349: /**
0350: * Removes the component, specified by <code>index</code>,
0351: * from this container.
0352: * @param index the index of the component to be removed.
0353: * @see #add
0354: * @since JDK1.1
0355: */
0356: public void remove(int index) {
0357: synchronized (getTreeLock()) {
0358: /* 4629242 - Check if Container contains any components or if
0359: * index references a null array element.
0360: */
0361: if (ncomponents == 0 || component[index] == null) {
0362: throw new ArrayIndexOutOfBoundsException(
0363: "Invalid index : " + index + ".");
0364: }
0365: Component comp = component[index];
0366: if (xwindow != null) {
0367: comp.removeNotify();
0368: }
0369: if (layoutMgr != null) {
0370: layoutMgr.removeLayoutComponent(comp);
0371: }
0372: comp.parent = null;
0373: System.arraycopy(component, index + 1, component, index,
0374: ncomponents - index - 1);
0375: component[--ncomponents] = null;
0376: if (valid) {
0377: invalidate();
0378: }
0379: if (containerListener != null
0380: || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0) {
0381: ContainerEvent e = new ContainerEvent(this ,
0382: ContainerEvent.COMPONENT_REMOVED, comp);
0383: processEvent(e);
0384: }
0385: return;
0386: }
0387: }
0388:
0389: /**
0390: * Removes the specified component from this container.
0391: * @param comp the component to be removed
0392: * @see #add
0393: * @since JDK1.0
0394: */
0395: public void remove(Component comp) {
0396: synchronized (getTreeLock()) {
0397: if (comp.parent == this ) {
0398: /* Search backwards, expect that more recent additions
0399: * are more likely to be removed.
0400: */
0401: Component component[] = this .component;
0402: for (int i = ncomponents; --i >= 0;) {
0403: if (component[i] == comp) {
0404: remove(i);
0405: }
0406: }
0407: }
0408: }
0409: }
0410:
0411: /**
0412: * Removes all the components from this container.
0413: * @see #add
0414: * @see #remove
0415: * @since JDK1.0
0416: */
0417: public void removeAll() {
0418: synchronized (getTreeLock()) {
0419: while (ncomponents > 0) {
0420: Component comp = component[--ncomponents];
0421: component[ncomponents] = null;
0422: if (xwindow != null) {
0423: comp.removeNotify();
0424: }
0425: if (layoutMgr != null) {
0426: layoutMgr.removeLayoutComponent(comp);
0427: }
0428: comp.parent = null;
0429: if (containerListener != null
0430: || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0) {
0431: ContainerEvent e = new ContainerEvent(this ,
0432: ContainerEvent.COMPONENT_REMOVED, comp);
0433: processEvent(e);
0434: }
0435: }
0436: if (valid) {
0437: invalidate();
0438: }
0439: }
0440: }
0441:
0442: /**
0443: * Gets the layout manager for this container.
0444: * @see #doLayout
0445: * @see #setLayout
0446: * @since JDK1.0
0447: */
0448: public LayoutManager getLayout() {
0449: return layoutMgr;
0450: }
0451:
0452: /**
0453: * Sets the layout manager for this container.
0454: * @param mgr the specified layout manager
0455: * @see #doLayout
0456: * @see #getLayout
0457: * @since JDK1.0
0458: */
0459: public void setLayout(LayoutManager mgr) {
0460: layoutMgr = mgr;
0461: if (valid) {
0462: invalidate();
0463: }
0464: }
0465:
0466: /**
0467: * Causes this container to lay out its components. Most programs
0468: * should not call this method directly, but should invoke
0469: * the <code>validate</code> method instead.
0470: * @see java.awt.LayoutManager#layoutContainer
0471: * @see #setLayout
0472: * @see #validate
0473: * @since JDK1.1
0474: */
0475: public void doLayout() {
0476: layout();
0477: }
0478:
0479: /**
0480: * @deprecated As of JDK version 1.1,
0481: * replaced by <code>doLayout()</code>.
0482: */
0483: public void layout() {
0484: LayoutManager layoutMgr = this .layoutMgr;
0485: if (layoutMgr != null) {
0486: layoutMgr.layoutContainer(this );
0487: }
0488: }
0489:
0490: /**
0491: * Invalidates the container. The container and all parents
0492: * above it are marked as needing to be laid out. This method can
0493: * be called often, so it needs to execute quickly.
0494: * @see #validate
0495: * @see #layout
0496: * @see LayoutManager
0497: */
0498: public void invalidate() {
0499: if (layoutMgr instanceof LayoutManager2) {
0500: LayoutManager2 lm = (LayoutManager2) layoutMgr;
0501: lm.invalidateLayout(this );
0502: }
0503: super .invalidate();
0504: }
0505:
0506: /**
0507: * Validates this container and all of its subcomponents.
0508: * <p>
0509: * AWT uses <code>validate</code> to cause a container to lay out
0510: * its subcomponents again after the components it contains
0511: * have been added to or modified.
0512: * @see #validate
0513: * @see Component#invalidate
0514: * @since JDK1.0
0515: */
0516: public void validate() {
0517: /* Avoid grabbing lock unless really necessary. */
0518: if (!valid) {
0519: synchronized (getTreeLock()) {
0520: if (!valid && xwindow != null) {
0521: Cursor oldCursor = getCursor();
0522: validateTree();
0523: valid = true;
0524: }
0525: }
0526: }
0527: }
0528:
0529: /**
0530: * Recursively descends the container tree and recomputes the
0531: * layout for any subtrees marked as needing it (those marked as
0532: * invalid). Synchronization should be provided by the method
0533: * that calls this one: <code>validate</code>.
0534: */
0535: protected void validateTree() {
0536: if (!valid) {
0537: doLayout();
0538: Component component[] = this .component;
0539: for (int i = 0; i < ncomponents; ++i) {
0540: Component comp = component[i];
0541: if ((comp instanceof Container)
0542: && !(comp instanceof Window) && !comp.valid) {
0543: ((Container) comp).validateTree();
0544: } else {
0545: comp.validate();
0546: }
0547: }
0548: }
0549: valid = true;
0550: }
0551:
0552: /**
0553: * Returns the preferred size of this container.
0554: * @return an instance of <code>Dimension</code> that represents
0555: * the preferred size of this container.
0556: * @see java.awt.Container#getMinimumSize
0557: * @see java.awt.Container#getLayout
0558: * @see java.awt.LayoutManager#preferredLayoutSize(java.awt.Container)
0559: * @see java.awt.Component#getPreferredSize
0560: * @since JDK1.0
0561: */
0562: public Dimension getPreferredSize() {
0563: return preferredSize();
0564: }
0565:
0566: /**
0567: * @deprecated As of JDK version 1.1,
0568: * replaced by <code>getPreferredSize()</code>.
0569: */
0570: public Dimension preferredSize() {
0571: /* Avoid grabbing the lock if a reasonable cached size value
0572: * is available.
0573: */
0574: Dimension dim = prefSize;
0575: if (dim != null && isValid()) {
0576: return dim;
0577: }
0578: synchronized (getTreeLock()) {
0579: prefSize = (layoutMgr != null) ? layoutMgr
0580: .preferredLayoutSize(this ) : super .preferredSize();
0581: return prefSize;
0582: }
0583: }
0584:
0585: /**
0586: * Returns the minimum size of this container.
0587: * @return an instance of <code>Dimension</code> that represents
0588: * the minimum size of this container.
0589: * @see java.awt.Container#getPreferredSize
0590: * @see java.awt.Container#getLayout
0591: * @see java.awt.LayoutManager#minimumLayoutSize(java.awt.Container)
0592: * @see java.awt.Component#getMinimumSize
0593: * @since JDK1.1
0594: */
0595: public Dimension getMinimumSize() {
0596: return minimumSize();
0597: }
0598:
0599: /**
0600: * @deprecated As of JDK version 1.1,
0601: * replaced by <code>getMinimumSize()</code>.
0602: */
0603: public Dimension minimumSize() {
0604: /* Avoid grabbing the lock if a reasonable cached size value
0605: * is available.
0606: */
0607: Dimension dim = minSize;
0608: if (dim != null && isValid()) {
0609: return dim;
0610: }
0611: synchronized (getTreeLock()) {
0612: minSize = (layoutMgr != null) ? layoutMgr
0613: .minimumLayoutSize(this ) : super .minimumSize();
0614: return minSize;
0615: }
0616: }
0617:
0618: /**
0619: * Returns the maximum size of this container.
0620: * @see #getPreferredSize
0621: */
0622: public Dimension getMaximumSize() {
0623: /* Avoid grabbing the lock if a reasonable cached size value
0624: * is available.
0625: */
0626: Dimension dim = maxSize;
0627: if (dim != null && isValid()) {
0628: return dim;
0629: }
0630: if (layoutMgr instanceof LayoutManager2) {
0631: synchronized (getTreeLock()) {
0632: LayoutManager2 lm = (LayoutManager2) layoutMgr;
0633: maxSize = lm.maximumLayoutSize(this );
0634: }
0635: } else {
0636: maxSize = super .getMaximumSize();
0637: }
0638: return maxSize;
0639: }
0640:
0641: /**
0642: * Returns the alignment along the x axis. This specifies how
0643: * the component would like to be aligned relative to other
0644: * components. The value should be a number between 0 and 1
0645: * where 0 represents alignment along the origin, 1 is aligned
0646: * the furthest away from the origin, 0.5 is centered, etc.
0647: */
0648: public float getAlignmentX() {
0649: float xAlign;
0650: if (layoutMgr instanceof LayoutManager2) {
0651: synchronized (getTreeLock()) {
0652: LayoutManager2 lm = (LayoutManager2) layoutMgr;
0653: xAlign = lm.getLayoutAlignmentX(this );
0654: }
0655: } else {
0656: xAlign = super .getAlignmentX();
0657: }
0658: return xAlign;
0659: }
0660:
0661: /**
0662: * Returns the alignment along the y axis. This specifies how
0663: * the component would like to be aligned relative to other
0664: * components. The value should be a number between 0 and 1
0665: * where 0 represents alignment along the origin, 1 is aligned
0666: * the furthest away from the origin, 0.5 is centered, etc.
0667: */
0668: public float getAlignmentY() {
0669: float yAlign;
0670: if (layoutMgr instanceof LayoutManager2) {
0671: synchronized (getTreeLock()) {
0672: LayoutManager2 lm = (LayoutManager2) layoutMgr;
0673: yAlign = lm.getLayoutAlignmentY(this );
0674: }
0675: } else {
0676: yAlign = super .getAlignmentY();
0677: }
0678: return yAlign;
0679: }
0680:
0681: /**
0682: * Paints the container. This forwards the paint to any lightweight components
0683: * that are children of this container. If this method is reimplemented,
0684: * super.paint(g) should be called so that lightweight components are properly
0685: * rendered. If a child component is entirely clipped by the current clipping
0686: * setting in g, paint() will not be forwarded to that child.
0687: *
0688: * @param g the specified Graphics window
0689: * @see java.awt.Component#update(java.awt.Graphics)
0690: */
0691: public void paint(Graphics g) {
0692: if (isShowing()) {
0693: int ncomponents = this .ncomponents;
0694: Component component[] = this .component;
0695: Rectangle clip = g.getClipRect();
0696: for (int i = ncomponents - 1; i >= 0; i--) {
0697: Component comp = component[i];
0698: if (comp != null && comp.visible
0699: && comp.isLightweight()) {
0700: Rectangle cr = comp.getBounds();
0701: if ((clip == null) || cr.intersects(clip)) {
0702: Graphics cg = g.create(cr.x, cr.y, cr.width,
0703: cr.height);
0704: cg.setFont(comp.getFont());
0705: try {
0706: comp.paint(cg);
0707: } finally {
0708: cg.dispose();
0709: }
0710: }
0711: }
0712: }
0713: }
0714: }
0715:
0716: /**
0717: * Updates the container. This forwards the update to any lightweight components
0718: * that are children of this container. If this method is reimplemented,
0719: * super.update(g) should be called so that lightweight components are properly
0720: * rendered. If a child component is entirely clipped by the current clipping
0721: * setting in g, update() will not be forwarded to that child.
0722: *
0723: * @param g the specified Graphics window
0724: * @see java.awt.Component#update(java.awt.Graphics)
0725: */
0726: public void update(Graphics g) {
0727: if (isShowing()) {
0728: super .update(g);
0729: }
0730: }
0731:
0732: /**
0733: * Prints the container. This forwards the print to any lightweight components
0734: * that are children of this container. If this method is reimplemented,
0735: * super.print(g) should be called so that lightweight components are properly
0736: * rendered. If a child component is entirely clipped by the current clipping
0737: * setting in g, print() will not be forwarded to that child.
0738: *
0739: * @param g the specified Graphics window
0740: * @see java.awt.Component#update(java.awt.Graphics)
0741: */
0742: public void print(Graphics g) {
0743: super .print(g); // By default, Component.print() calls paint()
0744: int ncomponents = this .ncomponents;
0745: Component component[] = this .component;
0746: Rectangle clip = g.getClipRect();
0747: for (int i = ncomponents - 1; i >= 0; i--) {
0748: Component comp = component[i];
0749: if (comp != null) {
0750: Rectangle cr = comp.getBounds();
0751: if ((clip == null) || cr.intersects(clip)) {
0752: Graphics cg = g.create(cr.x, cr.y, cr.width,
0753: cr.height);
0754: cg.setFont(comp.getFont());
0755: try {
0756: comp.print(cg);
0757: } finally {
0758: cg.dispose();
0759: }
0760: }
0761: }
0762: }
0763: }
0764:
0765: /**
0766: * Paints each of the components in this container.
0767: * @param g the graphics context.
0768: * @see java.awt.Component#paint
0769: * @see java.awt.Component#paintAll
0770: * @since JDK1.0
0771: */
0772: public void paintComponents(Graphics g) {
0773: int ncomponents = this .ncomponents;
0774: Component component[] = this .component;
0775: for (int i = ncomponents - 1; i >= 0; i--) {
0776: Component comp = component[i];
0777: if (comp != null) {
0778: Graphics cg = comp.getGraphics();
0779: Rectangle parentRect = g.getClipRect();
0780: // Calculate the clipping region of the child's graphics
0781: // context, by taking the intersection of the parent's
0782: // clipRect (if any) and the child's bounds, and then
0783: // translating it's coordinates to be relative to the child.
0784: if (parentRect != null) {
0785: Rectangle childRect = comp.getBounds();
0786: if (childRect.intersects(parentRect) == false) {
0787: // Child component is completely clipped out: ignore.
0788: continue;
0789: }
0790: Rectangle childClipRect = childRect
0791: .intersection(parentRect);
0792: childClipRect.translate(-childRect.x, -childRect.y);
0793: cg.clipRect(childClipRect.x, childClipRect.y,
0794: childClipRect.width, childClipRect.height);
0795: }
0796: try {
0797: comp.paintAll(cg);
0798: } finally {
0799: cg.dispose();
0800: }
0801: }
0802: }
0803: }
0804:
0805: /**
0806: * Prints each of the components in this container.
0807: * @param g the graphics context.
0808: * @see java.awt.Component#print
0809: * @see java.awt.Component#printAll
0810: * @since JDK1.0
0811: */
0812: public void printComponents(Graphics g) {
0813: int ncomponents = this .ncomponents;
0814: Component component[] = this .component;
0815: for (int i = ncomponents - 1; i >= 0; i--) {
0816: Component comp = component[i];
0817: if (comp != null) {
0818: Graphics cg = g.create(comp.x, comp.y, comp.width,
0819: comp.height);
0820: cg.setFont(comp.getFont());
0821: try {
0822: comp.printAll(cg);
0823: } finally {
0824: cg.dispose();
0825: }
0826: }
0827: }
0828: }
0829:
0830: /**
0831: * Simulates the peer callbacks into java.awt for printing of
0832: * lightweight Containers.
0833: * @param g the graphics context to use for printing.
0834: * @see Component#printAll
0835: * @see #printComponents
0836: */
0837: void lightweightPrint(Graphics g) {
0838: super .lightweightPrint(g);
0839: printComponents(g);
0840: }
0841:
0842: /**
0843: * Adds the specified container listener to receive container events
0844: * from this container.
0845: * @param l the container listener
0846: */
0847: public synchronized void addContainerListener(ContainerListener l) {
0848: containerListener = AWTEventMulticaster.add(containerListener,
0849: l);
0850: checkEnableNewEventsOnly(l);
0851: }
0852:
0853: /**
0854: * Removes the specified container listener so it no longer receives
0855: * container events from this container.
0856: * @param l the container listener
0857: */
0858: public synchronized void removeContainerListener(ContainerListener l) {
0859: containerListener = AWTEventMulticaster.remove(
0860: containerListener, l);
0861: }
0862:
0863: // NOTE: remove when filtering is done at lower level
0864: boolean eventEnabled(AWTEvent e) {
0865: int id = e.getID();
0866: if (id == ContainerEvent.COMPONENT_ADDED
0867: || id == ContainerEvent.COMPONENT_REMOVED) {
0868: if ((eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0
0869: || containerListener != null) {
0870: return true;
0871: }
0872: return false;
0873: }
0874: return super .eventEnabled(e);
0875: }
0876:
0877: /**
0878: * Processes events on this container. If the event is a ContainerEvent,
0879: * it invokes the processContainerEvent method, else it invokes its
0880: * superclass's processEvent.
0881: * @param e the event
0882: */
0883: protected void processEvent(AWTEvent e) {
0884: if (e instanceof ContainerEvent) {
0885: processContainerEvent((ContainerEvent) e);
0886: return;
0887: }
0888: super .processEvent(e);
0889: }
0890:
0891: /**
0892: * Processes container events occurring on this container by
0893: * dispatching them to any registered ContainerListener objects.
0894: * NOTE: This method will not be called unless container events
0895: * are enabled for this component; this happens when one of the
0896: * following occurs:
0897: * a) A ContainerListener object is registered via addContainerListener()
0898: * b) Container events are enabled via enableEvents()
0899: * @see Component#enableEvents
0900: * @param e the container event
0901: */
0902: protected void processContainerEvent(ContainerEvent e) {
0903: if (containerListener != null) {
0904: switch (e.getID()) {
0905: case ContainerEvent.COMPONENT_ADDED:
0906: containerListener.componentAdded(e);
0907: break;
0908:
0909: case ContainerEvent.COMPONENT_REMOVED:
0910: containerListener.componentRemoved(e);
0911: break;
0912: }
0913: }
0914: }
0915:
0916: Window getWindow() {
0917: Container w = this ;
0918: while (!(w instanceof Window)) {
0919: w = w.getParent();
0920: }
0921: return (Window) w;
0922: }
0923:
0924: /**
0925: * @deprecated As of JDK version 1.1,
0926: * replaced by <code>dispatchEvent(AWTEvent e)</code>
0927: */
0928: public void deliverEvent(Event e) {
0929: Component comp = getComponentAt(e.x, e.y);
0930: if ((comp != null) && (comp != this )) {
0931: e.translate(-comp.x, -comp.y);
0932: comp.deliverEvent(e);
0933: } else {
0934: postEvent(e);
0935: }
0936: }
0937:
0938: /**
0939: * Locates the component that contains the x,y position. The
0940: * top-most child component is returned in the case where there
0941: * is overlap in the components. This is determined by finding
0942: * the component closest to the index 0 that claims to contain
0943: * the given point via Component.contains().
0944: * @param x the <i>x</i> coordinate
0945: * @param y the <i>y</i> coordinate
0946: * @return null if the component does not contain the position.
0947: * If there is no child component at the requested point and the
0948: * point is within the bounds of the container the container itself
0949: * is returned; otherwise the top-most child is returned.
0950: * @see Component#contains
0951: * @since JDK1.1
0952: */
0953: public Component getComponentAt(int x, int y) {
0954: return locate(x, y);
0955: }
0956:
0957: /**
0958: * @deprecated As of JDK version 1.1,
0959: * replaced by <code>getComponentAt(int, int)</code>.
0960: */
0961: public Component locate(int x, int y) {
0962: if (!contains(x, y)) {
0963: return null;
0964: }
0965: int ncomponents = this .ncomponents;
0966: Component component[] = this .component;
0967: for (int i = 0; i < ncomponents; i++) {
0968: Component comp = component[i];
0969: if (comp != null) {
0970: if (comp.contains(x - comp.x, y - comp.y)) {
0971: return comp;
0972: }
0973: }
0974: }
0975: return this ;
0976: }
0977:
0978: /**
0979: * Gets the component that contains the specified point.
0980: * @param p the point.
0981: * @return returns the component that contains the point,
0982: * or <code>null</code> if the component does
0983: * not contain the point.
0984: * @see java.awt.Component#contains
0985: * @since JDK1.1
0986: */
0987: public Component getComponentAt(Point p) {
0988: return getComponentAt(p.x, p.y);
0989: }
0990:
0991: /**
0992: * Notifies the container to create a peer. It will also
0993: * notify the components contained in this container.
0994: * This method should be called by <code>Container.add</code>,
0995: * and not by user code directly.
0996: * @see #removeNotify
0997: * @since JDK1.0
0998: */
0999: public void addNotify() {
1000: synchronized (getTreeLock()) {
1001: super .addNotify();
1002: int ncomponents = this .ncomponents;
1003: Component component[] = this .component;
1004: for (int i = ncomponents - 1; i >= 0; i--) {
1005: Component c = component[i];
1006: if (c.isLightweightWhenDisplayable())
1007: component[i].addNotify();
1008: }
1009: for (int i = ncomponents - 1; i >= 0; i--) {
1010: Component c = component[i];
1011: if (!c.isLightweightWhenDisplayable())
1012: component[i].addNotify();
1013: }
1014: }
1015: }
1016:
1017: /**
1018: * Notifies this container and all of its subcomponents to remove
1019: * their peers.
1020: * This method should be invoked by the container's
1021: * <code>remove</code> method, and not directly by user code.
1022: * @see java.awt.Container#remove(int)
1023: * @see java.awt.Container#remove(java.awt.Component)
1024: * @since JDK1.0
1025: */
1026: public void removeNotify() {
1027: synchronized (getTreeLock()) {
1028: int ncomponents = this .ncomponents;
1029: Component component[] = this .component;
1030: for (int i = 0; i < ncomponents; i++) {
1031: component[i].removeNotify();
1032: }
1033: // if ( dispatcher != null ) {
1034: // dispatcher.dispose();
1035: // }
1036: super .removeNotify();
1037: }
1038: }
1039:
1040: /**
1041: * Checks if the component is contained in the component hierarchy of
1042: * this container.
1043: * @param c the component
1044: * @return <code>true</code> if it is an ancestor;
1045: * <code>true</code> otherwise.
1046: * @since JDK1.1
1047: */
1048: public boolean isAncestorOf(Component c) {
1049: Container p;
1050: if (c == null || ((p = c.getParent()) == null)) {
1051: return false;
1052: }
1053: while (p != null) {
1054: if (p == this ) {
1055: return true;
1056: }
1057: p = p.getParent();
1058: }
1059: return false;
1060: }
1061:
1062: /**
1063: * Returns the parameter string representing the state of this
1064: * container. This string is useful for debugging.
1065: * @return the parameter string of this container.
1066: * @since JDK1.0
1067: */
1068: protected String paramString() {
1069: String str = super .paramString();
1070: LayoutManager layoutMgr = this .layoutMgr;
1071: if (layoutMgr != null) {
1072: str += ",layout=" + layoutMgr.getClass().getName();
1073: }
1074: return str;
1075: }
1076:
1077: /**
1078: * Prints a listing of this container to the specified output
1079: * stream. The listing starts at the specified indentation.
1080: * @param out a print stream.
1081: * @param indent the number of spaces to indent.
1082: * @see java.awt.Component#list(java.io.PrintStream, int)
1083: * @since JDK
1084: */
1085: public void list(PrintStream out, int indent) {
1086: super .list(out, indent);
1087: int ncomponents = this .ncomponents;
1088: Component component[] = this .component;
1089: for (int i = 0; i < ncomponents; i++) {
1090: Component comp = component[i];
1091: if (comp != null) {
1092: comp.list(out, indent + 1);
1093: }
1094: }
1095: }
1096:
1097: /**
1098: * Prints out a list, starting at the specified indention, to the specified
1099: * print writer.
1100: */
1101: public void list(PrintWriter out, int indent) {
1102: super .list(out, indent);
1103: int ncomponents = this .ncomponents;
1104: Component component[] = this .component;
1105: for (int i = 0; i < ncomponents; i++) {
1106: Component comp = component[i];
1107: if (comp != null) {
1108: comp.list(out, indent + 1);
1109: }
1110: }
1111: }
1112:
1113: void transferFocus(Component base) {
1114: nextFocus(base);
1115: }
1116:
1117: /**
1118: * @deprecated As of JDK version 1.1,
1119: * replaced by transferFocus(Component).
1120: */
1121: void nextFocus(Component base) {
1122: Container parent = this .parent;
1123: if (parent != null) {
1124: parent.transferFocus(base);
1125: }
1126: }
1127:
1128: /* Serialization support. A Container is responsible for
1129: * restoring the parent fields of its component children.
1130: */
1131:
1132: private int containerSerializedDataVersion = 1;
1133:
1134: private void writeObject(ObjectOutputStream s) throws IOException {
1135: s.defaultWriteObject();
1136: AWTEventMulticaster.save(s, containerListenerK,
1137: containerListener);
1138: s.writeObject(null);
1139: }
1140:
1141: private void readObject(ObjectInputStream s)
1142: throws ClassNotFoundException, IOException {
1143: s.defaultReadObject();
1144: Component component[] = this .component;
1145: for (int i = 0; i < ncomponents; i++)
1146: component[i].parent = this ;
1147: Object keyOrNull;
1148: while (null != (keyOrNull = s.readObject())) {
1149: String key = ((String) keyOrNull).intern();
1150: if (containerListenerK == key)
1151: addContainerListener((ContainerListener) (s
1152: .readObject()));
1153: else
1154: // skip value for unrecognized key
1155: s.readObject();
1156: }
1157: }
1158: }
|