Index: javax/swing/JLayeredPane.java =================================================================== RCS file: /cvsroot/classpath/classpath/javax/swing/JLayeredPane.java,v retrieving revision 1.7 diff -u -b -B -r1.7 JLayeredPane.java --- javax/swing/JLayeredPane.java 2 Dec 2003 16:50:20 -0000 1.7 +++ javax/swing/JLayeredPane.java 8 Jan 2004 08:49:04 -0000 @@ -1,39 +1,40 @@ /* JLayeredPane.java -- Copyright (C) 2002 Free Software Foundation, Inc. -This file is part of GNU Classpath. + 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. */ + 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 javax.swing; @@ -45,37 +46,51 @@ /** - * The "Layered Pane" is a container which divides its children into 6 (or - * more) disjoint sets. the pre-defined sets are: + *

The "Layered Pane" is a container which divides its children into 6 (or + * more) disjoint sets. the pre-defined sets are:

* - * "Frame Content", "Default", "Palette", "Modal", "Popup", and "Drag". + * * - * A child is in exactly one of these layers at any time, though there may - * be other layers if someone creates them. + *

A child is in exactly one of these layers at any time, though there may + * be other layers if someone creates them.

* - * The purpose of this class is to translate this view of "layers" into a + *

The purpose of this class is to translate this view of "layers" into a * contiguous array of components: the one held in our ancestor, - * java.awt.Container. + * address@hidden java.awt.Container}.

* - * There is a precise set of words we will use to refer to numbers within - * this class: + *

There is a precise set of words we will use to refer to numbers within + * this class:

* - * Internal Component Index: an offset into the "component" array held in - * our ancestor, java.awt.Container, from [0 .. component.length). The - * drawing rule with internal indices is that 0 is drawn first. - * - * External Component Index: an offset into the "logical drawing order" of - * this container. If I is the internal index of a component, the external - * index E = component.length - I. The rule with external indices is that 0 - * is drawn last. - * - * Layer Number: a general int specifying a layer within this component. - * Negative numbers are drawn first, then layer 0, then positive numbered - * layers, in ascending order. - * - * Position: an offset into a layer's "logical drawing order". Layer - * position 0 is drawn last. Layer position -1 is a synonym for the first - * layer position (the logical "bottom"). + *
+ *
Internal Component Index:
+ *
An offset into the component array held in our ancestor, + * address@hidden java.awt.Container}, from [0 .. component.length). The drawing + * rule with internal indices is that 0 is drawn first.
+ * + *
External Component Index:
+ *
An offset into the "logical drawing order" of this container. If I + * is the internal index of a component, the external index E = + * component.length - I. The rule with external indices is that 0 is + * drawn last.
+ * + *
Layer Number:
+ *
A general int specifying a layer within this component. Negative + * numbers are drawn first, then layer 0, then positive numbered layers, in + * ascending order.
+ * + *
Position:
+ *
An offset into a layer's "logical drawing order". Layer position 0 + * is drawn last. Layer position -1 is a synonym for the first layer + * position (the logical "bottom").
+ * + * @author Graydon Hoare */ public class JLayeredPane extends JComponent implements Accessible @@ -94,6 +109,21 @@ TreeMap layers; // Layer Number (Integer) -> Layer Size (Integer) Hashtable componentToLayer; // Component -> Layer Number (Integer) + JLayeredPane() + { + layers = new TreeMap (); + componentToLayer = new Hashtable (); + } + + + /** + * Looks up the layer a child component is currently assigned to. + * + * @param c the component to look up. + * @return the layer the component is currently assigned to, in this container. + * @throws IllegalArgumentException if the component is not a child of this container. + */ + protected Integer getLayer (Component c) { if (! componentToLayer.containsKey (c)) @@ -101,10 +131,20 @@ return (Integer) componentToLayer.get (c); } - // this returns a half-open range [bottom, top), which is the range of - // internal component indices this layer number corresponds to. note - // that top is *not* included in the range of component indices in this - // layer: a layer with 0 elements in it has ret[0] == ret[1]. + /** + * Returns a pair of ints representing a half-open interval + * [bottom, top), which is the range of internal component + * indices the provided layer number corresponds to. + * + * Note that "top" is not included in the interval of + * component indices in this layer: a layer with 0 elements in it has + * ret[0] == ret[1]. + * + * @param layer the layer to look up. + * @return the half-open range of internal indices this layer spans. + * @throws IllegalArgumentException if layer does not refer to an active layer + * in this container. + */ protected int[] layerToRange (Integer layer) { @@ -129,6 +169,13 @@ throw new IllegalArgumentException (); } + /** + * Increments the recorded size of a given layer. + * + * @param layer the layer number to increment. + * @see #incrLayer() + */ + protected void incrLayer(Integer layer) { int sz = 1; @@ -137,6 +184,13 @@ layers.put (layer, new Integer(sz)); } + /** + * Decrements the recorded size of a given layer. + * + * @param layer the layer number to decrement. + * @see #decrLayer() + */ + protected void decrLayer(Integer layer) { int sz = 0; @@ -145,18 +199,13 @@ layers.put (layer, new Integer(sz)); } - JLayeredPane() - { - layers = new TreeMap (); - layers.put (FRAME_CONTENT_LAYER, new Integer (0)); - layers.put (DEFAULT_LAYER, new Integer (0)); - layers.put (PALETTE_LAYER, new Integer (0)); - layers.put (MODAL_LAYER, new Integer (0)); - layers.put (POPUP_LAYER, new Integer (0)); - layers.put (DRAG_LAYER, new Integer (0)); - - componentToLayer = new Hashtable (); - } + /** + * Return the greatest layer number currently in use, in this container. + * This number may legally be positive or negative. + * + * @return the least layer number. + * @see #lowestLayer() + */ public int highestLayer() { @@ -165,6 +214,14 @@ return ((Integer)(layers.lastKey ())).intValue (); } + /** + * Return the least layer number currently in use, in this container. + * This number may legally be positive or negative. + * + * @return the least layer number. + * @see #highestLayer() + */ + public int lowestLayer() { if (layers.size() == 0) @@ -172,16 +229,54 @@ return ((Integer)(layers.firstKey ())).intValue (); } + /** + * Moves a component to the "front" of its layer. The "front" is a + * synonym for position 0, which is also the last position drawn in each + * layer, so is usually the component which occludes the most other + * components in its layer. + * + * @param c the component to move to the front of its layer. + * @throws IllegalArgumentException if the component is not a child of + * this container. + * @see #moveToBack() + */ + public void moveToFront(Component c) { setPosition (c, 0); } + /** + *

