home *** CD-ROM | disk | FTP | other *** search
/ Java 1.2 How-To / JavaHowTo.iso / 3rdParty / jbuilder / unsupported / JDK1.2beta3 / SOURCE / SRC.ZIP / java / awt / Container.java < prev    next >
Encoding:
Java Source  |  1998-03-20  |  51.9 KB  |  1,657 lines

  1. /*
  2.  * @(#)Container.java    1.117 98/03/18
  3.  *
  4.  * Copyright 1995-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14. package java.awt;
  15.  
  16. import java.io.PrintStream;
  17. import java.io.PrintWriter;
  18. import java.awt.peer.ContainerPeer;
  19. import java.awt.event.KeyEvent;
  20. import java.awt.event.MouseEvent;
  21. import java.awt.event.FocusEvent;
  22. import java.awt.event.ContainerEvent;
  23. import java.awt.event.ContainerListener;
  24. import java.io.ObjectOutputStream;
  25. import java.io.ObjectInputStream;
  26. import java.io.IOException;
  27.  
  28. /**
  29.  * A generic Abstract Window Toolkit(AWT) container object is a component 
  30.  * that can contain other AWT components.
  31.  * <p>
  32.  * Components added to a container are tracked in a list.  The order
  33.  * of the list will define the components' front-to-back stacking order 
  34.  * within the container.  If no index is specified when adding a
  35.  * component to a container, it will be added to the end of the list
  36.  * (and hence to the bottom of the stacking order).
  37.  * @version     1.117 03/18/98
  38.  * @author     Arthur van Hoff
  39.  * @author     Sami Shaio
  40.  * @see       java.awt.Container#add(java.awt.Component, int)
  41.  * @see       java.awt.Container#getComponent(int)
  42.  * @see       java.awt.LayoutManager
  43.  * @since     JDK1.0
  44.  */
  45. public class Container extends Component {
  46.  
  47.     /**
  48.      * The number of components in this container.
  49.      */
  50.     int ncomponents;
  51.  
  52.     /** 
  53.      * The components in this container.
  54.      */
  55.     Component component[] = new Component[4];
  56.  
  57.     /** 
  58.      * Layout manager for this container.
  59.      */
  60.     LayoutManager layoutMgr;
  61.  
  62.     /**
  63.      * Event router for lightweight components.  If this container
  64.      * is native, this dispatcher takes care of forwarding and 
  65.      * retargeting the events to lightweight components contained
  66.      * (if any).
  67.      */
  68.     private LightweightDispatcher dispatcher;
  69.  
  70.     /** Internal, cached size information */
  71.     private Dimension maxSize;
  72.  
  73.     transient ContainerListener containerListener;
  74.  
  75.     /*
  76.      * JDK 1.1 serialVersionUID 
  77.      */
  78.      private static final long serialVersionUID = 4613797578919906343L;  
  79.  
  80.     /**
  81.      * Constructs a new Container. Containers can be extended directly, 
  82.      * but are lightweight in this case and must be contained by a parent
  83.      * somewhere higher up in the component tree that is native.
  84.      * (such as Frame for example).
  85.      */
  86.     public Container() {
  87.     }
  88.  
  89.     /** 
  90.      * Gets the number of components in this panel.
  91.      * @return    the number of components in this panel.
  92.      * @see       java.awt.Container#getComponent
  93.      * @since     JDK1.1
  94.      */
  95.     public int getComponentCount() {
  96.     return countComponents();
  97.     }
  98.  
  99.     /** 
  100.      * @deprecated As of JDK version 1.1,
  101.      * replaced by getComponentCount().
  102.      */
  103.     public int countComponents() {
  104.     return ncomponents;
  105.     }
  106.  
  107.     /** 
  108.      * Gets the nth component in this container.
  109.      * @param      n   the index of the component to get.
  110.      * @return     the n<sup>th</sup> component in this container.
  111.      * @exception  ArrayIndexOutOfBoundsException  
  112.      *                 if the n<sup>th</sup> value does not exist.     
  113.      */
  114.     public Component getComponent(int n) {
  115.     synchronized (Component.LOCK) {
  116.         if ((n < 0) || (n >= ncomponents)) {
  117.         throw new ArrayIndexOutOfBoundsException("No such child: " + n);
  118.         }
  119.         return component[n];
  120.     }
  121.     }
  122.  
  123.     /**
  124.      * Gets all the components in this container.
  125.      * @return    an array of all the components in this container.     
  126.      */
  127.     public Component[] getComponents() {
  128.     synchronized (Component.LOCK) {
  129.         Component list[] = new Component[ncomponents];
  130.         System.arraycopy(component, 0, list, 0, ncomponents);
  131.         return list;
  132.     }
  133.     }
  134.  
  135.     /**
  136.      * Determines the insets of this container, which indicate the size 
  137.      * of the container's border. 
  138.      * <p>
  139.      * A <code>Frame</code> object, for example, has a top inset that 
  140.      * corresponds to the height of the frame's title bar. 
  141.      * @return    the insets of this container.
  142.      * @see       java.awt.Insets
  143.      * @see       java.awt.LayoutManager
  144.      * @since     JDK1.1
  145.      */
  146.     public Insets getInsets() {
  147.         return insets();
  148.     }
  149.  
  150.     /**
  151.      * @deprecated As of JDK version 1.1,
  152.      * replaced by <code>getInsets()</code>.
  153.      */
  154.     public Insets insets() {
  155.     if (this.peer != null && this.peer instanceof ContainerPeer) {
  156.         ContainerPeer peer = (ContainerPeer)this.peer;
  157.         return peer.insets();
  158.     }
  159.     return new Insets(0, 0, 0, 0);
  160.     }
  161.  
  162.     /** 
  163.      * Adds the specified component to the end of this container. 
  164.      * @param     comp   the component to be added.
  165.      * @return    the component argument.     
  166.      */
  167.     public Component add(Component comp) {
  168.         addImpl(comp, null, -1);
  169.     return comp;
  170.     }
  171.  
  172.     /**
  173.      * Adds the specified component to this container.
  174.      * It is strongly advised to use the 1.1 method, add(Component, Object),
  175.      * in place of this method.
  176.      */
  177.     public Component add(String name, Component comp) {
  178.     addImpl(comp, name, -1);
  179.     return comp;
  180.     }
  181.  
  182.     /** 
  183.      * Adds the specified component to this container at the given 
  184.      * position. 
  185.      * @param     comp   the component to be added.
  186.      * @param     index    the position at which to insert the component, 
  187.      *                   or <code>-1</code> to insert the component at the end.
  188.      * @return    the component <code>comp</code>
  189.      * @see      #remove
  190.      */
  191.     public Component add(Component comp, int index) {
  192.     addImpl(comp, null, index);
  193.     return comp;
  194.     }
  195.  
  196.     /**
  197.      * Adds the specified component to the end of this container.
  198.      * Also notifies the layout manager to add the component to 
  199.      * this container's layout using the specified constraints object.
  200.      * @param     comp the component to be added
  201.      * @param     constraints an object expressing 
  202.      *                  layout contraints for this component
  203.      * @see       java.awt.LayoutManager
  204.      * @since     JDK1.1
  205.      */
  206.     public void add(Component comp, Object constraints) {
  207.     addImpl(comp, constraints, -1);
  208.     }
  209.  
  210.     /**
  211.      * Adds the specified component to this container with the specified
  212.      * constraints at the specified index.  Also notifies the layout 
  213.      * manager to add the component to the this container's layout using 
  214.      * the specified constraints object.
  215.      * @param comp the component to be added
  216.      * @param constraints an object expressing layout contraints for this
  217.      * @param index the position in the container's list at which to insert
  218.      * the component. -1 means insert at the end.
  219.      * component
  220.      * @see #remove
  221.      * @see LayoutManager
  222.      */
  223.     public void add(Component comp, Object constraints, int index) {
  224.        addImpl(comp, constraints, index);
  225.     }
  226.  
  227.     /**
  228.      * Adds the specified component to this container at the specified
  229.      * index. This method also notifies the layout manager to add 
  230.      * the component to this container's layout using the specified 
  231.      * constraints object.
  232.      * <p>
  233.      * This is the method to override if a program needs to track 
  234.      * every add request to a container. An overriding method should 
  235.      * usually include a call to the superclass's version of the method:
  236.      * <p>
  237.      * <blockquote>
  238.      * <code>super.addImpl(comp, constraints, index)</code>
  239.      * </blockquote>
  240.      * <p>
  241.      * @param     comp       the component to be added.
  242.      * @param     constraints an object expressing layout contraints 
  243.      *                 for this component.
  244.      * @param     index the position in the container's list at which to
  245.      *                 insert the component, where <code>-1</code> 
  246.      *                 means insert at the end.
  247.      * @see       java.awt.Container#add(java.awt.Component)       
  248.      * @see       java.awt.Container#add(java.awt.Component, int)       
  249.      * @see       java.awt.Container#add(java.awt.Component, java.lang.Object)       
  250.      * @see       java.awt.LayoutManager
  251.      * @since     JDK1.1
  252.      */
  253.     protected void addImpl(Component comp, Object constraints, int index) {
  254.     synchronized (Component.LOCK) {
  255.  
  256.         /* Check for correct arguments:  index in bounds,
  257.          * comp cannot be one of this container's parents,
  258.          * and comp cannot be a window.
  259.          */
  260.         if (index > ncomponents || (index < 0 && index != -1)) {
  261.         throw new IllegalArgumentException(
  262.               "illegal component position");
  263.         }
  264.         if (comp instanceof Container) {
  265.         for (Container cn = this; cn != null; cn=cn.parent) {
  266.             if (cn == comp) {
  267.             throw new IllegalArgumentException(
  268.                   "adding container's parent to itself");
  269.             }
  270.         }
  271.         }
  272.         if (comp instanceof Window) {
  273.             throw new IllegalArgumentException(
  274.                  "adding a window to a container");
  275.         }
  276.  
  277.         /* Reparent the component and tidy up the tree's state. */
  278.         if (comp.parent != null) {
  279.         comp.parent.remove(comp);
  280.         }
  281.  
  282.         /* Add component to list; allocate new array if necessary. */
  283.         if (ncomponents == component.length) {
  284.         Component newcomponents[] = new Component[ncomponents * 2];
  285.         System.arraycopy(component, 0, newcomponents, 0, ncomponents);
  286.         component = newcomponents;
  287.         }
  288.         if (index == -1 || index == ncomponents) {
  289.         component[ncomponents++] = comp;
  290.         } else {
  291.         System.arraycopy(component, index, component,
  292.                  index + 1, ncomponents - index);
  293.         component[index] = comp;
  294.         ncomponents++;
  295.         }
  296.         comp.parent = this;
  297.         if (valid) {
  298.         invalidate();
  299.         }
  300.         if (peer != null) {
  301.         comp.addNotify();
  302.         }
  303.         
  304.         /* Notify the layout manager of the added component. */
  305.         if (layoutMgr != null) {
  306.         if (layoutMgr instanceof LayoutManager2) {
  307.             ((LayoutManager2)layoutMgr).addLayoutComponent(comp, constraints);
  308.         } else if (constraints instanceof String) {
  309.             layoutMgr.addLayoutComponent((String)constraints, comp);
  310.         }
  311.         }
  312.             if (containerListener != null || 
  313.                 (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0) {
  314.                 ContainerEvent e = new ContainerEvent(this, 
  315.                                      ContainerEvent.COMPONENT_ADDED,
  316.                                      comp);
  317.                 processEvent(e);
  318.             }
  319.     }
  320.     }
  321.  
  322.     /** 
  323.      * Removes the component, specified by <code>index</code>, 
  324.      * from this container. 
  325.      * @param     index   the index of the component to be removed.
  326.      * @see #add
  327.      * @since JDK1.1
  328.      */
  329.     public void remove(int index) {
  330.     synchronized (Component.LOCK) {
  331.             Component comp = component[index];
  332.         if (peer != null) {
  333.         comp.removeNotify();
  334.         }
  335.         if (layoutMgr != null) {
  336.         layoutMgr.removeLayoutComponent(comp);
  337.         }
  338.         comp.parent = null;
  339.         System.arraycopy(component, index + 1,
  340.                  component, index,
  341.                  ncomponents - index - 1);
  342.         component[--ncomponents] = null;
  343.         if (valid) {
  344.         invalidate();
  345.         }
  346.             if (containerListener != null ||
  347.                 (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0) {
  348.                 ContainerEvent e = new ContainerEvent(this, 
  349.                                      ContainerEvent.COMPONENT_REMOVED,
  350.                                      comp);
  351.                 processEvent(e);
  352.             }
  353.         return;
  354.     }
  355.     }
  356.  
  357.     /** 
  358.      * Removes the specified component from this container.
  359.      * @param comp the component to be removed
  360.      * @see #add
  361.      */
  362.     public void remove(Component comp) {
  363.     synchronized (Component.LOCK) {
  364.         if (comp.parent == this)  {
  365.             /* Search backwards, expect that more recent additions
  366.          * are more likely to be removed.
  367.                  */
  368.                 Component component[] = this.component;
  369.         for (int i = ncomponents; --i >= 0; ) {
  370.             if (component[i] == comp) {
  371.                         remove(i);
  372.             }
  373.         }
  374.         }
  375.     }
  376.     }
  377.  
  378.     /** 
  379.      * Removes all the components from this container.
  380.      * @see #add
  381.      * @see #remove
  382.      */
  383.     public void removeAll() {
  384.     synchronized (Component.LOCK) {
  385.         while (ncomponents > 0) {
  386.         Component comp = component[--ncomponents];
  387.         component[ncomponents] = null;
  388.  
  389.         if (peer != null) {
  390.             comp.removeNotify();
  391.         }
  392.         if (layoutMgr != null) {
  393.             layoutMgr.removeLayoutComponent(comp);
  394.         }
  395.         comp.parent = null;
  396.                 if (containerListener != null ||
  397.                    (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0) {
  398.                     ContainerEvent e = new ContainerEvent(this, 
  399.                                      ContainerEvent.COMPONENT_REMOVED,
  400.                                      comp);
  401.                     processEvent(e);
  402.                 }
  403.         }
  404.         if (valid) {
  405.         invalidate();
  406.     }
  407.     }
  408.     }
  409.  
  410.     /** 
  411.      * Gets the layout manager for this container.  
  412.      * @see #doLayout
  413.      * @see #setLayout
  414.      */
  415.     public LayoutManager getLayout() {
  416.     return layoutMgr;
  417.     }
  418.  
  419.     /** 
  420.      * Sets the layout manager for this container.
  421.      * @param mgr the specified layout manager
  422.      * @see #doLayout
  423.      * @see #getLayout
  424.      */
  425.     public void setLayout(LayoutManager mgr) {
  426.     layoutMgr = mgr;
  427.     if (valid) {
  428.         invalidate();
  429.     }
  430.     }
  431.  
  432.     /** 
  433.      * Causes this container to lay out its components.  Most programs 
  434.      * should not call this method directly, but should invoke 
  435.      * the <code>validate</code> method instead.
  436.      * @see java.awt.LayoutManager#layoutContainer
  437.      * @see #setLayout
  438.      * @see #validate
  439.      * @since JDK1.1
  440.      */
  441.     public void doLayout() {
  442.     layout();
  443.     }
  444.  
  445.     /** 
  446.      * @deprecated As of JDK version 1.1,
  447.      * replaced by <code>doLayout()</code>.
  448.      */
  449.     public void layout() {
  450.     LayoutManager layoutMgr = this.layoutMgr;
  451.     if (layoutMgr != null) {
  452.         layoutMgr.layoutContainer(this);
  453.     }
  454.     }
  455.  
  456.     /** 
  457.      * Invalidates the container.  The container and all parents
  458.      * above it are marked as needing to be laid out.  This method can
  459.      * be called often, so it needs to execute quickly.
  460.      * @see #validate
  461.      * @see #layout
  462.      * @see LayoutManager
  463.      */
  464.     public void invalidate() {
  465.     if (layoutMgr instanceof LayoutManager2) {
  466.         LayoutManager2 lm = (LayoutManager2) layoutMgr;
  467.         lm.invalidateLayout(this);
  468.     }
  469.     super.invalidate();
  470.     }
  471.  
  472.     /** 
  473.      * Validates this container and all of its subcomponents.
  474.      * <p>
  475.      * AWT uses <code>validate</code> to cause a container to lay out   
  476.      * its subcomponents again after the components it contains
  477.      * have been added to or modified.
  478.      * @see #validate
  479.      * @see Component#invalidate
  480.      */
  481.     public void validate() {
  482.         /* Avoid grabbing lock unless really necessary. */
  483.     if (!valid) {
  484.         synchronized (Component.LOCK) {
  485.         if (!valid && peer != null) {
  486.                     Cursor oldCursor = getCursor();
  487.             ContainerPeer p = null;
  488.             if (peer instanceof ContainerPeer) {
  489.             p = (ContainerPeer) peer;
  490.             }
  491.             if (p != null) {
  492.             p.beginValidate();
  493.             }
  494.             validateTree();
  495.             valid = true;
  496.             if (p != null) {
  497.             p.endValidate();
  498.             }
  499.         }
  500.         }
  501.     }
  502.     }
  503.  
  504.     /**
  505.      * Recursively descends the container tree and recomputes the
  506.      * layout for any subtrees marked as needing it (those marked as
  507.      * invalid).  Synchronization should be provided by the method
  508.      * that calls this one:  <code>validate</code>.
  509.      */
  510.     protected void validateTree() {
  511.     if (!valid) {
  512.         doLayout();
  513.             Component component[] = this.component;
  514.         for (int i = 0 ; i < ncomponents ; ++i) {
  515.         Component comp = component[i];
  516.         if (   (comp instanceof Container) 
  517.                 && !(comp instanceof Window)
  518.             && !comp.valid) {
  519.             ((Container)comp).validateTree();
  520.         } else {
  521.             comp.validate();
  522.         }
  523.         }
  524.     }
  525.     valid = true;
  526.     }
  527.  
  528.     /** 
  529.      * Returns the preferred size of this container.  
  530.      * @return    an instance of <code>Dimension</code> that represents 
  531.      *                the preferred size of this container.
  532.      * @see       java.awt.Container#getMinimumSize       
  533.      * @see       java.awt.Container#getLayout
  534.      * @see       java.awt.LayoutManager#preferredLayoutSize(java.awt.Container)
  535.      * @see       java.awt.Component#getPreferredSize
  536.      */
  537.     public Dimension getPreferredSize() {
  538.     return preferredSize();
  539.     }
  540.  
  541.     /** 
  542.      * @deprecated As of JDK version 1.1,
  543.      * replaced by <code>getPreferredSize()</code>.
  544.      */
  545.     public Dimension preferredSize() {
  546.     /* Avoid grabbing the lock if a reasonable cached size value
  547.      * is available.
  548.      */ 
  549.         Dimension dim = prefSize;
  550.         if (dim != null && isValid()) {
  551.         return dim;
  552.     }
  553.     synchronized (Component.LOCK) {
  554.         prefSize = (layoutMgr != null) ?
  555.                    layoutMgr.preferredLayoutSize(this) :
  556.                    super.preferredSize();
  557.         
  558.         return prefSize;
  559.     }
  560.     }
  561.  
  562.     /** 
  563.      * Returns the minimum size of this container.  
  564.      * @return    an instance of <code>Dimension</code> that represents 
  565.      *                the minimum size of this container.
  566.      * @see       java.awt.Container#getPreferredSize       
  567.      * @see       java.awt.Container#getLayout
  568.      * @see       java.awt.LayoutManager#minimumLayoutSize(java.awt.Container)
  569.      * @see       java.awt.Component#getMinimumSize
  570.      * @since     JDK1.1
  571.      */
  572.     public Dimension getMinimumSize() {
  573.     return minimumSize();
  574.     }
  575.  
  576.     /** 
  577.      * @deprecated As of JDK version 1.1,
  578.      * replaced by <code>getMinimumSize()</code>.
  579.      */
  580.     public Dimension minimumSize() {
  581.     /* Avoid grabbing the lock if a reasonable cached size value
  582.      * is available.
  583.      */ 
  584.         Dimension dim = minSize;
  585.         if (dim != null && isValid()) {
  586.         return dim;
  587.     }
  588.     synchronized (Component.LOCK) {
  589.         minSize = (layoutMgr != null) ?
  590.            layoutMgr.minimumLayoutSize(this) :
  591.            super.minimumSize();
  592.         return minSize;
  593.     }
  594.     }
  595.  
  596.     /** 
  597.      * Returns the maximum size of this container.  
  598.      * @see #getPreferredSize
  599.      */
  600.     public Dimension getMaximumSize() {
  601.     /* Avoid grabbing the lock if a reasonable cached size value
  602.      * is available.
  603.      */ 
  604.         Dimension dim = maxSize;
  605.         if (dim != null && isValid()) {
  606.         return dim;
  607.     }
  608.     if (layoutMgr instanceof LayoutManager2) {
  609.         synchronized (Component.LOCK) {
  610.         LayoutManager2 lm = (LayoutManager2) layoutMgr;
  611.         maxSize = lm.maximumLayoutSize(this);
  612.         }
  613.     } else {
  614.         maxSize = super.getMaximumSize();
  615.     }
  616.     return maxSize;
  617.     }
  618.  
  619.     /**
  620.      * Returns the alignment along the x axis.  This specifies how
  621.      * the component would like to be aligned relative to other 
  622.      * components.  The value should be a number between 0 and 1
  623.      * where 0 represents alignment along the origin, 1 is aligned
  624.      * the furthest away from the origin, 0.5 is centered, etc.
  625.      */
  626.     public float getAlignmentX() {
  627.     float xAlign;
  628.     if (layoutMgr instanceof LayoutManager2) {
  629.         synchronized (Component.LOCK) {
  630.         LayoutManager2 lm = (LayoutManager2) layoutMgr;
  631.         xAlign = lm.getLayoutAlignmentX(this);
  632.         }
  633.     } else {
  634.         xAlign = super.getAlignmentX();
  635.     }
  636.     return xAlign;
  637.     }
  638.  
  639.     /**
  640.      * Returns the alignment along the y axis.  This specifies how
  641.      * the component would like to be aligned relative to other 
  642.      * components.  The value should be a number between 0 and 1
  643.      * where 0 represents alignment along the origin, 1 is aligned
  644.      * the furthest away from the origin, 0.5 is centered, etc.
  645.      */
  646.     public float getAlignmentY() {
  647.     float yAlign;
  648.     if (layoutMgr instanceof LayoutManager2) {
  649.         synchronized (Component.LOCK) {
  650.         LayoutManager2 lm = (LayoutManager2) layoutMgr;
  651.         yAlign = lm.getLayoutAlignmentY(this);
  652.         }
  653.     } else {
  654.         yAlign = super.getAlignmentY();
  655.     }
  656.     return yAlign;
  657.     }
  658.  
  659.     /** 
  660.      * Paints the container.  This forwards the paint to any lightweight components 
  661.      * that are children of this container.  If this method is reimplemented, 
  662.      * super.paint(g) should be called so that lightweight components are properly
  663.      * rendered.  If a child component is entirely clipped by the current clipping
  664.      * setting in g, paint() will not be forwarded to that child.
  665.      *
  666.      * @param g the specified Graphics window
  667.      * @see   java.awt.Component#update(java.awt.Graphics)
  668.      */
  669.     public void paint(Graphics g) {
  670.     if (isShowing()) {
  671.         int ncomponents = this.ncomponents;
  672.             Component component[] = this.component;
  673.         Rectangle clip = g.getClipRect();
  674.         for (int i = ncomponents - 1 ; i >= 0 ; i--) {
  675.         Component comp = component[i];
  676.         if (comp != null && 
  677.             comp.peer instanceof java.awt.peer.LightweightPeer &&
  678.             comp.visible == true) {
  679.  
  680.             Rectangle cr = comp.getBounds();
  681.             if ((clip == null) || cr.intersects(clip)) {
  682.             Graphics cg = g.create(cr.x, cr.y, cr.width, cr.height);
  683.             try {
  684.                 comp.paint(cg);
  685.             } finally {
  686.                 cg.dispose();
  687.             }
  688.             }
  689.         }
  690.         }
  691.     }
  692.     }
  693.  
  694.     /** 
  695.      * Updates the container.  This forwards the update to any lightweight components 
  696.      * that are children of this container.  If this method is reimplemented, 
  697.      * super.update(g) should be called so that lightweight components are properly
  698.      * rendered.  If a child component is entirely clipped by the current clipping
  699.      * setting in g, update() will not be forwarded to that child.
  700.      *
  701.      * @param g the specified Graphics window
  702.      * @see   java.awt.Component#update(java.awt.Graphics)
  703.      */
  704.     public void update(Graphics g) {
  705.         if (isShowing()) {
  706.             if (! (peer instanceof java.awt.peer.LightweightPeer)) {
  707.                 g.clearRect(0, 0, width, height);
  708.             }
  709.             super.update(g);  // By default, Component.update() calls paint()
  710.         }
  711.     }
  712.  
  713.     /** 
  714.      * Prints the container.  This forwards the print to any lightweight components 
  715.      * that are children of this container.  If this method is reimplemented, 
  716.      * super.print(g) should be called so that lightweight components are properly
  717.      * rendered.  If a child component is entirely clipped by the current clipping
  718.      * setting in g, print() will not be forwarded to that child.
  719.      *
  720.      * @param g the specified Graphics window
  721.      * @see   java.awt.Component#update(java.awt.Graphics)
  722.      */
  723.     public void print(Graphics g) {
  724.         super.print(g);  // By default, Component.print() calls paint()
  725.  
  726.         int ncomponents = this.ncomponents;
  727.         Component component[] = this.component;
  728.     Rectangle clip = g.getClipRect();
  729.     for (int i = ncomponents - 1 ; i >= 0 ; i--) {
  730.         Component comp = component[i];
  731.         if (comp != null && comp.peer instanceof java.awt.peer.LightweightPeer) {
  732.         Rectangle cr = comp.getBounds();
  733.         if (cr.intersects(clip)) {
  734.             Graphics cg = g.create(cr.x, cr.y, cr.width, cr.height);
  735.             try {
  736.             comp.print(cg);
  737.             } finally {
  738.             cg.dispose();
  739.             }
  740.         }
  741.         }
  742.     }
  743.     }
  744.  
  745.     /** 
  746.      * Paints each of the components in this container. 
  747.      * @param     g   the graphics context.
  748.      * @see       java.awt.Component#paint
  749.      * @see       java.awt.Component#paintAll
  750.      */
  751.     public void paintComponents(Graphics g) {
  752.         int ncomponents = this.ncomponents;
  753.         Component component[] = this.component;
  754.     for (int i = ncomponents - 1 ; i >= 0 ; i--) {
  755.         Component comp = component[i];
  756.         if (comp != null) {
  757.                 Graphics cg = comp.getGraphics();
  758.                 Rectangle parentRect = g.getClipRect();
  759.  
  760.                 // Calculate the clipping region of the child's graphics
  761.                 // context, by taking the intersection of the parent's
  762.                 // clipRect (if any) and the child's bounds, and then 
  763.                 // translating it's coordinates to be relative to the child.
  764.                 if (parentRect != null) {
  765.                     Rectangle childRect = comp.getBounds();
  766.                     if (childRect.intersects(parentRect) == false) {
  767.                         // Child component is completely clipped out: ignore.
  768.                         continue;
  769.                     }
  770.                     Rectangle childClipRect = 
  771.                         childRect.intersection(parentRect);
  772.                     childClipRect.translate(-childRect.x, -childRect.y);
  773.                     cg.clipRect(childClipRect.x, childClipRect.y,
  774.                                 childClipRect.width, childClipRect.height);
  775.                 }
  776.  
  777.         try {
  778.             comp.paintAll(cg);
  779.         } finally {
  780.             cg.dispose();
  781.         }
  782.         }
  783.     }
  784.     }
  785.  
  786.     /** 
  787.      * Prints each of the components in this container. 
  788.      * @param     g   the graphics context.
  789.      * @see       java.awt.Component#print
  790.      * @see       java.awt.Component#printAll
  791.      */
  792.     public void printComponents(Graphics g) {
  793.         int ncomponents = this.ncomponents;
  794.         Component component[] = this.component;
  795.     for (int i = 0 ; i < ncomponents ; i++) {
  796.         Component comp = component[i];
  797.         if (comp != null) {
  798.         Graphics cg = g.create(comp.x, comp.y, comp.width, comp.height);
  799.         try {
  800.             comp.printAll(cg);
  801.         } finally {
  802.             cg.dispose();
  803.         }
  804.         }
  805.     }
  806.     }
  807.  
  808.     /**
  809.      * Adds the specified container listener to receive container events
  810.      * from this container.
  811.      * @param l the container listener
  812.      */ 
  813.     public synchronized void addContainerListener(ContainerListener l) {
  814.     containerListener = AWTEventMulticaster.add(containerListener, l);
  815.         newEventsOnly = true;    
  816.     }
  817.  
  818.     /**
  819.      * Removes the specified container listener so it no longer receives
  820.      * container events from this container.
  821.      * @param l the container listener
  822.      */ 
  823.     public void removeContainerListener(ContainerListener l) {
  824.     containerListener = AWTEventMulticaster.remove(containerListener, l);
  825.     }
  826.  
  827.     // REMIND: remove when filtering is done at lower level
  828.     boolean eventEnabled(AWTEvent e) {
  829.         int id = e.getID();
  830.  
  831.         if (id == ContainerEvent.COMPONENT_ADDED ||
  832.             id == ContainerEvent.COMPONENT_REMOVED) {
  833.             if ((eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
  834.                 containerListener != null) {
  835.                 return true;
  836.             }
  837.             return false;
  838.         }
  839.         return super.eventEnabled(e);
  840.     }          
  841.  
  842.     /**
  843.      * Processes events on this container. If the event is a ContainerEvent,
  844.      * it invokes the processContainerEvent method, else it invokes its
  845.      * superclass's processEvent.
  846.      * @param e the event
  847.      */
  848.     protected void processEvent(AWTEvent e) {
  849.         if (e instanceof ContainerEvent) {
  850.             processContainerEvent((ContainerEvent)e);     
  851.             return;
  852.         }
  853.     super.processEvent(e);
  854.     }
  855.  
  856.     /** 
  857.      * Processes container events occurring on this container by
  858.      * dispatching them to any registered ContainerListener objects.
  859.      * NOTE: This method will not be called unless container events
  860.      * are enabled for this component; this happens when one of the
  861.      * following occurs:
  862.      * a) A ContainerListener object is registered via addContainerListener()
  863.      * b) Container events are enabled via enableEvents()
  864.      * @see Component#enableEvents
  865.      * @param e the container event
  866.      */  
  867.     protected void processContainerEvent(ContainerEvent e) {
  868.         if (containerListener != null) {
  869.             switch(e.getID()) {
  870.               case ContainerEvent.COMPONENT_ADDED:
  871.                 containerListener.componentAdded(e);
  872.                 break;
  873.               case ContainerEvent.COMPONENT_REMOVED:
  874.                 containerListener.componentRemoved(e);
  875.                 break;
  876.             }
  877.         }
  878.     }
  879.  
  880.     /*
  881.      * Dispatches an event to this component or one of its sub components.
  882.      * @param e the event
  883.      */
  884.     void dispatchEventImpl(AWTEvent e) {
  885.     if ((dispatcher != null) && dispatcher.dispatchEvent(e)) {
  886.         // event was sent to a lightweight component.  The
  887.         // native-produced event sent to the native container
  888.         // must be properly disposed of by the peer, so it 
  889.         // gets forwarded.  If the native host has been removed
  890.         // as a result of the sending the lightweight event, 
  891.         // the peer reference will be null.
  892.         e.consume();
  893.         if (peer != null) {
  894.         peer.handleEvent(e);
  895.         }
  896.         return;
  897.     }
  898.     super.dispatchEventImpl(e);
  899.     }
  900.  
  901.     /**
  902.      * Fetchs the top-most (deepest) lightweight component that is interested
  903.      * in receiving mouse events.
  904.      */
  905.     Component getMouseEventTarget(int x, int y) {
  906.     int ncomponents = this.ncomponents;
  907.         Component component[] = this.component;
  908.     for (int i = 0 ; i < ncomponents ; i++) {
  909.         Component comp = component[i];
  910.         if ((comp != null) && (comp.contains(x - comp.x, y - comp.y)) &&
  911.         (comp.peer instanceof java.awt.peer.LightweightPeer) &&
  912.         (comp.visible == true)) {
  913.         // found a component that intersects the point, see if there is 
  914.         // a deeper possibility.
  915.         if (comp instanceof Container) {
  916.             Container child = (Container) comp;
  917.             Component deeper = child.getMouseEventTarget(x - child.x, y - child.y);
  918.             if (deeper != null) {
  919.             return deeper;
  920.             }
  921.         } else {
  922.             if ((comp.mouseListener != null) || 
  923.             ((comp.eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0) ||
  924.             (comp.mouseMotionListener != null) ||
  925.             ((comp.eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0)) {
  926.             // there isn't a deeper target, but this component is a target
  927.             return comp;
  928.             }
  929.         }
  930.         }
  931.     }
  932.     // didn't find a child target, return this component if it's a possible target
  933.     if (((mouseListener != null) || 
  934.          ((eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0) ||
  935.          (mouseMotionListener != null) ||
  936.          ((eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0)) &&
  937.         (peer instanceof java.awt.peer.LightweightPeer)) {
  938.         
  939.         return this;
  940.     }
  941.     // no possible target
  942.     return null;
  943.     }
  944.  
  945.     /**
  946.      * This is called by lightweight components that want the containing
  947.      * windowed parent to enable some kind of events on their behalf.
  948.      * This is needed for events that are normally only dispatched to 
  949.      * windows to be accepted so that they can be forwarded downward to 
  950.      * the lightweight component that has enabled them.
  951.      */
  952.     void proxyEnableEvents(long events) {
  953.     if (peer instanceof java.awt.peer.LightweightPeer) {
  954.         // this container is lightweight.... continue sending it
  955.         // upward.
  956.         parent.proxyEnableEvents(events);
  957.     } else {
  958.         // This is a native container, so it needs to host
  959.         // one of it's children.  If this function is called before
  960.         // a peer has been created we don't yet have a dispatcher
  961.         // because it has not yet been determined if this instance
  962.         // is lightweight.
  963.         if (dispatcher != null) {
  964.         dispatcher.enableEvents(events);
  965.         }
  966.     }
  967.     }
  968.  
  969.     Window getWindow() {
  970.         Container w = this;
  971.         while(!(w instanceof Window)) {
  972.             w = w.getParent();
  973.         }
  974.         return (Window)w;
  975.     }
  976.  
  977.     /**
  978.      * This is called by lightweight components that have requested focus.
  979.      * The focus request is propagated upward until a native container is
  980.      * found, at which point the native container requests focus and records
  981.      * the component the host is requesting focus for.
  982.      */
  983.     void proxyRequestFocus(Component c) {
  984.     if (peer instanceof java.awt.peer.LightweightPeer) {
  985.         // this container is lightweight... continue sending it
  986.         // upward.
  987.         parent.proxyRequestFocus(c);
  988.     } else {
  989.         // This is a windowed container, so record true focus
  990.         // component and request focus from the native window
  991.         // if needed.
  992.         if (dispatcher.setFocusRequest(c)) {
  993.         peer.requestFocus();
  994.                 Toolkit.getEventQueue().changeKeyEventFocus(this);
  995.         }
  996.     }
  997.     }
  998.  
  999.     /**
  1000.      * @deprecated As of JDK version 1.1,
  1001.      * replaced by <code>dispatchEvent(AWTEvent e)</code>
  1002.      */
  1003.     public void deliverEvent(Event e) {
  1004.     Component comp = getComponentAt(e.x, e.y);
  1005.     if ((comp != null) && (comp != this)) {
  1006.         e.translate(-comp.x, -comp.y);
  1007.         comp.deliverEvent(e);
  1008.     } else {
  1009.         postEvent(e);
  1010.     }
  1011.     }
  1012.  
  1013.     /**
  1014.      * Locates the component that contains the x,y position.  The
  1015.      * top-most child component is returned in the case where there
  1016.      * is overlap in the components.  This is determined by finding
  1017.      * the component closest to the index 0 that claims to contain
  1018.      * the given point via Component.contains().
  1019.      * @param x the <i>x</i> coordinate
  1020.      * @param y the <i>y</i> coordinate
  1021.      * @return null if the component does not contain the position.
  1022.      * If there is no child component at the requested point and the 
  1023.      * point is within the bounds of the container the container itself 
  1024.      * is returned; otherwise the top-most child is returned.
  1025.      * @see Component#contains
  1026.      * @since JDK1.1
  1027.      */
  1028.     public Component getComponentAt(int x, int y) {
  1029.     return locate(x, y);
  1030.     }
  1031.  
  1032.     /**
  1033.      * @deprecated As of JDK version 1.1,
  1034.      * replaced by <code>getComponentAt(int, int)</code>.
  1035.      */
  1036.     public Component locate(int x, int y) {
  1037.     if (!contains(x, y)) {
  1038.         return null;
  1039.     }
  1040.     int ncomponents = this.ncomponents;
  1041.         Component component[] = this.component;
  1042.     for (int i = 0 ; i < ncomponents ; i++) {
  1043.         Component comp = component[i];
  1044.         if (comp != null) {
  1045.         if (comp.contains(x - comp.x, y - comp.y)) {
  1046.             return comp;
  1047.         }
  1048.         }
  1049.     }
  1050.     return this;
  1051.     }
  1052.  
  1053.     /**
  1054.      * Gets the component that contains the specified point.
  1055.      * @param      p   the point.
  1056.      * @return     returns the component that contains the point,
  1057.      *                 or <code>null</code> if the component does 
  1058.      *                 not contain the point. 
  1059.      * @see        java.awt.Component#contains 
  1060.      * @since      JDK1.1 
  1061.      */
  1062.     public Component getComponentAt(Point p) {
  1063.     return getComponentAt(p.x, p.y);
  1064.     }
  1065.  
  1066.     /**
  1067.      * Locates the visible child component that contains the specified
  1068.      * position.  The top-most child component is returned in the case 
  1069.      * where there is overlap in the components.  If the containing child 
  1070.      * component is a Container, this method will continue searching for 
  1071.      * the deepest nested child component.  Components which are not
  1072.      * visible are ignored during the search.<p>
  1073.      *
  1074.      * The findComponentAt method is different from getComponentAt in
  1075.      * that getComponentAt only searches the Container's immediate
  1076.      * children; if the containing component is a Container, 
  1077.      * findComponentAt will search that child to find a nested component.
  1078.      *
  1079.      * @param x the <i>x</i> coordinate
  1080.      * @param y the <i>y</i. coordinate
  1081.      * @return null if the component does not contain the position.
  1082.      * If there is no child component at the requested point and the 
  1083.      * point is within the bounds of the container the container itself 
  1084.      * is returned.
  1085.      * @see Component#contains
  1086.      * @see getComponentAt
  1087.      * @since JDK1.2
  1088.      */
  1089.     public Component findComponentAt(int x, int y) {
  1090.     if (!contains(x, y)) {
  1091.         return null;
  1092.     }
  1093.         int ncomponents = this.ncomponents;
  1094.         Component component[] = this.component;
  1095.         for (int i = 0 ; i < ncomponents ; i++) {
  1096.             Component comp = component[i];
  1097.             if (comp != null) {
  1098.                 if (comp instanceof Container) {
  1099.                     comp = ((Container)comp).findComponentAt(x - comp.x,
  1100.                                                              y - comp.y);
  1101.                 } else {
  1102.                     comp = comp.locate(x - comp.x, y - comp.y);
  1103.                 }
  1104.                 if (comp != null && comp.isVisible()) {
  1105.                     return comp;
  1106.                 }
  1107.             }
  1108.         }
  1109.     return this;
  1110.     }
  1111.  
  1112.     /**
  1113.      * Locates the visible child component that contains the specified
  1114.      * point.  The top-most child component is returned in the case 
  1115.      * where there is overlap in the components.  If the containing child 
  1116.      * component is a Container, this method will continue searching for 
  1117.      * the deepest nested child component.  Components which are not
  1118.      * visible are ignored during the search.<p>
  1119.      *
  1120.      * The findComponentAt method is different from getComponentAt in
  1121.      * that getComponentAt only searches the Container's immediate
  1122.      * children; if the containing component is a Container, 
  1123.      * findComponentAt will search that child to find a nested component.
  1124.      *
  1125.      * @param      p   the point.
  1126.      * @return null if the component does not contain the position.
  1127.      * If there is no child component at the requested point and the 
  1128.      * point is within the bounds of the container the container itself 
  1129.      * is returned.
  1130.      * @see Component#contains
  1131.      * @see getComponentAt
  1132.      * @since JDK1.2
  1133.      */
  1134.     public Component findComponentAt(Point p) {
  1135.         return findComponentAt(p.x, p.y);
  1136.     }
  1137.  
  1138.     /** 
  1139.      * Notifies the container to create a peer. It will also
  1140.      * notify the components contained in this container.
  1141.      * This method should be called by <code>Container.add</code>, 
  1142.      * and not by user code directly.
  1143.      * @see #removeNotify
  1144.      */
  1145.     public void addNotify() {
  1146.     // addNotify() on the children may cause proxy event enabling
  1147.     // on this instance, so we first call super.addNotify() and
  1148.     // possibly create an lightweight event dispatcher before calling
  1149.     // addNotify() on the children which may be lightweight.
  1150.     super.addNotify();
  1151.     if (! (peer instanceof java.awt.peer.LightweightPeer)) {
  1152.         dispatcher = new LightweightDispatcher(this);
  1153.     }
  1154.  
  1155.         synchronized (Component.LOCK) {
  1156.         int ncomponents = this.ncomponents;
  1157.             Component component[] = this.component;
  1158.         for (int i = 0 ; i < ncomponents ; i++) {
  1159.             component[i].addNotify();
  1160.         }
  1161.         }
  1162.     }
  1163.  
  1164.     /** 
  1165.      * Notifies this container and all of its subcomponents to remove 
  1166.      * their peers. 
  1167.      * This method should be invoked by the container's 
  1168.      * <code>remove</code> method, and not directly by user code.
  1169.      * @see       java.awt.Container#remove(int)
  1170.      * @see       java.awt.Container#remove(java.awt.Component)
  1171.      */
  1172.     public void removeNotify() {
  1173.         synchronized (Component.LOCK) {
  1174.         int ncomponents = this.ncomponents;
  1175.             Component component[] = this.component;
  1176.         for (int i = 0 ; i < ncomponents ; i++) {
  1177.             component[i].removeNotify();
  1178.         }
  1179.         super.removeNotify();
  1180.         }
  1181.     }
  1182.  
  1183.     /**
  1184.      * Checks if the component is contained in the component hierarchy of
  1185.      * this container.
  1186.      * @param c the component
  1187.      * @return     <code>true</code> if it is an ancestor; 
  1188.      *             <code>false</code> otherwise.
  1189.      * @since      JDK1.1
  1190.      */
  1191.     public boolean isAncestorOf(Component c) {
  1192.     Container p;
  1193.     if (c == null || ((p = c.getParent()) == null)) {
  1194.         return false;
  1195.     }
  1196.     while (p != null) {
  1197.         if (p == this) {
  1198.         return true;
  1199.         }
  1200.         p = p.getParent();
  1201.     }
  1202.     return false;
  1203.     }
  1204.  
  1205.     /**
  1206.      * Returns the parameter string representing the state of this 
  1207.      * container. This string is useful for debugging. 
  1208.      * @return    the parameter string of this container.
  1209.      */
  1210.     protected String paramString() {
  1211.     String str = super.paramString();
  1212.     LayoutManager layoutMgr = this.layoutMgr;
  1213.     if (layoutMgr != null) {
  1214.         str += ",layout=" + layoutMgr.getClass().getName();
  1215.     }
  1216.     return str;
  1217.     }
  1218.  
  1219.     /**
  1220.      * Prints a listing of this container to the specified output 
  1221.      * stream. The listing starts at the specified indentation. 
  1222.      * @param    out      a print stream.
  1223.      * @param    indent   the number of spaces to indent.
  1224.      * @see      java.awt.Component#list(java.io.PrintStream, int)
  1225.      * @since    JDK
  1226.      */
  1227.     public void list(PrintStream out, int indent) {
  1228.     super.list(out, indent);
  1229.     int ncomponents = this.ncomponents;
  1230.         Component component[] = this.component;
  1231.     for (int i = 0 ; i < ncomponents ; i++) {
  1232.         Component comp = component[i];
  1233.         if (comp != null) {
  1234.         comp.list(out, indent+1);
  1235.         }
  1236.     }
  1237.     }
  1238.  
  1239.     /**
  1240.      * Prints out a list, starting at the specified indention, to the specified
  1241.      * print writer.
  1242.      */
  1243.     public void list(PrintWriter out, int indent) {
  1244.     super.list(out, indent);
  1245.     int ncomponents = this.ncomponents;
  1246.         Component component[] = this.component;
  1247.     for (int i = 0 ; i < ncomponents ; i++) {
  1248.         Component comp = component[i];
  1249.         if (comp != null) {
  1250.         comp.list(out, indent+1);
  1251.         }
  1252.     }
  1253.     }
  1254.  
  1255.     void setFocusOwner(Component c) {
  1256.     Container parent = this.parent;
  1257.     if (parent != null) {
  1258.         parent.setFocusOwner(c);
  1259.     }
  1260.     }
  1261.  
  1262.     void preProcessKeyEvent(KeyEvent e) {
  1263.         Container parent = this.parent;
  1264.         if (parent != null) {
  1265.             parent.preProcessKeyEvent(e);
  1266.         }
  1267.     }
  1268.  
  1269.     void postProcessKeyEvent(KeyEvent e) {
  1270.         Container parent = this.parent;
  1271.         if (parent != null) {
  1272.             parent.postProcessKeyEvent(e);
  1273.         }
  1274.     }
  1275.  
  1276.     void transferFocus(Component base) {
  1277.     nextFocus(base);
  1278.     }
  1279.  
  1280.     boolean postsOldMouseEvents() {
  1281.         return true;
  1282.     }
  1283.  
  1284.     /**
  1285.      * @deprecated As of JDK version 1.1,
  1286.      * replaced by transferFocus(Component).
  1287.      */
  1288.     void nextFocus(Component base) {
  1289.     Container parent = this.parent;
  1290.     if (parent != null) {
  1291.         parent.transferFocus(base);
  1292.     }
  1293.     }
  1294.  
  1295.     /* Serialization support.  A Container is responsible for
  1296.      * restoring the parent fields of its component children. 
  1297.      */
  1298.  
  1299.     private int containerSerializedDataVersion = 1;
  1300.  
  1301.  
  1302.     private void writeObject(ObjectOutputStream s)
  1303.       throws IOException 
  1304.     {
  1305.       s.defaultWriteObject();
  1306.  
  1307.       AWTEventMulticaster.save(s, containerListenerK, containerListener);
  1308.       s.writeObject(null);
  1309.     }
  1310.  
  1311.  
  1312.     private void readObject(ObjectInputStream s)
  1313.       throws ClassNotFoundException, IOException 
  1314.     {
  1315.       s.defaultReadObject();
  1316.  
  1317.       Component component[] = this.component;
  1318.       for(int i = 0; i < ncomponents; i++)
  1319.     component[i].parent = this;
  1320.  
  1321.       Object keyOrNull;
  1322.       while(null != (keyOrNull = s.readObject())) {
  1323.     String key = ((String)keyOrNull).intern();
  1324.  
  1325.     if (containerListenerK == key) 
  1326.       addContainerListener((ContainerListener)(s.readObject()));
  1327.  
  1328.     else // skip value for unrecognized key
  1329.       s.readObject();
  1330.       }
  1331.     }
  1332. }
  1333.  
  1334.  
  1335. /**
  1336.  * Class to manage the dispatching of events to the lightweight
  1337.  * components contained by a native container.
  1338.  * 
  1339.  * @author Timothy Prinzing
  1340.  */
  1341. class LightweightDispatcher implements java.io.Serializable {
  1342.  
  1343.     /*
  1344.      * JDK 1.1 serialVersionUID 
  1345.      */
  1346.     private static final long serialVersionUID = 5184291520170872969L;
  1347.  
  1348.     LightweightDispatcher(Container nativeContainer) {
  1349.     this.nativeContainer = nativeContainer;
  1350.     focus = null;
  1351.     mouseEventTarget = null;
  1352.     eventMask = 0;
  1353.     }
  1354.  
  1355.     /**
  1356.      * Enables events to lightweight components.
  1357.      */
  1358.     void enableEvents(long events) {
  1359.     eventMask |= events;
  1360.     }
  1361.  
  1362.     /**
  1363.      * This is called by the hosting native container on behalf of lightweight 
  1364.      * components that have requested focus.  The focus request is propagated 
  1365.      * upward from the requesting lightweight component until a windowed host 
  1366.      * is found, at which point the windowed host calls this method.  This method 
  1367.      * returns whether or not the peer associated with the native component needs 
  1368.      * to request focus from the native window system. 
  1369.      *
  1370.      * If a lightweight component already has focus the focus events are synthesized 
  1371.      * since there will be no native events to drive the focus.  If the native host 
  1372.      * already has focus, the focus gained is synthesized for the lightweight component 
  1373.      * requesting focus since it will receive no native focus requests.
  1374.      */
  1375.     boolean setFocusRequest(Component c) {
  1376.     boolean peerNeedsRequest = true;
  1377.     Window w = nativeContainer.getWindow();
  1378.     if (w != null && c != null) {
  1379.         Component focusOwner = w.getFocusOwner();
  1380.         if (focusOwner == nativeContainer) {
  1381.         // This container already has focus, so just 
  1382.         // send FOCUS_GAINED event to lightweight component
  1383.         focus = c ;
  1384.         c.dispatchEvent(new FocusEvent(c, FocusEvent.FOCUS_GAINED, false));
  1385.         peerNeedsRequest = false;
  1386.         } else if (focusOwner == c) {
  1387.         // lightweight already has the focus
  1388.         focus = c ;
  1389.         peerNeedsRequest = false;
  1390.         } else if (focusOwner == focus) {
  1391.         // a lightweight component has focus currently and a new one has been
  1392.         // requested.  There won't be any window-system events associated with
  1393.         // this so we go ahead and send FOCUS_LOST for the old and FOCUS_GAINED
  1394.         // for the new.
  1395.                 EventQueue eq = Toolkit.getEventQueue();
  1396.         if (focus != null) {
  1397.                     eq.postEvent(new FocusEvent(focus, 
  1398.                                                 FocusEvent.FOCUS_LOST, 
  1399.                                                 false));
  1400.         }
  1401.         focus = c ;
  1402.         eq.postEvent(new FocusEvent(c, FocusEvent.FOCUS_GAINED, false));
  1403.         peerNeedsRequest = false;
  1404.         }
  1405.        }
  1406.     return peerNeedsRequest;
  1407.     }
  1408.  
  1409.     /**
  1410.      * Dispatches an event to a lightweight sub-component if necessary, and
  1411.      * returns whether or not the event was forwarded to a lightweight
  1412.      * sub-component.
  1413.      *
  1414.      * @param e the event
  1415.      */
  1416.     boolean dispatchEvent(AWTEvent e) {
  1417.     if ((eventMask & PROXY_EVENT_MASK) != 0) {
  1418.         if ((e instanceof MouseEvent) && 
  1419.         ((eventMask & MOUSE_MASK) != 0)) {
  1420.         
  1421.         MouseEvent me = (MouseEvent) e;
  1422.         return processMouseEvent(me);
  1423.  
  1424.         } else if (e instanceof FocusEvent) {
  1425.         
  1426.         FocusEvent fe = (FocusEvent) e;
  1427.         return processFocusEvent(fe);
  1428.  
  1429.         } else if (e instanceof KeyEvent) {
  1430.  
  1431.         KeyEvent ke = (KeyEvent) e;
  1432.         return processKeyEvent(ke);
  1433.  
  1434.         }
  1435.     }
  1436.     return false;
  1437.     }
  1438.  
  1439.     private boolean processKeyEvent(KeyEvent e) {
  1440.     if (focus != null) {
  1441.         // Don't duplicate the event here.
  1442.         // The KeyEvent for LightWeightComponent is also passed to 
  1443.         // input methods and their native handlers. The native handlers
  1444.         // require the original native event data to be attached to
  1445.         // the KeyEvent.
  1446.         Component source = e.getComponent();
  1447.         e.setSource(focus);
  1448.         focus.dispatchEvent(e);
  1449.         e.setSource(source);
  1450.         return e.isConsumed();
  1451.     }
  1452.     return false;
  1453.     }
  1454.     
  1455.     private boolean processFocusEvent(FocusEvent e) {
  1456.     if (focus != null) {
  1457.         int id = e.getID();
  1458.         FocusEvent retargeted = new FocusEvent(focus, id, e.isTemporary());
  1459.         focus.dispatchEvent(retargeted);
  1460.         if ((id == FocusEvent.FOCUS_LOST) && (e.isTemporary() == false)) {
  1461.         focus = null;
  1462.         }
  1463.         return true;
  1464.     }
  1465.     return false;
  1466.     }
  1467.  
  1468.     /**
  1469.      * This method attempts to distribute a mouse event to a lightweight
  1470.      * component.  It tries to avoid doing any unnecessary probes down
  1471.      * into the component tree to minimize the overhead of determining
  1472.      * where to route the event, since mouse movement events tend to
  1473.      * come in large and frequent amounts.
  1474.      */
  1475.     private boolean processMouseEvent(MouseEvent e) {
  1476.     int id = e.getID();
  1477.     if (mouseEventTarget != null) {
  1478.         // we are currently forwarding to some component, check
  1479.         // to see if we should continue to forward.
  1480.         switch(id) {
  1481.         case MouseEvent.MOUSE_DRAGGED:
  1482.         retargetMouseEvent(id, e);
  1483.         break;
  1484.         case MouseEvent.MOUSE_PRESSED:
  1485.         dragging = true;
  1486.         retargetMouseEvent(id, e);
  1487.         break;
  1488.         case MouseEvent.MOUSE_RELEASED:
  1489.         dragging = false;
  1490.         retargetMouseEvent(id, e);
  1491.         Component tr = nativeContainer.getMouseEventTarget(e.getX(), e.getY());
  1492.         if (tr != mouseEventTarget) {
  1493.             setMouseTarget(tr, e);
  1494.         }
  1495.         break;
  1496.         case MouseEvent.MOUSE_CLICKED:
  1497.         retargetMouseEvent(id, e);
  1498.         break;
  1499.         case MouseEvent.MOUSE_ENTERED:
  1500.         retargetMouseEvent(id, e);
  1501.         break;
  1502.         case MouseEvent.MOUSE_EXITED:
  1503.         if (dragging) {
  1504.             retargetMouseEvent(id, e);
  1505.         } else {
  1506.             setMouseTarget(null, e);
  1507.         }
  1508.         break;
  1509.         case MouseEvent.MOUSE_MOVED:
  1510.         Component t = nativeContainer.getMouseEventTarget(e.getX(), e.getY());
  1511.         if (t != mouseEventTarget) {
  1512.             setMouseTarget(t, e);
  1513.         }
  1514.         if (mouseEventTarget != null) {
  1515.             retargetMouseEvent(id, e);
  1516.         }
  1517.         break;
  1518.         }
  1519.         e.consume();
  1520.     } else {
  1521.         // we are not forwarding, see if there is anything we might
  1522.         // start forwarding to.
  1523.         Component t = nativeContainer.getMouseEventTarget(e.getX(), e.getY());
  1524.         if (t != null) {
  1525.         setMouseTarget(t, e);
  1526.         if (id != MouseEvent.MOUSE_ENTERED) {
  1527.             retargetMouseEvent(id, e);
  1528.         }
  1529.         e.consume();
  1530.         }
  1531.     }
  1532.  
  1533.     return e.isConsumed();
  1534.     }
  1535.  
  1536.     /**
  1537.      * Change the current target of mouse events.  This sends 
  1538.      * the appropriate MOUSE_EXITED and MOUSE_ENTERED events.
  1539.      */
  1540.     void setMouseTarget(Component target, MouseEvent e) {
  1541.     if (mouseEventTarget != null) {
  1542.         retargetMouseEvent(MouseEvent.MOUSE_EXITED, e);
  1543.     } else {
  1544.         nativeCursor = nativeContainer.getCursor();
  1545.     }
  1546.     mouseEventTarget = target;
  1547.     if (mouseEventTarget != null) {
  1548.         retargetMouseEvent(MouseEvent.MOUSE_ENTERED, e);
  1549.     } else {
  1550.         nativeContainer.setCursor(nativeCursor);
  1551.     }
  1552.     }
  1553.  
  1554.     /**
  1555.      * Sends a mouse event to the current mouse event recipient using
  1556.      * the given event (sent to the windowed host) as a prototype.  If
  1557.      * the mouse event target is still in the component tree, the 
  1558.      * coordinates of the event are translated to those of the target.
  1559.      * If the target has been removed, we don't bother to send the
  1560.      * message.
  1561.      */
  1562.     void retargetMouseEvent(int id, MouseEvent e) {
  1563.         int x = e.getX(), y = e.getY();
  1564.         Component component;
  1565.  
  1566.         for(component = mouseEventTarget;
  1567.             component != null && component != nativeContainer;
  1568.             component = component.getParent()) {
  1569.             x -= component.x;
  1570.             y -= component.y;
  1571.         }
  1572.         if (component != null) {
  1573.             MouseEvent retargeted = new MouseEvent(mouseEventTarget, 
  1574.                                                    id, 
  1575.                                                    e.getWhen(), 
  1576.                                                    e.getModifiers(),
  1577.                                                    x, 
  1578.                                                    y, 
  1579.                                                    e.getClickCount(), 
  1580.                                                    e.isPopupTrigger());
  1581.             mouseEventTarget.dispatchEvent(retargeted);
  1582.  
  1583.             // update cursor if needed.  This is done after the event has
  1584.             // been sent to the target so the target has a chance to change
  1585.             // the cursor after reacting to the event.
  1586.             if (mouseEventTarget != null) {
  1587.                 Cursor c = mouseEventTarget.getCursor();
  1588.                 if (nativeContainer.getCursor() != c) {
  1589.                     nativeContainer.setCursor(c);
  1590.                 }
  1591.             }
  1592.         }
  1593.     }
  1594.     
  1595.     // --- member variables -------------------------------
  1596.  
  1597.     /**
  1598.      * The windowed container that might be hosting events for 
  1599.      * lightweight components.
  1600.      */
  1601.     private Container nativeContainer;
  1602.  
  1603.     /**
  1604.      * The current lightweight component that has focus that is being
  1605.      * hosted by this container.  If this is a null reference then 
  1606.      * there is currently no focus on a lightweight component being 
  1607.      * hosted by this container 
  1608.      */
  1609.     private Component focus;
  1610.  
  1611.     /**
  1612.      * The current lightweight component being hosted by this windowed
  1613.      * component that has mouse events being forwarded to it.  If this
  1614.      * is null, there are currently no mouse events being forwarded to 
  1615.      * a lightweight component.
  1616.      */
  1617.     private transient Component mouseEventTarget;
  1618.  
  1619.     /**
  1620.      * Indicates if the mouse pointer is currently being dragged...
  1621.      * this is needed because we may receive exit events while dragging
  1622.      * and need to keep the current mouse target in this case.
  1623.      */
  1624.     private boolean dragging;
  1625.  
  1626.     /**
  1627.      * The cursor used by the native container that is hosting the
  1628.      * lightweight components.  Since the Cursor used by the lightweight
  1629.      * components overwrites the Cursor set in the native container
  1630.      * we need to stash the native cursor so we can restore it after
  1631.      * the lightweight components are done having their cursor shown.
  1632.      */
  1633.     private Cursor nativeCursor;
  1634.  
  1635.     /**
  1636.      * The event mask for contained lightweight components.  Lightweight
  1637.      * components need a windowed container to host window-related 
  1638.      * events.  This seperate mask indicates events that have been 
  1639.      * requested by contained lightweight components without effecting
  1640.      * the mask of the windowed component itself.
  1641.      */
  1642.     private long eventMask;
  1643.  
  1644.     /**
  1645.      * The kind of events routed to lightweight components from windowed
  1646.      * hosts.
  1647.      */
  1648.     private static final long PROXY_EVENT_MASK =
  1649.         AWTEvent.FOCUS_EVENT_MASK | 
  1650.         AWTEvent.KEY_EVENT_MASK |
  1651.         AWTEvent.MOUSE_EVENT_MASK | 
  1652.         AWTEvent.MOUSE_MOTION_EVENT_MASK;
  1653.  
  1654.     private static final long MOUSE_MASK = 
  1655.         AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK;
  1656. }
  1657.