ExtendedGridLayout.java :  » Swing-Library » jEdit-4.3.1 » org » gjt » sp » jedit » gui » Java Open Source

Java Open Source » Swing Library » jEdit 4.3.1 
jEdit 4.3.1 » org » gjt » sp » jedit » gui » ExtendedGridLayout.java
/*
 * ExtendedGridLayout.java - a grid layout manager with variable cell sizes
 * that supports colspans and rowspans
 * :tabSize=8:indentSize=8:noTabs=false:
 * :folding=explicit:collapseFolds=1:
 *
 * Originally written by Bjrn Kautler for the jEdit project. This work has been
 * placed into the public domain. You may use this work in any way and for any
 * purpose you wish.
 *
 * THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, NOT EVEN THE
 * IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE, ASSUMES
 * _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE RESULTING FROM THE USE, MODIFICATION,
 * OR REDISTRIBUTION OF THIS SOFTWARE.
 */

package org.gjt.sp.jedit.gui;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager2;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;

import static java.awt.Component.CENTER_ALIGNMENT;

import static org.gjt.sp.jedit.gui.ExtendedGridLayoutConstraints.REMAINDER;

/**
  * A layout manager that places components in a rectangular grid
  * with variable cell sizes that supports colspans and rowspans.
  * <p>
  * The container is divided into rectangles, and each component is placed
  * in a rectangular space defined by its colspan and rowspan.
  * Each row is as large as the largest component in
  * that row, and each column is as wide as the widest component in
  * that column. </p>
  * <p>
  * This behavior is similar to 
  * <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/awt/GridLayout.html">{@code java.awt.GridLayout}</a>
  * but it supports different row heights and
  * column widths for each row/column. </p>
  * <p>
  * For example, the following is a Dialog that lays out ten buttons
  * exactly the same as in the example of the JavaDoc of
  * <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/awt/GridBagLayout.html">{@code java.awt.GridBagLayout}</a>
  * with the difference of vertical and horizontal gaps that can be configured:
  * <hr>
  * <blockquote><pre><font color="#000000">
  * <font color="#000000">   1:</font><font color="#009966"><strong>import</strong></font> java.awt.Button;
  * <font color="#000000">   2:</font><font color="#009966"><strong>import</strong></font> java.awt.Dimension;
  * <font color="#000000">   3:</font>
  * <font color="#000000">   4:</font><font color="#009966"><strong>import</strong></font> javax.swing.JDialog;
  * <font color="#990066">   5:</font>
  * <font color="#000000">   6:</font><font color="#009966"><strong>import</strong></font> org.gjt.sp.jedit.gui.ExtendedGridLayout;
  * <font color="#000000">   7:</font><font color="#009966"><strong>import</strong></font> org.gjt.sp.jedit.gui.ExtendedGridLayoutConstraints;
  * <font color="#000000">   8:</font>
  * <font color="#000000">   9:</font><font color="#009966"><strong>import</strong></font> <font color="#006699"><strong>static</strong></font> org.gjt.sp.jedit.gui.ExtendedGridLayoutConstraints.REMAINDER;
  * <font color="#990066">  10:</font>
  * <font color="#000000">  11:</font><font color="#006699"><strong>public</strong></font> <font color="#0099ff"><strong>class</strong></font> ExampleDialog <font color="#006699"><strong>extends</strong></font> JDialog <font color="#000000"><strong>{</strong></font>
  * <font color="#000000">  12:</font>    <font color="#006699"><strong>public</strong></font> <font color="#9966ff">ExampleDialog</font>() <font color="#000000"><strong>{</strong></font>
  * <font color="#000000">  13:</font>        <font color="#cc00cc">super</font>(<font color="#cc00cc">null</font>,<font color="#ff00cc">&quot;</font><font color="#ff00cc">Example</font><font color="#ff00cc"> </font><font color="#ff00cc">Dialog</font><font color="#ff00cc">&quot;</font>,<font color="#cc00cc">true</font>);
  * <font color="#000000">  14:</font>        <font color="#9966ff">setLayout</font>(<font color="#006699"><strong>new</strong></font> <font color="#9966ff">ExtendedGridLayout</font>(<font color="#ff0000">5</font>,<font color="#ff0000">5</font>,<font color="#006699"><strong>new</strong></font> <font color="#9966ff">Insets</font>(<font color="#ff0000">5</font>,<font color="#ff0000">5</font>,<font color="#ff0000">5</font>,<font color="#ff0000">5</font>)));
  * <font color="#990066">  15:</font>        
  * <font color="#000000">  16:</font>        <font color="#9966ff">add</font>(<font color="#9966ff">makeButton</font>(<font color="#ff00cc">&quot;</font><font color="#ff00cc">Button1</font><font color="#ff00cc">&quot;</font>));
  * <font color="#000000">  17:</font>        <font color="#9966ff">add</font>(<font color="#9966ff">makeButton</font>(<font color="#ff00cc">&quot;</font><font color="#ff00cc">Button2</font><font color="#ff00cc">&quot;</font>));
  * <font color="#000000">  18:</font>        <font color="#9966ff">add</font>(<font color="#9966ff">makeButton</font>(<font color="#ff00cc">&quot;</font><font color="#ff00cc">Button3</font><font color="#ff00cc">&quot;</font>));
  * <font color="#000000">  19:</font>        <font color="#9966ff">add</font>(<font color="#9966ff">makeButton</font>(<font color="#ff00cc">&quot;</font><font color="#ff00cc">Button4</font><font color="#ff00cc">&quot;</font>));
  * <font color="#990066">  20:</font>        Button button <font color="#000000"><strong>=</strong></font> <font color="#9966ff">makeButton</font>(<font color="#ff00cc">&quot;</font><font color="#ff00cc">Button5</font><font color="#ff00cc">&quot;</font>);
  * <font color="#000000">  21:</font>        <font color="#9966ff">add</font>(button,<font color="#006699"><strong>new</strong></font> <font color="#9966ff">ExtendedGridLayoutConstraints</font>(<font color="#ff0000">1</font>,REMAINDER,<font color="#ff0000">1</font>,button));
  * <font color="#000000">  22:</font>        button <font color="#000000"><strong>=</strong></font> <font color="#9966ff">makeButton</font>(<font color="#ff00cc">&quot;</font><font color="#ff00cc">Button6</font><font color="#ff00cc">&quot;</font>);
  * <font color="#000000">  23:</font>        <font color="#9966ff">add</font>(button,<font color="#006699"><strong>new</strong></font> <font color="#9966ff">ExtendedGridLayoutConstraints</font>(<font color="#ff0000">2</font>,<font color="#ff0000">3</font>,<font color="#ff0000">1</font>,button));
  * <font color="#000000">  24:</font>        button <font color="#000000"><strong>=</strong></font> <font color="#9966ff">makeButton</font>(<font color="#ff00cc">&quot;</font><font color="#ff00cc">Button7</font><font color="#ff00cc">&quot;</font>);
  * <font color="#990066">  25:</font>        <font color="#9966ff">add</font>(button,<font color="#006699"><strong>new</strong></font> <font color="#9966ff">ExtendedGridLayoutConstraints</font>(<font color="#ff0000">2</font>,button));
  * <font color="#000000">  26:</font>        button <font color="#000000"><strong>=</strong></font> <font color="#9966ff">makeButton</font>(<font color="#ff00cc">&quot;</font><font color="#ff00cc">Button8</font><font color="#ff00cc">&quot;</font>);
  * <font color="#000000">  27:</font>        <font color="#9966ff">add</font>(button,<font color="#006699"><strong>new</strong></font> <font color="#9966ff">ExtendedGridLayoutConstraints</font>(<font color="#ff0000">3</font>,<font color="#ff0000">1</font>,<font color="#ff0000">2</font>,button));
  * <font color="#000000">  28:</font>        button <font color="#000000"><strong>=</strong></font> <font color="#9966ff">makeButton</font>(<font color="#ff00cc">&quot;</font><font color="#ff00cc">Button9</font><font color="#ff00cc">&quot;</font>);
  * <font color="#000000">  29:</font>        <font color="#9966ff">add</font>(button,<font color="#006699"><strong>new</strong></font> <font color="#9966ff">ExtendedGridLayoutConstraints</font>(<font color="#ff0000">3</font>,<font color="#ff0000">3</font>,<font color="#ff0000">1</font>,button));
  * <font color="#990066">  30:</font>        button <font color="#000000"><strong>=</strong></font> <font color="#9966ff">makeButton</font>(<font color="#ff00cc">&quot;</font><font color="#ff00cc">Button10</font><font color="#ff00cc">&quot;</font>);
  * <font color="#000000">  31:</font>        <font color="#9966ff">add</font>(button,<font color="#006699"><strong>new</strong></font> <font color="#9966ff">ExtendedGridLayoutConstraints</font>(<font color="#ff0000">4</font>,REMAINDER,<font color="#ff0000">1</font>,button));
  * <font color="#000000">  32:</font>        
  * <font color="#000000">  33:</font>        <font color="#9966ff">pack</font>();
  * <font color="#000000">  34:</font>        <font color="#9966ff">setLocationRelativeTo</font>(<font color="#cc00cc">null</font>);
  * <font color="#990066">  35:</font>        <font color="#9966ff">setVisible</font>(<font color="#cc00cc">true</font>);
  * <font color="#000000">  36:</font>    <font color="#000000"><strong>}</strong></font>
  * <font color="#000000">  37:</font>    
  * <font color="#000000">  38:</font>    <font color="#006699"><strong>private</strong></font> Button <font color="#9966ff">makeButton</font>(String name) <font color="#000000"><strong>{</strong></font>
  * <font color="#000000">  39:</font>        Button button <font color="#000000"><strong>=</strong></font> <font color="#006699"><strong>new</strong></font> <font color="#9966ff">Button</font>(name);
  * <font color="#990066">  40:</font>        button.<font color="#9966ff">setMaximumSize</font>(<font color="#006699"><strong>new</strong></font> <font color="#9966ff">Dimension</font>(Integer.MAX_VALUE,Integer.MAX_VALUE));
  * <font color="#000000">  41:</font>        <font color="#006699"><strong>return</strong></font> button;
  * <font color="#000000">  42:</font>    <font color="#000000"><strong>}</strong></font>
  * <font color="#000000">  43:</font><font color="#000000"><strong>}</strong></font>
  * </font></pre></blockquote>
  * <hr>
  * If you use {@code REMAINDER} as colspan or rowspan then a component takes
  * up the remaining space in that column or row. Any additional components in
  * a row are ignored and not displayed. Additional components in a column are
  * moved rightside. If a rowspan hits a colspan, the colspan ends and the
  * rowspan takes precedence.
  * <p>
  * Components for which {@code isVisible() == false} are ignored. Because
  * of this, components can be replaced "in-place" by adding two components next to
  * each other, with different {@code isVisible()} values, and toggling the 
  * {@code setVisible()} values of both when we wish to swap the currently
  * visible component with the one that is hidden. </p>
  *
  * <p>
  * If you want to reserve free space in a row inbetween components,  
  * add a <a href="http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/Box.Filler.html">{@code javax.swing.Box.Filler}</a>
  * to the layout if the free space is in the middle of a row,
  * or just don't add components if the free space
  * should be at the end of a row.</p>
  * <p>
  * If a row is taller, or a column is wider than the {@code maximumSize} of a component,
  * the component is resized to its maximum size and aligned according to its
  * {@code alignmentX} and {@code alignmentY} values. </p>
  * <p>
  * One instance of this class can be used to layout multiple
  * containers at the same time. </p>
  *
  * @author Bjrn "Vampire" Kautler
  * @version 1.0
  * @see ExtendedGridLayoutConstraints
  * @see <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/awt/Component.html"><code>java.awt.Component</code></a>
  * @see <a href="http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/Box.Filler.html"><code>javax.swing.Box.Filler</code></a>
  */