Moves a component to the "back" of its layer. The "back" is a + * synonym for position N-1 (also known as position -1), where N is the + * size of the layer.

+ * + *

The "back" of a layer is the first position drawn, so the component at + * the "back" is usually the component which is occluded by the most + * other components in its layer.

+ * + * @param c the component to move to the back of its layer. + * @throws IllegalArgumentException if the component is not a child of + * this container. + * @see #moveToFront() + */ + public void moveToBack(Component c) { setPosition (c, -1); } + /** + * Return the position of a component within its layer. Positions are assigned + * from the "front" (position 0) to the "back" (position N-1), and drawn from + * the back towards the front. + * + * @param c the component to get the position of. + * @throws IllegalArgumentException if the component is not a child of + * this container. + * @see #setPosition() + */ + public int getPosition(Component c) { Integer layer = getLayer (c); @@ -197,6 +292,18 @@ throw new IllegalArgumentException (); } + /** + * Change the position of a component within its layer. Positions are assigned + * from the "front" (position 0) to the "back" (position N-1), and drawn from + * the back towards the front. + * + * @param c the component to change the position of. + * @param position the position to assign the component to. + * @throws IllegalArgumentException if the component is not a child of + * this container. + * @see #getPosition() + */ + public void setPosition(Component c, int position) { Integer layer = getLayer (c); @@ -223,15 +330,19 @@ // should have found it throw new IllegalArgumentException (); - // System.err.println("set component position to " + position + " in layer " + layer); - - Component tmp = comps[curr]; - super.remove (curr); - super.add (tmp, targ); - super.validate (); + super.swapComponents (curr, targ); + validate(); + repaint(); } - + /** + * Return an array of all components within a layer of this + * container. Components are ordered back-to-front, with the "back" + * element (which draws first) at position 0 of the returned array. + * + * @param layer the layer to return components from. + * @return the components in the layer. + */ public Component[] getComponentsInLayer(int layer) { @@ -249,20 +360,46 @@ } } + /** + * Return the number of components within a layer of this + * container. + * + * @param layer the layer count components in. + * @return the number of components in the layer. + */ + public int getComponentCountInLayer(int layer) { int[] range = layerToRange (getObjectForLayer (layer)); if (range[0] == range[1]) return 0; else - return ((range[1] - 1) - range[0]); + return (range[1] - range[0]); } + /** + * Return a hashtable mapping child components of this container to + * Integer objects representing the component's layer assignments. + */ + protected Hashtable getComponentToLayer() { return componentToLayer; } + + /** + * Return the index of a component within the underlying (contiguous) + * array of children. This is a "raw" number which does not represent the + * child's position in a layer, but rather its position in the + * concatenation of all layers within the container. + * + * @param c the component to look up. + * @return the internal index of the component. + * @throws IllegalArgumentException if the component is not a child of + * this container. + */ + protected int getInternalIndexOf(Component c) { Integer layer = getLayer (c); @@ -278,6 +415,18 @@ } + /** + * Return the external index of a component within the underlying + * (contiguous) array of children. This is a "raw" number which does not + * represent the child's position in a layer, but rather its position in + * the logical drawing order of all children of the container. + * + * @param c the component to look up. + * @return the external index of the component. + * @throws IllegalArgumentException if the component is not a child of + * this container. + */ + public int getIndexOf(Component c) { // returns the *external* index of the component. @@ -285,6 +434,14 @@ return top - getIndexOf (c); } + /** + * Return an Integer object which holds the same int value as the + * parameter. This is strictly an optimization to minimize the number of + * identical Integer objects which we allocate. + * + * @param layer the layer number as an int. + * @return the layer number as an Integer, possibly shared. + */ protected Integer getObjectForLayer(int layer) { @@ -315,9 +472,23 @@ return new Integer(layer); } + /** + * Computes an internal index at which to request the superclass address@hidden + * java.awt.Container} inserts a component, given an abstract layer and + * position number. + * + * @param layer the layer in which to insert a component. + * @param position the position in the layer at which to insert a component. + * @return the internal index at which to insert the component. + */ + protected int insertIndexForLayer(int layer, int position) { - int[] range = layerToRange (getObjectForLayer (layer)); + + Integer lobj = getObjectForLayer (layer); + if (! layers.containsKey(lobj)) + layers.put (lobj, new Integer (0)); + int[] range = layerToRange (lobj); if (range[0] == range[1]) return range[0]; @@ -330,6 +501,13 @@ return top - position; } + /** + * Removes a child from this container. The child is specified by + * internal index. After removal, the child no longer occupies a layer. + * + * @param index the internal index of the child component to remove. + */ + public void remove (int index) { Component c = getComponent (index); @@ -339,35 +517,64 @@ super.remove (index); } + /** + * Removes a child from this container. The child is specified directly. + * After removal, the child no longer occupies a layer. + * + * @param comp the child to remove. + */ + public void remove (Component comp) { - Integer layer = getLayer (comp); - decrLayer (layer); - componentToLayer.remove (comp); - super.remove (comp); + remove (getInternalIndexOf (comp)); } - public void removeAll () - { - componentToLayer.clear (); - layers.clear (); - super.removeAll (); - } + /** + *

