/*
* @(#)GridBagLayout.java 1.64 04/06/08
*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package java.awt;
import java.util.Hashtable;
import java.util.Vector;
class GridBagLayoutInfo implements java.io.Serializable {
int width, height; /* number of cells horizontally, vertically */
int startx, starty; /* starting point for layout */
int minWidth[]; /* largest minWidth in each column */
int minHeight[]; /* largest minHeight in each row */
double weightX[]; /* largest weight in each column */
double weightY[]; /* largest weight in each row */
GridBagLayoutInfo () {
/* fix for 5055696 (avoiding AIOOBE by enlarging sizes) */
minWidth = new int[GridBagLayout.MAXGRIDSIZE];
minHeight = new int[GridBagLayout.MAXGRIDSIZE];
weightX = new double[GridBagLayout.MAXGRIDSIZE];
weightY = new double[GridBagLayout.MAXGRIDSIZE];
}
}
/**
* The GridBagLayout
class is a flexible layout
* manager that aligns components vertically and horizontally,
* without requiring that the components be of the same size.
* Each GridBagLayout
object maintains a dynamic,
* rectangular grid of cells, with each component occupying
* one or more cells, called its display area.
*
* Each component managed by a GridBagLayout
is associated with
* an instance of {@link GridBagConstraints}. The constraints object
* specifies where a component's display area should be located on the grid
* and how the component should be positioned within its display area. In
* addition to its constraints object, the GridBagLayout
also
* considers each component's minimum and preferred sizes in order to
* determine a component's size.
*
* The overall orientation of the grid depends on the container's * {@link ComponentOrientation} property. For horizontal left-to-right * orientations, grid coordinate (0,0) is in the upper left corner of the * container with x increasing to the right and y increasing downward. For * horizontal right-to-left orientations, grid coordinate (0,0) is in the upper * right corner of the container with x increasing to the left and y * increasing downward. *
* To use a grid bag layout effectively, you must customize one or more
* of the GridBagConstraints
objects that are associated
* with its components. You customize a GridBagConstraints
* object by setting one or more of its instance variables:
*
*
gridx = 0
,
* gridy = 0
. For horizontal left-to-right layout,
* a component's leading corner is its upper left. For horizontal
* right-to-left layout, a component's leading corner is its upper right.
* Use GridBagConstraints.RELATIVE
(the default value)
* to specify that the component be placed immediately following
* (along the x axis for gridx
or the y axis for
* gridy
) the component that was added to the container
* just before this component was added.
* gridwidth
)
* or column (for gridheight
)
* in the component's display area.
* The default value is 1.
* Use GridBagConstraints.REMAINDER
to specify
* that the component's display area will be from gridx
* to the last cell in the row (for gridwidth
)
* or from gridy
to the last cell in the column
* (for gridheight
).
*
* Use GridBagConstraints.RELATIVE
to specify
* that the component's display area will be from gridx
* to the next to the last cell in its row (for gridwidth
* or from gridy
to the next to the last cell in its
* column (for gridheight
).
*
* GridBagConstraints.NONE
(the default),
* GridBagConstraints.HORIZONTAL
* (make the component wide enough to fill its display area
* horizontally, but don't change its height),
* GridBagConstraints.VERTICAL
* (make the component tall enough to fill its display area
* vertically, but don't change its width), and
* GridBagConstraints.BOTH
* (make the component fill its display area entirely).
* ipadx
pixels. Similarly, the height of
* the component will be at least the minimum height plus
* ipady
pixels.
* ComponentOrientation
property while absolute values
* are not. Valid values are:*
Absolute Values |
* Relative Values |
*
---|---|
* GridBagConstraints.NORTH GridBagConstraints.SOUTH GridBagConstraints.WEST GridBagConstraints.EAST GridBagConstraints.NORTHWEST GridBagConstraints.NORTHEAST GridBagConstraints.SOUTHWEST GridBagConstraints.SOUTHEAST GridBagConstraints.CENTER (the default) |
*
* GridBagConstraints.PAGE_START GridBagConstraints.PAGE_END GridBagConstraints.LINE_START GridBagConstraints.LINE_END GridBagConstraints.FIRST_LINE_START GridBagConstraints.FIRST_LINE_END GridBagConstraints.LAST_LINE_START GridBagConstraints.LAST_LINE_END |
*
*
weightx
) and column (weighty
),
* all the components clump together in the center of their container.
* This is because when the weight is zero (the default),
* the GridBagLayout
object puts any extra space
* between its grid of cells and the edges of the container.
* * The following figures show ten components (all buttons) * managed by a grid bag layout. Figure 1 shows the layout for a horizontal, * left-to-right container and Figure 2 shows the layout for a horizontal, * right-to-left container. *
*
* * | ** * | *
Figure 1: Horizontal, Left-to-Right | *Figure 2: Horizontal, Right-to-Left | *
* Each of the ten components has the fill
field
* of its associated GridBagConstraints
object
* set to GridBagConstraints.BOTH
.
* In addition, the components have the following non-default constraints:
*
*
weightx = 1.0
* weightx = 1.0
,
* gridwidth = GridBagConstraints.REMAINDER
* gridwidth = GridBagConstraints.REMAINDER
* gridwidth = GridBagConstraints.RELATIVE
* gridwidth = GridBagConstraints.REMAINDER
* gridheight = 2
,
* weighty = 1.0
* gridwidth = GridBagConstraints.REMAINDER
* * Here is the code that implements the example shown above: *
*
* import java.awt.*; * import java.util.*; * import java.applet.Applet; * * public class GridBagEx1 extends Applet { * * protected void makebutton(String name, * GridBagLayout gridbag, * GridBagConstraints c) { * Button button = new Button(name); * gridbag.setConstraints(button, c); * add(button); * } * * public void init() { * GridBagLayout gridbag = new GridBagLayout(); * GridBagConstraints c = new GridBagConstraints(); * * setFont(new Font("SansSerif", Font.PLAIN, 14)); * setLayout(gridbag); * * c.fill = GridBagConstraints.BOTH; * c.weightx = 1.0; * makebutton("Button1", gridbag, c); * makebutton("Button2", gridbag, c); * makebutton("Button3", gridbag, c); * * c.gridwidth = GridBagConstraints.REMAINDER; //end row * makebutton("Button4", gridbag, c); * * c.weightx = 0.0; //reset to the default * makebutton("Button5", gridbag, c); //another row * * c.gridwidth = GridBagConstraints.RELATIVE; //next-to-last in row * makebutton("Button6", gridbag, c); * * c.gridwidth = GridBagConstraints.REMAINDER; //end row * makebutton("Button7", gridbag, c); * * c.gridwidth = 1; //reset to the default * c.gridheight = 2; * c.weighty = 1.0; * makebutton("Button8", gridbag, c); * * c.weighty = 0.0; //reset to the default * c.gridwidth = GridBagConstraints.REMAINDER; //end row * c.gridheight = 1; //reset to the default * makebutton("Button9", gridbag, c); * makebutton("Button10", gridbag, c); * * setSize(300, 100); * } * * public static void main(String args[]) { * Frame f = new Frame("GridBag Layout Example"); * GridBagEx1 ex1 = new GridBagEx1(); * * ex1.init(); * * f.add("Center", ex1); * f.pack(); * f.setSize(f.getPreferredSize()); * f.show(); * } * } *
* @version 1.64, 06/08/04
* @author Doug Stein
* @see java.awt.GridBagConstraints
* @see java.awt.ComponentOrientation
* @since JDK1.0
*/
public class GridBagLayout implements LayoutManager2,
java.io.Serializable {
/* Maximum number of grid positions */
protected static final int MAXGRIDSIZE = 512;
/**
* The smallest grid that can be laid out by the grid bag layout.
*/
protected static final int MINSIZE = 1;
/**
* The preferred grid size that can be laid out by the grid bag layout.
*/
protected static final int PREFERREDSIZE = 2;
/**
* This hashtable maintains the association between
* a component and its gridbag constraints.
* The Keys in
* If
* Most applications do not call this method directly.
* @return an array of two arrays, containing the widths
* of the layout columns and
* the heights of the layout rows
* @since JDK1.1
*/
public int [][] getLayoutDimensions () {
if (layoutInfo == null)
return new int[2][0];
int dim[][] = new int [2][];
dim[0] = new int[layoutInfo.width];
dim[1] = new int[layoutInfo.height];
System.arraycopy(layoutInfo.minWidth, 0, dim[0], 0, layoutInfo.width);
System.arraycopy(layoutInfo.minHeight, 0, dim[1], 0, layoutInfo.height);
return dim;
}
/**
* Determines the weights of the layout grid's columns and rows.
* Weights are used to calculate how much a given column or row
* stretches beyond its preferred size, if the layout has extra
* room to fill.
*
* Most applications do not call this method directly.
* @return an array of two arrays, representing the
* horizontal weights of the layout columns
* and the vertical weights of the layout rows
* @since JDK1.1
*/
public double [][] getLayoutWeights () {
if (layoutInfo == null)
return new double[2][0];
double weights[][] = new double [2][];
weights[0] = new double[layoutInfo.width];
weights[1] = new double[layoutInfo.height];
System.arraycopy(layoutInfo.weightX, 0, weights[0], 0, layoutInfo.width);
System.arraycopy(layoutInfo.weightY, 0, weights[1], 0, layoutInfo.height);
return weights;
}
/**
* Determines which cell in the layout grid contains the point
* specified by
* If the
* Most applications do not call this method directly.
* @param comp the component to be removed.
* @see java.awt.Container#remove(java.awt.Component)
* @see java.awt.Container#removeAll()
*/
public void removeLayoutComponent(Component comp) {
removeConstraints(comp);
}
/**
* Determines the preferred size of the
* Most applications do not call this method directly.
*
* @param parent the container in which to do the layout
* @see java.awt.Container#getPreferredSize
* @return the preferred size of the
* Most applications do not call this method directly.
* @param parent the container in which to do the layout
* @see java.awt.Container#doLayout
* @return the minimum size of the
* @return the value
* @return the value
* Most applications do not call this method directly.
* @param parent the container in which to do the layout
* @see java.awt.Container
* @see java.awt.Container#doLayout
*/
public void layoutContainer(Container parent) {
arrangeGrid(parent);
}
/**
* Returns a string representation of this grid bag layout's values.
* @return a string representation of this grid bag layout.
*/
public String toString() {
return getClass().getName();
}
/**
* Print the layout information. Useful for debugging.
*/
/* DEBUG
*
* protected void dumpLayoutInfo(GridBagLayoutInfo s) {
* int x;
*
* System.out.println("Col\tWidth\tWeight");
* for (x=0; x
* This method should only be used internally by
* comptable
are the components and the
* values are the instances of GridBagConstraints
.
*
* @serial
* @see java.awt.GridBagConstraints
*/
protected HashtabledefaultConstraints
.
*
* @serial
* @see #getConstraints(Component)
* @see #setConstraints(Component, GridBagConstraints)
* @see #lookupConstraints(Component)
*/
protected GridBagConstraints defaultConstraints;
/**
* This field holds the layout information
* for the gridbag. The information in this field
* is based on the most recent validation of the
* gridbag.
* If layoutInfo
is null
* this indicates that there are no components in
* the gridbag or if there are components, they have
* not yet been validated.
*
* @serial
* @see #getLayoutInfo(Container, int)
*/
protected GridBagLayoutInfo layoutInfo;
/**
* This field holds the overrides to the column minimum
* width. If this field is non-null
the values are
* applied to the gridbag after all of the minimum columns
* widths have been calculated.
* If columnWidths has more elements than the number of
* columns, columns are added to the gridbag to match
* the number of elements in columnWidth.
*
* @serial
* @see #getLayoutDimensions()
*/
public int columnWidths[];
/**
* This field holds the overrides to the row minimum
* heights. If this field is non-null the values are
* applied to the gridbag after all of the minimum row
* heights have been calculated.
* If rowHeights
has more elements than the number of
* rows, rowa are added to the gridbag to match
* the number of elements in rowHeights
.
*
* @serial
* @see #getLayoutDimensions()
*/
public int rowHeights[];
/**
* This field holds the overrides to the column weights.
* If this field is non-null
the values are
* applied to the gridbag after all of the columns
* weights have been calculated.
* If columnWeights[i]
> weight for column i, then
* column i is assigned the weight in columnWeights[i]
.
* If columnWeights
has more elements than the number
* of columns, the excess elements are ignored - they do
* not cause more columns to be created.
*
* @serial
*/
public double columnWeights[];
/**
* This field holds the overrides to the row weights.
* If this field is non-null the values are
* applied to the gridbag after all of the rows
* weights have been calculated.
* If rowWeights[i]
> weight for row i, then
* row i is assigned the weight in rowWeights[i]
.
* If rowWeights
has more elements than the number
* of rows, the excess elements are ignored - they do
* not cause more rows to be created.
*
* @serial
*/
public double rowWeights[];
/**
* Creates a grid bag layout manager.
*/
public GridBagLayout () {
comptable = new HashtableGridBagConstraints
object is returned.
* @param comp the component to be queried
* @return the constraint for the specified component in this
* grid bag layout; a copy of the actual constraint
* object is returned
*/
public GridBagConstraints getConstraints(Component comp) {
GridBagConstraints constraints = comptable.get(comp);
if (constraints == null) {
setConstraints(comp, defaultConstraints);
constraints = comptable.get(comp);
}
return (GridBagConstraints)constraints.clone();
}
/**
* Retrieves the constraints for the specified component.
* The return value is not a copy, but is the actual
* GridBagConstraints
object used by the layout mechanism.
* comp
is not in the GridBagLayout
,
* a set of default GridBagConstraints
are returned.
* A comp
value of null
is invalid
* and returns null
.
*
* @param comp the component to be queried
* @return the contraints for the specified component
*/
protected GridBagConstraints lookupConstraints(Component comp) {
GridBagConstraints constraints = comptable.get(comp);
if (constraints == null) {
setConstraints(comp, defaultConstraints);
constraints = comptable.get(comp);
}
return constraints;
}
/**
* Removes the constraints for the specified component in this layout
* @param comp the component to be modified
*/
private void removeConstraints(Component comp) {
comptable.remove(comp);
}
/**
* Determines the origin of the layout area, in the graphics coordinate
* space of the target container. This value represents the pixel
* coordinates of the top-left corner of the layout area regardless of
* the ComponentOrientation
value of the container. This
* is distinct from the grid origin given by the cell coordinates (0,0).
* Most applications do not call this method directly.
* @return the graphics origin of the cell in the top-left
* corner of the layout grid
* @see java.awt.ComponentOrientation
* @since JDK1.1
*/
public Point getLayoutOrigin () {
Point origin = new Point(0,0);
if (layoutInfo != null) {
origin.x = layoutInfo.startx;
origin.y = layoutInfo.starty;
}
return origin;
}
/**
* Determines column widths and row heights for the layout grid.
* (x, y)
. Each cell is identified
* by its column index (ranging from 0 to the number of columns
* minus 1) and its row index (ranging from 0 to the number of
* rows minus 1).
* (x, y)
point lies
* outside the grid, the following rules are used.
* The column index is returned as zero if x
lies to the
* left of the layout for a left-to-right container or to the right of
* the layout for a right-to-left container. The column index is returned
* as the number of columns if x
lies
* to the right of the layout in a left-to-right container or to the left
* in a right-to-left container.
* The row index is returned as zero if y
lies above the
* layout, and as the number of rows if y
lies
* below the layout. The orientation of a container is determined by its
* ComponentOrientation
property.
* @param x the x coordinate of a point
* @param y the y coordinate of a point
* @return an ordered pair of indexes that indicate which cell
* in the layout grid contains the point
* (x, y).
* @see java.awt.ComponentOrientation
* @since JDK1.1
*/
public Point location(int x, int y) {
Point loc = new Point(0,0);
int i, d;
if (layoutInfo == null)
return loc;
d = layoutInfo.startx;
if (!rightToLeft) {
for (i=0; iconstraints
object. Note that constraints
* are mutable and are, therefore, cloned when cached.
*
* @param comp the component to be added
* @param constraints an object that determines how
* the component is added to the layout
* @exception IllegalArgumentException if constraints
* is not a GridBagConstraint
*/
public void addLayoutComponent(Component comp, Object constraints) {
if (constraints instanceof GridBagConstraints) {
setConstraints(comp, (GridBagConstraints)constraints);
} else if (constraints != null) {
throw new IllegalArgumentException("cannot add to layout: constraints must be a GridBagConstraint");
}
}
/**
* Removes the specified component from this layout.
* parent
* container using this grid bag layout.
* parent
* container
*/
public Dimension preferredLayoutSize(Container parent) {
GridBagLayoutInfo info = getLayoutInfo(parent, PREFERREDSIZE);
return getMinSize(parent, info);
}
/**
* Determines the minimum size of the parent
container
* using this grid bag layout.
* parent
container
*/
public Dimension minimumLayoutSize(Container parent) {
GridBagLayoutInfo info = getLayoutInfo(parent, MINSIZE);
return getMinSize(parent, info);
}
/**
* Returns the maximum dimensions for this layout given the components
* in the specified target container.
* @param target the container which needs to be laid out
* @see Container
* @see #minimumLayoutSize(Container)
* @see #preferredLayoutSize(Container)
* @return the maximum dimensions for this layout
*/
public Dimension maximumLayoutSize(Container target) {
return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
}
/**
* Returns the alignment along the x axis. This specifies how
* the component would like to be aligned relative to other
* components. The value should be a number between 0 and 1
* where 0 represents alignment along the origin, 1 is aligned
* the furthest away from the origin, 0.5 is centered, etc.
* 0.5f
to indicate centered
*/
public float getLayoutAlignmentX(Container parent) {
return 0.5f;
}
/**
* Returns the alignment along the y axis. This specifies how
* the component would like to be aligned relative to other
* components. The value should be a number between 0 and 1
* where 0 represents alignment along the origin, 1 is aligned
* the furthest away from the origin, 0.5 is centered, etc.
* 0.5f
to indicate centered
*/
public float getLayoutAlignmentY(Container parent) {
return 0.5f;
}
/**
* Invalidates the layout, indicating that if the layout manager
* has cached information it should be discarded.
*/
public void invalidateLayout(Container target) {
}
/**
* Lays out the specified container using this grid bag layout.
* This method reshapes components in the specified container in
* order to satisfy the contraints of this GridBagLayout
* object.
*
*
*
* This also caches the minsizes for all the children when they are
* first encountered (so subsequent loops don't need to ask again).
* GridBagLayout
.
*
* @param parent the layout container
* @param sizeflag either PREFERREDSIZE
or
* MINSIZE
* @return the GridBagLayoutInfo
for the set of children
* @since 1.4
*/
protected GridBagLayoutInfo getLayoutInfo(Container parent, int sizeflag) {
return GetLayoutInfo(parent, sizeflag);
}
/**
* This method is obsolete and supplied for backwards
* compatability only; new code should call {@link
* #getLayoutInfo(java.awt.Container, int) getLayoutInfo} instead.
* This method is the same as getLayoutInfo
;
* refer to getLayoutInfo
for details on parameters
* and return value.
*/
protected GridBagLayoutInfo GetLayoutInfo(Container parent, int sizeflag) {
synchronized (parent.getTreeLock()) {
GridBagLayoutInfo r = new GridBagLayoutInfo();
Component comp;
GridBagConstraints constraints;
Dimension d;
Component components[] = parent.getComponents();
int compindex, i, j, k, px, py, pixels_diff, nextSize;
int curX, curY, curWidth, curHeight, curRow, curCol;
double weight_diff, weight, start, size;
int xMax[], yMax[];
/*
* Pass #1
*
* Figure out the dimensions of the layout grid (use a value of 1 for
* zero or negative widths and heights).
*/
r.width = r.height = 0;
curRow = curCol = -1;
xMax = new int[MAXGRIDSIZE];
yMax = new int[MAXGRIDSIZE];
for (compindex = 0 ; compindex < components.length ; compindex++) {
comp = components[compindex];
if (!comp.isVisible())
continue;
constraints = lookupConstraints(comp);
curX = constraints.gridx;
curY = constraints.gridy;
curWidth = constraints.gridwidth;
if (curWidth <= 0)
curWidth = 1;
curHeight = constraints.gridheight;
if (curHeight <= 0)
curHeight = 1;
/* If x or y is negative, then use relative positioning: */
if (curX < 0 && curY < 0) {
if (curRow >= 0)
curY = curRow;
else if (curCol >= 0)
curX = curCol;
else
curY = 0;
}
if (curX < 0) {
px = 0;
for (i = curY; i < (curY + curHeight); i++) {
px = Math.max(px, xMax[i]);
}
curX = px - curX - 1;
if(curX < 0)
curX = 0;
}
else if (curY < 0) {
py = 0;
for (i = curX; i < (curX + curWidth); i++) {
py = Math.max(py, yMax[i]);
}
curY = py - curY - 1;
if(curY < 0)
curY = 0;
}
/* Adjust the grid width and height */
for (px = curX + curWidth; r.width < px; r.width++);
for (py = curY + curHeight; r.height < py; r.height++);
/* Adjust xMax and yMax */
for (i = curX; i < (curX + curWidth); i++) {
yMax[i] = py;
}
for (i = curY; i < (curY + curHeight); i++) {
xMax[i] = px;
}
/* Cache the current slave's size. */
if (sizeflag == PREFERREDSIZE)
d = comp.getPreferredSize();
else
d = comp.getMinimumSize();
constraints.minWidth = d.width;
constraints.minHeight = d.height;
/* Zero width and height must mean that this is the last item (or
* else something is wrong). */
if (constraints.gridheight == 0 && constraints.gridwidth == 0)
curRow = curCol = -1;
/* Zero width starts a new row */
if (constraints.gridheight == 0 && curRow < 0)
curCol = curX + curWidth;
/* Zero height starts a new column */
else if (constraints.gridwidth == 0 && curCol < 0)
curRow = curY + curHeight;
}
/*
* Apply minimum row/column dimensions
*/
if (columnWidths != null && r.width < columnWidths.length)
r.width = columnWidths.length;
if (rowHeights != null && r.height < rowHeights.length)
r.height = rowHeights.length;
/*
* Pass #2
*
* Negative values for gridX are filled in with the current x value.
* Negative values for gridY are filled in with the current y value.
* Negative or zero values for gridWidth and gridHeight end the current
* row or column, respectively.
*/
curRow = curCol = -1;
xMax = new int[MAXGRIDSIZE];
yMax = new int[MAXGRIDSIZE];
for (compindex = 0 ; compindex < components.length ; compindex++) {
comp = components[compindex];
if (!comp.isVisible())
continue;
constraints = lookupConstraints(comp);
curX = constraints.gridx;
curY = constraints.gridy;
curWidth = constraints.gridwidth;
curHeight = constraints.gridheight;
/* If x or y is negative, then use relative positioning: */
if (curX < 0 && curY < 0) {
if(curRow >= 0)
curY = curRow;
else if(curCol >= 0)
curX = curCol;
else
curY = 0;
}
if (curX < 0) {
if (curHeight <= 0) {
curHeight += r.height - curY;
if (curHeight < 1)
curHeight = 1;
}
px = 0;
for (i = curY; i < (curY + curHeight); i++)
px = Math.max(px, xMax[i]);
curX = px - curX - 1;
if(curX < 0)
curX = 0;
}
else if (curY < 0) {
if (curWidth <= 0) {
curWidth += r.width - curX;
if (curWidth < 1)
curWidth = 1;
}
py = 0;
for (i = curX; i < (curX + curWidth); i++)
py = Math.max(py, yMax[i]);
curY = py - curY - 1;
if(curY < 0)
curY = 0;
}
if (curWidth <= 0) {
curWidth += r.width - curX;
if (curWidth < 1)
curWidth = 1;
}
if (curHeight <= 0) {
curHeight += r.height - curY;
if (curHeight < 1)
curHeight = 1;
}
px = curX + curWidth;
py = curY + curHeight;
for (i = curX; i < (curX + curWidth); i++) { yMax[i] = py; }
for (i = curY; i < (curY + curHeight); i++) { xMax[i] = px; }
/* Make negative sizes start a new row/column */
if (constraints.gridheight == 0 && constraints.gridwidth == 0)
curRow = curCol = -1;
if (constraints.gridheight == 0 && curRow < 0)
curCol = curX + curWidth;
else if (constraints.gridwidth == 0 && curCol < 0)
curRow = curY + curHeight;
/* Assign the new values to the gridbag slave */
constraints.tempX = curX;
constraints.tempY = curY;
constraints.tempWidth = curWidth;
constraints.tempHeight = curHeight;
}
/*
* Apply minimum row/column dimensions and weights
*/
if (columnWidths != null)
System.arraycopy(columnWidths, 0, r.minWidth, 0, columnWidths.length);
if (rowHeights != null)
System.arraycopy(rowHeights, 0, r.minHeight, 0, rowHeights.length);
if (columnWeights != null)
System.arraycopy(columnWeights, 0, r.weightX, 0, Math.min(r.weightX.length, columnWeights.length));
if (rowWeights != null)
System.arraycopy(rowWeights, 0, r.weightY, 0, Math.min(r.weightY.length, rowWeights.length));
/*
* Pass #3
*
* Distribute the minimun widths and weights:
*/
nextSize = Integer.MAX_VALUE;
for (i = 1;
i != Integer.MAX_VALUE;
i = nextSize, nextSize = Integer.MAX_VALUE) {
for (compindex = 0 ; compindex < components.length ; compindex++) {
comp = components[compindex];
if (!comp.isVisible())
continue;
constraints = lookupConstraints(comp);
if (constraints.tempWidth == i) {
px = constraints.tempX + constraints.tempWidth; /* right column */
/*
* Figure out if we should use this slave\'s weight. If the weight
* is less than the total weight spanned by the width of the cell,
* then discard the weight. Otherwise split the difference
* according to the existing weights.
*/
weight_diff = constraints.weightx;
for (k = constraints.tempX; k < px; k++)
weight_diff -= r.weightX[k];
if (weight_diff > 0.0) {
weight = 0.0;
for (k = constraints.tempX; k < px; k++)
weight += r.weightX[k];
for (k = constraints.tempX; weight > 0.0 && k < px; k++) {
double wt = r.weightX[k];
double dx = (wt * weight_diff) / weight;
r.weightX[k] += dx;
weight_diff -= dx;
weight -= wt;
}
/* Assign the remainder to the rightmost cell */
r.weightX[px-1] += weight_diff;
}
/*
* Calculate the minWidth array values.
* First, figure out how wide the current slave needs to be.
* Then, see if it will fit within the current minWidth values.
* If it will not fit, add the difference according to the
* weightX array.
*/
pixels_diff =
constraints.minWidth + constraints.ipadx +
constraints.insets.left + constraints.insets.right;
for (k = constraints.tempX; k < px; k++)
pixels_diff -= r.minWidth[k];
if (pixels_diff > 0) {
weight = 0.0;
for (k = constraints.tempX; k < px; k++)
weight += r.weightX[k];
for (k = constraints.tempX; weight > 0.0 && k < px; k++) {
double wt = r.weightX[k];
int dx = (int)((wt * ((double)pixels_diff)) / weight);
r.minWidth[k] += dx;
pixels_diff -= dx;
weight -= wt;
}
/* Any leftovers go into the rightmost cell */
r.minWidth[px-1] += pixels_diff;
}
}
else if (constraints.tempWidth > i && constraints.tempWidth < nextSize)
nextSize = constraints.tempWidth;
if (constraints.tempHeight == i) {
py = constraints.tempY + constraints.tempHeight; /* bottom row */
/*
* Figure out if we should use this slave's weight. If the weight
* is less than the total weight spanned by the height of the cell,
* then discard the weight. Otherwise split it the difference
* according to the existing weights.
*/
weight_diff = constraints.weighty;
for (k = constraints.tempY; k < py; k++)
weight_diff -= r.weightY[k];
if (weight_diff > 0.0) {
weight = 0.0;
for (k = constraints.tempY; k < py; k++)
weight += r.weightY[k];
for (k = constraints.tempY; weight > 0.0 && k < py; k++) {
double wt = r.weightY[k];
double dy = (wt * weight_diff) / weight;
r.weightY[k] += dy;
weight_diff -= dy;
weight -= wt;
}
/* Assign the remainder to the bottom cell */
r.weightY[py-1] += weight_diff;
}
/*
* Calculate the minHeight array values.
* First, figure out how tall the current slave needs to be.
* Then, see if it will fit within the current minHeight values.
* If it will not fit, add the difference according to the
* weightY array.
*/
pixels_diff =
constraints.minHeight + constraints.ipady +
constraints.insets.top + constraints.insets.bottom;
for (k = constraints.tempY; k < py; k++)
pixels_diff -= r.minHeight[k];
if (pixels_diff > 0) {
weight = 0.0;
for (k = constraints.tempY; k < py; k++)
weight += r.weightY[k];
for (k = constraints.tempY; weight > 0.0 && k < py; k++) {
double wt = r.weightY[k];
int dy = (int)((wt * ((double)pixels_diff)) / weight);
r.minHeight[k] += dy;
pixels_diff -= dy;
weight -= wt;
}
/* Any leftovers go into the bottom cell */
r.minHeight[py-1] += pixels_diff;
}
}
else if (constraints.tempHeight > i &&
constraints.tempHeight < nextSize)
nextSize = constraints.tempHeight;
}
}
return r;
}
}
/**
* Adjusts the x, y, width, and height fields to the correct
* values depending on the constraint geometry and pads.
* This method should only be used internally by
* GridBagLayout
.
*
* @param constraints the constraints to be applied
* @param r the Rectangle
to be adjusted
* @since 1.4
*/
protected void adjustForGravity(GridBagConstraints constraints,
Rectangle r) {
AdjustForGravity(constraints, r);
}
/**
* This method is obsolete and supplied for backwards
* compatability only; new code should call {@link
* #adjustForGravity(java.awt.GridBagConstraints, java.awt.Rectangle)
* adjustForGravity} instead.
* This method is the same as adjustForGravity
;
* refer to adjustForGravity
for details
* on parameters.
*/
protected void AdjustForGravity(GridBagConstraints constraints,
Rectangle r) {
int diffx, diffy;
if (!rightToLeft) {
r.x += constraints.insets.left;
} else {
r.x -= r.width - constraints.insets.right;
}
r.width -= (constraints.insets.left + constraints.insets.right);
r.y += constraints.insets.top;
r.height -= (constraints.insets.top + constraints.insets.bottom);
diffx = 0;
if ((constraints.fill != GridBagConstraints.HORIZONTAL &&
constraints.fill != GridBagConstraints.BOTH)
&& (r.width > (constraints.minWidth + constraints.ipadx))) {
diffx = r.width - (constraints.minWidth + constraints.ipadx);
r.width = constraints.minWidth + constraints.ipadx;
}
diffy = 0;
if ((constraints.fill != GridBagConstraints.VERTICAL &&
constraints.fill != GridBagConstraints.BOTH)
&& (r.height > (constraints.minHeight + constraints.ipady))) {
diffy = r.height - (constraints.minHeight + constraints.ipady);
r.height = constraints.minHeight + constraints.ipady;
}
switch (constraints.anchor) {
case GridBagConstraints.CENTER:
r.x += diffx/2;
r.y += diffy/2;
break;
case GridBagConstraints.PAGE_START:
case GridBagConstraints.NORTH:
r.x += diffx/2;
break;
case GridBagConstraints.NORTHEAST:
r.x += diffx;
break;
case GridBagConstraints.EAST:
r.x += diffx;
r.y += diffy/2;
break;
case GridBagConstraints.SOUTHEAST:
r.x += diffx;
r.y += diffy;
break;
case GridBagConstraints.PAGE_END:
case GridBagConstraints.SOUTH:
r.x += diffx/2;
r.y += diffy;
break;
case GridBagConstraints.SOUTHWEST:
r.y += diffy;
break;
case GridBagConstraints.WEST:
r.y += diffy/2;
break;
case GridBagConstraints.NORTHWEST:
break;
case GridBagConstraints.LINE_START:
if (rightToLeft) {
r.x += diffx;
}
r.y += diffy/2;
break;
case GridBagConstraints.LINE_END:
if (!rightToLeft) {
r.x += diffx;
}
r.y += diffy/2;
break;
case GridBagConstraints.FIRST_LINE_START:
if (rightToLeft) {
r.x += diffx;
}
break;
case GridBagConstraints.FIRST_LINE_END:
if (!rightToLeft) {
r.x += diffx;
}
break;
case GridBagConstraints.LAST_LINE_START:
if (rightToLeft) {
r.x += diffx;
}
r.y += diffy;
break;
case GridBagConstraints.LAST_LINE_END:
if (!rightToLeft) {
r.x += diffx;
}
r.y += diffy;
break;
default:
throw new IllegalArgumentException("illegal anchor value");
}
}
/**
* Figures out the minimum size of the
* master based on the information from getLayoutInfo
.
* This method should only be used internally by
* GridBagLayout
.
*
* @param parent the layout container
* @param info the layout info for this parent
* @return a Dimension
object containing the
* minimum size
* @since 1.4
*/
protected Dimension getMinSize(Container parent, GridBagLayoutInfo info) {
return GetMinSize(parent, info);
}
/**
* This method is obsolete and supplied for backwards
* compatability only; new code should call {@link
* #getMinSize(java.awt.Container, GridBagLayoutInfo) getMinSize} instead.
* This method is the same as getMinSize
;
* refer to getMinSize
for details on parameters
* and return value.
*/
protected Dimension GetMinSize(Container parent, GridBagLayoutInfo info) {
Dimension d = new Dimension();
int i, t;
Insets insets = parent.getInsets();
t = 0;
for(i = 0; i < info.width; i++)
t += info.minWidth[i];
d.width = t + insets.left + insets.right;
t = 0;
for(i = 0; i < info.height; i++)
t += info.minHeight[i];
d.height = t + insets.top + insets.bottom;
return d;
}
transient boolean rightToLeft = false;
/**
* Lays out the grid.
* This method should only be used internally by
* GridBagLayout
.
*
* @param parent the layout container
* @since 1.4
*/
protected void arrangeGrid(Container parent) {
ArrangeGrid(parent);
}
/**
* This method is obsolete and supplied for backwards
* compatability only; new code should call {@link
* #arrangeGrid(Container) arrangeGrid} instead.
* This method is the same as arrangeGrid
;
* refer to arrangeGrid
for details on the
* parameter.
*/
protected void ArrangeGrid(Container parent) {
Component comp;
int compindex;
GridBagConstraints constraints;
Insets insets = parent.getInsets();
Component components[] = parent.getComponents();
Dimension d;
Rectangle r = new Rectangle();
int i, diffw, diffh;
double weight;
GridBagLayoutInfo info;
rightToLeft = !parent.getComponentOrientation().isLeftToRight();
/*
* If the parent has no slaves anymore, then don't do anything
* at all: just leave the parent's size as-is.
*/
if (components.length == 0 &&
(columnWidths == null || columnWidths.length == 0) &&
(rowHeights == null || rowHeights.length == 0)) {
return;
}
/*
* Pass #1: scan all the slaves to figure out the total amount
* of space needed.
*/
info = getLayoutInfo(parent, PREFERREDSIZE);
d = getMinSize(parent, info);
if (parent.width < d.width || parent.height < d.height) {
info = getLayoutInfo(parent, MINSIZE);
d = getMinSize(parent, info);
}
layoutInfo = info;
r.width = d.width;
r.height = d.height;
/*
* DEBUG
*
* DumpLayoutInfo(info);
* for (compindex = 0 ; compindex < components.length ; compindex++) {
* comp = components[compindex];
* if (!comp.isVisible())
* continue;
* constraints = lookupConstraints(comp);
* DumpConstraints(constraints);
* }
* System.out.println("minSize " + r.width + " " + r.height);
*/
/*
* If the current dimensions of the window don't match the desired
* dimensions, then adjust the minWidth and minHeight arrays
* according to the weights.
*/
diffw = parent.width - r.width;
if (diffw != 0) {
weight = 0.0;
for (i = 0; i < info.width; i++)
weight += info.weightX[i];
if (weight > 0.0) {
for (i = 0; i < info.width; i++) {
int dx = (int)(( ((double)diffw) * info.weightX[i]) / weight);
info.minWidth[i] += dx;
r.width += dx;
if (info.minWidth[i] < 0) {
r.width -= info.minWidth[i];
info.minWidth[i] = 0;
}
}
}
diffw = parent.width - r.width;
}
else {
diffw = 0;
}
diffh = parent.height - r.height;
if (diffh != 0) {
weight = 0.0;
for (i = 0; i < info.height; i++)
weight += info.weightY[i];
if (weight > 0.0) {
for (i = 0; i < info.height; i++) {
int dy = (int)(( ((double)diffh) * info.weightY[i]) / weight);
info.minHeight[i] += dy;
r.height += dy;
if (info.minHeight[i] < 0) {
r.height -= info.minHeight[i];
info.minHeight[i] = 0;
}
}
}
diffh = parent.height - r.height;
}
else {
diffh = 0;
}
/*
* DEBUG
*
* System.out.println("Re-adjusted:");
* DumpLayoutInfo(info);
*/
/*
* Now do the actual layout of the slaves using the layout information
* that has been collected.
*/
info.startx = diffw/2 + insets.left;
info.starty = diffh/2 + insets.top;
for (compindex = 0 ; compindex < components.length ; compindex++) {
comp = components[compindex];
if (!comp.isVisible())
continue;
constraints = lookupConstraints(comp);
if (!rightToLeft) {
r.x = info.startx;
for(i = 0; i < constraints.tempX; i++)
r.x += info.minWidth[i];
} else {
r.x = parent.width - (diffw/2 + insets.right);
for(i = 0; i < constraints.tempX; i++)
r.x -= info.minWidth[i];
}
r.y = info.starty;
for(i = 0; i < constraints.tempY; i++)
r.y += info.minHeight[i];
r.width = 0;
for(i = constraints.tempX;
i < (constraints.tempX + constraints.tempWidth);
i++) {
r.width += info.minWidth[i];
}
r.height = 0;
for(i = constraints.tempY;
i < (constraints.tempY + constraints.tempHeight);
i++) {
r.height += info.minHeight[i];
}
adjustForGravity(constraints, r);
/* fix for 4408108 - components were being created outside of the container */
/* fix for 4969409 "-" replaced by "+" */
if (r.x < 0) {
r.width += r.x;
r.x = 0;
}
if (r.y < 0) {
r.height += r.y;
r.y = 0;
}
/*
* If the window is too small to be interesting then
* unmap it. Otherwise configure it and then make sure
* it's mapped.
*/
if ((r.width <= 0) || (r.height <= 0)) {
comp.setBounds(0, 0, 0, 0);
}
else {
if (comp.x != r.x || comp.y != r.y ||
comp.width != r.width || comp.height != r.height) {
comp.setBounds(r.x, r.y, r.width, r.height);
}
}
}
}
// Added for serial backwards compatability (4348425)
static final long serialVersionUID = 8838754796412211005L;
}