public class ExtendedGridLayout implements LayoutManager2
{
  /**
    * This hashtable maintains the association between
    * a component and its ExtendedGridLayoutConstraints.
    * The Keys in {@code comptable} are the components and the
    * values are the instances of {@code ExtendedGridLayoutConstraints}.
    *
    * @see ExtendedGridLayoutConstraints
    */
  private final Hashtable<Component,ExtendedGridLayoutConstraints> comptable;
  
  /**
    * Specifies the horizontal space between two columns.
    * The default value is 0.
    * 
    * @see #distanceToBorders
    * @see #vgap
    */
  private final int hgap;
  
  /**
    * Specifies the vertical space between two rows.
    * The default value is 0.
    * 
    * @see #distanceToBorders
    * @see #hgap
    */
  private final int vgap;
  
  /**
    * Specifies the gap between the grid and the borders of the parent container.
    * The default value is 0 for all four borders.
    * 
    * @see #hgap
    * @see #vgap
    */
  private final Insets distanceToBorders;
  
  /**
    * An enum to tell the {@code getSize()} method which size is requested.
    * 
    * @see #getSize()
    */
  private static enum LayoutSize { MINIMUM, PREFERRED, MAXIMUM }
  
  /**
    * Creates an extended grid layout manager with the specified horizontal
    * and vertical gap, and the specified distance to the borders
    * of the parent container.
    * 
    * @param hgap The horizontal space between two columns ({@literal >=0})
    * @param vgap The vertical space between two rows ({@literal >=0})
    * @param distanceToBorders The distances to the borders of the parent container
    * @throws IllegalArgumentException if hgap {@literal < 0}
    * @throws IllegalArgumentException if vgap {@literal < 0}
    */
  public ExtendedGridLayout(int hgap, int vgap, Insets distanceToBorders)
  {
    if (hgap < 0)
    {
      throw new IllegalArgumentException("hgap must be non-negative (" + hgap + ')');
    }
    if (vgap < 0)
    {
      throw new IllegalArgumentException("vgap must be non-negative (" + vgap + ')');
    }
    this.hgap = hgap;
    this.vgap = vgap;
    this.distanceToBorders = (Insets)distanceToBorders.clone();
    comptable = new Hashtable<Component,ExtendedGridLayoutConstraints>();
  }
  
