mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			1084 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			1084 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			Java
		
	
	
	
| /* Copyright (C) 1999, 2000, 2002  Free Software Foundation
 | |
| 
 | |
| This file is part of GNU Classpath.
 | |
| 
 | |
| GNU Classpath is free software; you can redistribute it and/or modify
 | |
| it under the terms of the GNU General Public License as published by
 | |
| the Free Software Foundation; either version 2, or (at your option)
 | |
| any later version.
 | |
| 
 | |
| GNU Classpath is distributed in the hope that it will be useful, but
 | |
| WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
| General Public License for more details.
 | |
| 
 | |
| You should have received a copy of the GNU General Public License
 | |
| along with GNU Classpath; see the file COPYING.  If not, write to the
 | |
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 | |
| 02111-1307 USA.
 | |
| 
 | |
| Linking this library statically or dynamically with other modules is
 | |
| making a combined work based on this library.  Thus, the terms and
 | |
| conditions of the GNU General Public License cover the whole
 | |
| combination.
 | |
| 
 | |
| As a special exception, the copyright holders of this library give you
 | |
| permission to link this library with independent modules to produce an
 | |
| executable, regardless of the license terms of these independent
 | |
| modules, and to copy and distribute the resulting executable under
 | |
| terms of your choice, provided that you also meet, for each linked
 | |
| independent module, the terms and conditions of the license of that
 | |
| module.  An independent module is a module which is not derived from
 | |
| or based on this library.  If you modify this library, you may extend
 | |
| this exception to your version of the library, but you are not
 | |
| obligated to do so.  If you do not wish to do so, delete this
 | |
| exception statement from your version. */
 | |
| 
 | |
| package java.awt;
 | |
| 
 | |
| import java.awt.event.*;
 | |
| import java.io.PrintStream;
 | |
| import java.io.PrintWriter;
 | |
| import java.util.EventListener;
 | |
| import java.awt.peer.ComponentPeer;
 | |
| import java.awt.peer.ContainerPeer;
 | |
| import java.awt.peer.LightweightPeer;
 | |
| 
 | |
| /* A somewhat incomplete class. */
 | |
| 
 | |
| public class Container extends Component
 | |
