Index: javax/swing/SizeRequirements.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/SizeRequirements.java,v
retrieving revision 1.11
diff -u -r1.11 SizeRequirements.java
--- javax/swing/SizeRequirements.java 13 Sep 2005 10:23:50 -0000 1.11
+++ javax/swing/SizeRequirements.java 25 Sep 2005 10:11:14 -0000
@@ -166,7 +166,31 @@
public static SizeRequirements
getAlignedSizeRequirements(SizeRequirements[] children)
{
- return null; // TODO
+ float minLeft = 0;
+ float minRight = 0;
+ float prefLeft = 0;
+ float prefRight = 0;
+ float maxLeft = 0;
+ float maxRight = 0;
+ for (int i = 0; i < children.length; i++)
+ {
+ float myMinLeft = children[i].minimum * children[i].alignment;
+ float myMinRight = children[i].minimum - myMinLeft;
+ minLeft = Math.max(myMinLeft, minLeft);
+ minRight = Math.max(myMinRight, minRight);
+ float myPrefLeft = children[i].preferred * children[i].alignment;
+ float myPrefRight = children[i].preferred - myMinLeft;
+ prefLeft = Math.max(myPrefLeft, prefLeft);
+ prefRight = Math.max(myPrefRight, prefRight);
+ float myMaxLeft = children[i].maximum * children[i].alignment;
+ float myMaxRight = children[i].maximum - myMinLeft;
+ maxLeft = Math.max(myMaxLeft, maxLeft);
+ maxRight = Math.max(myMaxRight, maxRight);
+ }
+ int minSize = (int) (minLeft + minRight);
+ int prefSize = (int) (prefLeft + prefRight);
+ int maxSize = (int) (maxLeft + maxRight);
+ return new SizeRequirements(minSize, prefSize, maxSize, 0.5F);
}
/**
@@ -317,11 +341,24 @@
int[] offset, int[] spans,
boolean forward)
{
- // TODO: Implement this correctly.
- for (int i = 0; i < children.length; ++i)
+ // First we compute the position of the baseline.
+ float left = 0;
+ float right = 0;
+ for (int i = 0; i < children.length; i++)
+ {
+ float myLeft = children[i].preferred * children[i].alignment;
+ float myRight = children[i].preferred - myLeft;
+ left = Math.max(myLeft, left);
+ right = Math.max(myRight, right);
+ }
+ int baseline = (int) ((left / (left + right)) * allocated);
+ // Now we can layout the components along the baseline.
+ for (int i = 0; i < children.length; i++)
{
- // This is only a hack to make things work a little.
- spans[i] = Math.min(allocated, children[i].maximum);
+ // FIXME: Handle the case when span[i] results in exceeding
+ // the available space.
+ spans[i] = children[i].preferred;
+ offset[i] = baseline - (int) (children[i].alignment * ((float) spans[i]));
}
}
Index: javax/swing/BoxLayout.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/BoxLayout.java,v
retrieving revision 1.17
diff -u -r1.17 BoxLayout.java
--- javax/swing/BoxLayout.java 26 Jul 2005 15:30:54 -0000 1.17
+++ javax/swing/BoxLayout.java 25 Sep 2005 10:11:14 -0000
@@ -45,7 +45,6 @@
import java.awt.Insets;
import java.awt.LayoutManager2;
import java.io.Serializable;
-import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
@@ -63,248 +62,6 @@
{
/**
- * This is an abstraction that allows the BoxLayout algorithm to
- * be applied to both direction (X and Y) without duplicating the
- * algorithm. It defines several methods that access properties of
- * a component for a specific direction.
- */
- static interface Direction
- {
- /**
- * Returns the correct part of d
for this direction. This will
- * be d.width
for horizontal and d.height
for
- * vertical direction.
- *
- * @param d the size as Dimension object
- *
- * @return the correct part of d
for this direction
- */
- int size(Dimension d);
-
- /**
- * Returns the lower bounds of the address@hidden Insets} object according to this
- * direction. This will be insets.top
for vertical direction
- * and insets.left
for horizontal direction.
- *
- * @param the address@hidden Insets} object from which to return the lower bounds
- *
- * @return the lower bounds of the address@hidden Insets} object according to this
- * direction
- */
- int lower(Insets insets);
-
- /**
- * Returns the alignment property according to this direction.
- *
- * @param comp the Component for which to return the alignment property
- *
- * @return the alignment property according to this direction
- */
- float alignment(Component comp);
-
- /**
- * Sets the location for Component c
. coord1
- * specifies the coordinate of the location in this direction,
- * coord2
the coordinate of the location in the opposite
- * direction.
- *
- * @param c the Component for which to set the location
- * @param coord1 the coordinate in this direction
- * @param coord2 the coordinate in the opposite direction
- */
- void setLocation(Component c, int coord1, int coord2);
-
- /**
- * Sets the size for Component c
. coord1
- * specifies the size in this direction,
- * coord2
the size in the opposite
- * direction.
- *
- * @param c the Component for which to set the size
- * @param size1 the size in this direction
- * @param size2 the size in the opposite direction
- */
- void setSize(Component c, int size1, int size2);
- }
-
- /**
- * The horizontal direction.
- */
- static class Horizontal implements Direction
- {
- /**
- * Returns the correct part of d
for this direction. This will
- * be d.width
for horizontal and d.height
for
- * vertical direction.
- *
- * @param d the size as Dimension object
- *
- * @return the correct part of d
for this direction
- */
- public int size(Dimension d)
- {
- return d.width;
- }
-
- /**
- * Returns the lower bounds of the address@hidden Insets} object according to this
- * direction. This will be insets.top
for vertical direction
- * and insets.left
for horizontal direction.
- *
- * @param insets the address@hidden Insets} object from which to return the lower
- * bounds
- *
- * @return the lower bounds of the address@hidden Insets} object according to this
- * direction
- */
- public int lower(Insets insets)
- {
- return insets.left;
- }
-
- /**
- * Returns the alignment property according to this direction.
- *
- * @param comp the Component for which to return the alignment property
- *
- * @return the alignment property according to this direction
- */
- public float alignment(Component comp)
- {
- return comp.getAlignmentX();
- }
-
- /**
- * Sets the location for Component c
. coord1
- * specifies the coordinate of the location in this direction,
- * coord2
the coordinate of the location in the opposite
- * direction.
- *
- * @param c the Component for which to set the location
- * @param coord1 the coordinate in this direction
- * @param coord2 the coordinate in the opposite direction
- */
- public void setLocation(Component c, int coord1, int coord2)
- {
- c.setLocation(coord1, coord2);
- }
-
- /**
- * Sets the size for Component c
. coord1
- * specifies the size in this direction,
- * coord2
the size in the opposite
- * direction.
- *
- * @param c the Component for which to set the size
- * @param size1 the size in this direction
- * @param size2 the size in the opposite direction
- */
- public void setSize(Component c, int size1, int size2)
- {
- c.setSize(size1, size2);
- }
- }
- /**
- * The vertical direction.
- */
- static class Vertical implements Direction
- {
- /**
- * Returns the correct part of d
for this direction. This will
- * be d.width
for horizontal and d.height
for
- * vertical direction.
- *
- * @param d the size as Dimension object
- *
- * @return the correct part of d
for this direction
- */
- public int size(Dimension d)
- {
- return d.height;
- }
-
- /**
- * Returns the lower bounds of the address@hidden Insets} object according to this
- * direction. This will be insets.top
for vertical direction
- * and insets.left
for horizontal direction.
- *
- * @param insets the address@hidden Insets} object from which to return the lower
- * bounds
- *
- * @return the lower bounds of the address@hidden Insets} object according to this
- * direction
- */
- public int lower(Insets insets)
- {
- return insets.top;
- }
-
- /**
- * Returns the alignment property according to this direction.
- *
- * @param comp the Component for which to return the alignment property
- *
- * @return the alignment property according to this direction
- */
- public float alignment(Component comp)
- {
- return comp.getAlignmentY();
- }
-
- /**
- * Sets the location for Component c
. coord1
- * specifies the coordinate of the location in this direction,
- * coord2
the coordinate of the location in the opposite
- * direction.
- *
- * @param c the Component for which to set the location
- * @param coord1 the coordinate in this direction
- * @param coord2 the coordinate in the opposite direction
- */
- public void setLocation(Component c, int coord1, int coord2)
- {
- c.setLocation(coord2, coord1);
- }
-
- /**
- * Sets the size for Component c
. coord1
- * specifies the size in this direction,
- * coord2
the size in the opposite
- * direction.
- *
- * @param c the Component for which to set the size
- * @param size1 the size in this direction
- * @param size2 the size in the opposite direction
- */
- public void setSize(Component c, int size1, int size2)
- {
- c.setSize(size2, size1);
- }
- }
-
- /**
- * A helper class that temporarily stores the size specs of a component.
- */
- static class SizeReq
- {
- int size;
- int min;
- int pref;
- int max;
- float align;
- Component comp;
- SizeReq(Component comp, Direction dir)
- {
- this.min = dir.size(comp.getMinimumSize());
- this.pref = dir.size(comp.getPreferredSize());
- this.max = dir.size(comp.getMaximumSize());
- this.size = dir.size(comp.getSize());
- this.align = dir.alignment(comp);
- this.comp = comp;
- }
- }
-
- /**
* Specifies that components are laid out left to right.
*/
public static final int X_AXIS = 0;
@@ -339,12 +96,6 @@
*/
private int way = X_AXIS;
- /** Constant for the horizontal direction. */
- private static final Direction HORIZONTAL = new Horizontal();
-
- /** Constant for the vertical direction. */
- private static final Direction VERTICAL = new Vertical();
-
/**
* Constructs a BoxLayout
object.
*
@@ -404,42 +155,24 @@
if (parent != container)
throw new AWTError("invalid parent");
- Insets insets = parent.getInsets();
- int x = 0;
- int y = 0;
-
- List children = AWTUtilities.getVisibleChildren(parent);
-
- if (isHorizontalIn(parent))
- {
- x = insets.left + insets.right;
- // sum up preferred widths of components, find maximum of preferred
- // heights
- for (Iterator i = children.iterator(); i.hasNext();)
- {
- Component comp = (Component) i.next();
- Dimension sz = comp.getPreferredSize();
- x += sz.width;
- y = Math.max(y, sz.height);
- }
- y += insets.bottom + insets.top;
- }
- else
- {
- y = insets.top + insets.bottom;
- // sum up preferred heights of components, find maximum of
- // preferred widths
- for (Iterator i = children.iterator(); i.hasNext();)
- {
- Component comp = (Component) i.next();
- Dimension sz = comp.getPreferredSize();
- y += sz.height;
- x = Math.max(x, sz.width);
- }
- x += insets.left + insets.right;
+ // Setup the SizeRequirements for both the X and Y axis.
+ Component[] children = container.getComponents();
+ SizeRequirements[] hSizeReqs = new SizeRequirements[children.length];
+ SizeRequirements[] vSizeReqs = new SizeRequirements[children.length];
+ getSizeRequirements(hSizeReqs, vSizeReqs);
+ SizeRequirements hReq;
+ SizeRequirements vReq;
+ if (isHorizontalIn(container))
+ {
+ hReq = SizeRequirements.getTiledSizeRequirements(hSizeReqs);
+ vReq = SizeRequirements.getAlignedSizeRequirements(vSizeReqs);
}
-
- return new Dimension(x, y);
+ else
+ {
+ hReq = SizeRequirements.getAlignedSizeRequirements(hSizeReqs);
+ vReq = SizeRequirements.getTiledSizeRequirements(vSizeReqs);
+ }
+ return new Dimension(hReq.preferred, vReq.preferred);
}
/**
@@ -454,38 +187,24 @@
if (parent != container)
throw new AWTError("invalid parent");
- Insets insets = parent.getInsets();
- int x = insets.left + insets.right;
- int y = insets.bottom + insets.top;
-
- List children = AWTUtilities.getVisibleChildren(parent);
-
- if (isHorizontalIn(parent))
+ // Setup the SizeRequirements for both the X and Y axis.
+ Component[] children = container.getComponents();
+ SizeRequirements[] hSizeReqs = new SizeRequirements[children.length];
+ SizeRequirements[] vSizeReqs = new SizeRequirements[children.length];
+ getSizeRequirements(hSizeReqs, vSizeReqs);
+ SizeRequirements hReq;
+ SizeRequirements vReq;
+ if (isHorizontalIn(container))
{
- // sum up preferred widths of components, find maximum of preferred
- // heights
- for (Iterator i = children.iterator(); i.hasNext();)
- {
- Component comp = (Component) i.next();
- Dimension sz = comp.getMinimumSize();
- x += sz.width;
- y = Math.max(y, sz.height);
- }
+ hReq = SizeRequirements.getTiledSizeRequirements(hSizeReqs);
+ vReq = SizeRequirements.getAlignedSizeRequirements(vSizeReqs);
}
else
{
- // sum up preferred heights of components, find maximum of
- // preferred widths
- for (Iterator i = children.iterator(); i.hasNext();)
- {
- Component comp = (Component) i.next();
- Dimension sz = comp.getMinimumSize();
- y += sz.height;
- x = Math.max(x, sz.width);
- }
+ hReq = SizeRequirements.getAlignedSizeRequirements(hSizeReqs);
+ vReq = SizeRequirements.getTiledSizeRequirements(vSizeReqs);
}
-
- return new Dimension(x, y);
+ return new Dimension(hReq.minimum, vReq.minimum);
}
/**
@@ -495,10 +214,38 @@
*/
public void layoutContainer(Container parent)
{
- if (isHorizontalIn(parent))
- layoutAlgorithm(parent, HORIZONTAL, VERTICAL);
+ // Setup the SizeRequirements for both the X and Y axis.
+ Component[] children = container.getComponents();
+ SizeRequirements[] hSizeReqs = new SizeRequirements[children.length];
+ SizeRequirements[] vSizeReqs = new SizeRequirements[children.length];
+ getSizeRequirements(hSizeReqs, vSizeReqs);
+
+ int[] hSpans = new int[children.length];
+ int[] hOffsets = new int[children.length];
+ int[] vSpans = new int[children.length];
+ int[] vOffsets = new int[children.length];
+
+ if (isHorizontalIn(container))
+ {
+ SizeRequirements.calculateTiledPositions(container.getWidth(), null,
+ hSizeReqs, hOffsets, hSpans);
+ SizeRequirements.calculateAlignedPositions(container.getHeight(), null,
+ vSizeReqs, vOffsets, vSpans);
+ }
else
- layoutAlgorithm(parent, VERTICAL, HORIZONTAL);
+ {
+ SizeRequirements.calculateTiledPositions(container.getHeight(), null,
+ vSizeReqs, vOffsets, vSpans);
+ SizeRequirements.calculateAlignedPositions(container.getWidth(), null,
+ hSizeReqs, hOffsets, hSpans);
+ }
+
+ // Set positions and widths of child components.
+ for (int i = 0; i < children.length; i++)
+ {
+ Component child = children[i];
+ child.setBounds(hOffsets[i], vOffsets[i], hSpans[i], vSpans[i]);
+ }
}
/**
@@ -565,185 +312,61 @@
if (parent != container)
throw new AWTError("invalid parent");
- Insets insets = parent.getInsets();
- int x = insets.left + insets.right;
- int y = insets.top + insets.bottom;
-
- List children = AWTUtilities.getVisibleChildren(parent);
-
- if (isHorizontalIn(parent))
+ // Setup the SizeRequirements for both the X and Y axis.
+ Component[] children = container.getComponents();
+ SizeRequirements[] hSizeReqs = new SizeRequirements[children.length];
+ SizeRequirements[] vSizeReqs = new SizeRequirements[children.length];
+ getSizeRequirements(hSizeReqs, vSizeReqs);
+ SizeRequirements hReq;
+ SizeRequirements vReq;
+ if (isHorizontalIn(container))
{
-
- // sum up preferred widths of components, find maximum of preferred
- // heights
- for (Iterator i = children.iterator(); i.hasNext();)
- {
- Component comp = (Component) i.next();
- Dimension sz = comp.getMaximumSize();
- x += sz.width;
- // Check for overflow.
- if (x < 0)
- x = Integer.MAX_VALUE;
- y = Math.max(y, sz.height);
- }
+ hReq = SizeRequirements.getTiledSizeRequirements(hSizeReqs);
+ vReq = SizeRequirements.getAlignedSizeRequirements(vSizeReqs);
}
else
{
- // sum up preferred heights of components, find maximum of
- // preferred widths
- for (Iterator i = children.iterator(); i.hasNext();)
- {
- Component comp = (Component) i.next();
- Dimension sz = comp.getMaximumSize();
- y += sz.height;
- // Check for overflow
- if (y < 0)
- y = Integer.MAX_VALUE;
- x = Math.max(x, sz.width);
- }
- }
- return new Dimension(x, y);
+ hReq = SizeRequirements.getAlignedSizeRequirements(hSizeReqs);
+ vReq = SizeRequirements.getTiledSizeRequirements(vSizeReqs);
+ }
+ return new Dimension(hReq.maximum, vReq.maximum);
}
/**
- * Lays out the Container c
in the layout direction
- * layoutDir
. The direction that is crossing the layout
- * direction is specified in crossDir
.
+ * Fills arrays of SizeRequirements for the horizontal and vertical
+ * requirements of the children of component.
*
- * @param parent
- * @param layoutDir
- * @param crossDir
+ * @param hSizeReqs the horizontal requirements to be filled by this method
+ * @param vSizeReqs the vertical requirements to be filled by this method
*/
- void layoutAlgorithm(Container parent, Direction layoutDir, Direction crossDir)
+ private void getSizeRequirements(SizeRequirements[] hSizeReqs,
+ SizeRequirements[] vSizeReqs)
{
- if (parent != container)
- throw new AWTError("invalid parent");
-
- Dimension parentSize = parent.getSize();
- Insets insets = parent.getInsets();
- Dimension innerSize = new Dimension(parentSize.width - insets.left
- - insets.right, parentSize.height
- - insets.bottom - insets.top);
-
- // Set all components to their preferredSizes and sum up the allocated
- // space. Create SizeReqs for each component and store them in
- // sizeReqs. Find the maximum size in the crossing direction.
- List children = AWTUtilities.getVisibleChildren(parent);
- Vector sizeReqs = new Vector();
- int allocated = 0;
- for (Iterator i = children.iterator(); i.hasNext();)
+ Component[] children = container.getComponents();
+ for (int i = 0; i < children.length; i++)
{
- Component c = (Component) i.next();
- SizeReq sizeReq = new SizeReq(c, layoutDir);
- int preferred = layoutDir.size(c.getPreferredSize());
- sizeReq.size = preferred;
- allocated += preferred;
- sizeReqs.add(sizeReq);
- }
-
- // Distribute remaining space (may be positive or negative) over components
- int remainder = layoutDir.size(innerSize) - allocated;
- distributeSpace(sizeReqs, remainder, layoutDir);
-
- // Resize and relocate components. If the component can be sized to
- // take the full space in the crossing direction, then do so, otherwise
- // align according to its alingnmentX or alignmentY property.
- int loc = 0;
- int offset1 = layoutDir.lower(insets);
- int offset2 = crossDir.lower(insets);
- for (Iterator i = sizeReqs.iterator(); i.hasNext();)
- {
- SizeReq sizeReq = (SizeReq) i.next();
- Component c = sizeReq.comp;
- int availCrossSize = crossDir.size(innerSize);
- int maxCross = crossDir.size(c.getMaximumSize());
- int crossSize = Math.min(availCrossSize, maxCross);
- int crossRemainder = availCrossSize - crossSize;
- int crossLoc = (int) (crossDir.alignment(c) * crossRemainder);
- layoutDir.setSize(c, sizeReq.size, crossSize);
- layoutDir.setLocation(c, offset1 + loc, offset2 + crossLoc);
- loc += sizeReq.size;
- }
- }
-
- /**
- * Distributes some space over a set of components. This implementation
- * tries to set the components as close as possible to their
- * preferredSize
s, and respects the components
- * minimumSize
and maximumSize
.
- *
- * The algorithm is implemented as follows:
- *
- *
remainder
is divided by the number of components
- * in freeComponents
.minimumSize
or maximumSize
of a
- * component is exceeded, then this component is set to its
- * minimumSize
or maximumSize
, it is removed from
- * freeComponents
and the difference is added to a new
- * remainder.freeComponents.size() != 0
, then this method is called
- * recursivly to distribute the newly allocated remaining space.