  /**
    * Creates an extended grid layout manager with zero horizontal
    * and vertical gap, and zero distance to the borders
    * of the parent container.
    */
  public ExtendedGridLayout()
  {
    this(0,0,new Insets(0,0,0,0));
  }
  
  /**
    * If the layout manager uses a per-component string,
    * adds the component <code>component</code> to the layout,
    * associating it with the string specified by <code>name</code>.
    * 
    * @param name      The string to be associated with the component.
    *                  Has to be {@code null}, so that default constraints are used.
    * @param component The component to be added
    * @throws IllegalArgumentException if {@code name} is not {@code null}
    * @see #addLayoutComponent(java.awt.Component, java.lang.Object)
    */
  public void addLayoutComponent(String name, Component component)
  {
    addLayoutComponent(component,name);
  }
  
  /**
    * Adds the specified component to the layout, using the specified
    * constraints object.
    * 
    * @param component    The component to be added
    * @param constraints  Where/how the component is added to the layout.
    * @throws IllegalArgumentException if {@code constraints} is not an ExtendedGridLayoutConstraints object
    * @throws IllegalArgumentException if {@code constraints} is a placeholder
    * @throws IllegalArgumentException if {@code constraints} is not the right one for the component
    * @see ExtendedGridLayoutConstraints
    */
  public void addLayoutComponent(Component component, Object constraints)
  {
    if (null == constraints)
    {
      constraints = new ExtendedGridLayoutConstraints(component);
    }
    if (constraints instanceof ExtendedGridLayoutConstraints)
    {
      ExtendedGridLayoutConstraints eglConstraints = (ExtendedGridLayoutConstraints)constraints;
      if (eglConstraints.isPlaceholder())
      {
        throw new IllegalArgumentException("constraints must not be a placeholder");
      }
      else if (component != eglConstraints.getComponent())
      {
        throw new IllegalArgumentException("constraints is not the right one for this component");
      }
      comptable.put(component,eglConstraints);
    }
    else 
    {
      throw new IllegalArgumentException("constraints must not be an ExtendedGridLayoutConstraints object");
    }
  }
  
  /**
    * Retrieves the constraints for the specified {@code component}.
    * If {@code component} is not in the {@code ExtendedGridLayout},
    * a set of default {@code ExtendedGridLayoutConstraints} are returned.
    * 
    * @param component the {@code component} to be queried
    * @return the contraints for the specified {@code component}
    * @throws NullPointerException if {@code component} is {@code null}
    * @see ExtendedGridLayoutConstraints
    */
  private ExtendedGridLayoutConstraints lookupConstraints(Component component)
  {
    if (null == component)
    {
      throw new NullPointerException("component must not be null");
    }
    ExtendedGridLayoutConstraints constraints = comptable.get(component);
    if (null == constraints)
    {
      constraints = new ExtendedGridLayoutConstraints(component);
      comptable.put(component,constraints);
    }
    return constraints;
  }
  
  /**
    * Removes the specified component from the layout.
    * 
    * @param component The component to be removed
    */
  public void removeLayoutComponent(Component component)
  {
    comptable.remove(component);
  }
  
  /**
    * 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.
    * 
    * @param container The container for which the alignment should be returned
    * @return {@code java.awt.Component.CENTER_ALIGNMENT}
    */
  public float getLayoutAlignmentX(Container container)
  {
    return CENTER_ALIGNMENT;
  }
  
  /**
    * 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.
    * 
    * @param container The container for which the alignment should be returned
    * @return {@code java.awt.Component.CENTER_ALIGNMENT}
    */
  public float getLayoutAlignmentY(Container container)
  {
    return CENTER_ALIGNMENT;
  }
  
  /**
    * Calculates the minimum size dimensions for the specified
    * container, given the components it contains.
    * 
    * @param parent The component to be laid out
    * @return The minimum size for the container
    * @see #maximumLayoutSize
    * @see #preferredLayoutSize
    */
  public Dimension minimumLayoutSize(Container parent)
  {
    synchronized (parent.getTreeLock())
    {
      List<List<ExtendedGridLayoutConstraints>> gridRows = new ArrayList<List<ExtendedGridLayoutConstraints>>();
      Set<ExtendedGridLayoutConstraints> colspans = new HashSet<ExtendedGridLayoutConstraints>();
      Set<ExtendedGridLayoutConstraints> rowspans = new HashSet<ExtendedGridLayoutConstraints>();
      Dimension gridSize = buildGrid(parent,gridRows,colspans,rowspans);
      return getSize(parent,LayoutSize.MINIMUM,false,gridSize,gridRows,colspans,rowspans,new int[0][0]);
    }
  }
  