| {
 | |
|   /* Serialized fields from the serialization spec. */
 | |
|   int ncomponents;
 | |
|   Component[] component;
 | |
|   LayoutManager layoutMgr;
 | |
|   /* LightweightDispatcher dispatcher; */ // wtf?
 | |
|   Dimension maxSize;
 | |
|   int containerSerializedDataVersion;
 | |
| 
 | |
|   /* Anything else is non-serializable, and should be declared "transient". */
 | |
|   transient ContainerListener containerListener;  
 | |
| 
 | |
|   /**
 | |
|    * Default constructor for subclasses.
 | |
|    */
 | |
|   public Container()
 | |
|   {
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the number of components in this container.
 | |
|    *
 | |
|    * @return The number of components in this container.
 | |
|    */
 | |
|   public int getComponentCount()
 | |
|   {
 | |
|     return ncomponents;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the number of components in this container.
 | |
|    *
 | |
|    * @return The number of components in this container.
 | |
|    *
 | |
|    * @deprecated This method is deprecated in favor of 
 | |
|    * <code>getComponentCount()</code>.
 | |
|    */
 | |
|   public int countComponents()
 | |
|   {
 | |
|     return ncomponents;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the component at the specified index.
 | |
|    *
 | |
|    * @param index The index of the component to retrieve.
 | |
|    *
 | |
|    * @return The requested component.
 | |
|    *
 | |
|    * @exception ArrayIndexOutOfBoundsException If the specified index is not
 | |
|    * valid.
 | |
|    */
 | |
|   public Component getComponent (int n)
 | |
|   {
 | |
|     if (n < 0 || n >= ncomponents)
 | |
|       throw new ArrayIndexOutOfBoundsException("no such component");
 | |
|     return component[n];
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns an array of the components in this container.
 | |
|    *
 | |
|    * @return The components in this container.
 | |
|    */
 | |
|   public Component[] getComponents()
 | |
|   {
 | |
|     Component[] result = new Component[ncomponents];
 | |
|     if (ncomponents > 0)
 | |
|       System.arraycopy(component, 0, result, 0, ncomponents);
 | |
|     return result;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the insets for this container, which is the space used for
 | |
|    * borders, the margin, etc.
 | |
|    *
 | |
|    * @return The insets for this container.
 | |
|    */
 | |
|   public Insets getInsets()
 | |
|   {
 | |
|     if (peer == null)
 | |
|       return new Insets(0, 0, 0, 0);
 | |
|     return ((ContainerPeer) peer).getInsets();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the insets for this container, which is the space used for
 | |
|    * borders, the margin, etc.
 | |
|    *
 | |
|    * @return The insets for this container.
 | |
|    *
 | |
|    * @deprecated This method is deprecated in favor of
 | |
|    * <code>getInsets()</code>.
 | |
|    */
 | |
|   public Insets insets()
 | |
|   {
 | |
|     return getInsets();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Adds the specified component to this container at the end of the
 | |
|    * component list.
 | |
|    *
 | |
|    * @param component The component to add to the container.
 | |
|    *
 | |
|    * @return The same component that was added.
 | |
|    */
 | |
|   public Component add (Component comp)
 | |
|   {
 | |
|     addImpl (comp, null, -1);
 | |
|     return comp;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Adds the specified component to the container at the end of the
 | |
|    * component list.  This method should not be used. Instead, use
 | |
|    * <code>add(Component, Object</code>.
 | |
|    *
 | |
|    * @param name FIXME
 | |
|    * @param component The component to be added.
 | |
|    *
 | |
|    * @return The same component that was added.
 | |
|    */
 | |
|   public Component add (String name, Component comp)
 | |
|   {
 | |
|     addImpl (comp, name, -1);
 | |
|     return comp;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Adds the specified component to this container at the specified index
 | |
|    * in the component list.
 | |
|    *
 | |
|    * @param component The component to be added.
 | |
|    * @param index The index in the component list to insert this child
 | |
|    * at, or -1 to add at the end of the list.
 | |
|    *
 | |
|    * @return The same component that was added.
 | |
|    *
 | |
|    * @param throws ArrayIndexOutOfBounds If the specified index is invalid.
 | |
|    */
 | |
|   public Component add (Component comp, int index)
 | |
|   {
 | |
|     addImpl (comp, null, index);
 | |
|     return comp;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Adds the specified component to this container at the end of the
 | |
|    * component list.  The layout manager will use the specified constraints
 | |
|    * when laying out this component.
 | |
|    *
 | |
|    * @param component The component to be added to this container.
 | |
|    * @param constraints The layout constraints for this component.
 | |
|    */
 | |
|   public void add (Component comp, Object constraints)
 | |
|   {
 | |
|     addImpl (comp, constraints, -1);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Adds the specified component to this container at the specified index
 | |
|    * in the component list.  The layout manager will use the specified
 | |
|    * constraints when layout out this component.
 | |
|    *
 | |
|    * @param component The component to be added.
 | |
|    * @param constraints The layout constraints for this component.
 | |
|    * @param index The index in the component list to insert this child
 | |
|    * at, or -1 to add at the end of the list.
 | |
|    *
 | |
|    * @param throws ArrayIndexOutOfBounds If the specified index is invalid.
 | |
|    */
 | |
|   public void add (Component comp, Object constraints, int index)
 | |
|   {
 | |
|     addImpl (comp, constraints, index);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * This method is called by all the <code>add()</code> methods to perform
 | |
|    * the actual adding of the component.  Subclasses who wish to perform
 | |
|    * their own processing when a component is added should override this
 | |
|    * method.  Any subclass doing this must call the superclass version of
 | |
|    * this method in order to ensure proper functioning of the container.
 | |
|    *
 | |
|    * @param component The component to be added.
 | |
|    * @param constraints The layout constraints for this component, or
 | |
|    * <code>null</code> if there are no constraints.
 | |
|    * @param index The index in the component list to insert this child
 | |
|    * at, or -1 to add at the end of the list.
 | |
|    *
 | |
|    * @param throws ArrayIndexOutOfBounds If the specified index is invalid.
 | |
|    */
 | |
|   protected void addImpl (Component comp, Object constraints, int index)
 | |
|   {
 | |
|     if (index > ncomponents
 | |
| 	|| (index < 0 && index != -1)
 | |
| 	|| comp instanceof Window
 | |
| 	|| (comp instanceof Container
 | |
| 	    && ((Container) comp).isAncestorOf (this)))
 | |
|       throw new IllegalArgumentException ();
 | |
| 
 | |
|     // Reparent component, and make sure component is instantiated if
 | |
|     // we are.
 | |
|     if (comp.parent != null)
 | |
|       comp.parent.remove (comp);
 | |
|     comp.parent = this;
 | |
|     if (peer != null)
 | |
|       {
 | |
| 	comp.addNotify ();
 | |
| 
 | |
| 	if (comp.isLightweight())
 | |
| 	  enableEvents(comp.eventMask);
 | |
|       }
 | |
| 
 | |
|     invalidate ();
 | |
| 
 | |
|     if (component == null)
 | |
|       component = new Component[4]; // FIXME, better initial size?
 | |
| 
 | |
|     // This isn't the most efficient implementation.  We could do less
 | |
|     // copying when growing the array.  It probably doesn't matter.
 | |
|     if (ncomponents >= component.length)
 | |
|       {
 | |
| 	int nl = component.length * 2;
 | |
| 	Component[] c = new Component[nl];
 | |
| 	System.arraycopy (component, 0, c, 0, ncomponents);
 | |
| 	component = c;
 | |
|       }
 | |
|     if (index == -1)
 | |
|       component[ncomponents++] = comp;
 | |
|     else
 | |
|       {
 | |
| 	System.arraycopy (component, index, component, index + 1,
 | |
| 			  ncomponents - index);
 | |
| 	component[index] = comp;
 | |
| 	++ncomponents;
 | |
|       }
 | |
| 
 | |
|     // Notify the layout manager.
 | |
|     if (layoutMgr != null)
 | |
|       {
 | |
| 	if (layoutMgr instanceof LayoutManager2)
 | |
| 	  {
 | |
| 	    LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
 | |
| 	    lm2.addLayoutComponent (comp, constraints);
 | |
| 	  }
 | |
| 	else if (constraints instanceof String)
 | |
| 	  layoutMgr.addLayoutComponent ((String) constraints, comp);
 | |
| 	else
 | |
| 	  layoutMgr.addLayoutComponent (null, comp);
 | |
|       }
 | |
| 
 | |
|     // Post event to notify of adding the container.
 | |
|     ContainerEvent ce = new ContainerEvent (this,
 | |
| 					    ContainerEvent.COMPONENT_ADDED,
 | |
| 					    comp);
 | |
|     getToolkit().getSystemEventQueue().postEvent(ce);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Removes the component at the specified index from this container.
 | |
|    *
 | |
|    * @param index The index of the component to remove.
 | |
|    */
 | |
|   public void remove (int index)
 | |
|   {
 | |
|     Component r = component[index];
 | |
| 
 | |
|     r.removeNotify ();
 | |
| 
 | |
|     System.arraycopy (component, index + 1, component, index,
 | |
| 		      ncomponents - index - 1);
 | |
|     component[--ncomponents] = null;
 | |
| 
 | |
|     invalidate ();
 | |
| 
 | |
|     if (layoutMgr != null)
 | |
|       layoutMgr.removeLayoutComponent (r);
 | |
| 
 | |
|     // Post event to notify of adding the container.
 | |
|     ContainerEvent ce = new ContainerEvent (this,
 | |
| 					    ContainerEvent.COMPONENT_REMOVED,
 | |
| 					    r);
 | |
|     getToolkit().getSystemEventQueue().postEvent(ce);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Removes the specified component from this container.
 | |
|    *
 | |
|    * @return component The component to remove from this container.
 | |
|    */
 | |
|   public void remove (Component comp)
 | |
|   {
 | |
|     for (int i = 0; i < ncomponents; ++i)
 | |
|       {
 | |
| 	if (component[i] == comp)
 | |
| 	  {
 | |
| 	    remove (i);
 | |
| 	    break;
 | |
| 	  }
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Removes all components from this container.
 | |
|    */
 | |
|   public void removeAll()
 | |
|   {
 | |
|     while (ncomponents > 0)
 | |
|       remove (0);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the current layout manager for this container.
 | |
|    *
 | |
|    * @return The layout manager for this container.
 | |
|    */
 | |
|   public LayoutManager getLayout()
 | |
|   {
 | |
|     return layoutMgr;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Sets the layout manager for this container to the specified layout
 | |
|    * manager.
 | |
|    *
 | |
|    * @param mgr The new layout manager for this container.
 | |
|    */
 | |
|   public void setLayout(LayoutManager mgr)
 | |
|   {
 | |
|     layoutMgr = mgr;
 | |
|     invalidate ();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Layout the components in this container.
 | |
|    */
 | |
|   public void doLayout()
 | |
|   {
 | |
|     if (layoutMgr != null)
 | |
|       layoutMgr.layoutContainer (this);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Layout the components in this container.
 | |
|    *
 | |
|    * @deprecated This method is deprecated in favor of
 | |
|    * <code>doLayout()</code>.
 | |
|    */
 | |
|   public void layout()
 | |
|   {
 | |
|     doLayout();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Invalidates this container to indicate that it (and all parent
 | |
|    * containers) need to be laid out.
 | |
|    */
 | |
|   public void invalidate()
 | |
|   {
 | |
|     super.invalidate ();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Re-lays out the components in this container.
 | |
|    */
 | |
|   public void validate()
 | |
|   {
 | |
|     // FIXME: use the tree lock?
 | |
|     synchronized (this)
 | |
|       {
 | |
| 	if (! isValid ())
 | |
| 	  {
 | |
| 	    validateTree ();
 | |
| 	  }
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Recursively validates the container tree, recomputing any invalid
 | |
|    * layouts.
 | |
|    */
 | |
|   protected void validateTree()
 | |
|   {
 | |
|     if (valid)
 | |
|       return; 
 | |
| 
 | |
|     ContainerPeer cPeer = null;
 | |
|     if ((peer != null) && !(peer instanceof LightweightPeer))
 | |
|       {
 | |
| 	cPeer = (ContainerPeer) peer;
 | |
| 	cPeer.beginValidate();
 | |
|       }
 | |
| 
 | |
|     doLayout ();
 | |
|     for (int i = 0; i < ncomponents; ++i)
 | |
|       {
 | |
| 	Component comp = component[i];
 | |
| 	if (! comp.isValid ())
 | |
| 	  {
 | |
| 	    if (comp instanceof Container)
 | |
| 	      {
 | |
| 		((Container) comp).validateTree();
 | |
| 	      }
 | |
| 	    else
 | |
| 	      {
 | |
| 		component[i].validate();
 | |
| 	      }
 | |
| 	  }
 | |
|       }
 | |
| 
 | |
|     /* children will call invalidate() when they are layed out. It
 | |
|        is therefore imporant that valid is not set to true
 | |
|        before after the children has been layed out. */
 | |
|     valid = true;
 | |
| 
 | |
|     if (cPeer != null)
 | |
|       cPeer.endValidate();
 | |
|   }
 | |
| 
 | |
|   public void setFont(Font f)
 | |
|   {
 | |
|     super.setFont(f);
 | |
|     // FIXME, should invalidate all children with font == null
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the preferred size of this container.
 | |
|    *
 | |
|    * @return The preferred size of this container.
 | |
|    */
 | |
|   public Dimension getPreferredSize()
 | |
|   {
 | |
|     if (layoutMgr != null)
 | |
|       return layoutMgr.preferredLayoutSize (this);
 | |
|     else
 | |
|       return super.getPreferredSize ();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the preferred size of this container.
 | |
|    *
 | |
|    * @return The preferred size of this container.
 | |
|    * 
 | |
|    * @deprecated This method is deprecated in favor of 
 | |
|    * <code>getPreferredSize()</code>.
 | |
|    */
 | |
|   public Dimension preferredSize()
 | |
|   {
 | |
|     return getPreferredSize();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the minimum size of this container.
 | |
|    *
 | |
|    * @return The minimum size of this container.
 | |
|    */
 | |
|   public Dimension getMinimumSize()
 | |
|   {
 | |
|     if (layoutMgr != null)
 | |
|       return layoutMgr.minimumLayoutSize (this);
 | |
|     else
 | |
|       return super.getMinimumSize ();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the minimum size of this container.
 | |
|    *
 | |
|    * @return The minimum size of this container.
 | |
|    * 
 | |
|    * @deprecated This method is deprecated in favor of 
 | |
|    * <code>getMinimumSize()</code>.
 | |
|    */
 | |
|   public Dimension minimumSize()
 | |
|   {
 | |
|     return getMinimumSize();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the maximum size of this container.
 | |
|    *
 | |
|    * @return The maximum size of this container.
 | |
|    */
 | |
|   public Dimension getMaximumSize()
 | |
|   {
 | |
|     if (layoutMgr != null && layoutMgr instanceof LayoutManager2)
 | |
|       {
 | |
| 	LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
 | |
| 	return lm2.maximumLayoutSize (this);
 | |
|       }
 | |
|     else
 | |
|       return super.getMaximumSize ();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the preferred alignment along the X axis.  This is a value
 | |
|    * between 0 and 1 where 0 represents alignment flush left and
 | |
|    * 1 means alignment flush right, and 0.5 means centered.
 | |
|    *
 | |
|    * @return The preferred alignment along the X axis.
 | |
|    */
 | |
|   public float getAlignmentX()
 | |
|   {
 | |
|     if (layoutMgr instanceof LayoutManager2)
 | |
|       {
 | |
| 	LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
 | |
| 	return lm2.getLayoutAlignmentX (this);
 | |
|       }
 | |
|     else
 | |
|       return super.getAlignmentX();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the preferred alignment along the Y axis.  This is a value
 | |
|    * between 0 and 1 where 0 represents alignment flush top and
 | |
|    * 1 means alignment flush bottom, and 0.5 means centered.
 | |
|    *
 | |
|    * @return The preferred alignment along the Y axis.
 | |
|    */
 | |
|   public float getAlignmentY()
 | |
|   {
 | |
|     if (layoutMgr instanceof LayoutManager2)
 | |
|       {
 | |
| 	LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
 | |
| 	return lm2.getLayoutAlignmentY (this);
 | |
|       }
 | |
|     else
 | |
|       return super.getAlignmentY();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Paints this container.  The implementation of this method in this
 | |
|    * class forwards to any lightweight components in this container.  If
 | |
|    * this method is subclassed, this method should still be invoked as
 | |
|    * a superclass method so that lightweight components are properly
 | |
|    * drawn.
 | |
|    *
 | |
|    * @param graphics The graphics context for this paint job.
 | |
|    */
 | |
|   public void paint(Graphics g)
 | |
|   {
 | |
|     if (!isShowing())
 | |
|       return;
 | |
|     super.paint(g);
 | |
|     visitChildren(g, GfxPaintVisitor.INSTANCE, true);
 | |
|   }
 | |
| 
 | |
|   /** 
 | |
|    * Perform a graphics operation on the children of this container.
 | |
|    * For each applicable child, the visitChild() method will be called
 | |
|    * to perform the graphics operation.
 | |
|    *
 | |
|    * @param gfx The graphics object that will be used to derive new
 | |
|    * graphics objects for the children.
 | |
|    *
 | |
|    * @param visitor Object encapsulating the graphics operation that
 | |
|    * should be performed.
 | |
|    *
 | |
|    * @param lightweightOnly If true, only lightweight components will
 | |
|    * be visited.
 | |
|    */
 | |
|   private void visitChildren(Graphics gfx, GfxVisitor visitor,
 | |
| 			     boolean lightweightOnly)
 | |
|   {
 | |
|     // FIXME: do locking
 | |
| 
 | |
|     for (int i = 0; i < ncomponents; ++i)
 | |
|       {
 | |
| 	Component comp = component[i];
 | |
| 	boolean applicable = comp.isVisible()
 | |
| 	  && (comp.isLightweight() || !lightweightOnly);
 | |
| 
 | |
| 	if (applicable)
 | |
| 	  visitChild(gfx, visitor, comp);
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Perform a graphics operation on a child. A translated and clipped
 | |
|    * graphics object will be created, and the visit() method of the
 | |
|    * visitor will be called to perform the operation.
 | |
|    *
 | |
|    * @param gfx The graphics object that will be used to derive new
 | |
|    * graphics objects for the child.
 | |
|    *
 | |
|    * @param visitor Object encapsulating the graphics operation that
 | |
|    * should be performed.
 | |
|    *
 | |
|    * @param comp The child component that should be visited.
 | |
|    */
 | |
|   private void visitChild(Graphics gfx, GfxVisitor visitor,
 | |
| 			  Component comp)
 | |
|   {
 | |
|     Rectangle bounds = comp.getBounds();
 | |
|     Rectangle clip = gfx.getClipBounds().intersection(bounds);
 | |
|     
 | |
|     if (clip.isEmpty()) return;
 | |
| 
 | |
|     Graphics gfx2 = gfx.create();
 | |
|     gfx2.setClip(clip.x, clip.y, clip.width, clip.height);
 | |
|     gfx2.translate(bounds.x, bounds.y);
 | |
|     
 | |
|     visitor.visit(comp, gfx2);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Updates this container.  The implementation of this method in this
 | |
|    * class forwards to any lightweight components in this container.  If
 | |
|    * this method is subclassed, this method should still be invoked as
 | |
|    * a superclass method so that lightweight components are properly
 | |
|    * drawn.
 | |
|    *
 | |
|    * @param graphics The graphics context for this update.
 | |
|    */
 | |
|   public void update(Graphics g)
 | |
|   {
 | |
|     super.update(g);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Prints this container.  The implementation of this method in this
 | |
|    * class forwards to any lightweight components in this container.  If
 | |
|    * this method is subclassed, this method should still be invoked as
 | |
|    * a superclass method so that lightweight components are properly
 | |
|    * drawn.
 | |
|    *
 | |
|    * @param graphics The graphics context for this print job.
 | |
|    */
 | |
|   public void print(Graphics g)
 | |
|   {
 | |
|     super.print(g);
 | |
|     visitChildren(g, GfxPrintVisitor.INSTANCE, true);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Paints all of the components in this container.
 | |
|    *
 | |
|    * @param graphics The graphics context for this paint job.
 | |
|    */
 | |
|   public void paintComponents(Graphics g)
 | |
|   {
 | |
|     super.paint(g);
 | |
|     visitChildren(g, GfxPaintAllVisitor.INSTANCE, true);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Prints all of the components in this container.
 | |
|    *
 | |
|    * @param graphics The graphics context for this print job.
 | |
|    */
 | |
|   public void printComponents(Graphics g)
 | |
|   {
 | |
|     super.paint(g);
 | |
|     visitChildren(g, GfxPrintAllVisitor.INSTANCE, true);
 | |
|   }
 | |
| 
 | |
|   void dispatchEventImpl(AWTEvent e)
 | |
|   {
 | |
|     if ((e.id <= ContainerEvent.CONTAINER_LAST
 | |
|              && e.id >= ContainerEvent.CONTAINER_FIRST)
 | |
| 	&& (containerListener != null
 | |
| 	    || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0))
 | |
|       processEvent(e); 
 | |
|     else
 | |
|       super.dispatchEventImpl(e);
 | |
|   }  
 | |
| 
 | |
|   /**
 | |
|    * Adds the specified container listener to this object's list of
 | |
|    * container listeners.
 | |
|    *
 | |
|    * @param listener The listener to add.
 | |
|    */
 | |
|   public synchronized void addContainerListener(ContainerListener l)
 | |
|   {
 | |
|     containerListener = AWTEventMulticaster.add (containerListener, l);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Removes the specified container listener from this object's list of
 | |
|    * container listeners.
 | |
|    *
 | |
|    * @param listener The listener to remove.
 | |
|    */
 | |
|   public synchronized void removeContainerListener(ContainerListener l)
 | |
|   {
 | |
|     containerListener = AWTEventMulticaster.remove(containerListener, l);
 | |
|   }
 | |
| 
 | |
|   /** @since 1.3 */
 | |
|   public EventListener[] getListeners(Class listenerType)
 | |
|   {
 | |
|     if (listenerType == ContainerListener.class)
 | |
|       return getListenersImpl(listenerType, containerListener);
 | |
|     else return super.getListeners(listenerType);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Processes the specified event.  This method calls
 | |
|    * <code>processContainerEvent()</code> if this method is a
 | |
|    * <code>ContainerEvent</code>, otherwise it calls the superclass
 | |
|    * method.
 | |
|    *
 | |
|    * @param event The event to be processed.
 | |
|    */
 | |
|   protected void processEvent(AWTEvent e)
 | |
|   {
 | |
|     if (e instanceof ContainerEvent)
 | |
|       processContainerEvent((ContainerEvent) e);
 | |
|     else super.processEvent(e);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Called when a container event occurs if container events are enabled.
 | |
|    * This method calls any registered listeners.
 | |
|    *
 | |
|    * @param event The event that occurred.
 | |
|    */
 | |
|   protected void processContainerEvent(ContainerEvent e)
 | |
|   {
 | |
|     if (containerListener == null)
 | |
|       return;
 | |
|     switch (e.id)
 | |
|       {
 | |
|       case ContainerEvent.COMPONENT_ADDED:
 | |
| 	containerListener.componentAdded(e);
 | |
| 	break;
 | |
| 
 | |
|       case ContainerEvent.COMPONENT_REMOVED:
 | |
| 	containerListener.componentRemoved(e);
 | |
| 	break;    
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * AWT 1.0 event processor.
 | |
|    *
 | |
|    * @param event The event that occurred.
 | |
|    *
 | |
|    * @deprecated This method is deprecated in favor of 
 | |
|    * <code>dispatchEvent()</code>.
 | |
|    */
 | |
|   public void deliverEvent(Event e)
 | |
|   {
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the component located at the specified point.  This is done
 | |
|    * by checking whether or not a child component claims to contain this
 | |
|    * point.  The first child component that does is returned.  If no
 | |
|    * child component claims the point, the container itself is returned,
 | |
|    * unless the point does not exist within this container, in which
 | |
|    * case <code>null</code> is returned.
 | |
|    *
 | |
|    * @param x The X coordinate of the point.
 | |
|    * @param y The Y coordinate of the point.
 | |
|    *
 | |
|    * @return The component containing the specified point, or
 | |
|    * <code>null</code> if there is no such point.
 | |
|    */
 | |
|   public Component getComponentAt (int x, int y)
 | |
|   {
 | |
|     if (! contains (x, y))
 | |
|       return null;
 | |
|     for (int i = 0; i < ncomponents; ++i)
 | |
|       {
 | |
| 	// Ignore invisible children...
 | |
| 	if (!component[i].isVisible())
 | |
| 	  continue;
 | |
| 
 | |
| 	int x2 = x - component[i].x;
 | |
| 	int y2 = y - component[i].y;
 | |
| 	if (component[i].contains (x2, y2))
 | |
| 	  return component[i];
 | |
|       }
 | |
|     return this;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the component located at the specified point.  This is done
 | |
|    * by checking whether or not a child component claims to contain this
 | |
|    * point.  The first child component that does is returned.  If no
 | |
|    * child component claims the point, the container itself is returned,
 | |
|    * unless the point does not exist within this container, in which
 | |
|    * case <code>null</code> is returned.
 | |
|    *
 | |
|    * @param point The point to return the component at.
 | |
|    *
 | |
|    * @return The component containing the specified point, or <code>null</code>
 | |
|    * if there is no such point.
 | |
|    *
 | |
|    * @deprecated This method is deprecated in favor of
 | |
|    * <code>getComponentAt(int, int)</code>.
 | |
|    */
 | |
|   public Component locate(int x, int y)
 | |
|   {
 | |
|     return getComponentAt(x, y);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the component located at the specified point.  This is done
 | |
|    * by checking whether or not a child component claims to contain this
 | |
|    * point.  The first child component that does is returned.  If no
 | |
|    * child component claims the point, the container itself is returned,
 | |
|    * unless the point does not exist within this container, in which
 | |
|    * case <code>null</code> is returned.
 | |
|    *
 | |
|    * @param point The point to return the component at.
 | |
|    *
 | |
|    * @return The component containing the specified point, or <code>null</code>
 | |
|    * if there is no such point.
 | |
|    */
 | |
|   public Component getComponentAt(Point p)
 | |
|   {
 | |
|     return getComponentAt(p.x, p.y);
 | |
|   }
 | |
| 
 | |
|   public Component findComponentAt (int x, int y)
 | |
|   {
 | |
|     if (! contains (x, y))
 | |
|       return null;
 | |
| 
 | |
|     for (int i = 0; i < ncomponents; ++i)
 | |
|       {
 | |
| 	// Ignore invisible children...
 | |
| 	if (!component[i].isVisible())
 | |
| 	  continue;
 | |
| 
 | |
| 	int x2 = x - component[i].x;
 | |
| 	int y2 = y - component[i].y;
 | |
| 	// We don't do the contains() check right away because
 | |
| 	// findComponentAt would redundantly do it first thing.
 | |
| 	if (component[i] instanceof Container)
 | |
| 	  {
 | |
| 	    Container k = (Container) component[i];
 | |
| 	    Component r = k.findComponentAt (x2, y2);
 | |
| 	    if (r != null)
 | |
| 	      return r;
 | |
| 	  }
 | |
| 	else if (component[i].contains (x2, y2))
 | |
| 	  return component[i];
 | |
|       }
 | |
| 
 | |
|     return this;
 | |
|   }
 | |
| 
 | |
|   public Component findComponentAt(Point p)
 | |
|   {
 | |
|     return findComponentAt(p.x, p.y);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Called when this container is added to another container to inform it
 | |
|    * to create its peer.  Peers for any child components will also be
 | |
|    * created.
 | |
|    */
 | |
|   public void addNotify ()
 | |
|   {
 | |
|     if (peer == null)
 | |
|       {
 | |
| 	addNotifyContainerChildren ();
 | |
| 	super.addNotify();
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   private void addNotifyContainerChildren()
 | |
|   {
 | |
|     for (int i = ncomponents;  --i >= 0; )
 | |
|       {
 | |
| 	component[i].addNotify();
 | |
| 	if (component[i].isLightweight())
 | |
| 	  enableEvents(component[i].eventMask);
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Called when this container is removed from its parent container to
 | |
|    * inform it to destroy its peer.  This causes the peers of all child
 | |
|    * component to be destroyed as well.
 | |
|    */
 | |
|   public void removeNotify()
 | |
|   {
 | |
|     for (int i = 0; i < ncomponents; ++i)
 | |
|       component[i].removeNotify ();
 | |
|     super.removeNotify();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Tests whether or not the specified component is contained within
 | |
|    * this components subtree.
 | |
|    *
 | |
|    * @param component The component to test.
 | |
|    *
 | |
|    * @return <code>true</code> if this container is an ancestor of the
 | |
|    * specified component, <code>false</code>.
 | |
|    */
 | |
|   public boolean isAncestorOf (Component comp)
 | |
|   {
 | |
|     for (;;)
 | |
|       {
 | |
| 	if (comp == null)
 | |
| 	  return false;
 | |
| 	if (comp == this)
 | |
| 	  return true;
 | |
| 	comp = comp.getParent();
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns a string representing the state of this container for
 | |
|    * debugging purposes.
 | |
|    *
 | |
|    * @return A string representing the state of this container.
 | |
|    */
 | |
|   protected String paramString()
 | |
|   {
 | |
|     String param = super.paramString();
 | |
|     if (layoutMgr != null)
 | |
|       param = param + "," + layoutMgr.getClass().getName();
 | |
| 
 | |
|     return param;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Writes a listing of this container to the specified stream starting
 | |
|    * at the specified indentation point.
 | |
|    *
 | |
|    * @param stream The <code>PrintStream</code> to write to.
 | |
|    * @param indent The indentation point.
 | |
|    */
 | |
|   public void list (PrintStream out, int indent)
 | |
|   {
 | |
|     super.list (out, indent);
 | |
|     for (int i = 0; i < ncomponents; ++i)
 | |
|       component[i].list (out, indent + 2);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Writes a listing of this container to the specified stream starting
 | |
|    * at the specified indentation point.
 | |
|    *
 | |
|    * @param stream The <code>PrintWriter</code> to write to.
 | |
|    * @param indent The indentation point.
 | |
|    */
 | |
|   public void list(PrintWriter out, int indent)
 | |
|   {
 | |
|     super.list (out, indent);
 | |
|     for (int i = 0; i < ncomponents; ++i)
 | |
|       component[i].list (out, indent + 2);
 | |
|   }
 | |
| 
 | |
| 
 | |
|   /* The following classes are used in concert with the
 | |
|      visitChildren() method to implement all the graphics operations
 | |
|      that requires traversal of the containment hierarchy. */
 | |
| 
 | |
|   abstract static class GfxVisitor
 | |
|   {
 | |
|     public abstract void visit(Component c, Graphics gfx);
 | |
|   }
 | |
| 
 | |
|   static class GfxPaintVisitor extends GfxVisitor
 | |
|   {
 | |
|     public void visit(Component c, Graphics gfx) { c.paint(gfx); }
 | |
|     public static final GfxVisitor INSTANCE = new GfxPaintVisitor();
 | |
|   }
 | |
| 
 | |
|   static class GfxPrintVisitor extends GfxVisitor
 | |
|   {
 | |
|     public void visit(Component c, Graphics gfx) { c.print(gfx); }
 | |
|     public static final GfxVisitor INSTANCE = new GfxPrintVisitor();
 | |
|   }
 | |
| 
 | |
|   static class GfxPaintAllVisitor extends GfxVisitor
 | |
|   {
 | |
|     public void visit(Component c, Graphics gfx) { c.paintAll(gfx); }
 | |
|     public static final GfxVisitor INSTANCE = new GfxPaintAllVisitor();
 | |
|   }
 | |
| 
 | |
|   static class GfxPrintAllVisitor extends GfxVisitor
 | |
|   {
 | |
|     public void visit(Component c, Graphics gfx) { c.printAll(gfx); }
 | |
|     public static final GfxVisitor INSTANCE = new GfxPrintAllVisitor();
 | |
|   }
 | |
| 
 | |
|   // This is used to implement Component.transferFocus.
 | |
|   Component findNextFocusComponent (Component child)
 | |
|   {
 | |
|     int start, end;
 | |
|     if (child != null)
 | |
|       {
 | |
| 	for (start = 0; start < ncomponents; ++start)
 | |
| 	  {
 | |
| 	    if (component[start] == child)
 | |
| 	      break;
 | |
| 	  }
 | |
| 	end = start;
 | |
| 	// This special case lets us be sure to terminate.
 | |
| 	if (end == 0)
 | |
| 	  end = ncomponents;
 | |
| 	++start;
 | |
|       }
 | |
|     else
 | |
|       {
 | |
| 	start = 0;
 | |
| 	end = ncomponents;
 | |
|       }
 | |
| 
 | |
|     for (int j = start; j != end; ++j)
 | |
|       {
 | |
| 	if (j >= ncomponents)
 | |
| 	  {
 | |
| 	    // The JCL says that we should wrap here.  However, that
 | |
| 	    // seems wrong.  To me it seems that focus order should be
 | |
| 	    // global within in given window.  So instead if we reach
 | |
| 	    // the end we try to look in our parent, if we have one.
 | |
| 	    if (parent != null)
 | |
| 	      return parent.findNextFocusComponent (this);
 | |
| 	    j -= ncomponents;
 | |
| 	  }
 | |
| 	if (component[j] instanceof Container)
 | |
| 	  {
 | |
| 	    Component c = component[j];
 | |
| 	    c = c.findNextFocusComponent (null);
 | |
| 	    if (c != null)
 | |
| 	      return c;
 | |
| 	  }
 | |
| 	else if (component[j].isFocusTraversable ())
 | |
| 	  return component[j];
 | |
|       }
 | |
| 
 | |
|     return null;
 | |
|   }
 | |
| }
 |