Set the layer property for a component, within this container. The + * component will be implicitly mapped to the bottom-most position in the + * layer, but only if added after calling this method.

+ * + *

Read that carefully: this method should be called before the + * component is added to the container.

+ * + * @param c the component to set the layer property for. + * @param layer the layer number to assign to the component. + */ public void setLayer(Component c, int layer) { componentToLayer.put (c, getObjectForLayer (layer)); } + /** + * Set the layer and position of a component, within this container. + * + * @param c the child component to set the layer property for. + * @param layer the layer number to assign to the component. + * @param position the position number to assign to the component. + */ + public void setLayer(Component c, int layer, int position) { componentToLayer.put (c, getObjectForLayer (layer)); setPosition(c, position); + validate(); repaint(); } + /** + * Overrides the default implementation from address@hidden java.awt.Container} + * such that layerConstraint is interpreted as an address@hidden + * Integer}, specifying the layer to which the component will be added + * (at the bottom position). + * + * @param comp the component to add. + * @param layerConstraint an integer specifying the layer to add the component to. + * @param index an ignored parameter, for compatibility. + */ + protected void addImpl(Component comp, Object layerConstraint, int index) { Integer layer; @@ -382,8 +589,6 @@ componentToLayer.put (comp, layer); incrLayer (layer); - // System.err.println("adding component to layer " + layer); - super.addImpl(comp, null, newIdx); validate(); repaint();