  /**
    * Calculates the preferred size dimensions for the specified
    * container, given the components it contains.
    * 
    * @param parent The container to be laid out
    * @return The preferred size for the container
    * @see #maximumLayoutSize
    * @see #minimumLayoutSize
    */
  public Dimension preferredLayoutSize(Container parent)
  {
    synchronized (parent.getTreeLock())
    {
      List<List<ExtendedGridLayoutConstraints>> gridRows = new ArrayList<List<ExtendedGridLayoutConstraints>>();
      Set<ExtendedGridLayoutConstraints> colspans = new HashSet<ExtendedGridLayoutConstraints>();
      Set<ExtendedGridLayoutConstraints> rowspans = new HashSet<ExtendedGridLayoutConstraints>();
      Dimension gridSize = buildGrid(parent,gridRows,colspans,rowspans);
      return getSize(parent,LayoutSize.PREFERRED,false,gridSize,gridRows,colspans,rowspans,new int[0][0]);
    }
  }
  
  /**
    * Calculates the maximum size dimensions for the specified
    * container, given the components it contains.
    * 
    * @param parent The container to be laid out
    * @return The maximum size for the container
    * @see #minimumLayoutSize
    * @see #preferredLayoutSize
    */
  public Dimension maximumLayoutSize(Container parent)
  {
    synchronized (parent.getTreeLock())
    {
      List<List<ExtendedGridLayoutConstraints>> gridRows = new ArrayList<List<ExtendedGridLayoutConstraints>>();
      Set<ExtendedGridLayoutConstraints> colspans = new HashSet<ExtendedGridLayoutConstraints>();
      Set<ExtendedGridLayoutConstraints> rowspans = new HashSet<ExtendedGridLayoutConstraints>();
      Dimension gridSize = buildGrid(parent,gridRows,colspans,rowspans);
      return getSize(parent,LayoutSize.MAXIMUM,false,gridSize,gridRows,colspans,rowspans,new int[0][0]);
    }
  }
  
  /**
    * Invalidates the layout, indicating that if the layout manager
    * has cached information it should be discarded.
    * 
    * @param container The container for which the cached information should be discarded
    */
  public void invalidateLayout(Container container)
  {
  }
  
  /**
    * Lays out the specified container.
    * 
    * @param parent The container to be laid out 
    */
  public void layoutContainer(Container parent)
  {
    synchronized (parent.getTreeLock())
    {
      // Pass 1: build the grid
      List<List<ExtendedGridLayoutConstraints>> gridRows = new ArrayList<List<ExtendedGridLayoutConstraints>>();
      Set<ExtendedGridLayoutConstraints> colspans = new HashSet<ExtendedGridLayoutConstraints>();
      Set<ExtendedGridLayoutConstraints> rowspans = new HashSet<ExtendedGridLayoutConstraints>();
      Dimension gridSize = buildGrid(parent,gridRows,colspans,rowspans);
      
      // Pass 2: compute minimum, preferred and maximum column widths / row heights
      int[][] layoutSizes = new int[6][];
      Dimension preferredSize = getSize(parent,LayoutSize.PREFERRED,true,gridSize,gridRows,colspans,rowspans,layoutSizes);
      int[] minimumColWidths = layoutSizes[0];
      int[] minimumRowHeights = layoutSizes[1];
      int[] preferredColWidths = layoutSizes[2];
      int[] preferredRowHeights = layoutSizes[3];
      int[] maximumColWidths = layoutSizes[4];
      int[] maximumRowHeights = layoutSizes[5];
      
      // Pass 3: redistribute free space
      Dimension parentSize = parent.getSize();
      Insets insets = parent.getInsets();
      int freeWidth = parentSize.width
          - insets.left - insets.right
          - (gridSize.width - 1) * hgap
          - distanceToBorders.left - distanceToBorders.right;
      int freeHeight = parentSize.height
           - insets.top - insets.bottom
           - (gridSize.height - 1) * vgap
           - distanceToBorders.top - distanceToBorders.bottom;
      redistributeSpace(preferredSize.width,
            freeWidth,
            0,gridSize.width,
            preferredColWidths,
            minimumColWidths,
            maximumColWidths);
      redistributeSpace(preferredSize.height,
            freeHeight,
            0,gridSize.height,
            preferredRowHeights,
            minimumRowHeights,
            maximumRowHeights);
      
      // Pass 4: layout components
      for (int row=0, y=insets.top+distanceToBorders.top ; row<gridSize.height ; y+=preferredRowHeights[row]+vgap, row++)
      {
        List<ExtendedGridLayoutConstraints> gridRow = gridRows.get(row);
        for (int col=0, x=insets.left+distanceToBorders.left ; col<gridSize.width; x+=preferredColWidths[col]+hgap, col++)
        {
          ExtendedGridLayoutConstraints cell = gridRow.get(col);
          if ((null != cell) && (null != cell.getComponent()) && !cell.isPlaceholder())
          {
            Component component = cell.getComponent();
            Dimension maxSize = component.getMaximumSize();
            int fromCol = cell.getCol();
            int colspan = cell.getEffectiveColspan();
            int toCol = fromCol + colspan;
            int width = 0;
            for (int col2=fromCol ; col2<toCol ; col2++)
            {
              width += preferredColWidths[col2];
            }
            width += (colspan - 1) * hgap;
            int fromRow = cell.getRow();
            int rowspan = cell.getEffectiveRowspan();
            int toRow = fromRow + rowspan;
            int height = 0;
            for (int row2=fromRow ; row2<toRow ; row2++)
            {
              height += preferredRowHeights[row2];
            }
            height += (rowspan - 1) * vgap;
            int xCorrection = 0;
            int yCorrection = 0;
            if (width > maxSize.width)
            {
              xCorrection = (int)((width - maxSize.width) * component.getAlignmentX());
              width = maxSize.width;
            }
            if (height > maxSize.height)
            {
              yCorrection = (int)((height-maxSize.height) * component.getAlignmentY());
              height = maxSize.height;
            }
            
            component.setBounds(x + xCorrection, y + yCorrection, width, height);
          }
        }
      }
    }
  }
  
