diff options
Diffstat (limited to 'libjava/classpath/java/awt/GridBagLayout.java')
-rw-r--r-- | libjava/classpath/java/awt/GridBagLayout.java | 1069 |
1 files changed, 1069 insertions, 0 deletions
diff --git a/libjava/classpath/java/awt/GridBagLayout.java b/libjava/classpath/java/awt/GridBagLayout.java new file mode 100644 index 00000000000..767610c5693 --- /dev/null +++ b/libjava/classpath/java/awt/GridBagLayout.java @@ -0,0 +1,1069 @@ +/* GridBagLayout - Layout manager for components according to GridBagConstraints + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + +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., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 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; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Hashtable; + +/** + * @author Michael Koch (konqueror@gmx.de) + * @author Jeroen Frijters (jeroen@frijters.net) + */ +public class GridBagLayout + implements Serializable, LayoutManager2 +{ + private static final long serialVersionUID = 8838754796412211005L; + + protected static final int MINSIZE = 1; + protected static final int PREFERREDSIZE = 2; + protected static final int MAXGRIDSIZE = 512; + + // comptable remembers the original contraints given to us. + // internalcomptable is used to keep track of modified constraint values + // that we calculate, particularly when we are given RELATIVE and + // REMAINDER constraints. + // Constraints kept in comptable are never modified, and constraints + // kept in internalcomptable can be modified internally only. + protected Hashtable comptable; + private Hashtable internalcomptable; + protected GridBagLayoutInfo layoutInfo; + protected GridBagConstraints defaultConstraints; + + public double[] columnWeights; + public int[] columnWidths; + public double[] rowWeights; + public int[] rowHeights; + + public GridBagLayout () + { + this.comptable = new Hashtable(); + this.internalcomptable = new Hashtable(); + this.defaultConstraints= new GridBagConstraints(); + } + + /** + * Helper method to calc the sum of a range of elements in an int array. + */ + private int sumIntArray (int[] array, int upto) + { + int result = 0; + + for (int i = 0; i < upto; i++) + result += array [i]; + + return result; + } + + /** + * Helper method to calc the sum of all elements in an int array. + */ + private int sumIntArray (int[] array) + { + return sumIntArray(array, array.length); + } + + /** + * Helper method to calc the sum of all elements in an double array. + */ + private double sumDoubleArray (double[] array) + { + double result = 0; + + for (int i = 0; i < array.length; i++) + result += array [i]; + + return result; + } + + public void addLayoutComponent (String name, Component component) + { + // do nothing here. + } + + public void removeLayoutComponent (Component component) + { + // do nothing here + } + + public void addLayoutComponent (Component component, Object constraints) + { + if (constraints == null) + return; + + if (!(constraints instanceof GridBagConstraints)) + throw new IllegalArgumentException("constraints " + + constraints + + " are not an instance of GridBagConstraints"); + + setConstraints (component, (GridBagConstraints) constraints); + } + + public Dimension preferredLayoutSize (Container parent) + { + if (parent == null) + return new Dimension (0, 0); + + GridBagLayoutInfo li = getLayoutInfo (parent, PREFERREDSIZE); + return getMinSize (parent, li); + } + + public Dimension minimumLayoutSize (Container parent) + { + if (parent == null) + return new Dimension (0, 0); + + GridBagLayoutInfo li = getLayoutInfo (parent, MINSIZE); + return getMinSize (parent, li); + } + + public Dimension maximumLayoutSize (Container target) + { + return new Dimension (Integer.MAX_VALUE, Integer.MAX_VALUE); + } + + public void layoutContainer (Container parent) + { + arrangeGrid (parent); + } + + public float getLayoutAlignmentX (Container target) + { + return Component.CENTER_ALIGNMENT; + } + + public float getLayoutAlignmentY (Container target) + { + return Component.CENTER_ALIGNMENT; + } + + public void invalidateLayout (Container target) + { + this.layoutInfo = null; + } + + public void setConstraints (Component component, + GridBagConstraints constraints) + { + GridBagConstraints clone = (GridBagConstraints) constraints.clone(); + + if (clone.gridx < 0) + clone.gridx = GridBagConstraints.RELATIVE; + + if (clone.gridy < 0) + clone.gridy = GridBagConstraints.RELATIVE; + + if (clone.gridwidth == 0) + clone.gridwidth = GridBagConstraints.REMAINDER; + else if (clone.gridwidth < 0 + && clone.gridwidth != GridBagConstraints.REMAINDER + && clone.gridwidth != GridBagConstraints.RELATIVE) + clone.gridwidth = 1; + + if (clone.gridheight == 0) + clone.gridheight = GridBagConstraints.REMAINDER; + else if (clone.gridheight < 0 + && clone.gridheight != GridBagConstraints.REMAINDER + && clone.gridheight != GridBagConstraints.RELATIVE) + clone.gridheight = 1; + + comptable.put (component, clone); + } + + public GridBagConstraints getConstraints (Component component) + { + return (GridBagConstraints) (lookupConstraints (component).clone()); + } + + protected GridBagConstraints lookupConstraints (Component component) + { + GridBagConstraints result = (GridBagConstraints) comptable.get (component); + + if (result == null) + { + setConstraints (component, defaultConstraints); + result = (GridBagConstraints) comptable.get (component); + } + + return result; + } + + private GridBagConstraints lookupInternalConstraints (Component component) + { + GridBagConstraints result = + (GridBagConstraints) internalcomptable.get (component); + + if (result == null) + { + result = (GridBagConstraints) lookupConstraints(component).clone(); + internalcomptable.put (component, result); + } + + return result; + } + + /** + * @since 1.1 + */ + public Point getLayoutOrigin () + { + if (layoutInfo == null) + return new Point (0, 0); + + return new Point (layoutInfo.pos_x, layoutInfo.pos_y); + } + + /** + * @since 1.1 + */ + public int[][] getLayoutDimensions () + { + int[][] result = new int [2][]; + if (layoutInfo == null) + { + result[0] = new int[0]; + result[1] = new int[0]; + + return result; + } + + result [0] = new int [layoutInfo.cols]; + System.arraycopy (layoutInfo.colWidths, 0, result [0], 0, layoutInfo.cols); + result [1] = new int [layoutInfo.rows]; + System.arraycopy (layoutInfo.rowHeights, 0, result [1], 0, layoutInfo.rows); + return result; + } + + public double[][] getLayoutWeights () + { + double[][] result = new double [2][]; + if (layoutInfo == null) + { + result[0] = new double[0]; + result[1] = new double[0]; + + return result; + } + + result [0] = new double [layoutInfo.cols]; + System.arraycopy (layoutInfo.colWeights, 0, result [0], 0, layoutInfo.cols); + result [1] = new double [layoutInfo.rows]; + System.arraycopy (layoutInfo.rowWeights, 0, result [1], 0, layoutInfo.rows); + return result; + } + + /** + * @since 1.1 + */ + public Point location (int x, int y) + { + if (layoutInfo == null) + return new Point (0, 0); + + int col; + int row; + int pixel_x = layoutInfo.pos_x; + int pixel_y = layoutInfo.pos_y; + + for (col = 0; col < layoutInfo.cols; col++) + { + int w = layoutInfo.colWidths [col]; + if (x < pixel_x + w) + break; + + pixel_x += w; + } + + for (row = 0; row < layoutInfo.rows; row++) + { + int h = layoutInfo.rowHeights [row]; + if (y < pixel_y + h) + break; + + pixel_y += h; + } + + return new Point (col, row); + } + + /** + * Obsolete. + */ + protected void AdjustForGravity (GridBagConstraints gbc, Rectangle rect) + { + // FIXME + throw new Error ("Not implemented"); + } + + /** + * Obsolete. + */ + protected void ArrangeGrid (Container parent) + { + Component[] components = parent.getComponents(); + + if (components.length == 0) + return; + + GridBagLayoutInfo info = getLayoutInfo (parent, PREFERREDSIZE); + if (info.cols == 0 && info.rows == 0) + return; + layoutInfo = info; + + // DEBUG + //dumpLayoutInfo (layoutInfo); + + for(int i = 0; i < components.length; i++) + { + Component component = components [i]; + + // If component is not visible we dont have to care about it. + if (!component.isVisible()) + continue; + + GridBagConstraints constraints = + lookupInternalConstraints(component); + + int cellx = sumIntArray(layoutInfo.colWidths, constraints.gridx); + int celly = sumIntArray(layoutInfo.rowHeights, constraints.gridy); + int cellw = sumIntArray(layoutInfo.colWidths, + constraints.gridx + constraints.gridwidth) - cellx; + int cellh = sumIntArray(layoutInfo.rowHeights, + constraints.gridy + constraints.gridheight) - celly; + + Insets insets = constraints.insets; + if (insets != null) + { + cellx += insets.left; + celly += insets.top; + cellw -= insets.left + insets.right; + cellh -= insets.top + insets.bottom; + } + + Dimension dim = component.getPreferredSize(); + + // Note: Documentation says that padding is added on both sides, but + // visual inspection shows that the Sun implementation only adds it + // once, so we do the same. + dim.width += constraints.ipadx; + dim.height += constraints.ipady; + + switch(constraints.fill) + { + case GridBagConstraints.HORIZONTAL: + dim.width = cellw; + break; + case GridBagConstraints.VERTICAL: + dim.height = cellh; + break; + case GridBagConstraints.BOTH: + dim.width = cellw; + dim.height = cellh; + break; + } + + int x; + int y; + + switch(constraints.anchor) + { + case GridBagConstraints.NORTH: + x = cellx + (cellw - dim.width) / 2; + y = celly; + break; + case GridBagConstraints.SOUTH: + x = cellx + (cellw - dim.width) / 2; + y = celly + cellh - dim.height; + break; + case GridBagConstraints.WEST: + x = cellx; + y = celly + (cellh - dim.height) / 2; + break; + case GridBagConstraints.EAST: + x = cellx + cellw - dim.width; + y = celly + (cellh - dim.height) / 2; + break; + case GridBagConstraints.NORTHEAST: + x = cellx + cellw - dim.width; + y = celly; + break; + case GridBagConstraints.NORTHWEST: + x = cellx; + y = celly; + break; + case GridBagConstraints.SOUTHEAST: + x = cellx + cellw - dim.width; + y = celly + cellh - dim.height; + break; + case GridBagConstraints.SOUTHWEST: + x = cellx; + y = celly + cellh - dim.height; + break; + default: + x = cellx + (cellw - dim.width) / 2; + y = celly + (cellh - dim.height) / 2; + break; + } + + component.setBounds(layoutInfo.pos_x + x, layoutInfo.pos_y + y, dim.width, dim.height); + } + + // DEBUG + //dumpLayoutInfo (layoutInfo); + } + + /** + * Obsolete. + */ + protected GridBagLayoutInfo GetLayoutInfo (Container parent, int sizeflag) + { + if (sizeflag != MINSIZE && sizeflag != PREFERREDSIZE) + throw new IllegalArgumentException(); + + Dimension parentDim = parent.getSize (); + Insets parentInsets = parent.getInsets (); + parentDim.width -= parentInsets.left + parentInsets.right; + parentDim.height -= parentInsets.top + parentInsets.bottom; + + int current_y = 0; + int max_x = 0; + int max_y = 0; + + // Guaranteed to contain the last component added to the given row + // or column, whose gridwidth/height is not REMAINDER. + HashMap lastInRow = new HashMap(); + HashMap lastInCol = new HashMap(); + + Component[] components = parent.getComponents(); + + // Components sorted by gridwidths/heights, + // smallest to largest, with REMAINDER and RELATIVE at the end. + // These are useful when determining sizes and weights. + ArrayList sortedByWidth = new ArrayList(components.length); + ArrayList sortedByHeight = new ArrayList(components.length); + + // STEP 1: first we figure out how many rows/columns + for (int i = 0; i < components.length; i++) + { + Component component = components [i]; + + // If component is not visible we dont have to care about it. + if (!component.isVisible()) + continue; + + // When looking up the constraint for the first time, check the + // original unmodified constraint. After the first time, always + // refer to the internal modified constraint. + GridBagConstraints originalConstraints = lookupConstraints (component); + GridBagConstraints constraints = (GridBagConstraints) originalConstraints.clone(); + internalcomptable.put(component, constraints); + + // Cases: + // + // 1. gridy == RELATIVE, gridx == RELATIVE + // + // use y as the row number; check for the next + // available slot at row y + // + // 2. only gridx == RELATIVE + // + // check for the next available slot at row gridy + // + // 3. only gridy == RELATIVE + // + // check for the next available slot at column gridx + // + // 4. neither gridx or gridy == RELATIVE + // + // nothing to check; just add it + + + // cases 1 and 2 + if(constraints.gridx == GridBagConstraints.RELATIVE) + { + if (constraints.gridy == GridBagConstraints.RELATIVE) + constraints.gridy = current_y; + + int x; + + // Check the component that occupies the right-most spot in this + // row. We want to add this component after it. + // If this row is empty, add to the 0 position. + if (!lastInRow.containsKey(new Integer(constraints.gridy))) + x = 0; + else + { + Component lastComponent = (Component) lastInRow.get(new Integer(constraints.gridy)); + GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent); + x = lastConstraints.gridx + Math.max(1, lastConstraints.gridwidth); + } + + // Determine if this component will fit in the slot vertically. + // If not, bump it over to where it does fit. + for (int y = constraints.gridy + 1; y < constraints.gridy + Math.max(1, constraints.gridheight); y++) + { + if (lastInRow.containsKey(new Integer(y))) + { + Component lastComponent = (Component) lastInRow.get(new Integer(y)); + GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent); + x = Math.max (x, + lastConstraints.gridx + Math.max(1, lastConstraints.gridwidth)); + } + } + + constraints.gridx = x; + } + // case 3 + else if(constraints.gridy == GridBagConstraints.RELATIVE) + { + int y; + // Check the component that occupies the bottom-most spot in + // this column. We want to add this component below it. + // If this column is empty, add to the 0 position. + if (!lastInCol.containsKey(new Integer(constraints.gridx))) + y = 0; + else + { + Component lastComponent = (Component)lastInCol.get(new Integer(constraints.gridx)); + GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent); + y = lastConstraints.gridy + Math.max(1, lastConstraints.gridheight); + } + + // Determine if this component will fit in the slot horizontally. + // If not, bump it down to where it does fit. + for (int x = constraints.gridx + 1; x < constraints.gridx + Math.max(1, constraints.gridwidth); x++) + { + if (lastInCol.containsKey(new Integer(x))) + { + Component lastComponent = (Component) lastInCol.get(new Integer(x)); + GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent); + y = Math.max (y, + lastConstraints.gridy + Math.max(1, lastConstraints.gridheight)); + } + } + + constraints.gridy = y; + } + // case 4: do nothing + + max_x = Math.max(max_x, + constraints.gridx + Math.max(1, constraints.gridwidth)); + max_y = Math.max(max_y, + constraints.gridy + Math.max(1, constraints.gridheight)); + + sortBySpan(component, constraints.gridwidth, sortedByWidth, true); + sortBySpan(component, constraints.gridheight, sortedByHeight, false); + + // Update our reference points for RELATIVE gridx and gridy. + if(constraints.gridwidth == GridBagConstraints.REMAINDER) + { + current_y = constraints.gridy + Math.max(1, constraints.gridheight); + } + else if (constraints.gridwidth != GridBagConstraints.REMAINDER) + { + for (int y = constraints.gridy; y < constraints.gridy + Math.max(1, constraints.gridheight); y++) + { + if(lastInRow.containsKey(new Integer(y))) + { + Component lastComponent = (Component) lastInRow.get(new Integer(y)); + GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent); + if (constraints.gridx > lastConstraints.gridx) + { + lastInRow.put(new Integer(y), component); + } + } + else + { + lastInRow.put(new Integer(y), component); + } + } + + for (int x = constraints.gridx; x < constraints.gridx + Math.max(1, constraints.gridwidth); x++) + { + if(lastInCol.containsKey(new Integer(x))) + { + Component lastComponent = (Component) lastInCol.get(new Integer(x)); + GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent); + if (constraints.gridy > lastConstraints.gridy) + { + lastInCol.put(new Integer(x), component); + } + } + else + { + lastInCol.put(new Integer(x), component); + } + } + } + } // end of STEP 1 + + GridBagLayoutInfo info = new GridBagLayoutInfo(max_x, max_y); + + // Check if column widths and row heights are overridden. + + for (int x = 0; x < max_x; x++) + { + if(columnWidths != null && columnWidths.length > x) + info.colWidths[x] = columnWidths[x]; + if(columnWeights != null && columnWeights.length > x) + info.colWeights[x] = columnWeights[x]; + } + + for (int y = 0; y < max_y; y++) + { + if(rowHeights != null && rowHeights.length > y) + info.rowHeights[y] = rowHeights[y]; + if(rowWeights != null && rowWeights.length > y) + info.rowWeights[y] = rowWeights[y]; + } + + // STEP 2: Fix up any cells with width/height as REMAINDER/RELATIVE. + for (int i = 0; i < components.length; i++) + { + Component component = components [i]; + + // If component is not visible we dont have to care about it. + if (!component.isVisible()) + continue; + + GridBagConstraints constraints = lookupInternalConstraints (component); + + if(constraints.gridwidth == GridBagConstraints.REMAINDER || constraints.gridwidth == GridBagConstraints.RELATIVE) + { + if(constraints.gridwidth == GridBagConstraints.REMAINDER) + { + for (int y = constraints.gridy; y < constraints.gridy + Math.max(1, constraints.gridheight); y++) + { + if (lastInRow.containsKey(new Integer(y))) + { + Component lastComponent = (Component) lastInRow.get(new Integer(y)); + GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent); + + if (lastConstraints.gridwidth == GridBagConstraints.RELATIVE) + { + constraints.gridx = max_x - 1; + break; + } + else + { + constraints.gridx = Math.max (constraints.gridx, + lastConstraints.gridx + Math.max (1, lastConstraints.gridwidth)); + } + } + } + constraints.gridwidth = max_x - constraints.gridx; + } + else if (constraints.gridwidth == GridBagConstraints.RELATIVE) + { + constraints.gridwidth = max_x - constraints.gridx - 1; + } + + // Re-sort + sortedByWidth.remove(sortedByWidth.indexOf(component)); + sortBySpan(component, constraints.gridwidth, sortedByWidth, true); + } + + if(constraints.gridheight == GridBagConstraints.REMAINDER || constraints.gridheight == GridBagConstraints.RELATIVE) + { + if(constraints.gridheight == GridBagConstraints.REMAINDER) + { + for (int x = constraints.gridx; x < constraints.gridx + Math.max(1, constraints.gridwidth); x++) + { + if (lastInCol.containsKey(new Integer(x))) + { + Component lastComponent = (Component) lastInRow.get(new Integer(x)); + GridBagConstraints lastConstraints = lookupInternalConstraints(lastComponent); + + if (lastConstraints.gridheight == GridBagConstraints.RELATIVE) + { + constraints.gridy = max_y - 1; + break; + } + else + { + constraints.gridy = Math.max (constraints.gridy, + lastConstraints.gridy + Math.max (1, lastConstraints.gridheight)); + } + } + } + constraints.gridheight = max_y - constraints.gridy; + } + else if (constraints.gridheight == GridBagConstraints.RELATIVE) + { + constraints.gridheight = max_y - constraints.gridy - 1; + } + + // Re-sort + sortedByHeight.remove(sortedByHeight.indexOf(component)); + sortBySpan(component, constraints.gridheight, sortedByHeight, false); + } + } // end of STEP 2 + + // STEP 3: Determine sizes and weights for columns. + for (int i = 0; i < sortedByWidth.size(); i++) + { + Component component = (Component) sortedByWidth.get(i); + + // If component is not visible we dont have to care about it. + if (!component.isVisible()) + continue; + + GridBagConstraints constraints = lookupInternalConstraints (component); + + int width = (sizeflag == PREFERREDSIZE) ? + component.getPreferredSize().width : + component.getMinimumSize().width; + + if(constraints.insets != null) + width += constraints.insets.left + constraints.insets.right; + + width += constraints.ipadx; + + distributeSizeAndWeight(width, + constraints.weightx, + constraints.gridx, + constraints.gridwidth, + info.colWidths, + info.colWeights); + } // end of STEP 3 + + // STEP 4: Determine sizes and weights for rows. + for (int i = 0; i < sortedByHeight.size(); i++) + { + Component component = (Component) sortedByHeight.get(i); + + // If component is not visible we dont have to care about it. + if (!component.isVisible()) + continue; + + GridBagConstraints constraints = lookupInternalConstraints (component); + + int height = (sizeflag == PREFERREDSIZE) ? + component.getPreferredSize().height : + component.getMinimumSize().height; + + if(constraints.insets != null) + height += constraints.insets.top + constraints.insets.bottom; + + height += constraints.ipady; + + distributeSizeAndWeight(height, + constraints.weighty, + constraints.gridy, + constraints.gridheight, + info.rowHeights, + info.rowWeights); + } // end of STEP 4 + + // Adjust cell sizes iff parent size not zero. + if (parentDim.width > 0 && parentDim.height > 0) + { + calcCellSizes (info.colWidths, info.colWeights, parentDim.width); + calcCellSizes (info.rowHeights, info.rowWeights, parentDim.height); + } + + int totalWidth = sumIntArray(info.colWidths); + int totalHeight = sumIntArray(info.rowHeights); + + // Make sure pos_x and pos_y are never negative. + if (totalWidth >= parentDim.width) + info.pos_x = parentInsets.left; + else + info.pos_x = parentInsets.left + (parentDim.width - totalWidth) / 2; + + if (totalHeight >= parentDim.height) + info.pos_y = parentInsets.top; + else + info.pos_y = parentInsets.top + (parentDim.height - totalHeight) / 2; + + // DEBUG + //dumpLayoutInfo (info); + + return info; + } + + /** + * Obsolete. + */ + protected Dimension GetMinSize (Container parent, GridBagLayoutInfo info) + { + if (parent == null || info == null) + return new Dimension (0, 0); + + Insets insets = parent.getInsets(); + int width = sumIntArray (info.colWidths) + insets.left + insets.right; + int height = sumIntArray (info.rowHeights) + insets.top + insets.bottom; + return new Dimension (width, height); + } + + /** + * @since 1.4 + */ + protected Dimension getMinSize (Container parent, GridBagLayoutInfo info) + { + return GetMinSize (parent, info); + } + + /** + * Helper method used by GetLayoutInfo to keep components sorted, either + * by gridwidth or gridheight. + * + * @param component Component to add to the sorted list. + * @param span Either the component's gridwidth or gridheight. + * @param list <code>ArrayList</code> of components, sorted by + * their span. + * @param sortByWidth Flag indicating sorting index. If true, sort by + * width. Otherwise, sort by height. + * FIXME: Use a better sorting algorithm. + */ + private void sortBySpan (Component component, int span, ArrayList list, boolean sortByWidth) + { + if (span == GridBagConstraints.REMAINDER + || span == GridBagConstraints.RELATIVE) + { + // Put all RELATIVE and REMAINDER components at the end. + list.add(component); + } + else + { + int i = 0; + if (list.size() > 0) + { + GridBagConstraints gbc = lookupInternalConstraints((Component) list.get(i)); + int otherspan = sortByWidth ? + gbc.gridwidth : + gbc.gridheight; + while (otherspan != GridBagConstraints.REMAINDER + && otherspan != GridBagConstraints.RELATIVE + && span >= otherspan) + { + i++; + if (i < list.size()) + { + gbc = lookupInternalConstraints((Component) list.get(i)); + otherspan = sortByWidth ? + gbc.gridwidth : + gbc.gridheight; + } + else + break; + } + } + list.add(i, component); + } + } + + /** + * Helper method used by GetLayoutInfo to distribute a component's size + * and weight. + * + * @param size Preferred size of component, with inset and padding + * already added. + * @param weight Weight of component. + * @param start Starting position of component. Either + * constraints.gridx or gridy. + * @param span Span of component. either contraints.gridwidth or + * gridheight. + * @param sizes Sizes of rows or columns. + * @param weights Weights of rows or columns. + */ + private void distributeSizeAndWeight (int size, double weight, + int start, int span, + int[] sizes, double[] weights) + { + if (span == 1) + { + sizes[start] = Math.max(sizes[start], size); + weights[start] = Math.max(weights[start], weight); + } + else + { + int numOccupied = span; + int lastOccupied = -1; + + for(int i = start; i < start + span; i++) + { + if (sizes[i] == 0.0) + numOccupied--; + else + { + size -= sizes[i]; + lastOccupied = i; + } + } + + // A component needs to occupy at least one row. + if(numOccupied == 0) + sizes[start + span - 1] = size; + else if (size > 0) + sizes[lastOccupied] += size; + + calcCellWeights(weight, weights, start, span); + } + } + + /** + * Helper method used by GetLayoutInfo to calculate weight distribution. + * @param weight Weight of component. + * @param weights Weights of rows/columns. + * @param start Starting position of component in grid (gridx/gridy). + * @param span Span of component (gridwidth/gridheight). + */ + private void calcCellWeights (double weight, double[] weights, int start, int span) + { + double totalWeight = 0.0; + for(int k = start; k < start + span; k++) + totalWeight += weights[k]; + + if(weight > totalWeight) + { + if (totalWeight == 0.0) + { + weights[start + span - 1] += weight; + } + else + { + double diff = weight - totalWeight ; + double remaining = diff; + + for(int k = start; k < start + span; k++) + { + double extraWeight = diff * weights[k] / totalWeight; + weights[k] += extraWeight; + remaining -= extraWeight; + } + + if (remaining > 0.0 && weights[start + span - 1] != 0.0) + { + weights[start + span - 1] += remaining; + } + } + } + } + + /** + * Helper method used by GetLayoutInfo to distribute extra space + * based on weight distribution. + * + * @param sizes Sizes of rows/columns. + * @param weights Weights of rows/columns. + * @param range Dimension of container. + */ + private void calcCellSizes (int[] sizes, double[] weights, int range) + { + int totalSize = sumIntArray (sizes); + double totalWeight = sumDoubleArray (weights); + + int diff = range - totalSize; + + if (diff == 0) + return; + + for (int i = 0; i < sizes.length; i++) + { + int newsize = (int) (sizes[i] + (((double) diff) * weights [i] / totalWeight )); + + if (newsize > 0) + sizes[i] = newsize; + } + } + + private void dumpLayoutInfo (GridBagLayoutInfo info) + { + System.out.println ("GridBagLayoutInfo:"); + System.out.println ("cols: " + info.cols + ", rows: " + info.rows); + System.out.print ("colWidths: "); + dumpArray(info.colWidths); + System.out.print ("rowHeights: "); + dumpArray(info.rowHeights); + System.out.print ("colWeights: "); + dumpArray(info.colWeights); + System.out.print ("rowWeights: "); + dumpArray(info.rowWeights); + } + + private void dumpArray(int[] array) + { + String sep = ""; + for(int i = 0; i < array.length; i++) + { + System.out.print(sep); + System.out.print(array[i]); + sep = ", "; + } + System.out.println(); + } + + private void dumpArray(double[] array) + { + String sep = ""; + for(int i = 0; i < array.length; i++) + { + System.out.print(sep); + System.out.print(array[i]); + sep = ", "; + } + System.out.println(); + } + + /** + * @since 1.4 + */ + protected void arrangeGrid (Container parent) + { + ArrangeGrid (parent); + } + + /** + * @since 1.4 + */ + protected GridBagLayoutInfo getLayoutInfo (Container parent, int sizeflag) + { + return GetLayoutInfo (parent, sizeflag); + } + + /** + * @since 1.4 + */ + protected void adjustForGravity (GridBagConstraints gbc, Rectangle rect) + { + AdjustForGravity (gbc, rect); + } +} |