/*
* NAME
* $RCSfile$ -
* DESCRIPTION
* [given below in javadoc format]
* DELTA
* $Revision: 11553 $
* CREATED
* $Date: 2007-06-05 15:06:23 -0700 (星期二, 05 六月 2007) $ by birgit
* COPYRIGHT
* West Consulting bv
* TO DO
*
*/
package tablelayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Point;
import java.util.Vector;
// Edit History
//
// 25Oct92 david Geometry management re-work
// 01Feb92 david Re-Implementation
/**
* TableLayout is a layout manager which allows components to be
* arranged
* in a tabular form. The TableLayout component has a layout
* resource which is used to specify the column and row position of each
* component. Components can span rows and/or columns. Layout options
* are available to control the initial sizes, justification, and dynamic
* resizing
*
* @author Birgit Arkesteijn
* @version $Revision: 11553 $ $Date: 2007-06-05 15:06:23 -0700 (星期二, 05 六月 2007) $
*/
public class TableLayout extends Object implements LayoutManager
{
private static final String version_id =
"@(#)$Id: TableLayout.java 11553 2007-06-05 22:06:23Z duns $ Copyright West Consulting bv";
boolean force_shrink; // Shrink smaller than pref'd
int col_spacing; // Space between columns
int row_spacing; // Space between rows
TableLoc layout; // Layout spec
// Lists of lists of components whose preferred dimensions
// should be considered to be the maximum of any individual named on the
// lists.
// Vector of Vector of Component
Vector same_width; // kids with same width
Vector same_height; // kids with same height
int margin_width;
int margin_height;
// internally computed members
TableCol cols; // Widths and opts of each col
TableRow rows; // Heights and opts of each row
/**
*
*/
public TableLayout()
{
layout = new TableLoc();
force_shrink = true;
col_spacing = 1;
row_spacing = 1;
same_width = new Vector();
same_height = new Vector();
margin_width = 0;
margin_height = 0;
cols = (TableCol)null;
rows = (TableRow)null;
}
/**
* Adds the specified component with the layout string to the layout
*
* @param layout represents the wanted layout of the component
* @param comp the component to be added
* @see tablelayout.TableLocRec
*/
public void addLayoutComponent(String name, Component comp)
{
try
{
TableLocRec rec = new TableLocRec(name);
layout.addElement(rec, comp);
}
catch(Exception e)
{
System.out.println("TableLayout: Syntax error in component: "
+ name);
return;
}
}
/**
* Removes the specified component from the layout
*
* @param comp the component to be removed
*/
public void removeLayoutComponent(Component comp)
{
layout.removeElement(comp);
}
/**
* Calculates the preferred size dimensions for the specified panel,
* given the components in the specified target container
*
* @param target the component to be laid out
*/
public Dimension preferredLayoutSize(Container target)
{
int nmembers = target.getComponentCount();
for (int i=0; i<nmembers; i++)
{
Component current = target.getComponent(i);
if (!current.isVisible()) continue;
TableLocRec rec = layout.element(current);
if (rec == null) continue;
rec.orig_width = current.getPreferredSize().width;
rec.orig_height = current.getPreferredSize().height;
rec.same_width = 0;
rec.same_height = 0;
}
considerSameWidth();
considerSameHeight();
cols = new TableCol(this);
rows = new TableRow(this);
int width = cols.getPreferredSize();
int height = rows.getPreferredSize();
// Is it the layout managers job to allow for the insets?
Insets insets = target.getInsets();
width += insets.left + insets.right;
height += insets.top + insets.bottom;
return new Dimension (width, height);
}
/**
* Calculates the minimum size dimensions for the specified panel,
* given the components in the specified target container
*
* @param target the component to be laid out
*/
public Dimension minimumLayoutSize(Container target)
{
int nmembers = target.getComponentCount();
for (int i=0; i<nmembers; i++)
{
Component current = target.getComponent(i);
if (!current.isVisible()) continue;
TableLocRec rec = layout.element(current);
if (rec == null) continue;
rec.orig_width = current.getPreferredSize().width;
rec.orig_height = current.getPreferredSize().height;
rec.same_width = 0;
rec.same_height = 0;
}
considerSameWidth();
considerSameHeight();
cols = new TableCol(this);
rows = new TableRow(this);
int width = cols.totalSize ();
int height = rows.totalSize ();
return new Dimension (width, height);
}
/**
* Lays out the container in the specified panel
*
* @param target the component to be laid out
*/
public void layoutContainer(Container target)
{
Dimension dim = target.getSize();
Insets insets = target.getInsets();
int nmembers = target.getComponentCount();
for (int i=0; i<nmembers; i++)
{
Component current = target.getComponent(i);
if (!current.isVisible()) continue;
TableLocRec rec = layout.element(current);
if (rec == null) continue;
current.doLayout();
rec.orig_width = current.getPreferredSize().width;
rec.orig_height = current.getPreferredSize().height;
rec.same_width = 0;
rec.same_height = 0;
}
considerSameWidth();
considerSameHeight();
cols = new TableCol(this);
rows = new TableRow(this);
cols.minimize();
rows.minimize();
tableMakeColsFitWidth(dim.width - insets.left - insets.right);
tableMakeRowsFitHeight(dim.height - insets.top - insets.bottom);
tableSetGeometryOfChildren(insets);
}
/**
* This resource is used to specify the names of components
* which will be constrained to remain the same width as
* the table shrinks and grows
*
* @param v the vector of component with the same width
*/
public void sameWidth(Vector v)
{
same_width.addElement(v);
}
/**
* This resource is used to specify the names of components
* which will be constrained to remain the same heigth as
* the table shrinks and grows
*
* @param v the vector of component with the same heigth
*/
public void sameHeight(Vector v)
{
same_height.addElement(v);
}
/**
* The minimum spacing between the left and right edges of the
* components in the Container
*
* @param i the spacing
*/
public void marginWidth(int i)
{
margin_width = i;
}
/**
* The minimum spacing between the top and bottom edges of the
* components in the Container
*
* @param i the spacing
*/
public void marginHeight(int i)
{
margin_height = i;
}
/**
* Specifies if components should be made smaller than their "preferred"
* sizes.
* The TableLayout component tries to respect the preferred geometries of
* its components.
*
* Components which are locked using options including any of
* "whWH" will continue to be excluded from
* stretching, but others will be
* stretched and then can be shrunk back to their initial preferred sizes
* from the time they were last managed.
* When the table is shrunk further, all
* components are shrunk an equal number of pixels until they are of size 1
* (the smallest legal size of a Components).
*
* By default, this resource is <em>true</em>.
* @param force boolean to indicate shrink should be forced
* @see tablelayout.TableOpts
*/
public void forceShrink(boolean force)
{
force_shrink = force;
}
/**
* Specifies the number of pixels between columns
*
* @param sp the spacing between columns
*/
public void columnSpacing(int sp)
{
col_spacing = sp;
}
/**
* Specifies the number of pixels between rows
*
* @param sp the spacing between rows
*/
public void rowSpacing(int sp)
{
row_spacing = sp;
}
private void considerSameWidth()
{
int nlist = same_width.size();
for (int ind1=0; ind1<nlist; ind1++)
{
Vector compv = (Vector) same_width.elementAt(ind1);
int max=0;
// find the maximum width
int ncomp = compv.size();
for (int ind2=0; ind2<ncomp; ind2++)
{
Component comp = (Component) compv.elementAt(ind2);
TableLocRec rec = layout.element(comp);
if (rec == null)
break;
if (rec.orig_width > max)
max = rec.orig_width;
}
// set the maximum width
for (int ind2=0; ind2<ncomp; ind2++)
{
Component comp = (Component) compv.elementAt(ind2);
TableLocRec rec = layout.element(comp);
if (rec == null)
break;
rec.same_width = max;
}
}
}
private void considerSameHeight()
{
int nlist = same_height.size();
for (int ind1=0; ind1<nlist; ind1++)
{
Vector compv = (Vector) same_height.elementAt(ind1);
int max=0;
// find the maximum height
int ncomp = compv.size();
for (int ind2=0; ind2<ncomp; ind2++)
{
Component comp = (Component) compv.elementAt(ind2);
TableLocRec rec = layout.element(comp);
if (rec == null)
break;
if (rec.orig_height > max)
max = rec.orig_height;
}
// find the maximum height
for (int ind2=0; ind2<ncomp; ind2++)
{
Component comp = (Component) compv.elementAt(ind2);
TableLocRec rec = layout.element(comp);
if (rec == null)
break;
rec.same_height = max;
}
}
}
private void tableMakeColsFitWidth(int width)
{
int change, current, prefer;
current = cols.totalSize ();
prefer = cols.getPreferredSize ();
if (width < prefer && force_shrink == false)
{
// Smallest size is preferred size. Excess clipped.
change = prefer - current;
}
else
{
change = width - current;
}
if (change != 0)
cols.adjust (change);
}
private void tableMakeRowsFitHeight(int height)
{
int change, current, prefer;
current = rows.totalSize ();
prefer = rows.getPreferredSize ();
if (height < prefer && force_shrink == false)
{
// Smallest size is preferred size. Excess clipped.
change = prefer - current;
}
else
{
change = height - current;
}
if (change != 0)
rows.adjust (change);
}
private void tableSetGeometryOfChildren (Insets insets)
{
TableLocRec rec;
Component comp;
int sz, index;
if (layout == (TableLoc)null
|| cols == (TableCol)null
|| rows == (TableRow)null)
return;
cols.computeOffsets(insets.left, col_spacing);
rows.computeOffsets(insets.top, row_spacing);
sz = layout.size();
for (index=0; index < sz; index++)
{
rec = layout.recElementAt(index);
comp = layout.compElementAt(index);
TableComputeChildPosition(rec, comp);
}
}
private void TableComputeChildPosition(TableLocRec rec, Component comp)
{
int cell_w, cell_h;
int cell_x, x;
int cell_y, y;
int width, prefer, height;
int i, pad;
// cell width may well span cols and spacing
pad = col_spacing;
cell_w = -pad;
for (i = 0; i < rec.col_span; i++)
cell_w += cols.elementAt(rec.col + i).value + pad;
// If size growth is prevented due to (W)
// then use the lesser of the cell size or the preferred size.
// Otherwise, use the cell size.
prefer = rec.preferredWidth();
if (rec.options.W && cell_w > prefer)
{
width = prefer;
}
else
{
width = cell_w;
}
// Be certain that the size does not go to zero, or negative!
if (width <= 0) width = 1;
pad = row_spacing;
cell_h = -pad;
for (i = 0; i < rec.row_span; i++)
cell_h += rows.elementAt(rec.row + i).value + pad;
prefer = rec.preferredHeight();
if (rec.options.H && cell_h > prefer)
{
height = prefer;
}
else
{
height = cell_h;
}
if (height <= 0) height = 1;
cell_x = cols.elementAt(rec.col).offset;
if (rec.options.l)
x = cell_x; // left justify in cell
else if (rec.options.r)
x = cell_x + cell_w - width; // right justify in cell
else
x = cell_x + (cell_w - width)/2; // center in cell
cell_y = rows.elementAt(rec.row).offset;
if (rec.options.t)
y = cell_y; // top justify in cell
else if (rec.options.b)
y = cell_y + cell_h - height; // bottom justify in cell
else
y = cell_y + (cell_h - height)/2; // center in cell
comp.setSize(width, height);
Point p = comp.getLocation();
if (x != p.x || y != p.y)
{
comp.setLocation(x, y);
}
}
/**
* Returns the String representation
*/
public String toString()
{
return (
"TableLayout [" +
"\nlayout: " + layout.toString() +
"\ncols: " + cols.toString() +
"\nrows: " + rows.toString() +
"\nsame_width: " + same_width.toString() +
"\nsame_height: " + same_height.toString() +
"\ncol_spacing: " + col_spacing +
"\nrow_spacing: " + row_spacing +
"\nforce_shrink: " + force_shrink +
"\nmargin_width: " + margin_width +
"\nmargin_height: " + margin_height +
" ]");
}
/**
* Creates a clone of the object. A new instance is allocated and all
* the variables of the class are cloned
*/
public Object clone()
{
TableLayout elem = new TableLayout();
elem.force_shrink = force_shrink;
elem.col_spacing = col_spacing;
elem.row_spacing = row_spacing;
elem.layout = (TableLoc) layout.clone();
elem.same_width = (Vector) same_width.clone();
elem.same_height = (Vector) same_height.clone();
elem.margin_width = margin_width;
elem.margin_height = margin_height;
elem.considerSameWidth();
elem.considerSameHeight();
elem.cols = new TableCol(this);
elem.rows = new TableRow(this);
return ((Object) elem);
}
}