  /**
    * Redistributs free space (positive or negative) to all available
    * columns or rows while taking elements maximum and minimum sizes into
    * account if possible.
    * 
    * @param totalSize             The cumulated preferred sizes of the components
    * @param freeSize              The available space for displaying components
    *                              without any gaps between components or between
    *                              the grid and the borders of the parent container
    * @param start                 The start in the arrays of rows or columns inclusive
    * @param stop                  The stop in the arrays of rows or columns exclusive
    * @param preferredElementSizes The preferredSizes of the rows or columns.
    *                              After invocation of this method, this array
    *                              holds the sizes that should be used
    * @param minimumElementSizes   The minimumSizes of the rows or columns
    * @param maximumElementSizes   The maximumSizes of the rows or columns
    */
  private void redistributeSpace(int totalSize, int freeSize,
               int start, int stop,
               int[] preferredElementSizes,
               int[] minimumElementSizes,
               int[] maximumElementSizes)
  {
    if (totalSize != freeSize)
    {
      boolean grow = totalSize < freeSize;
      // calculate the size that is available for redistribution
      freeSize = (freeSize - totalSize) * (grow ? 1 : -1);
      while (freeSize > 0)
      {
        // calculate the amount of elements that can be resized without violating
        // the minimum and maximum sizes and their current cumulated size
        int modifyableAmount = 0;
        long modifySize = 0;
        for (int i=start ; i<stop ; i++)
        {
          if ((grow && (preferredElementSizes[i] < maximumElementSizes[i])) ||
              (!grow && (preferredElementSizes[i] > minimumElementSizes[i])))
          {
            modifyableAmount++;
            modifySize += preferredElementSizes[i];
          }
        }
        boolean checkBounds = true;
        // if all elements are at their minimum or maximum size, resize all elements
        if (0 == modifyableAmount)
        {
          for (int i=start ; i<stop ; i++)
          {
            modifySize += preferredElementSizes[i];
          }
          checkBounds = false;
          modifyableAmount = stop - start;
        }
        // to prevent an endless loop if the container gets resized to a very small amount
        if (modifySize == 0)
        {
          break;
        }
        // resize the elements
        if (freeSize < modifyableAmount)
        {
          for (int i=start ; i<stop ; i++)
          {
            if ((freeSize != 0) &&
                (!checkBounds ||
                 (checkBounds &&
                  (grow && (preferredElementSizes[i] < maximumElementSizes[i])) ||
                  (!grow && (preferredElementSizes[i] > minimumElementSizes[i])))))
            {
              preferredElementSizes[i] += (grow ? 1 : -1);
              if (0 > preferredElementSizes[i])
              {
                preferredElementSizes[i] = 0;
              }
              freeSize--;
            }
          }
        }
        else
        {
          long modifySizeAddition = 0;
          double factor = (double)(freeSize + modifySize) / (double)modifySize;
          for (int i=start ; i<stop ; i++)
          {
            long modifyableSize = (checkBounds ? (grow ? maximumElementSizes[i] - preferredElementSizes[i] : preferredElementSizes[i] - minimumElementSizes[i]) : Integer.MAX_VALUE - preferredElementSizes[i]);
            long elementModifySize = Math.abs(Math.round((factor * preferredElementSizes[i]) - preferredElementSizes[i]));
            if (elementModifySize <= modifyableSize)
            {
              preferredElementSizes[i] += (grow ? elementModifySize : -elementModifySize);
              modifySizeAddition += (grow ? elementModifySize : -elementModifySize);
              freeSize -= elementModifySize;
            }
            else
            {
              preferredElementSizes[i] += (grow ? modifyableSize : -modifyableSize);
              modifySizeAddition += (grow ? modifyableSize : -modifyableSize);
              freeSize -= modifyableSize;
            }
            if (0 > preferredElementSizes[i])
            {
              preferredElementSizes[i] = 0;
            }
          }
          modifySize += modifySizeAddition;
        }
      }
    }
  }
  
