a0687c1fbc
2003-12-19 Thomas Fitzsimmons <fitzsim@redhat.com> * java/awt/FlowLayout.java (layoutContainer): Let components assume their preferred height. Centre components vertically. From-SVN: r74844
362 lines
9.8 KiB
Java
362 lines
9.8 KiB
Java
// FlowLayout.java - Grid-based layout engine
|
|
|
|
/* Copyright (C) 1999, 2000, 2001, 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.io.Serializable;
|
|
|
|
/** This class implements a flow-based layout. Components are laid
|
|
* out in order from left to right. When a component cannot be placed
|
|
* without horizontal clipping, a new row is started. This class
|
|
* supports horizontal and vertical gaps. These are used for spacing
|
|
* between components.
|
|
*
|
|
* @author Tom Tromey <tromey@redhat.com>
|
|
* @author Aaron M. Renn (arenn@urbanophile.com)
|
|
*/
|
|
public class FlowLayout implements LayoutManager, Serializable
|
|
{
|
|
/** Constant that specifies left alignment. */
|
|
public static final int LEFT = 0;
|
|
/** Constant that specifies center alignment. */
|
|
public static final int CENTER = 1;
|
|
/** Constant that specifies right alignment. */
|
|
public static final int RIGHT = 2;
|
|
|
|
/** Constant that specifies alignment to leading edge of container's
|
|
* orientation. */
|
|
public static final int LEADING = 3;
|
|
/** Constant that specifies alignment to trailing edge of container's
|
|
* orientation. */
|
|
public static final int TRAILING = 4;
|
|
|
|
// Serialization constant
|
|
private static final long serialVersionUID = -7262534875583282631L;
|
|
|
|
/** Add a new component to the layout. This particular implementation
|
|
* does nothing.
|
|
*/
|
|
public void addLayoutComponent (String name, Component comp)
|
|
{
|
|
// Nothing.
|
|
}
|
|
|
|
/**
|
|
* Returns the current justification value for this object.
|
|
*
|
|
* @return The current justification value for this object.
|
|
*/
|
|
public int getAlignment ()
|
|
{
|
|
return align;
|
|
}
|
|
|
|
/**
|
|
* Returns the horizontal gap between components.
|
|
*
|
|
* @return The horizontal gap between components.
|
|
*/
|
|
public int getHgap ()
|
|
{
|
|
return hgap;
|
|
}
|
|
|
|
/**
|
|
* Returns the vertical gap between lines of components.
|
|
*
|
|
* @return The vertical gap between lines of components.
|
|
*/
|
|
public int getVgap ()
|
|
{
|
|
return vgap;
|
|
}
|
|
|
|
/**
|
|
* Initializes a new instance of <code>FlowLayout</code> with a center
|
|
* justification and a default horizontal and vertical gap of 5.
|
|
*/
|
|
public FlowLayout ()
|
|
{
|
|
this (CENTER, 5, 5);
|
|
}
|
|
|
|
/**
|
|
* Initializes a new instance of <code>FlowLayout</code> with the specified
|
|
* justification and a default horizontal and vertical gap of 5.
|
|
*
|
|
* @param align The justification setting, which should be one of the
|
|
* contants in this class.
|
|
*/
|
|
public FlowLayout (int align)
|
|
{
|
|
this (align, 5, 5);
|
|
}
|
|
|
|
/**
|
|
* Initializes a new instance of <code>FlowLayout</code> with the specified
|
|
* justification and gap values
|
|
* @param align Alignment
|
|
* @param hgap The horizontal gap
|
|
* @param vgap The vertical gap
|
|
* @exception IllegalArgumentException If either gap is negative
|
|
*/
|
|
public FlowLayout (int align, int hgap, int vgap)
|
|
{
|
|
// Use methods to set fields so that we can have all the checking
|
|
// in one place.
|
|
setVgap (vgap);
|
|
setHgap (hgap);
|
|
setAlignment (align);
|
|
}
|
|
|
|
/** Lay out the container's components based on current settings.
|
|
* @param parent The parent container
|
|
*/
|
|
public void layoutContainer (Container parent)
|
|
{
|
|
synchronized (parent.getTreeLock ())
|
|
{
|
|
int num = parent.getComponentCount ();
|
|
// This is more efficient than calling getComponents().
|
|
Component[] comps = parent.component;
|
|
|
|
Dimension d = parent.getSize ();
|
|
Insets ins = parent.getInsets ();
|
|
|
|
ComponentOrientation orient = parent.getComponentOrientation ();
|
|
boolean left_to_right = orient.isLeftToRight ();
|
|
|
|
int y = ins.top + vgap;
|
|
int i = 0;
|
|
while (i < num)
|
|
{
|
|
// Find the components which go in the current row.
|
|
int new_w = ins.left + hgap + ins.right;
|
|
int new_h = 0;
|
|
int j;
|
|
boolean found_one = false;
|
|
for (j = i; j < num; ++j)
|
|
{
|
|
// Skip invisible items.
|
|
if (! comps[j].visible)
|
|
continue;
|
|
|
|
Dimension c = comps[j].getPreferredSize ();
|
|
|
|
int next_w = new_w + hgap + c.width;
|
|
if (next_w <= d.width || ! found_one)
|
|
{
|
|
new_w = next_w;
|
|
new_h = Math.max (new_h, c.height);
|
|
found_one = true;
|
|
}
|
|
else
|
|
{
|
|
// Must start a new row, and we already found an item
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Set the location of each component for this row.
|
|
int x;
|
|
|
|
int myalign = align;
|
|
if (align == LEADING)
|
|
myalign = left_to_right ? LEFT : RIGHT;
|
|
else if (align == TRAILING)
|
|
myalign = left_to_right ? RIGHT : LEFT;
|
|
|
|
if (myalign == LEFT)
|
|
x = ins.left + hgap;
|
|
else if (myalign == CENTER)
|
|
x = ins.left + (d.width - new_w) / 2 + hgap;
|
|
else
|
|
x = ins.left + (d.width - new_w) + hgap;
|
|
|
|
for (int k = i; k < j; ++k)
|
|
{
|
|
if (comps[k].visible)
|
|
{
|
|
Dimension c = comps[k].getPreferredSize ();
|
|
comps[k].setBounds (x, y + (new_h - c.height) / 2,
|
|
c.width, c.height);
|
|
x += c.width + hgap;
|
|
}
|
|
}
|
|
|
|
// Advance to next row.
|
|
i = j;
|
|
y += new_h + vgap;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the minimum layout size for the specified container using
|
|
* this layout.
|
|
* @param cont The parent container
|
|
* @return The minimum layout size.
|
|
*/
|
|
public Dimension minimumLayoutSize (Container cont)
|
|
{
|
|
return getSize (cont, true);
|
|
}
|
|
|
|
/**
|
|
* Returns the preferred layout size for the specified container using
|
|
* this layout.
|
|
* @param cont The parent container
|
|
* @return The preferred layout size.
|
|
*/
|
|
public Dimension preferredLayoutSize (Container cont)
|
|
{
|
|
return getSize (cont, false);
|
|
}
|
|
|
|
/** Remove the indicated component from this layout manager.
|
|
* This particular implementation does nothing.
|
|
* @param comp The component to remove
|
|
*/
|
|
public void removeLayoutComponent (Component comp)
|
|
{
|
|
// Nothing.
|
|
}
|
|
|
|
/**
|
|
* Sets the justification value for this object to the specified value.
|
|
*
|
|
* @param align The new justification value for this object, which must
|
|
* be one of the constants in this class.
|
|
*/
|
|
public void setAlignment (int align)
|
|
{
|
|
if (align != LEFT && align != RIGHT && align != CENTER
|
|
&& align != LEADING && align != TRAILING)
|
|
throw new IllegalArgumentException ("invalid alignment: " + align);
|
|
this.align = align;
|
|
}
|
|
|
|
/**
|
|
* Sets the horizontal gap between components to the specified value.
|
|
*
|
|
* @param hgap The new horizontal gap between components.
|
|
*/
|
|
public void setHgap (int hgap)
|
|
{
|
|
if (hgap < 0)
|
|
throw new IllegalArgumentException ("horizontal gap must be nonnegative");
|
|
this.hgap = hgap;
|
|
}
|
|
|
|
/**
|
|
* Sets the vertical gap between lines of components to the specified value.
|
|
*
|
|
* @param vgap The new vertical gap.
|
|
*/
|
|
public void setVgap (int vgap)
|
|
{
|
|
if (vgap < 0)
|
|
throw new IllegalArgumentException ("vertical gap must be nonnegative");
|
|
this.vgap = vgap;
|
|
}
|
|
|
|
/** Return String description of this object.
|
|
* @return A string representation of this object.
|
|
*/
|
|
public String toString ()
|
|
{
|
|
return ("[" + getClass ().getName () + ",hgap=" + hgap + ",vgap=" + vgap
|
|
+ ",align=" + align + "]");
|
|
}
|
|
|
|
// This method is used to compute the various sizes.
|
|
private Dimension getSize (Container parent, boolean is_min)
|
|
{
|
|
synchronized (parent.getTreeLock ())
|
|
{
|
|
int w, h, num = parent.getComponentCount ();
|
|
// This is more efficient than calling getComponents().
|
|
Component[] comps = parent.component;
|
|
|
|
w = 0;
|
|
h = 0;
|
|
for (int i = 0; i < num; ++i)
|
|
{
|
|
if (! comps[i].visible)
|
|
continue;
|
|
|
|
// FIXME: can we just directly read the fields in Component?
|
|
// Or will that not work with subclassing?
|
|
Dimension d;
|
|
|
|
if (is_min)
|
|
d = comps[i].getMinimumSize ();
|
|
else
|
|
d = comps[i].getPreferredSize ();
|
|
|
|
w += d.width;
|
|
h = Math.max (d.height, h);
|
|
}
|
|
|
|
Insets ins = parent.getInsets ();
|
|
|
|
w += (num + 1) * hgap + ins.left + ins.right;
|
|
h += 2 * vgap + ins.top + ins.bottom;
|
|
|
|
return new Dimension (w, h);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @serial The justification alignment of the lines of components, which
|
|
* will be one of the constants defined in this class.
|
|
*/
|
|
private int align;
|
|
|
|
/**
|
|
* @serial The horizontal gap between components.
|
|
*/
|
|
private int hgap;
|
|
|
|
/**
|
|
* @serial The vertical gap between lines of components.
|
|
*/
|
|
private int vgap;
|
|
}
|