home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 November / Chip_1998-11_cd.bin / tema / Cafe / main.bin / Container.java < prev    next >
Text File  |  1998-01-23  |  53KB  |  1,624 lines

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