  /**
    * Calculates the minimum, preferred or maximum size dimensions
    * for the specified container, given the components it contains.
    * 
    * @param parent       The container to be laid out
    * @param layoutSize   if {@code LayoutSize.MINIMUM} compute minimum layout size,
    *                     if {@code LayoutSize.PREFERRED} compute preferred layout size,
    *                     if {@code LayoutSize.MAXIMUM} compute maximum layout size,
    *                     if {@code fillRawSizes} is {@code true}, the layout size is computed
    *                     without applying gaps between components or between
    *                     the grid and the borders of the parent container
    * @param fillRawSizes Whether to fill the resultArrays with the raw
    *                     row heights and column widths and whether to apply
    *                     gaps between components or between
    *                     the grid and the borders of the parent container
    *                     when computing the layout size
    * @param gridSize     The amount of rows and columns in the grid
    * @param gridRows     The grid holding the constraints for the components
    * @param colspans     In this {@code Set} the constraints which are part
    *                     of a colspan are stored
    * @param rowspans     In this {@code Set} the constraints which are part
    *                     of a rowspan are stored
    * @param resultArrays If {@code fillRawSizes} is {@code true}, the first six arrays
    *                     get filled with the raw row heights and column widths.
    *                     resultArrays[0] = resultMinimumColWidths;
    *                     resultArrays[1] = resultMinimumRowHeights;
    *                     resultArrays[2] = resultPreferredColWidths;
    *                     resultArrays[3] = resultPreferredRowHeights;
    *                     resultArrays[4] = resultMaximumColWidths;
    *                     resultArrays[5] = resultMaximumRowHeights;
    * @return The minimum, preferred or maximum size dimensions for the specified container
    * @throws IllegalArgumentException If {@code fillRawSizes == true} and {@code resultArrays.length < 6}
    */
  private Dimension getSize(Container parent, LayoutSize layoutSize, boolean fillRawSizes,
          Dimension gridSize, List<List<ExtendedGridLayoutConstraints>> gridRows,
          Set<ExtendedGridLayoutConstraints> colspans,
          Set<ExtendedGridLayoutConstraints> rowspans,
          int[][] resultArrays)
  {
    if (fillRawSizes && (resultArrays.length < 6))
    {
      throw new IllegalArgumentException("If fillRawSizes is true, resultArrays.length must be >= 6 (" + resultArrays.length + ')');
    }
    int[] minimumColWidths = new int[gridSize.width];
    int[] minimumRowHeights = new int[gridSize.height];
    int[] preferredColWidths = new int[gridSize.width];
    int[] preferredRowHeights = new int[gridSize.height];
    int[] maximumColWidths = new int[gridSize.width];
    int[] maximumRowHeights = new int[gridSize.height];
    Arrays.fill(minimumColWidths,0);
    Arrays.fill(minimumRowHeights,0);
    Arrays.fill(preferredColWidths,0);
    Arrays.fill(preferredRowHeights,0);
    Arrays.fill(maximumColWidths,0);
    Arrays.fill(maximumRowHeights,0);
    
    // get the maximum of the minimum sizes,
    //     the maximum of the preferred sizes and
    //     the minimum of the maximum sizes
    // of all rows and columns, not taking
    // rowspans and colspans into account
    for (int row=0 ; row<gridSize.height ; row++)
    {
      List<ExtendedGridLayoutConstraints> gridRow = gridRows.get(row);
      for (int col=0 ; col<gridSize.width ; col++)
      {
        ExtendedGridLayoutConstraints cell = gridRow.get(col);
        if ((null != cell) && (null != cell.getComponent()))
        {
          Component component = cell.getComponent();
          Dimension minimumSize = component.getMinimumSize();
          Dimension preferredSize = component.getPreferredSize();
          Dimension maximumSize = component.getMaximumSize();
          if (!colspans.contains(cell))
          {
            minimumColWidths[col] = Math.max(minimumColWidths[col],minimumSize.width);
            preferredColWidths[col] = Math.max(preferredColWidths[col],preferredSize.width);
            maximumColWidths[col] = Math.max(maximumColWidths[col],maximumSize.width);
          }
          if (!rowspans.contains(cell))
          {
            minimumRowHeights[row] = Math.max(minimumRowHeights[row],minimumSize.height);
            preferredRowHeights[row] = Math.max(preferredRowHeights[row],preferredSize.height);
            maximumRowHeights[row] = Math.max(maximumRowHeights[row],maximumSize.height);
          }
        }
      }
    }
    
    // correct cases where
    // minimumColWidths[col] <= preferredColWidths[col] <= maximumColWidths[col]
    // is not true by clipping to the minimumColWidths and maximumColWidths
    for (int col=0 ; col<gridSize.width ; col++)
    {
      if (minimumColWidths[col] >= maximumColWidths[col])
      {
        maximumColWidths[col] = minimumColWidths[col];
        preferredColWidths[col] = minimumColWidths[col];
      }
      else if (preferredColWidths[col] < minimumColWidths[col])
      {
        preferredColWidths[col] = minimumColWidths[col];
      }
      else if (preferredColWidths[col] > maximumColWidths[col])
      {
        preferredColWidths[col] = maximumColWidths[col];
      }
    }
    
    // plug in the colspans and correct the minimum, preferred and
    // maximum column widths the colspans are part of
    for (ExtendedGridLayoutConstraints cell : colspans)
    {
      int fromCol = cell.getCol();
      int colspan = cell.getEffectiveColspan();
      int toCol = fromCol + colspan;
      int currentMinimumColWidth = 0;
      int currentPreferredColWidth = 0;
      int currentMaximumColWidth = 0;
      for (int col=fromCol ; col<toCol ; col++)
      {
        int minimumColWidth = minimumColWidths[col];
        if ((Integer.MAX_VALUE-minimumColWidth) < currentMinimumColWidth)
        {
          currentMinimumColWidth = Integer.MAX_VALUE;
        }
        else
        {
          currentMinimumColWidth += minimumColWidth;
        }
        int preferredColWidth = preferredColWidths[col];
        if ((Integer.MAX_VALUE-preferredColWidth) < currentPreferredColWidth)
        {
          currentPreferredColWidth = Integer.MAX_VALUE;
        }
        else
        {
          currentPreferredColWidth += preferredColWidth;
        }
        int maximumColWidth = maximumColWidths[col];
        if ((Integer.MAX_VALUE-maximumColWidth) < currentMaximumColWidth)
        {
          currentMaximumColWidth = Integer.MAX_VALUE;
        }
        else
        {
          currentMaximumColWidth += maximumColWidth;
        }
      }
      Component component = cell.getComponent();
      int wantedMaximumColWidth = component.getMaximumSize().width - ((colspan - 1) * hgap);
      if (currentMaximumColWidth < wantedMaximumColWidth)
      {
        redistributeSpace(currentMaximumColWidth,
              wantedMaximumColWidth,
              fromCol,toCol,
              maximumColWidths,
              maximumColWidths,
              maximumColWidths);
      }
      int wantedMinimumColWidth = component.getMinimumSize().width - ((colspan - 1) * hgap);
      if (currentMinimumColWidth < wantedMinimumColWidth)
      {
        redistributeSpace(currentMinimumColWidth,
              wantedMinimumColWidth,
              fromCol,toCol,
              minimumColWidths,
              minimumColWidths,
              maximumColWidths);
      }
      int wantedPreferredColWidth = component.getPreferredSize().width - ((colspan - 1) * hgap);
      if (currentPreferredColWidth < wantedPreferredColWidth)
      {
        redistributeSpace(currentPreferredColWidth,
              wantedPreferredColWidth,
              fromCol,toCol,
              preferredColWidths,
              minimumColWidths,
              maximumColWidths);
      }
    }
    
    // correct cases where
    // minimumColWidths[col] <= preferredColWidths[col] <= maximumColWidths[col]
    // is not true by clipping to the minimumColWidths and maximumColWidths
    for (int col=0 ; col<gridSize.width ; col++)
    {
      if (minimumColWidths[col] >= maximumColWidths[col])
      {
        maximumColWidths[col] = minimumColWidths[col];
        preferredColWidths[col] = minimumColWidths[col];
      }
      else if (preferredColWidths[col] < minimumColWidths[col])
      {
        preferredColWidths[col] = minimumColWidths[col];
      }
      else if (preferredColWidths[col] > maximumColWidths[col])
      {
        preferredColWidths[col] = maximumColWidths[col];
      }
    }
    
    // correct cases where
    // minimumRowHeights[row] <= preferredRowHeights[row] <= maximumRowHeights[row]
    // is not true by clipping to the minimumRowHeights and maximumRowHeights
    for (int row=0 ; row<gridSize.height ; row++)
    {
      if (minimumRowHeights[row] >= maximumRowHeights[row])
      {
        maximumRowHeights[row] = minimumRowHeights[row];
        preferredRowHeights[row] = minimumRowHeights[row];
      }
      else if (preferredRowHeights[row] < minimumRowHeights[row])
      {
        preferredRowHeights[row] = minimumRowHeights[row];
      }
      else if (preferredRowHeights[row] > maximumRowHeights[row])
      {
        preferredRowHeights[row] = maximumRowHeights[row];
      }
    }
    
    // plug in the rowspans and correct the minimum, preferred and
    // maximum row heights the rowspans are part of
    for (ExtendedGridLayoutConstraints cell : rowspans)
    {
      int fromRow = cell.getRow();
      int rowspan = cell.getEffectiveRowspan();
      int toRow = fromRow + rowspan;
      int currentMinimumRowHeight = 0;
      int currentPreferredRowHeight = 0;
      int currentMaximumRowHeight = 0;
      for (int row=fromRow ; row<toRow ; row++)
      {
        int minimumRowHeight = minimumRowHeights[row];
        if ((Integer.MAX_VALUE-minimumRowHeight) < currentMinimumRowHeight)
        {
          currentMinimumRowHeight = Integer.MAX_VALUE;
        }
        else
        {
          currentMinimumRowHeight += minimumRowHeight;
        }
        int preferredRowHeight = preferredRowHeights[row];
        if ((Integer.MAX_VALUE-preferredRowHeight) < currentPreferredRowHeight)
        {
          currentPreferredRowHeight = Integer.MAX_VALUE;
        }
        else
        {
          currentPreferredRowHeight += preferredRowHeight;
        }
        int maximumRowHeight = maximumRowHeights[row];
        if ((Integer.MAX_VALUE-maximumRowHeight) < currentMaximumRowHeight)
        {
          currentMaximumRowHeight = Integer.MAX_VALUE;
        }
        else
        {
          currentMaximumRowHeight += maximumRowHeight;
        }
      }
      Component component = cell.getComponent();
      int wantedMaximumRowHeight = component.getMaximumSize().height - ((rowspan - 1) * vgap);
      if (currentMaximumRowHeight < wantedMaximumRowHeight)
      {
        redistributeSpace(currentMaximumRowHeight,
              wantedMaximumRowHeight,
              fromRow,toRow,
              maximumRowHeights,
              maximumRowHeights,
              maximumRowHeights);
      }
      int wantedMinimumRowHeight = component.getMinimumSize().height - ((rowspan - 1) * vgap);
      if (currentMinimumRowHeight < wantedMinimumRowHeight)
      {
        redistributeSpace(currentMinimumRowHeight,
              wantedMinimumRowHeight,
              fromRow,toRow,
              minimumRowHeights,
              minimumRowHeights,
              maximumRowHeights);
      }
      int wantedPreferredRowHeight = component.getPreferredSize().height - ((rowspan - 1) * vgap);
      if (currentPreferredRowHeight < wantedPreferredRowHeight)
      {
        redistributeSpace(currentPreferredRowHeight,
              wantedPreferredRowHeight,
              fromRow,toRow,
              preferredRowHeights,
              minimumRowHeights,
              maximumRowHeights);
      }
    }
    
    // correct cases where
    // minimumRowHeights[row] <= preferredRowHeights[row] <= maximumRowHeights[row]
    // is not true by clipping to the minimumRowHeights and maximumRowHeights
    for (int row=0 ; row<gridSize.height ; row++)
    {
      if (minimumRowHeights[row] >= maximumRowHeights[row])
      {
        maximumRowHeights[row] = minimumRowHeights[row];
        preferredRowHeights[row] = minimumRowHeights[row];
      }
      else if (preferredRowHeights[row] < minimumRowHeights[row])
      {
        preferredRowHeights[row] = minimumRowHeights[row];
      }
      else if (preferredRowHeights[row] > maximumRowHeights[row])
      {
        preferredRowHeights[row] = maximumRowHeights[row];
      }
    }
    
    // copies the computed sizes to the result arrays
    if (fillRawSizes)
    {
      resultArrays[0] = minimumColWidths;
      resultArrays[1] = minimumRowHeights;
      resultArrays[2] = preferredColWidths;
      resultArrays[3] = preferredRowHeights;
      resultArrays[4] = maximumColWidths;
      resultArrays[5] = maximumRowHeights;
    }
    
    // sums up the sizes for return value
    int[] colWidths;
    int[] rowHeights;
    switch (layoutSize)
    {
      case MINIMUM:
        colWidths = minimumColWidths;
        rowHeights = minimumRowHeights;
        break;
      
      case PREFERRED:
        colWidths = preferredColWidths;
        rowHeights = preferredRowHeights;
        break;
      
      case MAXIMUM:
        colWidths = maximumColWidths;
        rowHeights = maximumRowHeights;
        break;
      
      default:
        throw new InternalError("Missing case branch for LayoutSize: " + layoutSize);
    }
    long totalWidth = 0;
    long totalHeight = 0;
    for (int width : colWidths)
    {
      totalWidth += width;
    }
    for (int height : rowHeights)
    {
      totalHeight += height;
    }
    
    // add space between components or between
    // componetns and the borders of the parent container
    if (!fillRawSizes)
    {
      Insets insets = parent.getInsets();
      totalWidth += insets.left + insets.right + ((gridSize.width - 1) * hgap) + distanceToBorders.left + distanceToBorders.right;
      totalHeight += insets.top + insets.bottom + ((gridSize.height - 1) * vgap) + distanceToBorders.top + distanceToBorders.bottom;
    }
    
    // clip the size to Integer.MAX_VALUE if too big
    if (totalWidth > Integer.MAX_VALUE)
    {
      totalWidth = Integer.MAX_VALUE;
    }
    if (totalHeight > Integer.MAX_VALUE)
    {
      totalHeight = Integer.MAX_VALUE;
    }
    
    return new Dimension((int)totalWidth,(int)totalHeight);
  }
  
  /**
    * Builds up the grid for the specified container,
    * given the components it contains.
    * 
    * @param parent   The container to be laid out
    * @param gridRows In this {@code List<List>} the grid gets stored
    * @param colspans In this {@code Set} the constraints which are part
    *                 of a colspan get stored
    * @param rowspans In this {@code Set} the constraints which are part
    *                 of a rowspan get stored
    * @return The amount of rows and columns in the grid
    */
  private Dimension buildGrid(Container parent, List<List<ExtendedGridLayoutConstraints>> gridRows,
            Set<ExtendedGridLayoutConstraints> colspans, Set<ExtendedGridLayoutConstraints> rowspans)
  {
    // put the parent's components in source rows
    List<List<ExtendedGridLayoutConstraints>> rows = new ArrayList<List<ExtendedGridLayoutConstraints>>();
    Component[] components = parent.getComponents();
    for (Component component : components)
    {
      if (component.isVisible())
      {
        ExtendedGridLayoutConstraints constraints = lookupConstraints(component).getWorkCopy();
        int rowNumber = constraints.getRow();
        for (int i=rowNumber, c=rows.size() ; i>=c ; i--)
        {
          rows.add(new ArrayList<ExtendedGridLayoutConstraints>());
        }
        List<ExtendedGridLayoutConstraints> row = rows.get(rowNumber);
        row.add(constraints);
      }
    }
    
    // initialize the rowIterators, gridRowIterators and gridRows
    List<Iterator<ExtendedGridLayoutConstraints>> rowIterators = new ArrayList<Iterator<ExtendedGridLayoutConstraints>>();
    List<ListIterator<ExtendedGridLayoutConstraints>> gridRowIterators = new ArrayList<ListIterator<ExtendedGridLayoutConstraints>>();
    boolean haveNext = false;
    for (List<ExtendedGridLayoutConstraints> row : rows)
    {
      Iterator<ExtendedGridLayoutConstraints> rowIterator = row.iterator();
      rowIterators.add(rowIterator);
      if (rowIterator.hasNext())
      {
        haveNext = true;
      }
      List<ExtendedGridLayoutConstraints> gridRow = new ArrayList<ExtendedGridLayoutConstraints>();
      gridRows.add(gridRow);
      gridRowIterators.add(gridRow.listIterator());
    }
    
    // build the grid
    int col = -1;
    while (haveNext)
    {
      col++;
      haveNext = false;
      for (int row=0, c=gridRows.size() ; row<c ; row++)
      {
        Iterator<ExtendedGridLayoutConstraints> rowIterator = rowIterators.get(row);
        ListIterator<ExtendedGridLayoutConstraints> gridRowIterator = gridRowIterators.get(row);
        
        // look for a rowspan in the previous row
        if (row > 0)
        {
          ExtendedGridLayoutConstraints rowspanSource = gridRows.get(row-1).get(col);
          if (null != rowspanSource)
          {
            ExtendedGridLayoutConstraints rowspanPlaceholder = rowspanSource.getRowspanPlaceholder(true);
            if (null != rowspanPlaceholder)
            {
              rowspans.add(rowspanSource);
              gridRowIterator.add(rowspanPlaceholder);
              if (null != rowspanPlaceholder.getColspanPlaceholder(false))
              {
                switch (rowspanPlaceholder.getColspan())
                {
                  case REMAINDER:
                    break;
                  
                  default:
                    haveNext = true;
                }
              }
              else if (rowIterator.hasNext())
              {
                haveNext = true;
              }
              continue;
            }
          }
        }
        
        // look for a colspan in the previous column
        if (gridRowIterator.hasPrevious())
        {
          ExtendedGridLayoutConstraints colspanSource = gridRowIterator.previous();
          gridRowIterator.next();
          if (null != colspanSource)
          {
            ExtendedGridLayoutConstraints colspanPlaceholder = colspanSource.getColspanPlaceholder(true);
            if (null != colspanPlaceholder)
            {
              colspans.add(colspanSource);
              gridRowIterator.add(colspanPlaceholder);
              if (null != colspanPlaceholder.getColspanPlaceholder(false))
              {
                switch (colspanPlaceholder.getColspan())
                {
                  case REMAINDER:
                    break;
                  
                  default:
                    haveNext = true;
                }
              }
              else if (rowIterator.hasNext())
              {
                haveNext = true;
              }
              continue;
            }
          }
        }
        
        // add a new element or null
        if (rowIterator.hasNext())
        {
          ExtendedGridLayoutConstraints newConstraints = rowIterator.next();
          newConstraints.setCol(col);
          gridRowIterator.add(newConstraints);
          if (null != newConstraints.getColspanPlaceholder(false))
          {
            switch (newConstraints.getColspan())
            {
              case REMAINDER:
                break;
              
              default:
                haveNext = true;
            }
          }
          else if (rowIterator.hasNext())
          {
            haveNext = true;
          }
        }
        else
        {
          gridRowIterator.add(null);
        }
      }
    }
    
    // check the last gridRow for rowspans and probably add rows for these
    haveNext = false;
    int gridRowsSize = gridRows.size();
    if (gridRowsSize > 0)
    {
      ListIterator<ExtendedGridLayoutConstraints> gridRowIterator = gridRows.get(gridRows.size()-1).listIterator();
      while (gridRowIterator.hasNext())
      {
        ExtendedGridLayoutConstraints cell = gridRowIterator.next();
        if ((null != cell) &&
            ((REMAINDER != cell.getRowspan()) &&
             (null != cell.getRowspanPlaceholder(false))))
        {
          haveNext = true;
          break;
        }
      }
      while (haveNext)
      {
        haveNext = false;
        gridRowIterator = gridRows.get(gridRows.size()-1).listIterator();
        List<ExtendedGridLayoutConstraints> gridRow = new ArrayList<ExtendedGridLayoutConstraints>();
        gridRows.add(gridRow);
        ListIterator<ExtendedGridLayoutConstraints> newGridRowIterator = gridRow.listIterator();
        while (gridRowIterator.hasNext())
        {
          ExtendedGridLayoutConstraints cell = gridRowIterator.next();
          if ((null != cell) &&
              (null != cell.getRowspanPlaceholder(false)))
          {
            rowspans.add(cell);
            ExtendedGridLayoutConstraints rowspanPlaceholder = cell.getRowspanPlaceholder(true);
            newGridRowIterator.add(rowspanPlaceholder);
          }
          else
          {
            newGridRowIterator.add(null);
          }
        }
        gridRowIterator = gridRow.listIterator();
        while (gridRowIterator.hasNext())
        {
          ExtendedGridLayoutConstraints cell = gridRowIterator.next();
          if ((null != cell) &&
              ((REMAINDER != cell.getRowspan()) &&
               (null != cell.getRowspanPlaceholder(false))))
          {
            haveNext = true;
            break;
          }
        }
      }
    }
    
    return new Dimension(col+1,gridRows.size());
  }
  
  /**
    * Returns a string representation of the object. In general, the
    * {@code toString} method returns a string that
    * "textually represents" this object. The result should
    * be a concise but informative representation that is easy for a
    * person to read.
    * 
    * @return  a string representation of the object.
    */
  public String toString()
  {
    return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap
      + ",distanceToBorders=" + distanceToBorders
      + ",comptable=" + comptable + "]";
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.