Java/Swing JFC/Customized Layout

Материал из Java эксперт
Версия от 18:01, 31 мая 2010; (обсуждение)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

A layout manager that displays a single component in the center of its container.

  
 
/*
 * JCommon : a free general purpose class library for the Java(tm) platform
 *
 *
 * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
 * 
 * Project Info:  http://www.jfree.org/jcommon/index.html
 *
 * This library is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU Lesser General Public License as published by 
 * the Free Software Foundation; either version 2.1 of the License, or 
 * (at your option) any later version.
 *
 * This library 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 Lesser General Public 
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
 * USA.  
 *
 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
 * in the United States and other countries.]
 * 
 * -----------------
 * CenterLayout.java
 * -----------------
 * (C) Copyright 2000-2005, by Object Refinery Limited.
 *
 * Original Author:  David Gilbert (for Object Refinery Limited);
 * Contributor(s):   -;
 *
 * $Id: CenterLayout.java,v 1.6 2005/11/16 15:58:40 taqua Exp $
 *
 * Changes (from 5-Nov-2001)
 * -------------------------
 * 05-Nov-2001 : Changed package to com.jrefinery.layout.* (DG);
 * 10-Oct-2002 : Fixed errors reported by Checkstyle (DG);
 *
 */
import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.io.Serializable;
/**
 * A layout manager that displays a single component in the center of its
 * container.
 * 
 * @author David Gilbert
 */
public class CenterLayout implements LayoutManager, Serializable {
  /** For serialization. */
  private static final long serialVersionUID = 469319532333015042L;
  /**
   * Creates a new layout manager.
   */
  public CenterLayout() {
  }
  /**
   * Returns the preferred size.
   * 
   * @param parent
   *          the parent.
   * 
   * @return the preferred size.
   */
  public Dimension preferredLayoutSize(final Container parent) {
    synchronized (parent.getTreeLock()) {
      final Insets insets = parent.getInsets();
      if (parent.getComponentCount() > 0) {
        final Component component = parent.getComponent(0);
        final Dimension d = component.getPreferredSize();
        return new Dimension((int) d.getWidth() + insets.left + insets.right, (int) d.getHeight()
            + insets.top + insets.bottom);
      } else {
        return new Dimension(insets.left + insets.right, insets.top + insets.bottom);
      }
    }
  }
  /**
   * Returns the minimum size.
   * 
   * @param parent
   *          the parent.
   * 
   * @return the minimum size.
   */
  public Dimension minimumLayoutSize(final Container parent) {
    synchronized (parent.getTreeLock()) {
      final Insets insets = parent.getInsets();
      if (parent.getComponentCount() > 0) {
        final Component component = parent.getComponent(0);
        final Dimension d = component.getMinimumSize();
        return new Dimension(d.width + insets.left + insets.right, d.height + insets.top
            + insets.bottom);
      } else {
        return new Dimension(insets.left + insets.right, insets.top + insets.bottom);
      }
    }
  }
  /**
   * Lays out the components.
   * 
   * @param parent
   *          the parent.
   */
  public void layoutContainer(final Container parent) {
    synchronized (parent.getTreeLock()) {
      if (parent.getComponentCount() > 0) {
        final Insets insets = parent.getInsets();
        final Dimension parentSize = parent.getSize();
        final Component component = parent.getComponent(0);
        final Dimension componentSize = component.getPreferredSize();
        final int xx = insets.left
            + (Math.max((parentSize.width - insets.left - insets.right - componentSize.width) / 2,
                0));
        final int yy = insets.top
            + (Math.max(
                (parentSize.height - insets.top - insets.bottom - componentSize.height) / 2, 0));
        component.setBounds(xx, yy, componentSize.width, componentSize.height);
      }
    }
  }
  /**
   * Not used.
   * 
   * @param comp
   *          the component.
   */
  public void addLayoutComponent(final Component comp) {
    // not used.
  }
  /**
   * Not used.
   * 
   * @param comp
   *          the component.
   */
  public void removeLayoutComponent(final Component comp) {
    // not used
  }
  /**
   * Not used.
   * 
   * @param name
   *          the component name.
   * @param comp
   *          the component.
   */
  public void addLayoutComponent(final String name, final Component comp) {
    // not used
  }
  /**
   * Not used.
   * 
   * @param name
   *          the component name.
   * @param comp
   *          the component.
   */
  public void removeLayoutComponent(final String name, final Component comp) {
    // not used
  }
}





A layout manager that spaces components over six columns in seven different formats.

  

/* 
 * JCommon : a free general purpose class library for the Java(tm) platform
 * 
 *
 * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
 * 
 * Project Info:  http://www.jfree.org/jcommon/index.html
 *
 * This library is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU Lesser General Public License as published by 
 * the Free Software Foundation; either version 2.1 of the License, or 
 * (at your option) any later version.
 *
 * This library 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 Lesser General Public 
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
 * USA.  
 *
 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
 * in the United States and other countries.]
 * 
 * -----------------
 * FormatLayout.java
 * -----------------
 * (C) Copyright 2000-2005, by Object Refinery Limited.
 *
 * Original Author:  David Gilbert (for Object Refinery Limited);
 * Contributor(s):   -;
 *
 * $Id: FormatLayout.java,v 1.4 2005/10/18 13:16:50 mungady Exp $
 *
 * Changes (from 26-Oct-2001)
 * --------------------------
 * 26-Oct-2001 : Changed package to com.jrefinery.layout.* (DG);
 * 26-Jun-2002 : Removed redundant code (DG);
 * 10-Oct-2002 : Fixed errors reported by Checkstyle (DG);
 *
 */

import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.io.Serializable;
/**
 * A layout manager that spaces components over six columns in seven different 
 * formats.
 *
 * @author David Gilbert
 */
public class FormatLayout implements LayoutManager, Serializable {
    /** For serialization. */
    private static final long serialVersionUID = 2866692886323930722L;
    
    /** A useful constant representing layout format 1. */
    public static final int C = 1;
    /** A useful constant representing layout format 2. */
    public static final int LC = 2;
    /** A useful constant representing layout format 3. */
    public static final int LCB = 3;
    /** A useful constant representing layout format 4. */
    public static final int LCLC = 4;
    /** A useful constant representing layout format 5. */
    public static final int LCLCB = 5;
    /** A useful constant representing layout format 6. */
    public static final int LCBLC = 6;
    /** A useful constant representing layout format 7. */
    public static final int LCBLCB = 7;
    /** The layout format for each row. */
    private int[] rowFormats;
    /** The gap between the rows. */
    private int rowGap;
    /** 
     * The gaps between the columns (gap[0] is the gap following column zero). 
     */
    private int[] columnGaps;
    /** Working array for recording the height of each row. */
    private int[] rowHeights;
    /** The total height of the layout. */
    private int totalHeight;
    /** Working array for recording the width of each column. */
    private int[] columnWidths;
    /** The total width of the layout. */
    private int totalWidth;
    /** Combined width of columns 1 and 2. */
    private int columns1and2Width;
    /** Combined width of columns 4 and 5. */
    private int columns4and5Width;
    /** Combined width of columns 1 to 4. */
    private int columns1to4Width;
    /** Combined width of columns 1 to 5. */
    private int columns1to5Width;
    /** Combined width of columns 0 to 5. */
    private int columns0to5Width;
    /**
     * Constructs a new layout manager that can be used to create input forms.  
     * The layout manager works by arranging components in rows using six 
     * columns (some components will use more than one column).
     * <P>
     * Any component can be added, but I think of them in terms of Labels,
     * Components, and Buttons.
     * The formats available are:  C, LC, LCB, LCLC, LCLCB, LCBLC or LCBLCB.
     * <table>
     * <tr>
     * <td>C</td>
     * <td>1 component in this row (spread across all six columns).</td>
     * </tr>
     * <tr>
     * <td>LC</td>
     * <td>2 components, a label in the 1st column, and a component using the
     *      remaining 5 columns).</td>
     * </tr>
     * <tr>
     * <td>LCB</td>
     * <td>3 components, a label in the 1st column, a component spread across
     *      the next 4, and a button in the last column.</td>
     * </tr>
     * <tr>
     * <td>LCLC</td>
     * <td>4 components, a label in column 1, a component in 2-3, a label in
     *       4 and a component in 5-6.</td>
     * </tr>
     * <tr>
     * <td>LCLCB</td>
     * <td>5 components, a label in column 1, a component in 2-3, a label
     *      in 4, a component in 5 and a button in 6.</td>
     * </tr>
     * <tr>
     * <td>LCBLC</td>
     * <td>5 components, a label in column 1, a component in 2, a button in 3,
     *  a label in 4, a component in 5-6.</td>
     * </tr>
     * <tr>
     * <td>LCBLCB</td>
     * <td>6 components, one in each column.</td>
     * </tr>
     * </table>
     * <P>
     * Columns 1 and 4 expand to accommodate the widest label, and 3 and 6 to
     * accommodate the widest button.
     * <P>
     * Each row will contain the number of components indicated by the format.  
     * Be sure to specify enough row formats to cover all the components you 
     * add to the layout.
     *
     * @param rowCount  the number of rows.
     * @param rowFormats  the row formats.
     */
    public FormatLayout(final int rowCount, final int[] rowFormats) {
        this.rowFormats = rowFormats;
        this.rowGap = 2;
        this.columnGaps = new int[5];
        this.columnGaps[0] = 10;
        this.columnGaps[1] = 5;
        this.columnGaps[2] = 5;
        this.columnGaps[3] = 10;
        this.columnGaps[4] = 5;
        // working structures...
        this.rowHeights = new int[rowCount];
        this.columnWidths = new int[6];
    }
    /**
     * Returns the preferred size of the component using this layout manager.
     *
     * @param parent  the parent.
     *
     * @return the preferred size of the component.
     */
    public Dimension preferredLayoutSize(final Container parent) {
        Component c0, c1, c2, c3, c4, c5;
        synchronized (parent.getTreeLock()) {
            final Insets insets = parent.getInsets();
            int componentIndex = 0;
            final int rowCount = this.rowHeights.length;
            for (int i = 0; i < this.columnWidths.length; i++) {
                this.columnWidths[i] = 0;
            }
            this.columns1and2Width = 0;
            this.columns4and5Width = 0;
            this.columns1to4Width = 0;
            this.columns1to5Width = 0;
            this.columns0to5Width = 0;
            this.totalHeight = 0;
            for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) {
            final int format 
                = this.rowFormats[rowIndex % this.rowFormats.length];
                switch (format) {
                    case FormatLayout.C:
                        c0 = parent.getComponent(componentIndex);
                        updateC(rowIndex, c0.getPreferredSize());
                        componentIndex = componentIndex + 1;
                        break;
                    case FormatLayout.LC:
                        c0 = parent.getComponent(componentIndex);
                        c1 = parent.getComponent(componentIndex + 1);
                        updateLC(rowIndex, c0.getPreferredSize(), 
                                c1.getPreferredSize());
                        componentIndex = componentIndex + 2;
                        break;
                    case FormatLayout.LCB:
                        c0 = parent.getComponent(componentIndex);
                        c1 = parent.getComponent(componentIndex + 1);
                        c2 = parent.getComponent(componentIndex + 2);
                        updateLCB(rowIndex,
                                  c0.getPreferredSize(),
                                  c1.getPreferredSize(),
                                  c2.getPreferredSize());
                        componentIndex = componentIndex + 3;
                        break;
                    case FormatLayout.LCLC:
                        c0 = parent.getComponent(componentIndex);
                        c1 = parent.getComponent(componentIndex + 1);
                        c2 = parent.getComponent(componentIndex + 2);
                        c3 = parent.getComponent(componentIndex + 3);
                        updateLCLC(rowIndex,
                                   c0.getPreferredSize(),
                                   c1.getPreferredSize(),
                                   c2.getPreferredSize(),
                                   c3.getPreferredSize());
                        componentIndex = componentIndex + 4;
                        break;
                    case FormatLayout.LCBLC:
                        c0 = parent.getComponent(componentIndex);
                        c1 = parent.getComponent(componentIndex + 1);
                        c2 = parent.getComponent(componentIndex + 2);
                        c3 = parent.getComponent(componentIndex + 3);
                        c4 = parent.getComponent(componentIndex + 4);
                        updateLCBLC(rowIndex,
                                    c0.getPreferredSize(),
                                    c1.getPreferredSize(),
                                    c2.getPreferredSize(),
                                    c3.getPreferredSize(),
                                    c4.getPreferredSize());
                        componentIndex = componentIndex + 5;
                        break;
                    case FormatLayout.LCLCB:
                        c0 = parent.getComponent(componentIndex);
                        c1 = parent.getComponent(componentIndex + 1);
                        c2 = parent.getComponent(componentIndex + 2);
                        c3 = parent.getComponent(componentIndex + 3);
                        c4 = parent.getComponent(componentIndex + 4);
                        updateLCLCB(rowIndex,
                                    c0.getPreferredSize(),
                                    c1.getPreferredSize(),
                                    c2.getPreferredSize(),
                                    c3.getPreferredSize(),
                                    c4.getPreferredSize());
                        componentIndex = componentIndex + 5;
                        break;
                    case FormatLayout.LCBLCB:
                        c0 = parent.getComponent(componentIndex);
                        c1 = parent.getComponent(componentIndex + 1);
                        c2 = parent.getComponent(componentIndex + 2);
                        c3 = parent.getComponent(componentIndex + 3);
                        c4 = parent.getComponent(componentIndex + 4);
                        c5 = parent.getComponent(componentIndex + 5);
                        updateLCBLCB(rowIndex,
                                     c0.getPreferredSize(),
                                     c1.getPreferredSize(),
                                     c2.getPreferredSize(),
                                     c3.getPreferredSize(),
                                     c4.getPreferredSize(),
                                     c5.getPreferredSize());
                        componentIndex = componentIndex + 6;
                        break;
                }
            }
            complete();
            return new Dimension(this.totalWidth + insets.left + insets.right,
                    this.totalHeight + (rowCount - 1) * this.rowGap
                                 + insets.top + insets.bottom);
        }
    }
    /**
     * Returns the minimum size of the component using this layout manager.
     *
     * @param parent  the parent.
     *
     * @return the minimum size of the component
     */
    public Dimension minimumLayoutSize(final Container parent) {
        Component c0, c1, c2, c3, c4, c5;
        synchronized (parent.getTreeLock()) {
            final Insets insets = parent.getInsets();
            int componentIndex = 0;
            final int rowCount = this.rowHeights.length;
            for (int i = 0; i < this.columnWidths.length; i++) {
                this.columnWidths[i] = 0;
            }
            this.columns1and2Width = 0;
            this.columns4and5Width = 0;
            this.columns1to4Width = 0;
            this.columns1to5Width = 0;
            this.columns0to5Width = 0;
            final int totalHeight = 0;
            for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) {
                final int format 
                    = this.rowFormats[rowIndex % this.rowFormats.length];
                switch (format) {
                    case FormatLayout.C:
                        c0 = parent.getComponent(componentIndex);
                        this.columns0to5Width = Math.max(
                            this.columns0to5Width, c0.getMinimumSize().width
                        );
                        componentIndex = componentIndex + 1;
                        break;
                    case FormatLayout.LC:
                        c0 = parent.getComponent(componentIndex);
                        c1 = parent.getComponent(componentIndex + 1);
                        updateLC(rowIndex,
                                 c0.getMinimumSize(),
                                 c1.getMinimumSize());
                        componentIndex = componentIndex + 2;
                        break;
                    case FormatLayout.LCB:
                        c0 = parent.getComponent(componentIndex);
                        c1 = parent.getComponent(componentIndex + 1);
                        c2 = parent.getComponent(componentIndex + 2);
                        updateLCB(rowIndex,
                                  c0.getMinimumSize(),
                                  c1.getMinimumSize(),
                                  c2.getMinimumSize());
                        componentIndex = componentIndex + 3;
                        break;
                    case FormatLayout.LCLC:
                        c0 = parent.getComponent(componentIndex);
                        c1 = parent.getComponent(componentIndex + 1);
                        c2 = parent.getComponent(componentIndex + 2);
                        c3 = parent.getComponent(componentIndex + 3);
                        updateLCLC(rowIndex,
                                   c0.getMinimumSize(),
                                   c1.getMinimumSize(),
                                   c2.getMinimumSize(),
                                   c3.getMinimumSize());
                        componentIndex = componentIndex + 3;
                        break;
                    case FormatLayout.LCBLC:
                        c0 = parent.getComponent(componentIndex);
                        c1 = parent.getComponent(componentIndex + 1);
                        c2 = parent.getComponent(componentIndex + 2);
                        c3 = parent.getComponent(componentIndex + 3);
                        c4 = parent.getComponent(componentIndex + 4);
                        updateLCBLC(rowIndex,
                                    c0.getMinimumSize(),
                                    c1.getMinimumSize(),
                                    c2.getMinimumSize(),
                                    c3.getMinimumSize(),
                                    c4.getMinimumSize());
                        componentIndex = componentIndex + 4;
                        break;
                    case FormatLayout.LCLCB:
                        c0 = parent.getComponent(componentIndex);
                        c1 = parent.getComponent(componentIndex + 1);
                        c2 = parent.getComponent(componentIndex + 2);
                        c3 = parent.getComponent(componentIndex + 3);
                        c4 = parent.getComponent(componentIndex + 4);
                        updateLCLCB(rowIndex,
                                    c0.getMinimumSize(),
                                    c1.getMinimumSize(),
                                    c2.getMinimumSize(),
                                    c3.getMinimumSize(),
                                    c4.getMinimumSize());
                        componentIndex = componentIndex + 4;
                        break;
                    case FormatLayout.LCBLCB:
                        c0 = parent.getComponent(componentIndex);
                        c1 = parent.getComponent(componentIndex + 1);
                        c2 = parent.getComponent(componentIndex + 2);
                        c3 = parent.getComponent(componentIndex + 3);
                        c4 = parent.getComponent(componentIndex + 4);
                        c5 = parent.getComponent(componentIndex + 5);
                        updateLCBLCB(rowIndex,
                                     c0.getMinimumSize(),
                                     c1.getMinimumSize(),
                                     c2.getMinimumSize(),
                                     c3.getMinimumSize(),
                                     c4.getMinimumSize(),
                                     c5.getMinimumSize());
                        componentIndex = componentIndex + 5;
                        break;
                }
            }
            complete();
            return new Dimension(this.totalWidth + insets.left + insets.right,
                                 totalHeight + (rowCount - 1) * this.rowGap
                                 + insets.top + insets.bottom);
        }
    }
    /**
     * Performs the layout of the container.
     *
     * @param parent  the parent.
     */
    public void layoutContainer(final Container parent) {
        Component c0, c1, c2, c3, c4, c5;
        synchronized (parent.getTreeLock()) {
            final Insets insets = parent.getInsets();
            int componentIndex = 0;
            final int rowCount = this.rowHeights.length;
            for (int i = 0; i < this.columnWidths.length; i++) {
                this.columnWidths[i] = 0;
            }
            this.columns1and2Width = 0;
            this.columns4and5Width = 0;
            this.columns1to4Width = 0;
            this.columns1to5Width = 0;
            this.columns0to5Width 
                = parent.getBounds().width - insets.left - insets.right;
            this.totalHeight = 0;
            for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) {
                final int format 
                    = this.rowFormats[rowIndex % this.rowFormats.length];
                switch (format) {
                    case FormatLayout.C:
                        c0 = parent.getComponent(componentIndex);
                        updateC(rowIndex, c0.getPreferredSize());
                        componentIndex = componentIndex + 1;
                        break;
                    case FormatLayout.LC:
                        c0 = parent.getComponent(componentIndex);
                        c1 = parent.getComponent(componentIndex + 1);
                        updateLC(rowIndex, c0.getPreferredSize(), 
                                c1.getPreferredSize());
                        componentIndex = componentIndex + 2;
                        break;
                    case FormatLayout.LCB:
                        c0 = parent.getComponent(componentIndex);
                        c1 = parent.getComponent(componentIndex + 1);
                        c2 = parent.getComponent(componentIndex + 2);
                        updateLCB(rowIndex,
                                  c0.getPreferredSize(),
                                  c1.getPreferredSize(),
                                  c2.getPreferredSize());
                        componentIndex = componentIndex + 3;
                        break;
                    case FormatLayout.LCLC:
                        c0 = parent.getComponent(componentIndex);
                        c1 = parent.getComponent(componentIndex + 1);
                        c2 = parent.getComponent(componentIndex + 2);
                        c3 = parent.getComponent(componentIndex + 3);
                        updateLCLC(rowIndex,
                                   c0.getPreferredSize(),
                                   c1.getPreferredSize(),
                                   c2.getPreferredSize(),
                                   c3.getPreferredSize());
                        componentIndex = componentIndex + 4;
                        break;
                    case FormatLayout.LCBLC:
                        c0 = parent.getComponent(componentIndex);
                        c1 = parent.getComponent(componentIndex + 1);
                        c2 = parent.getComponent(componentIndex + 2);
                        c3 = parent.getComponent(componentIndex + 3);
                        c4 = parent.getComponent(componentIndex + 4);
                        updateLCBLC(rowIndex,
                                    c0.getPreferredSize(),
                                    c1.getPreferredSize(),
                                    c2.getPreferredSize(),
                                    c3.getPreferredSize(),
                                    c4.getPreferredSize());
                        componentIndex = componentIndex + 5;
                        break;
                    case FormatLayout.LCLCB:
                        c0 = parent.getComponent(componentIndex);
                        c1 = parent.getComponent(componentIndex + 1);
                        c2 = parent.getComponent(componentIndex + 2);
                        c3 = parent.getComponent(componentIndex + 3);
                        c4 = parent.getComponent(componentIndex + 4);
                        updateLCLCB(rowIndex,
                                    c0.getPreferredSize(),
                                    c1.getPreferredSize(),
                                    c2.getPreferredSize(),
                                    c3.getPreferredSize(),
                                    c4.getPreferredSize());
                        componentIndex = componentIndex + 5;
                        break;
                    case FormatLayout.LCBLCB:
                        c0 = parent.getComponent(componentIndex);
                        c1 = parent.getComponent(componentIndex + 1);
                        c2 = parent.getComponent(componentIndex + 2);
                        c3 = parent.getComponent(componentIndex + 3);
                        c4 = parent.getComponent(componentIndex + 4);
                        c5 = parent.getComponent(componentIndex + 5);
                        updateLCBLCB(rowIndex,
                                     c0.getPreferredSize(),
                                     c1.getPreferredSize(),
                                     c2.getPreferredSize(),
                                     c3.getPreferredSize(),
                                     c4.getPreferredSize(),
                                     c5.getPreferredSize());
                        componentIndex = componentIndex + 6;
                        break;
                }
            }
            complete();
            componentIndex = 0;
            int rowY = insets.top;
            final int[] rowX = new int[6];
            rowX[0] = insets.left;
            rowX[1] = rowX[0] + this.columnWidths[0] + this.columnGaps[0];
            rowX[2] = rowX[1] + this.columnWidths[1] + this.columnGaps[1];
            rowX[3] = rowX[2] + this.columnWidths[2] + this.columnGaps[2];
            rowX[4] = rowX[3] + this.columnWidths[3] + this.columnGaps[3];
            rowX[5] = rowX[4] + this.columnWidths[4] + this.columnGaps[4];
            final int w1to2 = this.columnWidths[1] + this.columnGaps[1] 
                              + this.columnWidths[2];
            final int w4to5 = this.columnWidths[4] + this.columnGaps[4] 
                              + this.columnWidths[5];
            final int w1to4 = w1to2 + this.columnGaps[2] + this.columnWidths[3]
                        + this.columnGaps[3] + this.columnWidths[4];
            final int w1to5 = w1to4 + this.columnGaps[4] + this.columnWidths[5];
            final int w0to5 = w1to5 + this.columnWidths[0] + this.columnGaps[0];
            for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) {
                final int format 
                    = this.rowFormats[rowIndex % this.rowFormats.length];
                switch (format) {
                case FormatLayout.C:
                    c0 = parent.getComponent(componentIndex);
                    c0.setBounds(rowX[0], rowY, w0to5, 
                            c0.getPreferredSize().height);
                    componentIndex = componentIndex + 1;
                    break;
                case FormatLayout.LC:
                    c0 = parent.getComponent(componentIndex);
                    c0.setBounds(
                        rowX[0],
                        rowY + (this.rowHeights[rowIndex] 
                                     - c0.getPreferredSize().height) / 2,
                        this.columnWidths[0], c0.getPreferredSize().height
                    );
                    c1 = parent.getComponent(componentIndex + 1);
                    c1.setBounds(
                        rowX[1],
                        rowY + (this.rowHeights[rowIndex] 
                                     - c1.getPreferredSize().height) / 2,
                        w1to5, c1.getPreferredSize().height
                    );
                    componentIndex = componentIndex + 2;
                    break;
                case FormatLayout.LCB:
                    c0 = parent.getComponent(componentIndex);
                    c0.setBounds(
                        rowX[0],
                        rowY + (this.rowHeights[rowIndex] 
                                     - c0.getPreferredSize().height) / 2,
                        this.columnWidths[0], c0.getPreferredSize().height
                    );
                    c1 = parent.getComponent(componentIndex + 1);
                    c1.setBounds(
                        rowX[1],
                        rowY + (this.rowHeights[rowIndex] 
                                    - c1.getPreferredSize().height) / 2,
                        w1to4, c1.getPreferredSize().height
                    );
                    c2 = parent.getComponent(componentIndex + 2);
                    c2.setBounds(
                        rowX[5],
                        rowY + (this.rowHeights[rowIndex] 
                                    - c2.getPreferredSize().height) / 2,
                        this.columnWidths[5], c2.getPreferredSize().height
                    );
                    componentIndex = componentIndex + 3;
                    break;
                case FormatLayout.LCLC:
                    c0 = parent.getComponent(componentIndex);
                    c0.setBounds(
                        rowX[0],
                        rowY + (this.rowHeights[rowIndex] 
                                    - c0.getPreferredSize().height) / 2,
                        this.columnWidths[0], c0.getPreferredSize().height
                    );
                    c1 = parent.getComponent(componentIndex + 1);
                    c1.setBounds(
                        rowX[1],
                        rowY + (this.rowHeights[rowIndex] 
                                    - c1.getPreferredSize().height) / 2,
                        w1to2, c1.getPreferredSize().height
                    );
                    c2 = parent.getComponent(componentIndex + 2);
                    c2.setBounds(
                        rowX[3],
                        rowY + (this.rowHeights[rowIndex] 
                                    - c2.getPreferredSize().height) / 2,
                        this.columnWidths[3], c2.getPreferredSize().height
                    );
                    c3 = parent.getComponent(componentIndex + 3);
                    c3.setBounds(
                        rowX[4],
                        rowY + (this.rowHeights[rowIndex] 
                                    - c3.getPreferredSize().height) / 2,
                        w4to5, c3.getPreferredSize().height
                    );
                    componentIndex = componentIndex + 4;
                    break;
                case FormatLayout.LCBLC:
                    c0 = parent.getComponent(componentIndex);
                    c0.setBounds(
                        rowX[0],
                        rowY + (this.rowHeights[rowIndex] 
                                    - c0.getPreferredSize().height) / 2,
                        this.columnWidths[0], c0.getPreferredSize().height
                    );
                    c1 = parent.getComponent(componentIndex + 1);
                    c1.setBounds(
                        rowX[1],
                        rowY + (this.rowHeights[rowIndex] 
                                    - c1.getPreferredSize().height) / 2,
                        this.columnWidths[1], c1.getPreferredSize().height
                    );
                    c2 = parent.getComponent(componentIndex + 2);
                    c2.setBounds(
                        rowX[2],
                        rowY + (this.rowHeights[rowIndex] 
                                    - c2.getPreferredSize().height) / 2,
                        this.columnWidths[2], c2.getPreferredSize().height
                    );
                    c3 = parent.getComponent(componentIndex + 3);
                    c3.setBounds(
                        rowX[3],
                        rowY + (this.rowHeights[rowIndex] 
                                    - c3.getPreferredSize().height) / 2,
                        this.columnWidths[3], c3.getPreferredSize().height
                    );
                    c4 = parent.getComponent(componentIndex + 4);
                    c4.setBounds(
                        rowX[4],
                        rowY + (this.rowHeights[rowIndex] 
                                    - c4.getPreferredSize().height) / 2,
                        w4to5, c4.getPreferredSize().height
                    );
                    componentIndex = componentIndex + 5;
                    break;
                case FormatLayout.LCLCB:
                    c0 = parent.getComponent(componentIndex);
                    c0.setBounds(
                        rowX[0],
                        rowY + (this.rowHeights[rowIndex] 
                                    - c0.getPreferredSize().height) / 2,
                        this.columnWidths[0], c0.getPreferredSize().height
                    );
                    c1 = parent.getComponent(componentIndex + 1);
                    c1.setBounds(
                        rowX[1],
                        rowY + (this.rowHeights[rowIndex] 
                                    - c1.getPreferredSize().height) / 2,
                        w1to2, c1.getPreferredSize().height
                    );
                    c2 = parent.getComponent(componentIndex + 2);
                    c2.setBounds(
                        rowX[3],
                        rowY + (this.rowHeights[rowIndex] 
                                    - c2.getPreferredSize().height) / 2,
                        this.columnWidths[3], c2.getPreferredSize().height
                    );
                    c3 = parent.getComponent(componentIndex + 3);
                    c3.setBounds(
                        rowX[4],
                        rowY + (this.rowHeights[rowIndex] 
                                    - c3.getPreferredSize().height) / 2,
                        this.columnWidths[4], c3.getPreferredSize().height
                    );
                    c4 = parent.getComponent(componentIndex + 4);
                    c4.setBounds(
                        rowX[5],
                        rowY + (this.rowHeights[rowIndex] 
                                    - c4.getPreferredSize().height) / 2,
                        this.columnWidths[5], c4.getPreferredSize().height
                    );
                    componentIndex = componentIndex + 5;
                    break;
                case FormatLayout.LCBLCB:
                    c0 = parent.getComponent(componentIndex);
                    c0.setBounds(
                        rowX[0],
                        rowY + (this.rowHeights[rowIndex] 
                                     - c0.getPreferredSize().height) / 2,
                        this.columnWidths[0], c0.getPreferredSize().height
                    );
                    c1 = parent.getComponent(componentIndex + 1);
                    c1.setBounds(
                        rowX[1],
                        rowY + (this.rowHeights[rowIndex] 
                                     - c1.getPreferredSize().height) / 2,
                        this.columnWidths[1], c1.getPreferredSize().height
                    );
                    c2 = parent.getComponent(componentIndex + 2);
                    c2.setBounds(
                        rowX[2],
                        rowY + (this.rowHeights[rowIndex] 
                                     - c2.getPreferredSize().height) / 2,
                        this.columnWidths[2], c2.getPreferredSize().height
                    );
                    c3 = parent.getComponent(componentIndex + 3);
                    c3.setBounds(
                        rowX[3],
                        rowY + (this.rowHeights[rowIndex] 
                                     - c3.getPreferredSize().height) / 2,
                        this.columnWidths[3], c3.getPreferredSize().height
                    );
                    c4 = parent.getComponent(componentIndex + 4);
                    c4.setBounds(
                        rowX[4],
                        rowY + (this.rowHeights[rowIndex] 
                                     - c4.getPreferredSize().height) / 2,
                        this.columnWidths[4], c4.getPreferredSize().height
                    );
                    c5 = parent.getComponent(componentIndex + 5);
                    c5.setBounds(
                        rowX[5],
                        rowY + (this.rowHeights[rowIndex] 
                                     - c5.getPreferredSize().height) / 2,
                        this.columnWidths[5], c5.getPreferredSize().height
                    );
                    componentIndex = componentIndex + 6;
                    break;
                    }
                rowY = rowY + this.rowHeights[rowIndex] + this.rowGap;
            }
        }
    }
    /**
     * Processes a row in "C" format.
     *
     * @param rowIndex  the row index.
     * @param d0  dimension 0.
     */
    protected void updateC(final int rowIndex, final Dimension d0) {
        this.rowHeights[rowIndex] = d0.height;
        this.totalHeight = this.totalHeight + this.rowHeights[rowIndex];
        this.columns0to5Width = Math.max(this.columns0to5Width, d0.width);
    }
    /**
     * Processes a row in "LC" format.
     *
     * @param rowIndex  the row index.
     * @param d0  dimension 0.
     * @param d1  dimension 1.
     */
    protected void updateLC(final int rowIndex, final Dimension d0, 
                            final Dimension d1) {
        this.rowHeights[rowIndex] = Math.max(d0.height, d1.height);
        this.totalHeight = this.totalHeight + this.rowHeights[rowIndex];
        this.columnWidths[0] = Math.max(this.columnWidths[0], d0.width);
        this.columns1to5Width = Math.max(this.columns1to5Width, d1.width);
    }
    /**
     * Processes a row in "LCB" format.
     *
     * @param rowIndex  the row index.
     * @param d0  dimension 0.
     * @param d1  dimension 1.
     * @param d2  dimension 2.
     */
    protected void updateLCB(final int rowIndex,
                             final Dimension d0, final Dimension d1, 
                             final Dimension d2) {
        this.rowHeights[rowIndex] 
               = Math.max(d0.height, Math.max(d1.height, d2.height));
        this.totalHeight = this.totalHeight + this.rowHeights[rowIndex];
        this.columnWidths[0] = Math.max(this.columnWidths[0], d0.width);
        this.columns1to4Width = Math.max(this.columns1to4Width, d1.width);
        this.columnWidths[5] = Math.max(this.columnWidths[5], d2.width);
    }
    /**
     * Processes a row in "LCLC" format.
     *
     * @param rowIndex  the row index.
     * @param d0  dimension 0.
     * @param d1  dimension 1.
     * @param d2  dimension 2.
     * @param d3  dimension 3.
     */
    protected void updateLCLC(final int rowIndex, final Dimension d0, 
                              final Dimension d1, final Dimension d2, 
                              final Dimension d3) {
        this.rowHeights[rowIndex] = Math.max(Math.max(d0.height, d1.height),
                                        Math.max(d2.height, d3.height));
        this.totalHeight = this.totalHeight + this.rowHeights[rowIndex];
        this.columnWidths[0] = Math.max(this.columnWidths[0], d0.width);
        this.columns1and2Width = Math.max(this.columns1and2Width, d1.width);
        this.columnWidths[3] = Math.max(this.columnWidths[3], d2.width);
        this.columns4and5Width = Math.max(this.columns4and5Width, d3.width);
    }
    /**
     * Processes a row in "LCBLC" format.
     *
     * @param rowIndex  the row index.
     * @param d0  dimension 0.
     * @param d1  dimension 1.
     * @param d2  dimension 2.
     * @param d3  dimension 3.
     * @param d4  dimension 4.
     */
    protected void updateLCBLC(final int rowIndex, final Dimension d0, 
                               final Dimension d1, final Dimension d2, 
                               final Dimension d3, final Dimension d4) {
        this.rowHeights[rowIndex] = (Math.max(
            d0.height,
            Math.max(Math.max(d1.height, d2.height),
            Math.max(d3.height, d4.height)))
        );
        this.totalHeight = this.totalHeight + this.rowHeights[rowIndex];
        this.columnWidths[0] = Math.max(this.columnWidths[0], d0.width);
        this.columnWidths[1] = Math.max(this.columnWidths[1], d1.width);
        this.columnWidths[2] = Math.max(this.columnWidths[2], d2.width);
        this.columnWidths[3] = Math.max(this.columnWidths[3], d3.width);
        this.columns4and5Width = Math.max(this.columns4and5Width, d4.width);
    }
    /**
     * Processes a row in "LCLCB" format.
     *
     * @param rowIndex  the row index.
     * @param d0  dimension 0.
     * @param d1  dimension 1.
     * @param d2  dimension 2.
     * @param d3  dimension 3.
     * @param d4  dimension 4.
     */
    protected void updateLCLCB(final int rowIndex, final Dimension d0, 
                               final Dimension d1, final Dimension d2,
                               final Dimension d3, final Dimension d4) {
        this.rowHeights[rowIndex] = (Math.max(d0.height,
                                     Math.max(Math.max(d1.height, d2.height),
                                              Math.max(d3.height, d4.height))));
        this.totalHeight = this.totalHeight + this.rowHeights[rowIndex];
        this.columnWidths[0] = Math.max(this.columnWidths[0], d0.width);
        this.columns1and2Width = Math.max(this.columns1and2Width, d1.width);
        this.columnWidths[3] = Math.max(this.columnWidths[3], d2.width);
        this.columnWidths[4] = Math.max(this.columnWidths[4], d3.width);
        this.columnWidths[5] = Math.max(this.columnWidths[5], d4.width);
    }
    /**
     * Processes a row in "LCBLCB" format.
     *
     * @param rowIndex  the row index.
     * @param d0  dimension 0.
     * @param d1  dimension 1.
     * @param d2  dimension 2.
     * @param d3  dimension 3.
     * @param d4  dimension 4.
     * @param d5  dimension 5.
     */
    protected void updateLCBLCB(final int rowIndex,
                                final Dimension d0, final Dimension d1, 
                                final Dimension d2,
                                final Dimension d3, final Dimension d4, 
                                final Dimension d5) {
        this.rowHeights[rowIndex] = Math.max(
            Math.max(d0.height, d1.height),
            Math.max(Math.max(d2.height, d3.height),
                     Math.max(d4.height, d5.height))
        );
        this.totalHeight = this.totalHeight + this.rowHeights[rowIndex];
        this.columnWidths[0] = Math.max(this.columnWidths[0], d0.width);
        this.columnWidths[1] = Math.max(this.columnWidths[1], d1.width);
        this.columnWidths[2] = Math.max(this.columnWidths[2], d2.width);
        this.columnWidths[3] = Math.max(this.columnWidths[3], d3.width);
        this.columnWidths[4] = Math.max(this.columnWidths[4], d4.width);
        this.columnWidths[5] = Math.max(this.columnWidths[5], d5.width);
    }
    /**
     * Finishes of the processing.
     */
    public void complete() {
        this.columnWidths[1] = Math.max(
             this.columnWidths[1],
             this.columns1and2Width - this.columnGaps[1] - this.columnWidths[2]
        );
        this.columnWidths[4] = Math.max(
            this.columnWidths[4],
            Math.max(
                this.columns4and5Width - this.columnGaps[4] 
                - this.columnWidths[5],
                Math.max(
                    this.columns1to4Width - this.columnGaps[1] 
                        - this.columnGaps[2] - this.columnGaps[3] 
                        - this.columnWidths[1] - this.columnWidths[2] 
                        - this.columnWidths[3],
                    this.columns1to5Width - this.columnGaps[1] 
                        - this.columnGaps[2] - this.columnGaps[3] 
                        - this.columnWidths[1] - this.columnWidths[2] 
                        - this.columnWidths[3] - this.columnGaps[4]
                )
            )
        );
        int leftWidth = this.columnWidths[0] + this.columnGaps[0]
                      + this.columnWidths[1] + this.columnGaps[1] 
                      + this.columnWidths[2];
        int rightWidth = this.columnWidths[3] + this.columnGaps[3]
                       + this.columnWidths[4] + this.columnGaps[4] 
                       + this.columnWidths[5];
        if (splitLayout()) {
            if (leftWidth > rightWidth) {
                final int mismatch = leftWidth - rightWidth;
                this.columnWidths[4] = this.columnWidths[4] + mismatch;
                rightWidth = rightWidth + mismatch;
            }
            else {
                final int mismatch = rightWidth - leftWidth;
                this.columnWidths[1] = this.columnWidths[1] + mismatch;
                leftWidth = leftWidth + mismatch;
            }
        }
        this.totalWidth = leftWidth + this.columnGaps[2] + rightWidth;
        if (this.columns0to5Width > this.totalWidth) {
            final int spaceToAdd = (this.columns0to5Width - this.totalWidth);
            if (splitLayout()) {
                final int halfSpaceToAdd = spaceToAdd / 2;
                this.columnWidths[1] = this.columnWidths[1] + halfSpaceToAdd;
                this.columnWidths[4] = this.columnWidths[4] + spaceToAdd 
                    - halfSpaceToAdd;
                this.totalWidth = this.totalWidth + spaceToAdd;
            }
            else {
                this.columnWidths[1] = this.columnWidths[1] + spaceToAdd;
                this.totalWidth = this.totalWidth + spaceToAdd;
            }
        }
    }
    /**
     * Returns true if this layout involves a split into two sections.
     *
     * @return <code>true</code> if this layout involves a split into two 
     *         sections.
     */
    private boolean splitLayout() {
        for (int i = 0; i < this.rowFormats.length; i++) {
            if (this.rowFormats[i] > FormatLayout.LCB) {
                return true;
            }
        }
        return false;
    }
    /**
     * Not used.
     *
     * @param comp  the component.
     */
    public void addLayoutComponent(final Component comp) {
        // not used
    }
    /**
     * Not used.
     *
     * @param comp  the component.
     */
    public void removeLayoutComponent(final Component comp) {
        // not used
    }
    /**
     * Not used.
     *
     * @param name  the component name.
     * @param comp  the component.
     */
    public void addLayoutComponent(final String name, final Component comp) {
        // not used
    }
    /**
     * Not used.
     *
     * @param name  the component name.
     * @param comp  the component.
     */
    public void removeLayoutComponent(final String name, final Component comp) {
        // not used
    }
}





Applet GUI demo of TreeLayout layout manager

    
import java.applet.Applet;
import java.awt.Button;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Label;
import java.awt.LayoutManager;
import java.awt.List;
import java.awt.Rectangle;
import java.awt.TextField;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
/**
 * Applet GUI demo of Gamelan TreeLayout layout manager. Constructs a tree and,
 * for each entry, makes a button that jumps to it.
 * 
 * The input language is a file like this: R Java Resources # root L - Resources
 * at Sun # label B http://www.sun.ru/foo/bar Interesting Stuff # URLbutton B
 * http://javasoft.ru/b/c More Stuff # URLbutton
 * 
 * The result is (supposedly) a beautiful(?) tree. Each L is a top-level label,
 * and each B is in the tree below it.
 * 
 * Could be made much fancier with getParameter("FontName"), "FontSize",
 * adjusting width with fontMetrics, etc. Works adequately for now.
 */
public class TreeLinkTest extends Applet {
  TreeLayout tl;
  public void init() {
    tl = new TreeLayout();
    setLayout(tl);
    Button root = new Button("This is the root");
    add("Root", root);
    tl.setRoot(root);
    Component x = new Label("A random label");
    add("label", x);
    tl.setParent(x, root);
    Component y;
    y = new TextField("Add any component");
    add("comp", y);
    tl.setParent(y, root);
    x = new List();
    ((List) x).add("List entry");
    ((List) x).add("Similarly useless list entry");
    add("list", x);
    tl.setParent(x, root);
    x = new Button("Extremely long and unnecessary button title");
    add("button", x);
    tl.setParent(x, y);
    x = new MyCanvas(getImage(getDocumentBase(), "icons/tools.gif"));
    add("image", x);
    tl.setParent(x, y);
  }
  public void paint(Graphics g) {
    super.paint(g);
    tl.paintLines(g, getBackground());
  }
  class MyCanvas extends Canvas {
    Image img;
    MyCanvas(Image img) {
      this.img = img;
    }
    public Dimension getPreferredSize() {
      return new Dimension(64, 64);
    }
    public void update(Graphics g) {
      paint(g);
    }
    public void paint(Graphics g) {
      g.drawImage(img, 0, getSize().height / 2 - 16, 32, 32, this);
    }
  }
}
/**
 * Simple layout manager that arranges its children in a tree. The tree always
 * expands to fill the available area, and the internal components are resized
 * to fit the area proportional to their preferred size and the actual available
 * size.
 * 
 * This layout manager requires several method calls beyond the normal layout
 * manager. Please notice the following: * Components must be added using the
 * add(String, Component) method. The strings don"t have to be unique, but must
 * be present. * Each instance must have exactly one root object, which must be
 * add()ed, <I>then </I> setRoot()ed. * Each component after the root must first
 * be added and then must be connected into the tree using setParent(child,
 * parent). * If you want lines between parents and children, you <EM>must
 * </EM> call paintLines() from your applet"s paint() method.
 * 
 * @author name unknown, xxx@blackdown.org
 */
class TreeLayout implements LayoutManager {
  TreeNode root;
  Hashtable nodes;
  public TreeLayout() {
    nodes = new Hashtable();
  }
  public void addLayoutComponent(String name, Component comp) {
    TreeNode tn = new TreeNode(comp);
    nodes.put(comp, tn);
  }
  public void removeLayoutComponent(Component comp) {
    nodes.remove(comp);
  }
  /**
   * You <em>must</em> make this call, otherwise none of the components will
   * be layed out.
   */
  public void setRoot(Component c) {
    root = (TreeNode) nodes.get(c);
  }
  /**
   * Sets the tree parent of a child. The components <em>must</em> have been
   * previously added. If either component has not previously been added, this
   * injunction is silently ignored. Cycles are <em>not</em> checked.
   */
  public void setParent(Component child, Component parent) {
    TreeNode p = (TreeNode) nodes.get(parent);
    TreeNode c = (TreeNode) nodes.get(child);
    if ((p != null) && (c != null))
      p.addChild(c);
  }
  public Dimension minimumLayoutSize(Container target) {
    Dimension d = root.getMinimumSize();
    Insets insets = target.getInsets();
    d.width += insets.left + insets.right;
    d.height += insets.top + insets.bottom;
    return d;
  }
  public Dimension preferredLayoutSize(Container target) {
    Dimension d = root.getPreferredSize();
    Insets insets = target.getInsets();
    d.width += insets.left + insets.right;
    d.height += insets.top + insets.bottom;
    return d;
  }
  public void layoutContainer(Container target) {
    Insets insets = target.getInsets();
    Dimension d = target.getSize();
    Dimension root_pref = root.getPreferredSize();
    double xscale = ((double) (d.width - insets.left - insets.right) / (double) (root_pref.width));
    double yscale = ((double) (d.height - insets.top - insets.bottom) / (double) (root_pref.height));
    root.doLayout(xscale, yscale, insets.left, insets.top);
  }
  /**
   * This piece of hackery is needed since one cant really draw things from a
   * layout manager. Call this if you want to draw lines between components.
   */
  public void paintLines(Graphics g, Color bg) {
    Color dk = bg.darker();
    Color br = bg.brighter();
    root.paintLines(g, dk, br);
  }
}
class TreeNode {
  Component comp;
  Vector children;
  Dimension prefSz, minSz;
  TreeNode(Component comp) {
    super();
    this.rup = comp;
    children = new Vector();
  }
  Dimension getMinimumSize() {
    if (!comp.isVisible())
      return new Dimension(0, 0);
    if (minSz == null) {
      Dimension d = comp.getMinimumSize();
      minSz = new Dimension(d.width, d.height);
      if (children.size() > 0) {
        for (Enumeration e = children.elements(); e.hasMoreElements();) {
          TreeNode t = (TreeNode) (e.nextElement());
          if (t.rup.isVisible()) {
            d = t.getMinimumSize();
            minSz.height += d.height;
            minSz.width = Math.max(d.width, minSz.width);
          }
        }
      }
    }
    return minSz;
  }
  Dimension getPreferredSize() {
    if (!comp.isVisible())
      return new Dimension(0, 0);
    if (prefSz == null) {
      Dimension d = comp.getPreferredSize();
      prefSz = new Dimension(d.width, d.height);
      if (children.size() > 0) {
        int wmax = 0;
        for (Enumeration e = children.elements(); e.hasMoreElements();) {
          TreeNode t = (TreeNode) (e.nextElement());
          if (t.rup.isVisible()) {
            d = t.getPreferredSize();
            prefSz.height += d.height;
            if (wmax < d.width) {
              wmax = d.width;
            }
          }
        }
        prefSz.width += wmax;
      }
    }
    return prefSz;
  }
  void addChild(TreeNode t) {
    children.addElement(t);
    prefSz = null;
    minSz = null;
  }
  void removeChild(TreeNode t) {
    children.removeElement(t);
    prefSz = null;
    minSz = null;
  }
  void paintLines(Graphics g, Color dk, Color br) {
    if (comp.isVisible()) {
      Rectangle b = comp.getBounds();
      int x1off = b.x + b.width / 2;
      int x2off = b.x + b.width;
      int y1off = b.y;
      for (Enumeration e = children.elements(); e.hasMoreElements();) {
        TreeNode tn = (TreeNode) (e.nextElement());
        if (tn.rup.isVisible()) {
          Rectangle bn = tn.rup.getBounds();
          int y2off = bn.y + bn.height / 2;
          g.setColor(dk);
          g.drawLine(x1off, y1off, x1off, y2off);
          g.drawLine(x1off, y2off - 1, x2off, y2off - 1);
          g.setColor(br);
          g.drawLine(x1off + 1, y1off, x1off + 1, y2off);
          g.drawLine(x1off, y2off, x2off, y2off);
          tn.paintLines(g, dk, br);
        }
      }
    }
  }
  void doLayout(double xscale, double yscale, int x, int y) {
    // x and y are the offsets into the
    // Container where we start doing the
    // goodies for this Node
    if (comp.isVisible()) {
      Dimension pref = comp.getPreferredSize();
      int ht = (int) Math.round(yscale * pref.height);
      int wd = (int) Math.round(xscale * pref.width);
      ht = (pref.height < ht) ? pref.height : ht;
      wd = (pref.width < wd) ? pref.width : wd;
      comp.setBounds(x, y, wd, ht);
      y += ht;
      x += wd;
      for (Enumeration e = children.elements(); e.hasMoreElements();) {
        TreeNode tn = (TreeNode) (e.nextElement());
        if (tn.rup.isVisible()) {
          pref = tn.getPreferredSize();
          tn.doLayout(xscale, yscale, x, y);
          y += (int) Math.round(yscale * pref.height);
        }
      }
    }
  }
}





A simple layoutmanager to overlay all components of a parent.

  
/* 
 * JCommon : a free general purpose class library for the Java(tm) platform
 * 
 *
 * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
 * 
 * Project Info:  http://www.jfree.org/jcommon/index.html
 *
 * This library is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU Lesser General Public License as published by 
 * the Free Software Foundation; either version 2.1 of the License, or 
 * (at your option) any later version.
 *
 * This library 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 Lesser General Public 
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
 * USA.  
 *
 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
 * in the United States and other countries.]
 *
 * ------------------------------
 * OverlayLayout.java
 * ------------------------------
 * (C)opyright 2003, by Thomas Morgner and Contributors.
 *
 * Original Author:  Thomas Morgner;
 * Contributor(s):   -;
 *
 * $Id: OverlayLayout.java,v 1.5 2005/10/18 13:18:34 mungady Exp $
 *
 * Changes
 * -------------------------
 * 09-12-2003 : Initial version
 *
 */
import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Rectangle;
/**
 * A simple layoutmanager to overlay all components of a parent.
 * <p/>
 * This layout manager acts similiar to the card layout, but all
 * childs of the parent band have the same size and all childs can
 * be visible at the same time.
 *
 * @author Thomas Morgner
 */
public final class OverlayLayout implements LayoutManager {
    /**
     * A flag that defines, whether invisible components should be ignored when
     * computing the layout.
     */
    private boolean ignoreInvisible;
    /**
     * Creates a new instance.
     * 
     * @param ignoreInvisible  whether to ignore invisible components when computing the layout.
     */
    public OverlayLayout(final boolean ignoreInvisible) {
        this.ignoreInvisible = ignoreInvisible;
    }
    /**
     * DefaultConstructor.
     */
    public OverlayLayout() {
    }
    /**
     * If the layout manager uses a per-component string,
     * adds the component <code>comp</code> to the layout,
     * associating it
     * with the string specified by <code>name</code>.
     *
     * @param name the string to be associated with the component
     * @param comp the component to be added
     */
    public void addLayoutComponent(final String name, final Component comp) {
    }
    /**
     * Removes the specified component from the layout.
     *
     * @param comp the component to be removed
     */
    public void removeLayoutComponent(final Component comp) {
    }
    /**
     * Lays out the specified container.
     *
     * @param parent the container to be laid out
     */
    public void layoutContainer(final Container parent) {
        synchronized (parent.getTreeLock()) {
            final Insets ins = parent.getInsets();
            final Rectangle bounds = parent.getBounds();
            final int width = bounds.width - ins.left - ins.right;
            final int height = bounds.height - ins.top - ins.bottom;
            final Component[] comps = parent.getComponents();
            for (int i = 0; i < comps.length; i++) {
                final Component c = comps[i];
                if ((comps[i].isVisible() == false) && this.ignoreInvisible) {
                    continue;
                }
                c.setBounds(ins.left, ins.top, width, height);
            }
        }
    }
    /**
     * 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 computed for the parent.
     * @see #preferredLayoutSize
     */
    public Dimension minimumLayoutSize(final Container parent) {
        synchronized (parent.getTreeLock()) {
            final Insets ins = parent.getInsets();
            final Component[] comps = parent.getComponents();
            int height = 0;
            int width = 0;
            for (int i = 0; i < comps.length; i++) {
                if ((comps[i].isVisible() == false) && this.ignoreInvisible) {
                    continue;
                }
                final Dimension pref = comps[i].getMinimumSize();
                if (pref.height > height) {
                    height = pref.height;
                }
                if (pref.width > width) {
                    width = pref.width;
                }
            }
            return new Dimension(width + ins.left + ins.right,
                height + ins.top + ins.bottom);
        }
    }
    /**
     * 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 computed for the parent.
     * @see #minimumLayoutSize
     */
    public Dimension preferredLayoutSize(final Container parent) {
        synchronized (parent.getTreeLock()) {
            final Insets ins = parent.getInsets();
            final Component[] comps = parent.getComponents();
            int height = 0;
            int width = 0;
            for (int i = 0; i < comps.length; i++) {
                if ((comps[i].isVisible() == false) && this.ignoreInvisible) {
                    continue;
                }
                final Dimension pref = comps[i].getPreferredSize();
                if (pref.height > height) {
                    height = pref.height;
                }
                if (pref.width > width) {
                    width = pref.width;
                }
            }
            return new Dimension(width + ins.left + ins.right,
                height + ins.top + ins.bottom);
        }
    }
}





Basically two (or more) columns of different, but constant, widths

    
/*
 * Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
 * All rights reserved. Software written by Ian F. Darwin and others.
 * $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * 
 * Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
 * cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
 * pioneering role in inventing and promulgating (and standardizing) the Java 
 * language and environment is gratefully acknowledged.
 * 
 * The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
 * inventing predecessor languages C and C++ is also gratefully acknowledged.
 */
import java.awt.*;
/**
 * A simple layout manager, for "Entry" areas ith e.g., a list of labels and
 * their corresponding JTextFields. These typically look like:
 * 
 * <PRE>
 * 
 * Login:    _______________ 
 * Password: _______________
 * 
 * </PRE>
 * 
 * Basically two (or more) columns of different, but constant, widths. <b>Note:
 * all columns must be the same height! </b>.
 * <P>
 * Construct instances by passing an array of the column width percentages (as
 * doubles, fractions from 0.1 to 0.9, so 40%,60% would be {0.4, 0.6}). The
 * length of this array uniquely determines the number of columns. Columns are
 * forced to be the relevant widths. <b>Note: </b> As with GridLayout, the
 * number of items added <B>must </B> be an even multiple of the number of
 * columns. If not, exceptions may be thrown!
 * 
 * @author Ian F. Darwin, http://www.darwinsys.ru/
 * @version $Id: EntryLayout.java,v 1.11 2004/06/01 02:51:37 ian Exp $
 */
public class EntryLayout implements LayoutManager {
  /** The array of widths, as decimal fractions (0.4 == 40%, etc.). */
  protected final double[] widthPercentages;
  /** The number of columns. */
  protected final int COLUMNS;
  /** The default padding */
  protected final static int HPAD = 5, VPAD = 5;
  /** The actual padding */
  protected final int hpad, vpad;
  /** True if the list of widths was valid. */
  protected boolean validWidths = false;
  /**
   * Construct an EntryLayout with widths and padding specified.
   * 
   * @param relWidths
   *            Array of doubles specifying relative column widths.
   * @param h
   *            Horizontal padding between items
   * @param v
   *            Vertical padding between items
   */
  public EntryLayout(double[] relWidths, int h, int v) {
    COLUMNS = relWidths.length;
    widthPercentages = new double[COLUMNS];
    for (int i = 0; i < relWidths.length; i++) {
      if (relWidths[i] >= 1.0)
        throw new IllegalArgumentException(
            "EntryLayout: widths must be fractions < 1");
      widthPercentages[i] = relWidths[i];
    }
    validWidths = true;
    hpad = h;
    vpad = v;
  }
  /**
   * Construct an EntryLayout with widths and with default padding amounts.
   * 
   * @param relWidths
   *            Array of doubles specifying column widths.
   */
  public EntryLayout(double[] relWidths) {
    this(relWidths, HPAD, VPAD);
  }
  /**
   * Adds the specified component with the specified constraint to the layout;
   * required by LayoutManager but not used.
   */
  public void addLayoutComponent(String name, Component comp) {
    // nothing to do
  }
  /**
   * Removes the specified component from the layout; required by
   * LayoutManager, but does nothing.
   */
  public void removeLayoutComponent(Component comp) {
    // nothing to do
  }
  /**
   * Calculates the preferred size dimensions for the specified panel given
   * the components in the specified parent container.
   */
  public Dimension preferredLayoutSize(Container parent) {
    // System.out.println("preferredLayoutSize");
    return computeLayoutSize(parent, hpad, vpad);
  }
  /**
   * Find the minimum Dimension for the specified container given the
   * components therein.
   */
  public Dimension minimumLayoutSize(Container parent) {
    // System.out.println("minimumLayoutSize");
    return computeLayoutSize(parent, 0, 0);
  }
  /** The width of each column, as found by computLayoutSize(). */
  int[] widths;
  /** The height of each row, as found by computLayoutSize(). */
  int[] heights;
  /**
   * Compute the size of the whole mess. Serves as the guts of
   * preferredLayoutSize() and minimumLayoutSize().
   * 
   * @param parent
   *            The container in which to do the layout.
   * @param hp
   *            The horizontal padding (may be zero)
   * @param vp
   *            The Vertical Padding (may be zero).
   */
  protected Dimension computeLayoutSize(Container parent, int hp, int vp) {
    if (!validWidths)
      return null;
    Component[] components = parent.getComponents();
    Dimension contSize = parent.getSize();
    int preferredWidth = 0, preferredHeight = 0;
    widths = new int[COLUMNS];
    heights = new int[components.length / COLUMNS];
    // System.out.println("Grid: " + widths.length + ", " + heights.length);
    int i;
    // Pass One: Compute largest widths and heights.
    for (i = 0; i < components.length; i++) {
      int row = i / widthPercentages.length;
      int col = i % widthPercentages.length;
      Component c = components[i];
      Dimension d = c.getPreferredSize();
      widths[col] = Math.max(widths[col], d.width);
      heights[row] = Math.max(heights[row], d.height);
    }
    // Pass two: agregate them.
    for (i = 0; i < widths.length; i++)
      preferredWidth += widths[i] + hp;
    for (i = 0; i < heights.length; i++)
      preferredHeight += heights[i] + vp;
    // Finally, pass the sums back as the actual size.
    return new Dimension(preferredWidth, preferredHeight);
  }
  /**
   * Lays out the container in the specified panel. This is a row-column type
   * layout; find x, y, width and height of each Component.
   * 
   * @param parent
   *            The Container whose children we are laying out.
   */
  public void layoutContainer(Container parent) {
    
    if (!validWidths)
      return;
    Component[] components = parent.getComponents();
    Dimension contSize = parent.getSize();
    int x = 0;
    for (int i = 0; i < components.length; i++) {
      int row = i / COLUMNS;
      int col = i % COLUMNS;
      Component c = components[i];
      Dimension d = c.getPreferredSize();
      int colWidth = (int) (contSize.width * widthPercentages[col]);
      if (col == 0) {
        x = hpad;
      } else {
        x += hpad * (col - 1)
            + (int) (contSize.width * widthPercentages[col - 1]);
      }
      int y = vpad * (row) + (row * heights[row])
          + (heights[row] - d.height);
      Rectangle r = new Rectangle(x, y, colWidth, d.height);
      c.setBounds(r);
    }
  }
}





Center Layout

    
/*
    GNU LESSER GENERAL PUBLIC LICENSE
    Copyright (C) 2006 The Lobo Project
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.
    This library 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
    Lesser General Public License for more details.
    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    Contact info: lobochief@users.sourceforge.net
*/
/*
 * Created on Mar 19, 2005
 */
import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.LayoutManager;
/**
 * @author J. H. S.
 */
public class CenterLayout implements LayoutManager {
    public void addLayoutComponent(String arg0, Component arg1) {
    }
    public void removeLayoutComponent(Component arg0) {
    }
    public Dimension preferredLayoutSize(Container arg0) {
      java.awt.Insets insets = arg0.getInsets();
        int count = arg0.getComponentCount();
        if(count > 0) {
            Dimension d = arg0.getComponent(0).getPreferredSize();
            return new Dimension(d.width + insets.left + insets.right,
                           d.height + insets.top + insets.bottom);
        }
        else {
            return new Dimension(insets.left + insets.right, insets.top + insets.bottom);
        }
    }
    /* (non-Javadoc)
     * @see java.awt.LayoutManager#minimumLayoutSize(java.awt.Container)
     */
    public Dimension minimumLayoutSize(Container arg0) {
      java.awt.Insets insets = arg0.getInsets();
        int count = arg0.getComponentCount();
        if(count > 0) {
            Dimension d = arg0.getComponent(0).getMinimumSize();
            return new Dimension(d.width + insets.left + insets.right,
               d.height + insets.top + insets.bottom);
        }
        else {
            return new Dimension(insets.left + insets.right, insets.top + insets.bottom);
        }
    }
    /* (non-Javadoc)
     * @see java.awt.LayoutManager#layoutContainer(java.awt.Container)
     */
    public void layoutContainer(Container container) {
        int count = container.getComponentCount();
        if(count > 0) {
            Component child = container.getComponent(0); 
            java.awt.Insets insets = container.getInsets();
            int availWidth = container.getWidth() - insets.left - insets.right;
            int availHeight = container.getHeight() - insets.top - insets.bottom;
            Dimension preferredSize = child.getPreferredSize();
            double preferredWidth = preferredSize.getWidth();
            double preferredHeight = preferredSize.getHeight();
            int width;
            int height;
            int x;
            int y;
            if(preferredWidth < availWidth) {
              x = (int) Math.round(insets.left + (availWidth - preferredWidth) / 2);
              width = (int) Math.round(preferredWidth);
            }
            else {
              x = insets.left;
              width = availWidth;
            }
            if(preferredHeight < availHeight) {
              y = (int) Math.round(insets.top + (availHeight - preferredHeight) / 2);
              height = (int) Math.round(preferredHeight);
            }
            else {
              y = insets.top;
              height = availHeight;
            }
            child.setBounds(x, y, width, height);
        }
    }
    
    private static CenterLayout instance = new CenterLayout();
    
    public static CenterLayout getInstance() {
      return instance;
    }
}





ColumnLayout

    
/*
 * Copyright (c) 2000 David Flanagan.  All rights reserved.
 * This code is from the book Java Examples in a Nutshell, 2nd Edition.
 * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.
 * You may study, use, and modify it for any non-commercial purpose.
 * You may distribute it non-commercially as long as you retain this notice.
 * For a commercial use license, or to purchase the book (recommended),
 * visit http://www.davidflanagan.ru/javaexamples2.
 */
import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.Insets;
import java.awt.LayoutManager2;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
 * This LayoutManager arranges the components into a column. Components are
 * always given their preferred size.
 * 
 * When you create a ColumnLayout, you may specify four values: margin_height --
 * how much space to leave on top and bottom margin_width -- how much space to
 * leave on left and right spacing -- how much vertical space to leave between
 * items alignment -- the horizontal position of the components:
 * ColumnLayout.LEFT -- left-justify the components ColumnLayout.CENTER --
 * horizontally center the components ColumnLayout.RIGHT -- right-justify the
 * components
 * 
 * You never call the methods of a ColumnLayout object. Just create one and make
 * it the layout manager for your container by passing it to the addLayout()
 * method of the Container object.
 */
public class ColumnLayout implements LayoutManager2 {
  protected int margin_height;
  protected int margin_width;
  protected int spacing;
  protected int alignment;
  // Constants for the alignment argument to the constructor.
  public static final int LEFT = 0;
  public static final int CENTER = 1;
  public static final int RIGHT = 2;
  /** The constructor. See comment above for meanings of these arguments */
  public ColumnLayout(int margin_height, int margin_width, int spacing,
      int alignment) {
    this.margin_height = margin_height;
    this.margin_width = margin_width;
    this.spacing = spacing;
    this.alignment = alignment;
  }
  /**
   * A default constructor that creates a ColumnLayout using 5-pixel margin
   * width and height, 5-pixel spacing, and left alignment
   */
  public ColumnLayout() {
    this(5, 5, 5, LEFT);
  }
  /**
   * The method that actually performs the layout. Called by the Container
   */
  public void layoutContainer(Container parent) {
    Insets insets = parent.getInsets();
    Dimension parent_size = parent.getSize();
    Component kid;
    int nkids = parent.getComponentCount();
    int x0 = insets.left + margin_width; // The base X position
    int x;
    int y = insets.top + margin_height; // Start at the top of the column
    for (int i = 0; i < nkids; i++) { // Loop through the kids
      kid = parent.getComponent(i); // Get the kid
      if (!kid.isVisible())
        continue; // Skip hidden ones
      Dimension pref = kid.getPreferredSize(); // How big is it?
      switch (alignment) { // Compute X coordinate
      default:
      case LEFT:
        x = x0;
        break;
      case CENTER:
        x = (parent_size.width - pref.width) / 2;
        break;
      case RIGHT:
        x = parent_size.width - insets.right - margin_width
            - pref.width;
        break;
      }
      // Set the size and position of this kid
      kid.setBounds(x, y, pref.width, pref.height);
      y += pref.height + spacing; // Get Y position of the next one
    }
  }
  /** The Container calls this to find out how big the layout should to be */
  public Dimension preferredLayoutSize(Container parent) {
    return layoutSize(parent, 1);
  }
  /** The Container calls this to find out how big the layout must be */
  public Dimension minimumLayoutSize(Container parent) {
    return layoutSize(parent, 2);
  }
  /** The Container calls this to find out how big the layout can be */
  public Dimension maximumLayoutSize(Container parent) {
    return layoutSize(parent, 3);
  }
  // Compute min, max, or preferred size of all the visible children
  protected Dimension layoutSize(Container parent, int sizetype) {
    int nkids = parent.getComponentCount();
    Dimension size = new Dimension(0, 0);
    Insets insets = parent.getInsets();
    int num_visible_kids = 0;
    // Compute maximum width and total height of all visible kids
    for (int i = 0; i < nkids; i++) {
      Component kid = parent.getComponent(i);
      Dimension d;
      if (!kid.isVisible())
        continue;
      num_visible_kids++;
      if (sizetype == 1)
        d = kid.getPreferredSize();
      else if (sizetype == 2)
        d = kid.getMinimumSize();
      else
        d = kid.getMaximumSize();
      if (d.width > size.width)
        size.width = d.width;
      size.height += d.height;
    }
    // Now add in margins and stuff
    size.width += insets.left + insets.right + 2 * margin_width;
    size.height += insets.top + insets.bottom + 2 * margin_height;
    if (num_visible_kids > 1)
      size.height += (num_visible_kids - 1) * spacing;
    return size;
  }
  // Other LayoutManager(2) methods that are unused by this class
  public void addLayoutComponent(String constraint, Component comp) {
  }
  public void addLayoutComponent(Component comp, Object constraint) {
  }
  public void removeLayoutComponent(Component comp) {
  }
  public void invalidateLayout(Container parent) {
  }
  public float getLayoutAlignmentX(Container parent) {
    return 0.5f;
  }
  public float getLayoutAlignmentY(Container parent) {
    return 0.5f;
  }
}
class ColumnLayoutPane extends JPanel {
  public ColumnLayoutPane() {
    // Get rid of the default layout manager.
    // We"ll arrange the components ourselves.
    this.setLayout(new ColumnLayout(5, 5, 10, ColumnLayout.RIGHT));
    // Create some buttons and set their sizes and positions explicitly
    for (int i = 0; i < 6; i++) {
      int pointsize = 8 + i * 2;
      JButton b = new JButton("Point size " + pointsize);
      b.setFont(new Font("helvetica", Font.BOLD, pointsize));
      this.add(b);
    }
  }
  public static void main(String[] a) {
    JFrame f = new JFrame();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
    f.setContentPane(new ColumnLayoutPane());
    f.pack();
    f.setVisible(true);
  }
  
}





Compents are laid out in a circle.

  
/* 
 * JCommon : a free general purpose class library for the Java(tm) platform
 * 
 *
 * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
 * 
 * Project Info:  http://www.jfree.org/jcommon/index.html
 *
 * This library is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU Lesser General Public License as published by 
 * the Free Software Foundation; either version 2.1 of the License, or 
 * (at your option) any later version.
 *
 * This library 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 Lesser General Public 
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
 * USA.  
 *
 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
 * in the United States and other countries.]
 * 
 * -----------------
 * RadialLayout.java
 * -----------------
 * (C) Copyright 2003, 2004, by Bryan Scott (for Australian Antarctic Division).
 *
 * Original Author:  Bryan Scott (for Australian Antarctic Division);
 * Contributor(s):   David Gilbert (for Object Refinery Limited);
 *
 *
 * Changes:
 * --------
 * 30-Jun-2003 : Version 1 (BS);
 * 24-Jul-2003 : Completed missing Javadocs (DG);
 *
 */
import java.awt.Checkbox;
import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Panel;
import java.io.Serializable;
/**
 * RadialLayout is a component layout manager.  Compents are laid out in a
 * circle. If only one component is contained in the layout it is positioned
 * centrally, otherwise components are evenly spaced around the centre with
 * the first component placed to the North.
 *<P>
 * This code was developed to display CTD rosette firing control
 *
 * WARNING: Not thoughly tested, use at own risk.
 * 
 * @author Bryan Scott (for Australian Antarctic Division)
 */
public class RadialLayout implements LayoutManager, Serializable {
    
    /** For serialization. */
    private static final long serialVersionUID = -7582156799248315534L;
    
    /** The minimum width. */
    private int minWidth = 0;
    
    /** The minimum height. */
    private int minHeight = 0;
    
    /** The maximum component width. */
    private int maxCompWidth = 0;
    
    /** The maximum component height. */
    private int maxCompHeight = 0;
    
    /** The preferred width. */
    private int preferredWidth = 0;
    
    /** The preferred height. */
    private int preferredHeight = 0;
    
    /** Size unknown flag. */
    private boolean sizeUnknown = true;
    /** 
     * Constructs this layout manager with default properties. 
     */
    public RadialLayout() {
        super();
    }
    /**
     * Not used.
     *
     * @param comp  the component.
     */
    public void addLayoutComponent(final Component comp) {
        // not used
    }
    /**
     * Not used.
     *
     * @param comp  the component.
     */
    public void removeLayoutComponent(final Component comp) {
        // not used
    }
    /**
     * Not used.
     *
     * @param name  the component name.
     * @param comp  the component.
     */
    public void addLayoutComponent(final String name, final Component comp) {
        // not used
    }
    /**
     * Not used.
     *
     * @param name  the component name.
     * @param comp  the component.
     */
    public void removeLayoutComponent(final String name, final Component comp) {
        // not used
    }
    /**
     * Sets the sizes attribute of the RadialLayout object.
     *
     * @param  parent  the parent.
     * 
     * @see LayoutManager
     */
    private void setSizes(final Container parent) {
        final int nComps = parent.getComponentCount();
        //Reset preferred/minimum width and height.
        this.preferredWidth = 0;
        this.preferredHeight = 0;
        this.minWidth = 0;
        this.minHeight = 0;
        for (int i = 0; i < nComps; i++) {
            final Component c = parent.getComponent(i);
            if (c.isVisible()) {
                final Dimension d = c.getPreferredSize();
                if (this.maxCompWidth < d.width) {
                    this.maxCompWidth = d.width;
                }
                if (this.maxCompHeight < d.height) {
                    this.maxCompHeight = d.height;
                }
                this.preferredWidth += d.width;
                this.preferredHeight += d.height;
            }
        }
        this.preferredWidth  = this.preferredWidth / 2;
        this.preferredHeight = this.preferredHeight / 2;
        this.minWidth = this.preferredWidth;
        this.minHeight = this.preferredHeight;
    }
    /**
     * Returns the preferred size.
     *
     * @param parent  the parent.
     *
     * @return The preferred size.
     * @see LayoutManager
     */
    public Dimension preferredLayoutSize(final Container parent) {
        final Dimension dim = new Dimension(0, 0);
        setSizes(parent);
        //Always add the container"s insets!
        final Insets insets = parent.getInsets();
        dim.width = this.preferredWidth + insets.left + insets.right;
        dim.height = this.preferredHeight + insets.top + insets.bottom;
        this.sizeUnknown = false;
        return dim;
    }
    /**
     * Returns the minimum size.
     *
     * @param parent  the parent.
     *
     * @return The minimum size.
     * @see LayoutManager
     */
    public Dimension minimumLayoutSize(final Container parent) {
        final Dimension dim = new Dimension(0, 0);
        //Always add the container"s insets!
        final Insets insets = parent.getInsets();
        dim.width = this.minWidth + insets.left + insets.right;
        dim.height = this.minHeight + insets.top + insets.bottom;
        this.sizeUnknown = false;
        return dim;
    }
   /**
    * This is called when the panel is first displayed, and every time its size
    * changes.
    * Note: You CAN"T assume preferredLayoutSize or minimumLayoutSize will be
    * called -- in the case of applets, at least, they probably won"t be.
    *
    * @param  parent  the parent.
    * @see LayoutManager
    */
    public void layoutContainer(final Container parent) {
        final Insets insets = parent.getInsets();
        final int maxWidth = parent.getSize().width 
            - (insets.left + insets.right);
        final int maxHeight = parent.getSize().height 
            - (insets.top + insets.bottom);
        final int nComps = parent.getComponentCount();
        int x = 0;
        int y = 0;
        // Go through the components" sizes, if neither preferredLayoutSize nor
        // minimumLayoutSize has been called.
        if (this.sizeUnknown) {
            setSizes(parent);
        }
        if (nComps < 2) {
            final Component c = parent.getComponent(0);
            if (c.isVisible()) {
                final Dimension d = c.getPreferredSize();
                c.setBounds(x, y, d.width, d.height);
            }
        } 
        else {
            double radialCurrent = Math.toRadians(90);
            final double radialIncrement = 2 * Math.PI / nComps;
            final int midX = maxWidth / 2;
            final int midY = maxHeight / 2;
            final int a = midX - this.maxCompWidth;
            final int b = midY - this.maxCompHeight;
            for (int i = 0; i < nComps; i++) {
                final Component c = parent.getComponent(i);
                if (c.isVisible()) {
                    final Dimension d = c.getPreferredSize();
                    x = (int) (midX
                               - (a * Math.cos(radialCurrent))
                               - (d.getWidth() / 2)
                               + insets.left);
                    y = (int) (midY
                               - (b * Math.sin(radialCurrent))
                               - (d.getHeight() / 2)
                               + insets.top);
                    // Set the component"s size and position.
                    c.setBounds(x, y, d.width, d.height);
                }
                radialCurrent += radialIncrement;
            }
        }
    }
    /**
     * Returns the class name.
     * 
     * @return The class name.
     */
    public String toString() {
        return getClass().getName();
    }
    /**
     * Run a demonstration.
     *
     * @param args  ignored.
     * 
     * @throws Exception when an error occurs.
     */
    public static void main(final String[] args) throws Exception {
        final Frame frame = new Frame();
        final Panel panel = new Panel();
        panel.setLayout(new RadialLayout());
        panel.add(new Checkbox("One"));
        panel.add(new Checkbox("Two"));
        panel.add(new Checkbox("Three"));
        panel.add(new Checkbox("Four"));
        panel.add(new Checkbox("Five"));
        panel.add(new Checkbox("One"));
        panel.add(new Checkbox("Two"));
        panel.add(new Checkbox("Three"));
        panel.add(new Checkbox("Four"));
        panel.add(new Checkbox("Five"));
        frame.add(panel);
        frame.setSize(300, 500);
        frame.setVisible(true);
    }
}





Customized layout manager

    
import java.awt.Button;
import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
public class CircleLayoutTest extends JFrame {
  public CircleLayoutTest() {
    setTitle("CircleLayoutTest");
    setSize(300, 300);
    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
    getContentPane().setLayout(new CircleLayout());
    getContentPane().add(new Button("3"));
    getContentPane().add(new Button("4"));
    getContentPane().add(new Button("5"));
    getContentPane().add(new Button("6"));
    getContentPane().add(new Button("7"));
    getContentPane().add(new Button("8"));
    getContentPane().add(new Button("9"));
    getContentPane().add(new Button("10"));
    getContentPane().add(new Button("11"));
    getContentPane().add(new Button("12"));
    getContentPane().add(new Button("1"));
    getContentPane().add(new Button("2"));
  }
  public static void main(String[] args) {
    JFrame f = new CircleLayoutTest();
    f.show();
  }
}
class CircleLayout implements LayoutManager {
  private int minWidth = 0;
  private int minHeight = 0;
  private int preferredWidth = 0, preferredHeight = 0;
  private boolean sizesSet = false;
  private int maxComponentWidth = 0;
  private int maxComponentHeight = 0;
  public void addLayoutComponent(String name, Component comp) {
  }
  public void removeLayoutComponent(Component comp) {
  }
  public void setSizes(Container parent) {
    if (sizesSet)
      return;
    int comCount = parent.getComponentCount();
    for (int i = 0; i < comCount; i++) {
      Component c = parent.getComponent(i);
      if (c.isVisible()) {
        Dimension size = c.getPreferredSize();
        maxComponentWidth = Math.max(maxComponentWidth, size.width);
        maxComponentHeight = Math.max(maxComponentWidth, size.height);
        preferredHeight += size.height;
      }
    }
    preferredHeight += maxComponentHeight;
    preferredWidth = 2 * maxComponentWidth;
    minHeight = preferredHeight;
    minWidth = preferredWidth;
    sizesSet = true;
  }
  public Dimension preferredLayoutSize(Container parent) {
    Dimension dim = new Dimension(0, 0);
    setSizes(parent);
    Insets insets = parent.getInsets();
    dim.width = preferredWidth + insets.left + insets.right;
    dim.height = preferredHeight + insets.top + insets.bottom;
    return dim;
  }
  public Dimension minimumLayoutSize(Container parent) {
    return preferredLayoutSize(parent);
  }
  public void layoutContainer(Container parent) {
    Insets insets = parent.getInsets();
    int containerWidth = parent.getSize().width - insets.left
        - insets.right;
    int containerHeight = parent.getSize().height - insets.top
        - insets.bottom;
    int xradius = (containerWidth - maxComponentWidth) / 2;
    int yradius = (containerHeight - maxComponentHeight) / 2;
    setSizes(parent);
    int centerX = insets.left + containerWidth / 2;
    int centerY = insets.top + containerHeight / 2;
    int comCount = parent.getComponentCount();
    for (int i = 0; i < comCount; i++) {
      Component c = parent.getComponent(i);
      if (c.isVisible()) {
        Dimension size = c.getPreferredSize();
        double angle = 2 * Math.PI * i / comCount;
        int x = centerX + (int) (Math.cos(angle) * xradius);
        int y = centerY + (int) (Math.sin(angle) * yradius);
        c.setBounds(x - size.width / 2, y - size.height / 2, size.width,
            size.height);
      }
    }
  }
}





Custom Layout Demo

    
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * -Redistribution of source code must retain the above copyright notice, this
 *  list of conditions and the following disclaimer.
 *
 * -Redistribution in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed, licensed or intended
 * for use in the design, construction, operation or maintenance of any
 * nuclear facility.
 */
/*
 * CustomLayoutDemo.java is a 1.4 application that requires one other file:
 * DiagonalLayout.java
 */
import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;
import javax.swing.JButton;
import javax.swing.JFrame;
public class CustomLayoutDemo {
  public static void addComponentsToPane(Container pane) {
    pane.setLayout(new DiagonalLayout());
    pane.add(new JButton("Button 1"));
    pane.add(new JButton("Button 2"));
    pane.add(new JButton("Button 3"));
    pane.add(new JButton("Button 4"));
    pane.add(new JButton("Button 5"));
  }
  /**
   * Create the GUI and show it. For thread safety, this method should be
   * invoked from the event-dispatching thread.
   */
  private static void createAndShowGUI() {
    //Make sure we have nice window decorations.
    JFrame.setDefaultLookAndFeelDecorated(true);
    //Create and set up the window.
    JFrame frame = new JFrame("CustomLayoutDemo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //Set up the content pane.
    addComponentsToPane(frame.getContentPane());
    //Display the window.
    frame.pack();
    frame.setVisible(true);
  }
  public static void main(String[] args) {
    //Schedule a job for the event-dispatching thread:
    //creating and showing this application"s GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        createAndShowGUI();
      }
    });
  }
}
/*
 * 1.2+ version. Used by CustomLayoutDemo.java.
 */
class DiagonalLayout implements LayoutManager {
  private int vgap;
  private int minWidth = 0, minHeight = 0;
  private int preferredWidth = 0, preferredHeight = 0;
  private boolean sizeUnknown = true;
  public DiagonalLayout() {
    this(5);
  }
  public DiagonalLayout(int v) {
    vgap = v;
  }
  /* Required by LayoutManager. */
  public void addLayoutComponent(String name, Component comp) {
  }
  /* Required by LayoutManager. */
  public void removeLayoutComponent(Component comp) {
  }
  private void setSizes(Container parent) {
    int nComps = parent.getComponentCount();
    Dimension d = null;
    //Reset preferred/minimum width and height.
    preferredWidth = 0;
    preferredHeight = 0;
    minWidth = 0;
    minHeight = 0;
    for (int i = 0; i < nComps; i++) {
      Component c = parent.getComponent(i);
      if (c.isVisible()) {
        d = c.getPreferredSize();
        if (i > 0) {
          preferredWidth += d.width / 2;
          preferredHeight += vgap;
        } else {
          preferredWidth = d.width;
        }
        preferredHeight += d.height;
        minWidth = Math.max(c.getMinimumSize().width, minWidth);
        minHeight = preferredHeight;
      }
    }
  }
  /* Required by LayoutManager. */
  public Dimension preferredLayoutSize(Container parent) {
    Dimension dim = new Dimension(0, 0);
    int nComps = parent.getComponentCount();
    setSizes(parent);
    //Always add the container"s insets!
    Insets insets = parent.getInsets();
    dim.width = preferredWidth + insets.left + insets.right;
    dim.height = preferredHeight + insets.top + insets.bottom;
    sizeUnknown = false;
    return dim;
  }
  /* Required by LayoutManager. */
  public Dimension minimumLayoutSize(Container parent) {
    Dimension dim = new Dimension(0, 0);
    int nComps = parent.getComponentCount();
    //Always add the container"s insets!
    Insets insets = parent.getInsets();
    dim.width = minWidth + insets.left + insets.right;
    dim.height = minHeight + insets.top + insets.bottom;
    sizeUnknown = false;
    return dim;
  }
  /* Required by LayoutManager. */
  /*
   * This is called when the panel is first displayed, and every time its size
   * changes. Note: You CAN"T assume preferredLayoutSize or minimumLayoutSize
   * will be called -- in the case of applets, at least, they probably won"t
   * be.
   */
  public void layoutContainer(Container parent) {
    Insets insets = parent.getInsets();
    int maxWidth = parent.getWidth() - (insets.left + insets.right);
    int maxHeight = parent.getHeight() - (insets.top + insets.bottom);
    int nComps = parent.getComponentCount();
    int previousWidth = 0, previousHeight = 0;
    int x = 0, y = insets.top;
    int rowh = 0, start = 0;
    int xFudge = 0, yFudge = 0;
    boolean oneColumn = false;
    // Go through the components" sizes, if neither
    // preferredLayoutSize nor minimumLayoutSize has
    // been called.
    if (sizeUnknown) {
      setSizes(parent);
    }
    if (maxWidth <= minWidth) {
      oneColumn = true;
    }
    if (maxWidth != preferredWidth) {
      xFudge = (maxWidth - preferredWidth) / (nComps - 1);
    }
    if (maxHeight > preferredHeight) {
      yFudge = (maxHeight - preferredHeight) / (nComps - 1);
    }
    for (int i = 0; i < nComps; i++) {
      Component c = parent.getComponent(i);
      if (c.isVisible()) {
        Dimension d = c.getPreferredSize();
        // increase x and y, if appropriate
        if (i > 0) {
          if (!oneColumn) {
            x += previousWidth / 2 + xFudge;
          }
          y += previousHeight + vgap + yFudge;
        }
        // If x is too large,
        if ((!oneColumn)
            && (x + d.width) > (parent.getWidth() - insets.right)) {
          // reduce x to a reasonable number.
          x = parent.getWidth() - insets.bottom - d.width;
        }
        // If y is too large,
        if ((y + d.height) > (parent.getHeight() - insets.bottom)) {
          // do nothing.
          // Another choice would be to do what we do to x.
        }
        // Set the component"s size and position.
        c.setBounds(x, y, d.width, d.height);
        previousWidth = d.width;
        previousHeight = d.height;
      }
    }
  }
  public String toString() {
    String str = "";
    return getClass().getName() + "[vgap=" + vgap + str + "]";
  }
}





Custom layout: EdgeLayout

    
/*
Code from Desktop Java Live Source
URL: http://www.sourcebeat.ru/downloads/
*/

import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager2;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class EdgeLayoutExample {
    public static JPanel createPanel() {
        JPanel outerPanel = new JPanel();
        outerPanel.setLayout(new EdgeLayout());
        outerPanel.add(new JButton("West1"), EdgeLayout.WEST);
        outerPanel.add(new JButton("North1"), EdgeLayout.NORTH);
        outerPanel.add(new JButton("West2"), EdgeLayout.WEST);
        outerPanel.add(new JButton("North2"), EdgeLayout.NORTH);
        outerPanel.add(new JButton("East1"), EdgeLayout.EAST);
        outerPanel.add(new JButton("South1"), EdgeLayout.SOUTH);
        outerPanel.add(new JButton("West3"), EdgeLayout.WEST);
        outerPanel.add(new JButton("West4"), EdgeLayout.WEST);
        outerPanel.add(new JButton("South2"), EdgeLayout.SOUTH);
        outerPanel.add(new JButton("South3"), EdgeLayout.SOUTH);
        outerPanel.add(new JButton("Center1"), EdgeLayout.CENTER);
        return outerPanel;
    }
    public static void main(String[] a){
      JFrame f = new JFrame();
      f.setDefaultCloseOperation(1);
      f.add(createPanel());
      f.pack();
      f.setVisible(true);
    } 
}

class EdgeLayout implements LayoutManager2, java.io.Serializable {
    private List components = new ArrayList();
    private HashMap constraints = new HashMap();
    public static final String CENTER = "center";
    public static final String NORTH = "north";
    public static final String SOUTH = "south";
    public static final String EAST = "east";
    public static final String WEST = "west";
    public void addLayoutComponent(Component comp, Object constraints) {
        synchronized (comp.getTreeLock()) {
            if (constraints instanceof String && comp != null) {
                this.ruponents.add(comp);
                this.constraints.put(comp, constraints);
            } else {
                throw new IllegalArgumentException("Invalid component constraints.");
            }
        }
    }
    public Dimension maximumLayoutSize(Container target) {
        //Return a very large size since this layout manager will fill all available space.
        return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
    }
    public float getLayoutAlignmentX(Container target) {
        //Centered on the X
        return (float) 0.5;
    }
    public float getLayoutAlignmentY(Container target) {
        //Centered on the Y
        return (float) 0.5;
    }
    public void invalidateLayout(Container target) {
        //There is no caching in EdgeLayout to there is nothing to invalidate
    }
    public void addLayoutComponent(String name, Component comp) {
        throw new IllegalArgumentException("EdgeLayout only supports addition with contraints.");
    }
    public void removeLayoutComponent(Component comp) {
        synchronized (comp.getTreeLock()) {
            this.ruponents.remove(comp);
            this.constraints.remove(comp);
        }
    }
    public Dimension preferredLayoutSize(Container parent) {
        synchronized (parent.getTreeLock()) {
            int width = 0;
            int height = 0;
            //Add the preferred widths of all EAST/WEST components
            //Add the preferred height of all NORTH/SOUTH components
            for (int i = 0; i < this.ruponents.size(); i++) {
                Component c = (Component) this.ruponents.get(i);
                if (this.constraints.get(c).equals(WEST) || this.constraints.get(c).equals(EAST)) {
                    width += c.getPreferredSize().getWidth();
                } else {
                    height += c.getPreferredSize().getHeight();
                }
            }
            width += parent.getInsets().right + parent.getInsets().left;
            height += parent.getInsets().top + parent.getInsets().bottom;
            return new Dimension(width, height);
        }
    }
    public Dimension minimumLayoutSize(Container parent) {
        synchronized (parent.getTreeLock()) {
            int width = 0;
            int height = 0;
            //Add the minimum  widths of all EAST/WEST components
            //Add the minimum height of all NORTH/SOUTH components
            for (int i = 0; i < this.ruponents.size(); i++) {
                Component c = (Component) this.ruponents.get(i);
                if (this.constraints.get(c).equals(WEST) || this.constraints.get(c).equals(EAST)) {
                    width += c.getMinimumSize().getWidth();
                } else {
                    height += c.getMinimumSize().getHeight();
                }
            }
            width += parent.getInsets().right + parent.getInsets().left;
            height += parent.getInsets().top + parent.getInsets().bottom;
            return new Dimension(width, height);
        }
    }
    public void layoutContainer(Container parent) {
        synchronized (parent.getTreeLock()) {
            Insets insets = parent.getInsets();
            int top = insets.top;
            int left = insets.left;
            Dimension minimumSize = minimumLayoutSize(parent);
            int height = minimumSize.height;
            int width = minimumSize.width;
            int availableHeight = parent.getHeight() - insets.bottom - insets.top;
            int availableWidth = parent.getWidth() - insets.left - insets.right;
            if (height < availableHeight) {
                height = availableHeight;
            }
            if (width < availableWidth) {
                width = availableWidth;
            }
            int bottom = availableHeight;
            int right = availableWidth;
            Dimension preferredSize = preferredLayoutSize(parent);
            int preferredWidthAvailable = width - preferredSize.width;
            int preferredHeightAvailable = height - preferredSize.height;

            Component centerComp = null;
            for (int i = 0; i < this.ruponents.size(); i++) {
                Component c = (Component) this.ruponents.get(i);
                String constraint = (String) this.constraints.get(c);
                if (constraint.equals(CENTER)) {
                    centerComp = c;
                } else {
                    int compHeight;
                    int compWidth;
                    int xOrigin;
                    int yOrigin;

                    if (constraint.equals(NORTH) || constraint.equals(SOUTH)) {
                        compWidth = width;
                        if (preferredHeightAvailable > 0) {
                            int preferredHeightNeeded = c.getPreferredSize().height - c.getMinimumSize().height;
                            if (preferredHeightAvailable > preferredHeightNeeded) {
                                compHeight = c.getPreferredSize().height;
                                preferredHeightAvailable -= preferredHeightNeeded;
                            } else {
                                compHeight = c.getMinimumSize().height + preferredHeightAvailable;
                                preferredHeightAvailable = 0;
                            }
                        } else {
                            compHeight = c.getMinimumSize().height;
                        }
                        height = height - compHeight;
                        xOrigin = left;
                        if (constraint.equals(NORTH)) {
                            yOrigin = top;
                            top += compHeight;
                        } else {
                            yOrigin = bottom - compHeight;
                            bottom = yOrigin;
                        }
                    } else {
                        compHeight = height;
                        if (preferredWidthAvailable > 0) {
                            int preferredWidthNeeded = c.getPreferredSize().width - c.getMinimumSize().width;
                            if (preferredWidthAvailable > preferredWidthNeeded) {
                                compWidth = c.getPreferredSize().width;
                                preferredWidthAvailable -= preferredWidthNeeded;
                            } else {
                                compWidth = c.getMinimumSize().width + preferredWidthAvailable;
                                preferredWidthAvailable = 0;
                            }
                        } else {
                            compWidth = c.getMinimumSize().width;
                        }
                        width = width - compWidth;
                        yOrigin = top;
                        if (constraint.equals(WEST)) {
                            xOrigin = left;
                            left += compWidth;
                        } else {
                            xOrigin = right - compWidth;
                            right = xOrigin;
                        }
                    }
                    c.setSize(compWidth, compHeight);
                    c.setBounds(xOrigin, yOrigin, compWidth, compHeight);
                }
                if (centerComp != null) {
                    c.setSize(width, height);
                    c.setBounds(left, top, width, height);
                }
            }
        }
    }
}





DividerLayout is layout that divides two components with the column of actions

    
/*
 * $Id: DividerLayout.java,v 1.1.1.1 2005/04/07 18:36:20 pocho Exp $
 */
// Revised from javautils swing;
import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager2;
import java.awt.Rectangle;
/**
 * <p>
 * <code>DividerLayout</code> is layout that divides two components with the
 * column of actions. It is especially usefull for components that contains
 * two lists of elements and buttons for transfering elements between these
 * two lists.
 * </p>
 * <p>
 *   Components are indicated as {@link #WEST}, {@link #EAST} and {@link #CENTER}.
 * </p>
 * 
 * @version $Name:  $ - $Revision: 1.1.1.1 $ - $Date: 2005/04/07 18:36:20 $
 * TODO Test
 */
public class DividerLayout implements LayoutManager2 {
  
  /**
   * Indicates west component
   */
  public final static String WEST = "WEST";
  /**
   * indicates east component
   */
  public final static String EAST = "EAST";
  /**
   * indicates center component
   */
  public final static String CENTER = "CENTER";
  /**
   * west component
   */
  protected Component westComponent;
  
  /**
   * center component
   */
  protected Component centerComponent;
  
  /**
   * east component
   */
  protected Component eastComponent;
  
  /**
   * Adds a component to specified position.
   */
  public void addLayoutComponent(Component comp, Object constraints) {
    if (WEST.equalsIgnoreCase((String) constraints)) {
      westComponent = comp;
    }
    else if (CENTER.equalsIgnoreCase((String) constraints)) {
      centerComponent = comp;
    }
    else if (EAST.equalsIgnoreCase((String) constraints)) {
      eastComponent = comp;
    }
  }
  /**
   * @see java.awt.LayoutManager2#maximumLayoutSize(java.awt.Container)
   */
  public Dimension maximumLayoutSize(Container target) {
    Dimension size;
    int width = 0;
    int height = 0;
    if ((westComponent != null) && (westComponent.isVisible())) {
      size = westComponent.getMaximumSize();
      width = Math.max(width, size.width);
      height = Math.max(height, size.height);
    }
    if ((eastComponent != null) && (eastComponent.isVisible())) {
      size = eastComponent.getMaximumSize();
      width = Math.max(width, size.width);
      height = Math.max(height, size.height);
    }
    width *= 2;
    if ((centerComponent != null) && (centerComponent.isVisible())) {
      size = centerComponent.getPreferredSize();
      width += size.width;
      height = Math.max(height, size.height);
    }
    return new Dimension(width, height);
  }
  /**
   * @see java.awt.LayoutManager2#getLayoutAlignmentX(java.awt.Container)
   */
  public float getLayoutAlignmentX(Container target) {
    return 0.0f;
  }
  /**
   * @see java.awt.LayoutManager2#getLayoutAlignmentY(java.awt.Container)
   */
  public float getLayoutAlignmentY(Container target) {
    return 0.0f;
  }
  /**
   * @see java.awt.LayoutManager2#invalidateLayout(java.awt.Container)
   */
  public void invalidateLayout(Container target) {}
  /**
   * @see java.awt.LayoutManager#addLayoutComponent(java.lang.String, java.awt.ruponent)
   */
  public void addLayoutComponent(String name, Component comp) {
    addLayoutComponent(comp, name);
  }
  /**
   * @see java.awt.LayoutManager#removeLayoutComponent(java.awt.ruponent)
   */
  public void removeLayoutComponent(Component comp) {
    if (comp == westComponent) {
      westComponent = null;
    }
    else if (comp == centerComponent) {
      centerComponent = null;
    }
    else if (comp == eastComponent) {
      centerComponent = null;
    }
  }
  
  /**
   * @see java.awt.LayoutManager#preferredLayoutSize(java.awt.Container)
   */
  public Dimension preferredLayoutSize(Container parent) {
    Dimension size;
    int width = 0;
    int height = 0;
    if ((westComponent != null) && (westComponent.isVisible())) {
      size = westComponent.getPreferredSize();
      width = Math.max(width, size.width);
      height = Math.max(height, size.height);
    }
    if ((eastComponent != null) && (eastComponent.isVisible())) {
      size = eastComponent.getPreferredSize();
      width = Math.max(width, size.width);
      height = Math.max(height, size.height);
    }
    width *= 2;
    if ((centerComponent != null) && (centerComponent.isVisible())) {
      size = centerComponent.getPreferredSize();
      width += size.width;
      height = Math.max(height, size.height);
    }
    return new Dimension(width, height);
  }

  /**
   * @see java.awt.LayoutManager#minimumLayoutSize(java.awt.Container)
   */
  public Dimension minimumLayoutSize(Container parent) {
    Dimension size;
    int width = 0;
    int height = 0;
    if ((westComponent != null) && (westComponent.isVisible())) {
      size = westComponent.getMinimumSize();
      width = Math.max(width, size.width);
      height = Math.max(height, size.height);
    }
    if ((eastComponent != null) && (eastComponent.isVisible())) {
      size = eastComponent.getMinimumSize();
      width = Math.max(width, size.width);
      height = Math.max(height, size.height);
    }
    width *= 2;
    if ((centerComponent != null) && (centerComponent.isVisible())) {
      size = centerComponent.getPreferredSize();
      width += size.width;
      height += Math.max(height, size.height);
    }
    return new Dimension(width, height);
  }
  /**
   * @see java.awt.LayoutManager#layoutContainer(java.awt.Container)
   */
  public void layoutContainer(Container container) {
   Insets insets = container.getInsets();
   Dimension westSize = new Dimension(0, 0);
   Dimension centerSize = new Dimension(0, 0);
   Dimension eastSize = new Dimension(0, 0);
   Rectangle centerBounds = new Rectangle(0, 0, 0, 0);
   Dimension containerSize = container.getSize();
   int centerX = containerSize.width / 2;
   int centerY = containerSize.height / 2;
   if ((centerComponent != null) &&
       (centerComponent.isVisible())) {
     centerSize = centerComponent.getPreferredSize();
     centerSize.width = Math.min(centerSize.width,
         containerSize.width - insets.left -
         insets.right);
     centerSize.height = Math.min(centerSize.height,
         containerSize.height - insets.top -
         insets.bottom);
     centerComponent.setBounds(centerX -
         (centerSize.width / 2),
         centerY - (centerSize.height / 2),
         centerSize.width, centerSize.height);
     centerBounds = centerComponent.getBounds();
   }
   if ((westComponent != null) && (westComponent.isVisible())) {
     westSize = westComponent.getPreferredSize();
   }
   if ((eastComponent != null) && (eastComponent.isVisible())) {
     eastSize = eastComponent.getPreferredSize();
   }
  /* int maxWidth = Math.min(westSize.width, eastSize.width);
   maxWidth = Math.min(maxWidth, (containerSize.width -
       centerBounds.width - insets.left -
       insets.right) / 2);*/
  int maxWidth = (containerSize.width -
       centerBounds.width - insets.left -
       insets.right) / 2;
  /* int maxHeight = Math.min(westSize.height, eastSize.height);
    maxHeight = Math.max(maxHeight, containerSize.height -
       insets.top - insets.bottom);*/
  int maxHeight=containerSize.height - insets.top - insets.bottom;
   if (westComponent != null) {
     westComponent.setBounds(centerBounds.x - maxWidth,
         centerY - (maxHeight / 2),
         maxWidth, maxHeight);
   }
   if (eastComponent != null) {
     eastComponent.setBounds(centerBounds.x +
         centerBounds.width,
         centerY - (maxHeight / 2),
         maxWidth, maxHeight);
   }
 }

}





Flex Layout

    
//   FlexLayout
//   Copyright (C) by Andrea Carboni.
//   This file may be distributed under the terms of the LGPL license.

import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.util.StringTokenizer;
/** This class implements a combination of the GridBag and Border layouts. The
  * container is subdivided into rows and columns (basically a grid). Each cell
  * can be empty or can contain a component and a component can occupy one or more
  * cells. If a component is smaller than its cell, it can be aligned both horizontally
  * and vertically. The width of a column is the width of its largest component. The
  * height of a row is the height of its tallest component. Furthermore, a row or a
  * column can be expandable, that is its width/height changes depending on the container"s
  * size.<BR><BR>
  * <B>General design issues:</B><BR>
  * First, decide the grid size. Consider that some components (like panels) usually
  * spread over more cells so it is a good idea to make the grid a little bigger.<BR><BR>
  * Second, decide which row/column expand (this is done by the setColProp/setRowProp
  * methods).<BR><BR>
  * Third, add components to container (layout) giving proper constraints.<BR><BR>
  * <B>Example:</B><BR><PRE>
  * FlexLayout flexL = new FlexLayout(2, 3, 4, 4); //--- (1)
  * flexL.setColProp(1, FlexLayout.EXPAND);        //--- (2)
  * flexL.setRowProp(2, FlexLayout.EXPAND);        //--- (3)
  * setLayout(flexL);                              //--- (4)
  *
  * add("0,0",       new Label("Name"));         //--- (5)
  * add("0,1",       new Label("Surname"));      //--- (6)
  * add("1,0,x",     textField);                 //--- (7)
  * add("1,1,x",     textField);                 //--- (8)
  * add("0,2,x,x,2", panel);                     //--- (9)
  * </PRE><BR>
  * <I>Description:</I><BR>
  * line 1: creates a FlexLayout of 2 columns and 3 rows. The two 4 represent the gap
  * between each column and each row. To modify this gap use setXgap and setYgap.<BR>
  * line 2 & 3: column 1 and row 2 are set to expandable (the default is USEPREFERRED)
  * remember that row and column id starts from index 0.<BR>
  * line 4: the layout is added to the container.<BR>
  * line 5 & 6: add two labels in position (0,0) and (0,1)
  * line 7 & 8: add two textfields in position (1,0) and (1,1). The x means that the
  * width will be expanded to occupy all column size. Because column 1 is set to expandable,
  * when the container is resized the textfields are resized too.<BR>
  * line 9: adds a panel in position (0,2). Then panel is expanded both horizontally and
  * vertically and spreads over 2 cells in x direction.<BR><BR>
  * The complete command string is:<BR><PRE>
  * "x,y,xa,ya,xs,ys" where:
  *   x,y specify the component position (are the column-row indexes)
  *   xa specifies the x align of the component and can be:
  *     l - for left
  *     c - for center
  *     r - for right
  *     x - exands the component"s width
  *     (default is l)
  *   ya specifies the y align of the component and can be:
  *     t - for top
  *     c - for center
  *     b - for bottom
  *     x - exands the component"s height
  *     (default is c)
  *   xs and ys specify the number or columns/rows occupied by the component (default is 1)
  * </PRE>
  * <B>Notes:</B><BR>
  * - if a component occupies more than 1 cell in x direction, its preferred width is NOT
  *  taken into account (same for y).<BR>
  * - if a column / row is empty, its size is set to a default value. This value can be
  * changed using setXNullgap/setYNullgap methods.
  * <BR><BR>
  * Have fun!!!
  *
  * @author Andrea Carboni
  */
public class FlexLayout implements LayoutManager
{
   private int xgap;
   private int ygap;
   private int width;
   private int height;
   private int xnullgap = 24;
   private int ynullgap = 24;
   private FlexCell cells[][];
   //--- flags for rows and columns ---
   public static final int USEPREFERRED = 0; //--- default ---
   public static final int EXPAND       = 1;
   private int xflags[];
   private int yflags[];
   private int xpref[];
   private int ypref[];
   //---------------------------------------------------------------------------
   public FlexLayout(int width, int height)
   {
      this(width, height, 4, 4);
   }
   //---------------------------------------------------------------------------
   public FlexLayout(int width, int height, int xgap, int ygap)
   {
      if (width <1 || height <1)
         throw new IllegalArgumentException("width & height must be >0");
      this.width  = width;
      this.height = height;
      this.xgap   = xgap;
      this.ygap   = ygap;
      cells = new FlexCell[width][height];
      xflags = new int[width];
      yflags = new int[height];
      xpref  = new int[width];
      ypref  = new int[height];
   }
   //---------------------------------------------------------------------------
   public void setColProp(int index, int flag)
   {
      xflags[index] = flag;
   }
   //---------------------------------------------------------------------------
   public void setRowProp(int index, int flag)
   {
      yflags[index] = flag;
   }
   //---------------------------------------------------------------------------
   public void setNullGaps(int xgap, int ygap)
   {
      xnullgap = xgap;
      ynullgap = ygap;
   }
   //---------------------------------------------------------------------------
   public void setXgap(int xgap)  {  this.xgap = xgap;  }
   public void setYgap(int ygap)  {  this.ygap = ygap;  }
   public int getXgap()     {  return xgap;     }
   public int getYgap()     {  return ygap;     }
   public int getXNullgap() {  return xnullgap; }
   public int getYNullgap() {  return ynullgap; }
   public int getWidth()    {  return width;    }
   public int getHeight()   {  return height;   }
   //---------------------------------------------------------------------------
   //---
   //--- LayoutManager Interface
   //---
   //---------------------------------------------------------------------------
   public void addLayoutComponent(String name, Component comp)
   {
      StringTokenizer strTk = new StringTokenizer(name,",");
      int x      = 1;
      int y      = 1;
      int xalign = FlexCell.LEFT;
      int yalign = FlexCell.CENTERY;
      int xext   = 1;
      int yext   = 1;
      if (strTk.hasMoreTokens()) x = Integer.parseInt(strTk.nextToken());
      if (strTk.hasMoreTokens()) y = Integer.parseInt(strTk.nextToken());
      if (strTk.hasMoreTokens())
      {
         String align = strTk.nextToken().toLowerCase();
         if (align.equals("l")) xalign = FlexCell.LEFT;
         if (align.equals("c")) xalign = FlexCell.CENTERX;
         if (align.equals("r")) xalign = FlexCell.RIGHT;
         if (align.equals("x")) xalign = FlexCell.EXPANDX;
      }
      if (strTk.hasMoreTokens())
      {
         String align = strTk.nextToken().toLowerCase();
         if (align.equals("t")) yalign = FlexCell.TOP;
         if (align.equals("c")) yalign = FlexCell.CENTERY;
         if (align.equals("b")) yalign = FlexCell.BOTTOM;
         if (align.equals("x")) yalign = FlexCell.EXPANDY;
      }
      if (strTk.hasMoreTokens()) xext   = Integer.parseInt(strTk.nextToken());
      if (strTk.hasMoreTokens()) yext   = Integer.parseInt(strTk.nextToken());
      cells[x][y] = new FlexCell(xalign, yalign, xext, yext, comp);
   }
   //---------------------------------------------------------------------------
   public void removeLayoutComponent(Component comp)
   {
      for(int x=0; x<width; x++)
         for(int y=0; y<height; y++)
            if (cells[x][y].ruponent == comp)
            {
               cells[x][y] = null;
               return;
            }
   }
   //---------------------------------------------------------------------------
   public Dimension preferredLayoutSize(Container parent)
   {
      synchronized (parent.getTreeLock())
      {
         calcMaxWidthArray();
         calcMaxHeightArray();
         int maxW = 0;
         int maxH = 0;
         for(int x=0; x<width; x++)  maxW += xpref[x];
         for(int y=0; y<height; y++) maxH += ypref[y];
         Insets insets = parent.getInsets();
         return new Dimension(insets.left + insets.right  + maxW + (width-1)*xgap,
                              insets.top  + insets.bottom + maxH + (height-1)*ygap);
      }
   }
   //---------------------------------------------------------------------------
   public Dimension minimumLayoutSize(Container parent)
   {
      return preferredLayoutSize(parent);
   }
   //---------------------------------------------------------------------------
   public void layoutContainer(Container parent)
   {
      synchronized (parent.getTreeLock())
      {
         FlexCell cell;
         //--- maximun preferred Width & Height calculus for each column ---
         calcMaxWidthArray();
         calcMaxHeightArray();
         //---------------------------------------------------------------------
         //--- Layout Calculus
         //---------------------------------------------------------------------
         Insets i = parent.getInsets();
         int maxWidth  = parent.getSize().width - i.left - i.right - (width-1)*xgap;
         int maxHeight = parent.getSize().height- i.top  - i.bottom- (height-1)*ygap;
         //--- total space occupied by fixed columns (and rows) ---
         int fixedWidth  = 0;
         int fixedHeight = 0;
         //--- number of variable columns (and rows) ---
         int varXCount = 0;
         int varYCount = 0;
         //--- width of a variable column (or row) ---
         int varWidth  = 0;
         int varHeight = 0;
         //---------------------------------------------------------------------
         //---   Handle Columns
         //---------------------------------------------------------------------
         //--- calc totale space occupied by fixed columns ---
         for(int x=0; x<width; x++)
         {
            if (xflags[x] == USEPREFERRED) fixedWidth += xpref[x];
               else varXCount++;
         }
         //--- calc width of a generic variable column ---
         if (varXCount != 0)
         {
            varWidth = (maxWidth - fixedWidth) / varXCount;
            if (varWidth < 0) varWidth = 0;
         }
         //--- calc width for expandable columns ---
         for(int x=0; x<width; x++) if (xflags[x] == EXPAND) xpref[x] = varWidth;
         //---------------------------------------------------------------------
         //---   Handle Rows
         //---------------------------------------------------------------------
         //--- calc totale space occupied by fixed rows ---
         for(int y=0; y<height; y++)
         {
            if (yflags[y] == USEPREFERRED) fixedHeight += ypref[y];
               else varYCount++;
         }
         //--- calc height of a generic variable row ---
         if (varYCount != 0)
         {
            varHeight = (maxHeight - fixedHeight) / varYCount;
            if (varHeight < 0) varHeight = 0;
         }
         //--- calc width for expandable rows ---
         for(int y=0; y<height; y++) if (yflags[y] == EXPAND) ypref[y] = varHeight;
         //---------------------------------------------------------------------
         //---   Do Layout
         //---------------------------------------------------------------------
         int currentX = i.left;
         int currentY = i.top;
         int compX, compY, compW, compH;
         int cellW, cellH;
         int xc, yc;
         for(int y=0; y<height; y++)
         {
            currentX = i.left;
            for(int x=0; x<width; x++)
            {
               //--- calculate current cell width and height ---
               cellW = 0;
               cellH = 0;
               cell = cells[x][y];
               if (cell != null)
               {
                  for(xc = x; xc< x + cell.xext; xc++) cellW += xpref[xc];
                  for(yc = y; yc< y + cell.yext; yc++) cellH += ypref[yc];
                  Dimension compSize = cell.ruponent.getPreferredSize();
                  //------------------------------------------------------------
                  //--- calculate compX & compW depending on align
                  //------------------------------------------------------------
                  switch(cell.xalign)
                  {
                     case FlexCell.LEFT:
                              compX = currentX;
                              compW = compSize.width;
                              break;
                     case FlexCell.CENTERX:
                              compX = currentX + (cellW - compSize.width)/2;
                              compW = compSize.width;
                              break;
                     case FlexCell.RIGHT:
                              compX = currentX + cellW - compSize.width;
                              compW = compSize.width;
                              break;
                     case FlexCell.EXPANDX:
                              compX = currentX;
                              compW = cellW;
                              break;
                     default: System.out.println("FlexLayout: invalid X align type");
                              compX = currentX;
                              compW = cellW;
                              break;
                  }
                  //------------------------------------------------------------
                  //--- calculate compY & compH depending on align
                  //------------------------------------------------------------
                  switch(cell.yalign)
                  {
                     case FlexCell.TOP:
                              compY = currentY;
                              compH = compSize.height;
                              break;
                     case FlexCell.CENTERY:
                              compY = currentY + (cellH - compSize.height)/2;
                              compH = compSize.height;
                              break;
                     case FlexCell.BOTTOM:
                              compY = currentY + cellH - compSize.height;
                              compH = compSize.height;
                              break;
                     case FlexCell.EXPANDY:
                              compY = currentY;
                              compH = cellH;
                              break;
                     default: System.out.println("FlexLayout: invalid Y align type");
                              compY = currentY;
                              compH = cellH;
                             break;
                  }
                  //--- resize component ---
                  cell.ruponent.setBounds(compX, compY, compW + (cell.xext-1)*xgap,
                                                         compH + (cell.yext-1)*ygap);
               }
               currentX += xpref[x] + xgap;
            }
            currentY += ypref[y] + ygap;
         }
      }
   }
   //---------------------------------------------------------------------------
   private void calcMaxWidthArray()
   {
      //--- maximun preferred Width calculus for each column ---
      FlexCell cell;
      int maxPrefW, curPrefW;
      for(int x=0; x<width; x++)
      {
         maxPrefW = 0;
         for(int y=0; y<height; y++)
         {
            cell = cells[x][y];
            if (cell != null && cell.xext == 1)
            {
               curPrefW = cell.ruponent.getPreferredSize().width;
               if (curPrefW > maxPrefW) maxPrefW = curPrefW;
            }
         }
         if (maxPrefW == 0) maxPrefW = xnullgap;
         xpref[x] = maxPrefW;
      }
   }
   //---------------------------------------------------------------------------
   private void calcMaxHeightArray()
   {
      //--- maximun preferred Height calculus for each row ---
      FlexCell cell;
      int maxPrefH, curPrefH;
      for(int y=0; y<height; y++)
      {
         maxPrefH = 0;
         for(int x=0; x<width; x++)
         {
            cell = cells[x][y];
            if (cell != null && cell.yext == 1)
            {
               curPrefH = cell.ruponent.getPreferredSize().height;
               if (curPrefH > maxPrefH) maxPrefH = curPrefH;
            }
         }
         if (maxPrefH == 0) maxPrefH = ynullgap;
         ypref[y] = maxPrefH;
      }
   }
}
class FlexCell
{
   //--- X align constants ---
   public static final int LEFT    = 0;
   public static final int CENTERX = 1;
   public static final int RIGHT   = 2;
   public static final int EXPANDX = 3;
   //--- Y align constants ---
   public static final int TOP     = 0;
   public static final int CENTERY = 1;
   public static final int BOTTOM  = 2;
   public static final int EXPANDY = 3;
   public int xalign, xext;
   public int yalign, yext;
   public Component component;
   //---------------------------------------------------------------------------
   public FlexCell(int xalign, int yalign, int xext, int yext, Component c)
   {
      this.xalign = xalign;
      this.yalign = yalign;
      this.xext   = xext;
      this.yext   = yext;
      component   = c;
   }
}





GraphPaperLayout

    
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * -Redistribution of source code must retain the above copyright notice, this
 *  list of conditions and the following disclaimer.
 *
 * -Redistribution in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed, licensed or intended
 * for use in the design, construction, operation or maintenance of any
 * nuclear facility.
 */
import java.awt.BorderLayout;
import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.LayoutManager2;
import java.awt.Rectangle;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Hashtable;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GraphPaperTest extends JPanel {
  public GraphPaperTest() {
    setLayout(new GraphPaperLayout(new Dimension(5, 5)));
    // Add a 1x1 Rect at (0,0)
    add(new JButton("1"), new Rectangle(0, 0, 1, 1));
    // Add a 2x1 Rect at (2,0)
    add(new JButton("2"), new Rectangle(2, 0, 2, 1));
    // Add a 1x2 Rect at (1,1)
    add(new JButton("3"), new Rectangle(1, 1, 1, 2));
    // Add a 2x2 Rect at (3,2)
    add(new JButton("4"), new Rectangle(3, 2, 2, 2));
    // Add a 1x1 Rect at (0,4)
    add(new JButton("5"), new Rectangle(0, 4, 1, 1));
    // Add a 1x2 Rect at (2,3)
    add(new JButton("6"), new Rectangle(2, 3, 1, 2));
  }
  public static void main(String[] args) {
    JFrame f = new JFrame("GraphPaperTest");
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
    f.getContentPane().add(new GraphPaperTest(), BorderLayout.CENTER);
    f.pack();
    f.setVisible(true);
  }
}
/**
 * The <code>GraphPaperLayout</code> class is a layout manager that lays out a
 * container"s components in a rectangular grid, similar to GridLayout. Unlike
 * GridLayout, however, components can take up multiple rows and/or columns. The
 * layout manager acts as a sheet of graph paper. When a component is added to
 * the layout manager, the location and relative size of the component are
 * simply supplied by the constraints as a Rectangle.
 * <p>
 * <code><pre>
 * 
 * import java.awt.*;
 * import java.applet.Applet;
 * 
 * public class ButtonGrid extends Applet {
 *   public void init() {
 *     setLayout(new GraphPaperLayout(new Dimension(5, 5)));
 *     // Add a 1x1 Rect at (0,0)
 *     add(new Button(&quot;1&quot;), new Rectangle(0, 0, 1, 1));
 *     // Add a 2x1 Rect at (2,0)
 *     add(new Button(&quot;2&quot;), new Rectangle(2, 0, 2, 1));
 *     // Add a 1x2 Rect at (1,1)
 *     add(new Button(&quot;3&quot;), new Rectangle(1, 1, 1, 2));
 *     // Add a 2x2 Rect at (3,2)
 *     add(new Button(&quot;4&quot;), new Rectangle(3, 2, 2, 2));
 *     // Add a 1x1 Rect at (0,4)
 *     add(new Button(&quot;5&quot;), new Rectangle(0, 4, 1, 1));
 *     // Add a 1x2 Rect at (2,3)
 *     add(new Button(&quot;6&quot;), new Rectangle(2, 3, 1, 2));
 *   }
 * }
 * </pre></code>
 * 
 * @author Michael Martak
 */
class GraphPaperLayout implements LayoutManager2 {
  int hgap; //horizontal gap
  int vgap; //vertical gap
  Dimension gridSize; //grid size in logical units (n x m)
  Hashtable compTable; //constraints (Rectangles)
  /**
   * Creates a graph paper layout with a default of a 1 x 1 graph, with no
   * vertical or horizontal padding.
   */
  public GraphPaperLayout() {
    this(new Dimension(1, 1));
  }
  /**
   * Creates a graph paper layout with the given grid size, with no vertical
   * or horizontal padding.
   */
  public GraphPaperLayout(Dimension gridSize) {
    this(gridSize, 0, 0);
  }
  /**
   * Creates a graph paper layout with the given grid size and padding.
   * 
   * @param gridSize
   *            size of the graph paper in logical units (n x m)
   * @param hgap
   *            horizontal padding
   * @param vgap
   *            vertical padding
   */
  public GraphPaperLayout(Dimension gridSize, int hgap, int vgap) {
    if ((gridSize.width <= 0) || (gridSize.height <= 0)) {
      throw new IllegalArgumentException(
          "dimensions must be greater than zero");
    }
    this.gridSize = new Dimension(gridSize);
    this.hgap = hgap;
    this.vgap = vgap;
    compTable = new Hashtable();
  }
  /**
   * @return the size of the graph paper in logical units (n x m)
   */
  public Dimension getGridSize() {
    return new Dimension(gridSize);
  }
  /**
   * Set the size of the graph paper in logical units (n x m)
   */
  public void setGridSize(Dimension d) {
    setGridSize(d.width, d.height);
  }
  /**
   * Set the size of the graph paper in logical units (n x m)
   */
  public void setGridSize(int width, int height) {
    gridSize = new Dimension(width, height);
  }
  public void setConstraints(Component comp, Rectangle constraints) {
    compTable.put(comp, new Rectangle(constraints));
  }
  /**
   * Adds the specified component with the specified name to the layout. This
   * does nothing in GraphPaperLayout, since constraints are required.
   */
  public void addLayoutComponent(String name, Component comp) {
  }
  /**
   * Removes the specified component from the layout.
   * 
   * @param comp
   *            the component to be removed
   */
  public void removeLayoutComponent(Component comp) {
    compTable.remove(comp);
  }
  /**
   * Calculates the preferred size dimensions for the specified panel given
   * the components in the specified parent container.
   * 
   * @param parent
   *            the component to be laid out
   * 
   * @see #minimumLayoutSize
   */
  public Dimension preferredLayoutSize(Container parent) {
    return getLayoutSize(parent, true);
  }
  /**
   * Calculates the minimum size dimensions for the specified panel given the
   * components in the specified parent container.
   * 
   * @param parent
   *            the component to be laid out
   * @see #preferredLayoutSize
   */
  public Dimension minimumLayoutSize(Container parent) {
    return getLayoutSize(parent, false);
  }
  /**
   * Algorithm for calculating layout size (minimum or preferred).
   * <p>
   * The width of a graph paper layout is the largest cell width (calculated
   * in <code>getLargestCellSize()</code> times the number of columns, plus
   * the horizontal padding times the number of columns plus one, plus the
   * left and right insets of the target container.
   * <p>
   * The height of a graph paper layout is the largest cell height (calculated
   * in <code>getLargestCellSize()</code> times the number of rows, plus the
   * vertical padding times the number of rows plus one, plus the top and
   * bottom insets of the target container.
   * 
   * @param parent
   *            the container in which to do the layout.
   * @param isPreferred
   *            true for calculating preferred size, false for calculating
   *            minimum size.
   * @return the dimensions to lay out the subcomponents of the specified
   *         container.
   * @see java.awt.GraphPaperLayout#getLargestCellSize
   */
  protected Dimension getLayoutSize(Container parent, boolean isPreferred) {
    Dimension largestSize = getLargestCellSize(parent, isPreferred);
    Insets insets = parent.getInsets();
    largestSize.width = (largestSize.width * gridSize.width)
        + (hgap * (gridSize.width + 1)) + insets.left + insets.right;
    largestSize.height = (largestSize.height * gridSize.height)
        + (vgap * (gridSize.height + 1)) + insets.top + insets.bottom;
    return largestSize;
  }
  /**
   * Algorithm for calculating the largest minimum or preferred cell size.
   * <p>
   * Largest cell size is calculated by getting the applicable size of each
   * component and keeping the maximum value, dividing the component"s width
   * by the number of columns it is specified to occupy and dividing the
   * component"s height by the number of rows it is specified to occupy.
   * 
   * @param parent
   *            the container in which to do the layout.
   * @param isPreferred
   *            true for calculating preferred size, false for calculating
   *            minimum size.
   * @return the largest cell size required.
   */
  protected Dimension getLargestCellSize(Container parent, boolean isPreferred) {
    int ncomponents = parent.getComponentCount();
    Dimension maxCellSize = new Dimension(0, 0);
    for (int i = 0; i < ncomponents; i++) {
      Component c = parent.getComponent(i);
      Rectangle rect = (Rectangle) compTable.get(c);
      if (c != null && rect != null) {
        Dimension componentSize;
        if (isPreferred) {
          componentSize = c.getPreferredSize();
        } else {
          componentSize = c.getMinimumSize();
        }
        // Note: rect dimensions are already asserted to be > 0 when the
        // component is added with constraints
        maxCellSize.width = Math.max(maxCellSize.width,
            componentSize.width / rect.width);
        maxCellSize.height = Math.max(maxCellSize.height,
            componentSize.height / rect.height);
      }
    }
    return maxCellSize;
  }
  /**
   * Lays out the container in the specified container.
   * 
   * @param parent
   *            the component which needs to be laid out
   */
  public void layoutContainer(Container parent) {
    synchronized (parent.getTreeLock()) {
      Insets insets = parent.getInsets();
      int ncomponents = parent.getComponentCount();
      if (ncomponents == 0) {
        return;
      }
      // Total parent dimensions
      Dimension size = parent.getSize();
      int totalW = size.width - (insets.left + insets.right);
      int totalH = size.height - (insets.top + insets.bottom);
      // Cell dimensions, including padding
      int totalCellW = totalW / gridSize.width;
      int totalCellH = totalH / gridSize.height;
      // Cell dimensions, without padding
      int cellW = (totalW - ((gridSize.width + 1) * hgap))
          / gridSize.width;
      int cellH = (totalH - ((gridSize.height + 1) * vgap))
          / gridSize.height;
      for (int i = 0; i < ncomponents; i++) {
        Component c = parent.getComponent(i);
        Rectangle rect = (Rectangle) compTable.get(c);
        if (rect != null) {
          int x = insets.left + (totalCellW * rect.x) + hgap;
          int y = insets.top + (totalCellH * rect.y) + vgap;
          int w = (cellW * rect.width) - hgap;
          int h = (cellH * rect.height) - vgap;
          c.setBounds(x, y, w, h);
        }
      }
    }
  }
  // LayoutManager2 /////////////////////////////////////////////////////////
  /**
   * Adds the specified component to the layout, using the specified
   * constraint object.
   * 
   * @param comp
   *            the component to be added
   * @param constraints
   *            where/how the component is added to the layout.
   */
  public void addLayoutComponent(Component comp, Object constraints) {
    if (constraints instanceof Rectangle) {
      Rectangle rect = (Rectangle) constraints;
      if (rect.width <= 0 || rect.height <= 0) {
        throw new IllegalArgumentException(
            "cannot add to layout: rectangle must have positive width and height");
      }
      if (rect.x < 0 || rect.y < 0) {
        throw new IllegalArgumentException(
            "cannot add to layout: rectangle x and y must be >= 0");
      }
      setConstraints(comp, rect);
    } else if (constraints != null) {
      throw new IllegalArgumentException(
          "cannot add to layout: constraint must be a Rectangle");
    }
  }
  /**
   * Returns the maximum size of this component.
   * 
   * @see java.awt.ruponent#getMinimumSize()
   * @see java.awt.ruponent#getPreferredSize()
   * @see LayoutManager
   */
  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.
   */
  public float getLayoutAlignmentX(Container target) {
    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.
   */
  public float getLayoutAlignmentY(Container target) {
    return 0.5f;
  }
  /**
   * Invalidates the layout, indicating that if the layout manager has cached
   * information it should be discarded.
   */
  public void invalidateLayout(Container target) {
    // Do nothing
  }
}





Place components at exact locations (x, y, width, height) and then determine how they behave when the window containing them (their parent) is resized

    

import java.awt.*;
import java.util.*;
/*
 * @(#)FunLayout.java   1.0  96/10/12  Eric Swildens  Copyright (c) 1996
 *
 * Permission to use, copy, modify, and distribute this software
 * for any purpose is hereby granted provided that this copyright
 * notice appears in all copies.
 *
 * NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
 * THE SOFTWARE ARE GIVEN, EITHER EXPRESS OR IMPLIED, INCLUDING BUT
 * NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
 */
public class FunLayout implements LayoutManager
{
// Using this layout manager, you can place components at exact
// locations (x, y, width, height) and then determine how they
// behave when the window containing them (their parent) is resized.
//
// sample use:
//
// fun1.html:
//
//  <title>fun1 example</title>
//  <applet code="fun1.class" width=400 height=300> </applet>
//
// fun1.java:
//
//  import java.applet.Applet;
//  import java.awt.*;
//
//  public class fun1 extends Applet
//  {
//  public void init()
//    {
//    FunLayout layout = new FunLayout();
//    setLayout(layout);
//
//    setBackground(Color.lightGray);
//
//    Button rightButton1 = new Button("Button1");
//    rightButton1.reshape(300, 5, 90, 20);
//    add(rightButton1);
//    layout.movesRight(rightButton1);
//
//    Button rightButton2 = new Button("Button 2");
//    rightButton2.reshape(200, 5, 90, 20);
//    add(rightButton2);
//    layout.movesRight(rightButton2);
//
//    Panel midPanel = new Panel();
//    midPanel.reshape(5, 40, 390, 200);
//    midPanel.setBackground(Color.blue);
//    layout.widthChanges(midPanel);
//    layout.heightChanges(midPanel);
//    add(midPanel);
//
//    Panel statusBar = new Panel();
//    statusBar.reshape(5, 245, 390, 20);
//    statusBar.setBackground(Color.black);
//    layout.movesDown(statusBar);
//    layout.widthChanges(statusBar);
//    add(statusBar);
//    }
//  }
//
// The above code creates an applet containing 2 buttons, a center panel
// and a status panel.  The two buttons are placed next to each other
// in the upper right.  When the window is sized wider, the buttons
// will move to the right to stick near the edge of the window.
//
// The midPanel is placed in the center and when the window is sized
// larger (in both dimensions), the panel will grow wider and taller.
//
// The statusBar is placed on the bottom and sticks to the bottom of
// the panel when it is sized larger or smaller in height (it moves
// down if the window it is contained in is sized to a larger height).
// It will grow wider if the window it is contained in is sized wider.
//
// The advantage of the FunLayout is that you place components where you
// want them to appear (best when using an interface builder) and still
// have control over what happens during sizing.
//
// This is the default layout mechanism many interface systems use, such
// as Netscape"s IFC.  In fact, if you use this layout manager, you will
// find porting your code to Netscape"s IFC much easier, as the layout
// container here is very similar to Netscape"s IFC layout mechanism.
//
// There are only 4 methods which determine how components are resized
//
//   layout.movesRight(comp);
//   layout.movesDown(comp);
//   layout.widthChanges(comp);
//   layout.heightChanges(comp);
//
// When you determine which to choose, you should ask "What should the
// component do when the window is sized larger?"
//
// If you don"t call any of the above methods for a component, it will
// simply stay at its current location.
//
// It"s more Fun than a Bag of layouts :-)
//
private Hashtable _moves;
private Hashtable _negSized;
private Dimension _prevContainerSize;
private final static int MOVES_RIGHT     =  2;
private final static int MOVES_DOWN      =  4;
private final static int HEIGHT_CHANGES  =  8;
private final static int WIDTH_CHANGES   = 16;
public FunLayout()
  {
  _moves = new Hashtable();
  _negSized = new Hashtable();
  }
private int _getMove(Component comp)
  {
  if (!_moves.containsKey(comp))
    return 0;
  return ((Integer)_moves.get(comp)).intValue();
  }
//
// private methods
//
private void _setMove(Component comp, int move)
  {
  if (_moves.containsKey(comp))
    {
    move |= ((Integer)_moves.get(comp)).intValue();
    _moves.remove(comp);
    }
  _moves.put(comp, new Integer(move));
  }
//
// LayoutManager implementation
//
public void addLayoutComponent(String name, Component c)
  {
  }
/**
  * When the window containing the given component is stretched to a
  * larger height, the given component will grow taller (and shorter
  * when the window is shortened).
  * @param comp the target Component
  */
public void heightChanges(Component comp)
  {
  if ((_getMove(comp) & MOVES_DOWN) > 0)
    System.out.println(getClass() + ":layout conflict for " + comp);
  _setMove(comp, HEIGHT_CHANGES);
  }
public void layoutContainer(Container con)
  {
  int i, count, deltax, deltay, move;
  Dimension conSize;
  Rectangle rect;
  Component comp;
  conSize = con.getSize();
  if (_prevContainerSize == null)
    {
    _prevContainerSize = conSize;
    return;
    }
  deltax = conSize.width - _prevContainerSize.width;
  deltay = conSize.height - _prevContainerSize.height;
  _prevContainerSize = conSize;
  count = con.countComponents();
  for (i = 0; i < count; i++)
    {
    comp = con.getComponent(i);
    if (!comp.isVisible())
      continue;
    move = _getMove(comp);
    if (move == 0)
      continue;
    rect = comp.getBounds();
    if (_negSized.containsKey(comp))
      {
      // the component is really at a negative size
      rect = (Rectangle)_negSized.get(comp);
      _negSized.remove(comp);
      }
    if ((move & MOVES_RIGHT) > 0)
      rect.x += deltax;
    else if ((move & WIDTH_CHANGES) > 0)
      rect.width += deltax;
    if ((move & MOVES_DOWN) > 0)
      rect.y += deltay;
    else if ((move & HEIGHT_CHANGES) > 0)
      rect.height += deltay;
    // if a components size becomes negative, we track it since the AWT
    // does not allow components to have a size < (0, 0)
    if (rect.width < 0 || rect.height < 0)
      _negSized.put(comp, rect);
    comp.setBounds(rect.x, rect.y, rect.width, rect.height);
    }
  }
public Dimension minimumLayoutSize(Container target)
  {
  return new Dimension(10, 10);
  }
/**
  * When the window containing the given component is stretched to a
  * larger height, the given component will move down (and up
  * when the window is shortened).
  * @param comp the target Component
  */
public void movesDown(Component comp)
  {
  if ((_getMove(comp) & HEIGHT_CHANGES) > 0)
    System.out.println(getClass() + ":layout conflict for " + comp);
  _setMove(comp, MOVES_DOWN);
  }
//
// public methods
//
/**
  * When the window containing the given component is widened, the
  * component will move right (and left when the window is shrunk).
  * @param comp the target Component
  */
public void movesRight(Component comp)
  {
  if ((_getMove(comp) & WIDTH_CHANGES) > 0)
    System.out.println(getClass() + ":layout conflict for " + comp);
  _setMove(comp, MOVES_RIGHT);
  }
public Dimension preferredLayoutSize(Container con)
  {
  Component comp;
  Rectangle rect;
  int i, count;
  Dimension d;
  d = new Dimension(0, 0);
  count = con.countComponents();
  for (i = 0; i < count; i++)
    {
    comp = con.getComponent(i);
    if (!comp.isVisible())
      continue;
    rect = comp.getBounds();
    if (d.width < rect.x + rect.width)
      d.width = rect.x + rect.width;
    if (d.height < rect.y + rect.height)
      d.height = rect.y + rect.height;
    }
  return d;
  }
public void removeLayoutComponent(Component c)
  {
  if (_negSized.containsKey(c))
    _negSized.remove(c);
  }
/**
  * When the window containing the given component is widened, the
  * component will grow wider (and smaller when the window is shrunk).
  * @param comp the target Component
  */
public void widthChanges(Component comp)
  {
  if ((_getMove(comp) & MOVES_RIGHT) > 0)
    System.out.println(getClass() + ":layout conflict for " + comp);
  _setMove(comp, WIDTH_CHANGES);
  }
}





Relative Layout Manager for Java J2SE

    
/*
 * Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
 * All rights reserved. Software written by Ian F. Darwin and others.
 * $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * 
 * Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
 * cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
 * pioneering role in inventing and promulgating (and standardizing) the Java 
 * language and environment is gratefully acknowledged.
 * 
 * The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
 * inventing predecessor languages C and C++ is also gratefully acknowledged.
 */
import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Point;
import java.util.StringTokenizer;
import java.util.Vector;
/**
 * <p>
 * RelativeLayout, a Relative Layout Manager for Java J2SE. Mainly for porting
 * tired old code that uses x,y locations. You really can"t just assign x,y
 * locations to components in Java Java J2SE - it breaks badly when the user
 * resizes (and you can <em>not</em> mandate that the user can"t resize you --
 * see any book on UI design for <em>that</em> little discussion -- and can
 * also look bad due to resolution independance. Symantec Cafe 1.x, for example,
 * used to spit out unfortunate (and unmaintainable) code like this:
 * 
 * <pre>
 * setLayout(null);
 * setSize(331, 241);
 * label1 = new Label(&quot;Info Applet&quot;, Label.CENTER);
 * add(label1);
 * label1.setBounds(91, 19, 107, 15);
 * </pre>
 * 
 * </p>
 * <p>
 * <em>Bleaarrgghh!!!</em> To make it work properly at all resolutions and
 * survive user-initiated resize actions, change it to
 * 
 * <pre>
 * 
 *   setLayout(new RelativeLayout(331,241,false);
 *   label1=new Label(&quot;Info Applet&quot;, Label.CENTER);
 *   add(&quot;91,19&quot;, label1);
 *  
 * </pre>
 * 
 * Note that it"s actually <EM>less</EM> work to get it right. Symantec,
 * Microsoft, and others, please take note!
 * </p>
 * 
 * @author Ian Darwin, http://www.darwinsys.ru/
 */
public class RelativeLayout implements LayoutManager {
  /** requested absolute width of canvas */
  protected int reqWid;
  /** requested absolute height of canvas */
  protected int reqHgt;
  /** actual size width when laid out */
  protected int curWid;
  /** actual size height when laid out */
  protected int curHgt;
  /** to track Components added by named add form. */
  protected Vector curComps = new Vector();
  /**
   * Constructs an RelativeLayout, given original hard-coded size of panel.
   */
  public RelativeLayout(int wid, int ht) {
    this.reqWid = wid;
    this.reqHgt = ht;
  }
  /**
   * Called by AWT when the user uses the form add(name, Component). Adds the
   * specified component with the specified name to the layout.
   * 
   * @param name
   *            String with location for component c <EM>Note</EM>: the
   *            "name" <EM>must</EM> contain x, y location, ie., <BR>
   *            add("" + 320 + "," + 100, new Button("Quit")); <BR>
   *            or <BR>
   *            add("320,100", new Button("Quit"). <BR>
   *            This adds the Button at x=320, y=100 when the Panel is at its
   *            original full size.
   * @param c
   *            Component to be added.
   */
  public void addLayoutComponent(String name, Component c) {
    int x, y;
    StringTokenizer st = new StringTokenizer(name, ",");
    x = Integer.parseInt(st.nextToken());
    y = Integer.parseInt(st.nextToken());
    // System.out.println("Adding: Name " + name +"; obj " + c
    //   + "; x " + x + "; y " + y);
    Tracker t = new Tracker(x, y, c);
    curComps.addElement(t);
  }
  /**
   * Called by AWT to lay out the components in the target Container at its
   * current size.
   * 
   * @param target
   *            Container whose components are to be laid out.
   */
  public void layoutContainer(Container target) {
    Dimension targSize = target.getSize();
    Insets ins = target.getInsets();
    // System.out.println("layoutContainer: size " + targSize);
    curWid = targSize.width;
    curHgt = targSize.height;
    float widRatio = (float) curWid / (float) reqWid;
    float hgtRatio = (float) curHgt / (float) reqHgt;
    for (int i = 0; i < curComps.size(); i++) {
      int px, py, pw, ph;
      Tracker t = (Tracker) curComps.elementAt(i);
      Component tc = t.getComponent();
      Dimension d = tc.getPreferredSize();
      px = ins.right + (int) (t.getRequestedLoc().x * widRatio);
      py = ins.top + (int) (t.getRequestedLoc().y * hgtRatio);
      pw = d.width;
      ph = d.height;
      // System.out.println("layoutContainer["+i+"]: move " +
      // tc + " to " + px + ", " + py);
      tc.setBounds(px, py, pw, ph);
    }
  }
  /**
   * Called from AWT to calculate the minimum size dimensions for the target
   * panel given the components in it. But we use our own list of named
   * insertions, not the list of Components that the container keeps.
   * 
   * @param target
   *            Container to calculate for
   */
  public Dimension minimumLayoutSize(Container target) {
    int minw = 0, minh = 0;
    for (int i = 0; i < curComps.size(); i++) {
      Tracker t = (Tracker) curComps.elementAt(i);
      Component tc = t.getComponent();
      Dimension d = tc.getMinimumSize();
      Point rl = t.getRequestedLoc();
      minw = Math.max(minw, rl.x + d.width);
      minh = Math.max(minh, rl.y + d.height);
      // System.out.println("minLay, minw = " + minw
      // + "; minh = " + minh);
    }
    return new Dimension(minw, minw);
  }
  /**
   * Called by AWT to compute the preferred size for the target panel given
   * our list of the components that it contains.
   * 
   * @param target
   *            Container to calculate for
   */
  public Dimension preferredLayoutSize(Container target) {
    int prefw = 0, prefh = 0;
    for (int i = 0; i < curComps.size(); i++) {
      Tracker t = (Tracker) curComps.elementAt(i);
      Component tc = t.getComponent();
      Dimension d = tc.getMinimumSize();
      Point rl = t.getRequestedLoc();
      prefw = Math.max(prefw, rl.x + d.width);
      prefh = Math.max(prefh, rl.y + d.height);
      // System.out.println("prefLay, prefw = " +
      // prefw + "; prefh = " + prefh);
    }
    return new Dimension(prefw, prefh);
  }
  /**
   * Called by AWT to remove a given component from the layout.
   * 
   * @param c
   *            Component to be removed
   */
  public void removeLayoutComponent(Component c) {
    curComps.removeElement(c);
  }
  /**
   * Tracker is a class used only by RelativeLayout, to track the original
   * "requested" (hard-coded) x,y locations of each Component.
   */
  class Tracker {
    int absx, absy;
    Component theComp;
    /** Construct a tracker item given its location and Component. */
    Tracker(int x, int y, Component c) {
      this.absx = x;
      this.absy = y;
      this.theComp = c;
    }
    /** Extract the location as a Point. */
    public Point getRequestedLoc() {
      return new Point(absx, absy);
    }
    /** Extract the Component from this Tracker. */
    public Component getComponent() {
      return theComp;
    }
  }
}





Specialised layout manager for a grid of components.

  
/* 
 * JCommon : a free general purpose class library for the Java(tm) platform
 * 
 *
 * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
 * 
 * Project Info:  http://www.jfree.org/jcommon/index.html
 *
 * This library is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU Lesser General Public License as published by 
 * the Free Software Foundation; either version 2.1 of the License, or 
 * (at your option) any later version.
 *
 * This library 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 Lesser General Public 
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
 * USA.  
 *
 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
 * in the United States and other countries.]
 * 
 * --------------
 * LCBLayout.java
 * --------------
 * (C) Copyright 2000-2005, by Object Refinery Limited.
 *
 * Original Author:  David Gilbert (for Object Refinery Limited);
 * Contributor(s):   -;
 *
 * $Id: LCBLayout.java,v 1.5 2005/11/16 15:58:40 taqua Exp $
 *
 * Changes (from 26-Oct-2001)
 * --------------------------
 * 26-Oct-2001 : Changed package to com.jrefinery.layout.* (DG);
 * 10-Oct-2002 : Fixed errors reported by Checkstyle (DG);
 */

import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.io.Serializable;
/**
 * Specialised layout manager for a grid of components.
 *
 * @author David Gilbert
 */
public class LCBLayout implements LayoutManager, Serializable {
    /** For serialization. */
    private static final long serialVersionUID = -2531780832406163833L;
    
    /** A constant for the number of columns in the layout. */
    private static final int COLUMNS = 3;
    /** Tracks the column widths. */
    private int[] colWidth;
    /** Tracks the row heights. */
    private int[] rowHeight;
    /** The gap between each label and component. */
    private int labelGap;
    /** The gap between each component and button. */
    private int buttonGap;
    /** The gap between rows. */
    private int vGap;
    /**
     * Creates a new LCBLayout with the specified maximum number of rows.
     *
     * @param maxrows  the maximum number of rows.
     */
    public LCBLayout(final int maxrows) {
        this.labelGap = 10;
        this.buttonGap = 6;
        this.vGap = 2;
        this.colWidth = new int[COLUMNS];
        this.rowHeight = new int[maxrows];
    }
    /**
     * Returns the preferred size using this layout manager.
     *
     * @param parent  the parent.
     *
     * @return the preferred size using this layout manager.
    */
    public Dimension preferredLayoutSize(final Container parent) {
        synchronized (parent.getTreeLock()) {
            final Insets insets = parent.getInsets();
            final int ncomponents = parent.getComponentCount();
            final int nrows = ncomponents / COLUMNS;
            for (int c = 0; c < COLUMNS; c++) {
                for (int r = 0; r < nrows; r++) {
                    final Component component 
                        = parent.getComponent(r * COLUMNS + c);
                    final Dimension d = component.getPreferredSize();
                    if (this.colWidth[c] < d.width) {
                        this.colWidth[c] = d.width;
                    }
                    if (this.rowHeight[r] < d.height) {
                        this.rowHeight[r] = d.height;
                    }
                }
            }
            int totalHeight = this.vGap * (nrows - 1);
            for (int r = 0; r < nrows; r++) {
                totalHeight = totalHeight + this.rowHeight[r];
            }
            final int totalWidth = this.colWidth[0] + this.labelGap 
                + this.colWidth[1] + this.buttonGap + this.colWidth[2];
            return new Dimension(
                insets.left + insets.right + totalWidth + this.labelGap 
                    + this.buttonGap,
                insets.top + insets.bottom + totalHeight + this.vGap
            );
        }
    }
    /**
     * Returns the minimum size using this layout manager.
     *
     * @param parent  the parent.
     *
     * @return the minimum size using this layout manager.
     */
    public Dimension minimumLayoutSize(final Container parent) {
        synchronized (parent.getTreeLock()) {
            final Insets insets = parent.getInsets();
            final int ncomponents = parent.getComponentCount();
            final int nrows = ncomponents / COLUMNS;
            for (int c = 0; c < COLUMNS; c++) {
                for (int r = 0; r < nrows; r++) {
                    final Component component 
                        = parent.getComponent(r * COLUMNS + c);
                    final Dimension d = component.getMinimumSize();
                    if (this.colWidth[c] < d.width) {
                        this.colWidth[c] = d.width;
                    }
                    if (this.rowHeight[r] < d.height) {
                        this.rowHeight[r] = d.height;
                    }
                }
            }
            int totalHeight = this.vGap * (nrows - 1);
            for (int r = 0; r < nrows; r++) {
                totalHeight = totalHeight + this.rowHeight[r];
            }
            final int totalWidth = this.colWidth[0] + this.labelGap 
                + this.colWidth[1] + this.buttonGap + this.colWidth[2];
            return new Dimension(
                insets.left + insets.right + totalWidth + this.labelGap 
                + this.buttonGap,
                insets.top + insets.bottom + totalHeight + this.vGap
            );
        }
    }
    /**
     * Lays out the components.
     *
     * @param parent  the parent.
     */
    public void layoutContainer(final Container parent) {
        synchronized (parent.getTreeLock()) {
            final Insets insets = parent.getInsets();
            final int ncomponents = parent.getComponentCount();
            final int nrows = ncomponents / COLUMNS;
            for (int c = 0; c < COLUMNS; c++) {
                for (int r = 0; r < nrows; r++) {
                    final Component component 
                        = parent.getComponent(r * COLUMNS + c);
                    final Dimension d = component.getPreferredSize();
                    if (this.colWidth[c] < d.width) {
                        this.colWidth[c] = d.width;
                    }
                    if (this.rowHeight[r] < d.height) {
                        this.rowHeight[r] = d.height;
                    }
                }
            }
            int totalHeight = this.vGap * (nrows - 1);
            for (int r = 0; r < nrows; r++) {
                totalHeight = totalHeight + this.rowHeight[r];
            }
            final int totalWidth = this.colWidth[0] + this.colWidth[1] 
                                                    + this.colWidth[2];
            // adjust the width of the second column to use up all of parent
            final int available = parent.getWidth() - insets.left 
                - insets.right - this.labelGap - this.buttonGap;
            this.colWidth[1] = this.colWidth[1] + (available - totalWidth);
            // *** DO THE LAYOUT ***
            int x = insets.left;
            for (int c = 0; c < COLUMNS; c++) {
                int y = insets.top;
                for (int r = 0; r < nrows; r++) {
                    final int i = r * COLUMNS + c;
                    if (i < ncomponents) {
                        final Component component = parent.getComponent(i);
                        final Dimension d = component.getPreferredSize();
                        final int h = d.height;
                        final int adjust = (this.rowHeight[r] - h) / 2;
                        parent.getComponent(i).setBounds(x, y + adjust, 
                                this.colWidth[c], h);
                    }
                    y = y + this.rowHeight[r] + this.vGap;
                }
                x = x + this.colWidth[c];
                if (c == 0) {
                    x = x + this.labelGap;
                }
                if (c == 1) {
                    x = x + this.buttonGap;
                }
            }
        }
    }
    /**
     * Not used.
     *
     * @param comp  the component.
     */
    public void addLayoutComponent(final Component comp) {
        // not used
    }
    /**
     * Not used.
     *
     * @param comp  the component.
     */
    public void removeLayoutComponent(final Component comp) {
        // not used
    }
    /**
     * Not used.
     *
     * @param name  the component name.
     * @param comp  the component.
     */
    public void addLayoutComponent(final String name, final Component comp) {
        // not used
    }
    /**
     * Not used.
     *
     * @param name  the component name.
     * @param comp  the component.
     */
    public void removeLayoutComponent(final String name, final Component comp) {
        // not used
    }
}





Special simple layout used in TabbedContainer

  
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common
 * Development and Distribution License("CDDL") (collectively, the
 * "License"). You may not use this file except in compliance with the
 * License. You can obtain a copy of the License at
 * http://www.netbeans.org/cddl-gplv2.html
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
 * specific language governing permissions and limitations under the
 * License.  When distributing the software, include this License Header
 * Notice in each file and include the License file at
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the GPL Version 2 section of the License file that
 * accompanied this code. If applicable, add the following below the
 * License Header, with the fields enclosed by brackets [] replaced by
 * your own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 *
 * Contributor(s):
 *
 * The Original Software is NetBeans. The Initial Developer of the Original
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
 * Microsystems, Inc. All Rights Reserved.
 *
 * If you wish your version of this file to be governed by only the CDDL
 * or only the GPL Version 2, indicate your decision by adding
 * "[Contributor] elects to include this software in this distribution
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
 * single choice of license, a recipient has the option to distribute
 * your version of this file under either the CDDL, the GPL Version 2 or
 * to extend the choice of license to its licensees as provided above.
 * However, if you add GPL Version 2 code and therefore, elected the GPL
 * Version 2 license, then the option applies only if the new code is
 * made subject to such option by the copyright holder.
 */

import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.lang.ref.WeakReference;
import javax.swing.JComponent;
/**
 * Special simple layout used in TabbedContainer. Shows component in the
 * "stack", it means that only one component is visible at any time, others are
 * always hidden "below" the visible one. Use method showComponent to select
 * visible component.
 *
 * @author Dafe Simonek
 */
class StackLayout implements LayoutManager {
    
    // #100486 - hold visibleComp weakly, because removeLayoutComponent may not
    // be called and then visibleComp is not freed. See StackLayoutTest for details.
    /**
     * Holds currently visible component or null if no comp is visible
     */
    private WeakReference<Component> visibleComp = null;
    /**
     * Set the currently displayed component.  If passed null for the component,
     * all contained components will be made invisible (sliding windows do this)
     * @param c Component to show
     * @param parent Parent container
     */
    public void showComponent(Component c, Container parent) {
        Component comp = getVisibleComponent();
        if (comp != c) {
            if (!parent.isAncestorOf(c) && c != null) {
                parent.add(c);
            }
            synchronized (parent.getTreeLock()) {
                if (comp != null) {
                    comp.setVisible(false);
                }
                visibleComp = new WeakReference<Component>(c);
                if (c != null) {
                    c.setVisible(true);
                }
    // trigger re-layout
    if (c instanceof JComponent) {
        ((JComponent)c).revalidate();
    }
    else {
        parent.validate(); //XXX revalidate should work!
    }
            }
        }
    }
    
    /** Allows support for content policies 
     * @return Currently visible component or null
     */
    public Component getVisibleComponent() {
        return visibleComp == null ? null : visibleComp.get();
    }
    /**
     * ********** Implementation of LayoutManager interface *********
     */
    public void addLayoutComponent(String name, Component comp) {
        synchronized (comp.getTreeLock()) {
            comp.setVisible(false);
            // keep consistency if showComponent was already called on this
            // component before
            if (comp == getVisibleComponent()) {
                visibleComp = null;
            }
/*System.out.println("Border dump for " + comp.getName());
borderDump((javax.swing.JComponent)comp, "");*/
        }
    }
    
/*private void borderDump (javax.swing.JComponent comp, String space) {
    javax.swing.border.Border compBorder = comp.getBorder();
    if (compBorder == null) {
        System.out.println(space + comp.getClass().getName() + " has no border.");
    } else {
        System.out.println(space + comp.getClass().getName() + ": " + compBorder.getClass().getName());
    }
    Component curComp;
    for (int i = 0; i < comp.getComponentCount(); i++) {
        curComp = comp.getComponent(i);
        if (curComp instanceof javax.swing.JComponent) {
            borderDump((javax.swing.JComponent)curComp, space + " ");
        }
    }
}*/
    
    public void removeLayoutComponent(Component comp) {
        synchronized (comp.getTreeLock()) {
            if (comp == getVisibleComponent()) {
                visibleComp = null;
            }
            // kick out removed component as visible, so that others
            // don"t have problems with hidden components
            comp.setVisible(true);
        }
    }
    public void layoutContainer(Container parent) {
        Component visibleComp = getVisibleComponent();
        if (visibleComp != null) {
            synchronized (parent.getTreeLock()) {
                Insets insets = parent.getInsets();
                visibleComp.setBounds(insets.left, insets.top, parent.getWidth()
                   - (insets.left + insets.right), parent.getHeight()
                   - (insets.top + insets.bottom));
            }
        }
    }
    public Dimension minimumLayoutSize(Container parent) {
        return getEmptySize();
    }
    public Dimension preferredLayoutSize(Container parent) {
        return getEmptySize();
    }
    /**
     * Specifies default size of empty container
     */
    private static Dimension getEmptySize() {
        return new Dimension(50, 50);
    }
}





Square Layout

    
/**
 * The utillib library.
 * More information is available at http://www.jinchess.ru/.
 * Copyright (C) 2002 Alexander Maryanovsky.
 * All rights reserved.
 *
 * The utillib library is free software; you can redistribute
 * it and/or modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * The utillib library 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 Lesser
 * General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with utillib library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

import java.awt.*;

/**
 * A LayoutManager which lays out a single component making sure its height is
 * always the same as its width. If the parent container"s width differs from
 * it height, the child will be laid out according to its x and y alignment.
 */
public class SquareLayout implements LayoutManager{
  
  
  /**
   * Creates a new SquareLayout.
   */
  public SquareLayout(){
  }
  
  
  
  /**
   * Creates a new Container with SquareLayout which will contain the specified
   * component.
   */
   
  public static Container createSquareContainer(Component child){
    Container container = new Container();
    container.setLayout(new SquareLayout());
    container.add(child);
    
    return container;
  }

  /**
   * Adds the specified component with the specified name to the layout. 
   */
  public void addLayoutComponent(String name, Component component){
    
  }
  
  
  /**
   * Removes the specified component from the layout. 
   */
  public void removeLayoutComponent(Component component){
    
  }
  
  
  
  /**
   * Returns the sole child of the specified container, or <code>null</code> if
   * none. Throws an <code>IllegalStateException</code> if there is more than
   * one child.
   */
   
  private Component getChild(Container c){
    int childCount = c.getComponentCount();
    if (childCount > 1)
      throw new IllegalStateException("May not layout more than one component");
    else if (childCount == 0)
      return null;
    else
      return c.getComponent(childCount - 1);
  }

  /**
   * Lays out the container in the specified panel. 
   */
  public void layoutContainer(Container container){
    Component child = getChild(container);
    if (child == null)
      return;
    
    Dimension parentSize = container.getSize();
    Insets insets = container.getInsets();
    
    // A rectangle specifying the actual area available for layout. 
    Rectangle rect = new Rectangle(insets.left, insets.top,
      parentSize.width - insets.left - insets.right, parentSize.height - insets.top - insets.bottom);
    int minSize = rect.width < rect.height ? rect.width : rect.height;
    int widthSpace = rect.width - minSize;
    int heightSpace = rect.height - minSize;
    child.setBounds(rect.x + (int)(widthSpace*child.getAlignmentX()),
                    rect.y + (int)(heightSpace*child.getAlignmentY()), minSize, minSize);
  }
  
  /**
   * Calculates the minimum size dimensions for the specified panel given the 
   * components in the specified parent container. 
   */
  public Dimension minimumLayoutSize(Container container){
    Component child = getChild(container);
    if (child == null)
      return new Dimension(0, 0);
    
    Dimension childMinSize = child.getMinimumSize();
    Insets insets = container.getInsets();
    
    int width = childMinSize.width + insets.left + insets.right;
    int height = childMinSize.height + insets.top + insets.bottom;
    int maxSize = Math.max(width, height);
    return new Dimension(maxSize, maxSize);
  }


  /**
   * Calculates the preferred size dimensions for the specified panel given the
   * components in the specified parent container. 
   */
  public Dimension preferredLayoutSize(Container container){
    Component child = getChild(container);
    if (child == null)
      return new Dimension(0, 0);
    
    Dimension childPrefSize = child.getPreferredSize();
    Insets insets = container.getInsets();
    
    int width = childPrefSize.width + insets.left + insets.right;
    int height = childPrefSize.height + insets.top + insets.bottom;
    int maxSize = Math.max(width, height);
    return new Dimension(maxSize, maxSize);
  }

  
}





Stack Layout, uses an orientation to determine if the contents should be arranged horizontally or vertically.

  
/*
 *  StackLayout.java
 *  2005-07-15
 */

import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;
import javax.swing.JSeparator;
import javax.swing.JToolBar;
import javax.swing.SwingConstants;

/**
 * Similar to BoxLayout, uses an orientation to determine if the contents
 * should be arranged horizontally or vertically.  By default, Resizes each
 * item to equal width or height (depending on the orientation) based on the
 * maximum preferred width or height of all items.
 * @author Christopher Bach
 */
public class StackLayout implements LayoutManager
{
  public static final int   HORIZONTAL = SwingConstants.HORIZONTAL;
  public static final int   VERTICAL = SwingConstants.VERTICAL;
  private int     ourOrientation = HORIZONTAL;
  private int     ourSpacing = 0;
  private boolean   ourDepthsMatched = true;
  private boolean   ourLengthsMatched = false;
  private boolean   ourFill = false;
  private boolean   ourDrop = false;
  private int     ourSqueezeFactor = 100;



  /**
   * Creates a new StackLayout with a horizontal orientation.
   */
  public StackLayout()
  {
  }

  /**
   * Creates a new StackLayout with the specified orientation.
   */
  public StackLayout(int orientation)
  {
    setOrientation(orientation);
  }

  /**
   * Creates a new StackLayout with the specified orientation and spacing.
   */
  public StackLayout(int orientation, int spacing)
  {
    setOrientation(orientation);
    setSpacing(spacing);
  }

  /**
   * Creates a new StackLayout matching the component lengths and
   * depths as indicated.
   */
  public StackLayout(boolean matchLengths, boolean matchDepths)
  {
    setMatchesComponentLengths(matchLengths);
    setMatchesComponentDepths(matchDepths);
  }

  /**
   * Creates a new StackLayout with the specified orientation
   * and spacing, matching the component lengths and depths
   * as indicated.
   */
  public StackLayout(int orientation, int spacing,
          boolean matchLengths, boolean matchDepths)
  {
    setOrientation(orientation);
    setSpacing(spacing);
    setMatchesComponentLengths(matchLengths);
    setMatchesComponentDepths(matchDepths);
  }







  /**
   * Sets this StackLayout"s orientation, either
   * SwingConstants.HORIZONTAL or SwingConstants.VERTICAL.
   */
  public void setOrientation(int orientation)
  {
    if (orientation == HORIZONTAL || orientation == VERTICAL)
    {
      ourOrientation = orientation;
    }
  }

  /**
   * Returns this StackLayout"s orientation, either
   * SwingConstants.HORIZONTAL or SwingConstants.VERTICAL.
   */
  public int getOrientation()
  {
    return ourOrientation;
  }

  /**
   * Sets the spacing between components that this StackLayout uses
   * when laying out the components.
   */
  public void setSpacing(int spacing)
  {
    ourSpacing = Math.max(0, spacing);
  }

  /**
   * Returns the spacing between components that this StackLayout uses
   * when laying out the components.
   */
  public int getSpacing()
  {
    return ourSpacing;
  }

  /**
   * Sets whether or not the last component in the stack
   * should be stretched to fill any remaining space within
   * the parent container.  The default value is false.
   */
  public void setFillsTrailingSpace(boolean shouldFill)
  {
    ourFill = shouldFill;
  }

  /**
   * Returns whether or not the last component in the stack
   * should be stretched to fill any remaining space within
   * the parent container.
   */
  public boolean fillsTrailingSpace()
  {
    return ourFill;
  }

  /**
   * Sets whether or not components in the stack that do not
   * fit in the parent container should be left out of the layout.
   * The default value is false;
   */
  public void setDropsPartialComponents(boolean shouldDrop)
  {
    ourDrop = shouldDrop;
  }

  /**
   * Returns whether or not components in the stack that do not
   * fit in the parent container should be left out of the layout.
   */
  public boolean dropsPartialComponents()
  {
    return ourDrop;
  }

  /**
   * Sets whether or not all components in the stack will be sized
   * to the same height (when in a horizontal orientation) or width
   * (when in a vertical orientation).  The default value is true.
   */
  public void setMatchesComponentDepths(boolean match)
  {
    ourDepthsMatched = match;
  }

  /**
   * Returns whether or not all components in the stack will be sized
   * to the same height (when in a horizontal orientation) or width
   * (when in a vertical orientation).
   */
  public boolean matchesComponentDepths()
  {
    return ourDepthsMatched;
  }

  /**
   * Sets whether or not all components in the stack will be sized
   * to the same width (when in a horizontal orientation) or height
   * (when in a vertical orientation).  The default value is false.
   */
  public void setMatchesComponentLengths(boolean match)
  {
    ourLengthsMatched = match;
  }

  /**
   * Returns whether or not all components in the stack will be sized
   * to the same width (when in a horizontal orientation) or height
   * (when in a vertical orientation).
   */
  public boolean matchesComponentLengths()
  {
    return ourLengthsMatched;
  }

  /**
   * Sets the percentage of a component"s preferred size that it
   * may be squeezed in order to attempt to fit all components
   * into the layout.  The squeeze factor will only be applied
   * when this layout is set to match component lengths.
   *
   * For example, if the parent container is 100 pixels wide
   * and holds two buttons, the largest having a preferred
   * width of 80 pixels, a squeeze factor of 50 will allow each
   * button to be sized to as small as 40 pixels wide (50 percent
   * of the preferred width.
   *
   * The default value is 100.
   */
  public void setSqueezeFactor(int factor)
  {
    if (factor < 0) ourSqueezeFactor = 0;
    else if (factor > 100) ourSqueezeFactor = 100;
    else ourSqueezeFactor = factor;
  }

  /**
   * Returns the percentage of a component"s preferred size that it
   * may be squeezed in order to attempt to fit all components
   * into the layout.
   */
  public int getSqueezeFactor()
  {
    return ourSqueezeFactor;
  }










  ////// LayoutManager implementation //////

  /**
   * Adds the specified component with the specified name to this layout.
   */
  public void addLayoutComponent(String name, Component comp)
  {
  }

  /**
   * Removes the specified component from this layout.
   */
  public void removeLayoutComponent(Component comp)
  {
  }

  /**
   * Returns the preferred size for this layout to arrange the
   * indicated parent"s children.
   */
  public Dimension preferredLayoutSize(Container parent)
  {
    if (parent instanceof JToolBar)
    {
      setOrientation( ((JToolBar)parent).getOrientation() );
    }
    return preferredLayoutSize(parent, ourOrientation);
  }

  /**
   * Returns the preferred size for this layout to arrange the
   * indicated parent"s children at the specified orientation.
   */
  // public, because it"s useful - not one of the LayoutManager methods
  public Dimension preferredLayoutSize(Container parent, int orientation)
  {
    synchronized (parent.getTreeLock())
    {
      Component[] comps = parent.getComponents();
      Dimension total = new Dimension(0, 0);
      int depth = calculatePreferredDepth(comps, orientation);
      int length = ( ourLengthsMatched ?
        calculateAdjustedLength(comps, orientation, ourSpacing)
          : calculatePreferredLength(comps, orientation, ourSpacing) );

      total.width = (orientation == HORIZONTAL ? length : depth);
      total.height = (orientation == HORIZONTAL ? depth : length);

      Insets in = parent.getInsets();
      total.width += in.left + in.right;
      total.height += in.top + in.bottom;
      return total;
    }
    }


  /**
   * Returns the minimum size for this layout to arrange the
   * indicated parent"s children at the specified orientation.
   */
    public Dimension minimumLayoutSize(Container parent)
    {
    synchronized (parent.getTreeLock())
    {
      if (parent instanceof JToolBar)
      {
        setOrientation( ((JToolBar)parent).getOrientation() );
      }
      Component[] comps = parent.getComponents();
      Dimension total = new Dimension(0, 0);
      int depth = calculatePreferredDepth(comps, ourOrientation);
      int length = calculateMinimumLength(comps, ourOrientation, ourSpacing);
      total.width = (ourOrientation == HORIZONTAL ? length : depth);
      total.height = (ourOrientation == HORIZONTAL ? depth : length);
      Insets in = parent.getInsets();
      total.width += in.left + in.right;
      total.height += in.top + in.bottom;
      return total;
    }
    }


  /**
   * Lays out the child components within the indicated parent container.
   */
    public void layoutContainer(Container parent)
    {
    synchronized (parent.getTreeLock())
    {
      if (parent instanceof JToolBar)
      {
        setOrientation( ((JToolBar)parent).getOrientation() );
      }
      layoutComponents(parent);
    }
  }


  private void layoutComponents(Container parent)
  {
    Component[] components = parent.getComponents();
    Insets in = parent.getInsets();
    int maxHeight = parent.getHeight() - in.top - in.bottom;
    int maxWidth = parent.getWidth() - in.left - in.right;
    boolean horiz = (ourOrientation == HORIZONTAL);

    int totalDepth = calculatePreferredDepth(components, ourOrientation);
    totalDepth = Math.max( totalDepth, (horiz ? maxHeight : maxWidth) );
    int prefLength = ( ourLengthsMatched ?
              calculateAdjustedLength(components, ourOrientation, ourSpacing)
              : calculatePreferredLength(components, ourOrientation, ourSpacing) );
    int totalLength = Math.min( prefLength, (horiz ? maxWidth : maxHeight) );
    int a = (horiz ? in.left : in.top);
    int b = (horiz ? in.top : in.left);
    int l = 0, d = 0, sum = 0;
    int matchedLength = 0;
    Dimension prefsize = null;
    if (ourLengthsMatched)
    {
      matchedLength = ( horiz ? getMaxPrefWidth(components)
                    : getMaxPrefHeight(components) );
      if (prefLength > totalLength && ourSqueezeFactor < 100)
      {
        int minLength = calculateMinimumLength(components,
                      ourOrientation, ourSpacing);
        if (minLength >= totalLength)
        {
          matchedLength = (matchedLength * ourSqueezeFactor) / 100;
        }
        else
        {
          int numSeparators = countSeparators(components);
          int numComponents = components.length - numSeparators;
          int diff = (prefLength - totalLength) / numComponents;
          if ((prefLength - totalLength) % numComponents > 0) diff++;
          matchedLength -= diff;
        }
      }
    }

    for (int i=0; i < components.length; i++)
    {
      prefsize = components[i].getPreferredSize();
      if (!ourLengthsMatched) l = (horiz ? prefsize.width : prefsize.height);
      else l = matchedLength;
      if (components[i] instanceof JSeparator)
      {
        // l = Math.min(prefsize.width, prefsize.height);
        l = (horiz ? prefsize.width : prefsize.height);
        d = totalDepth;
        sum += l;
        if (ourDrop && sum > totalLength) l = 0;
      }
      else
      {
        sum += l;
        if (ourDrop && sum > totalLength) l = 0;
        else if (ourFill && !ourLengthsMatched && i == components.length - 1)
        {
          l = Math.max( l, (horiz ? maxWidth : maxHeight) );
        }
        if (ourDepthsMatched) d = totalDepth;
        else d = (horiz ? prefsize.height : prefsize.width);
      }

      if (horiz) components[i].setBounds(a, b + (totalDepth - d) / 2, l, d);
      else components[i].setBounds(b + (totalDepth - d) / 2, a, d, l);
      a += l + ourSpacing;
      sum += ourSpacing;
    }
  }










  /**
   * Returns the largest preferred width of the provided components.
   */
  private int getMaxPrefWidth(Component[] components)
  {
    int maxWidth = 0;
    int componentWidth = 0;
    Dimension d = null;
    for (int i=0; i < components.length; i++)
    {
      d = components[i].getPreferredSize();
      componentWidth = d.width;
      if (components[i] instanceof JSeparator)
      {
        componentWidth = Math.min(d.width, d.height);
      }
      maxWidth = Math.max(maxWidth, componentWidth);
    }
    return maxWidth;
  }

  /**
   * Returns the largest preferred height of the provided components.
   */
  private int getMaxPrefHeight(Component[] components)
  {
    int maxHeight = 0;
    int componentHeight = 0;
    Dimension d = null;
    for (int i=0; i < components.length; i++)
    {
      d = components[i].getPreferredSize();
      componentHeight = d.height;
      if (components[i] instanceof JSeparator)
      {
        componentHeight = Math.min(d.width, d.height);
      }
      else maxHeight = Math.max(maxHeight, componentHeight);
    }
    return maxHeight;
  }








  /**
   * Calculates the preferred "length" of this layout for the provided
   * components based on the largest component preferred size.
   */
  private int calculateAdjustedLength(Component[] components,
                    int orientation, int spacing)
  {
    int total = 0;
    int componentLength = ( orientation == HORIZONTAL ?
        getMaxPrefWidth(components) : getMaxPrefHeight(components) );

    for (int i=0; i < components.length; i++)
    {
      if (components[i] instanceof JSeparator)
      {
        Dimension d = components[i].getPreferredSize();
        // total += Math.min(d.width, d.height);
        total += (orientation == HORIZONTAL ? d.width : d.height);
      }
      else total += componentLength;
    }

    int gaps = Math.max(0, spacing * (components.length - 1));
    total += gaps;

    return total;
  }


  /**
   * Calculates the minimum "length" of this layout for the provided
   * components, taking the squeeze factor into account when necessary.
   */
  private int calculateMinimumLength(Component[] components,
                    int orientation, int spacing)
  {
    if (!ourLengthsMatched)  return calculatePreferredLength(
                      components, orientation, spacing );
    if (ourSqueezeFactor == 100)  return calculateAdjustedLength(
                      components, orientation, spacing);
    int total = 0;
    int componentLength = ( orientation == HORIZONTAL ?
        getMaxPrefWidth(components) : getMaxPrefHeight(components) );
    componentLength = (componentLength * ourSqueezeFactor) / 100;

    for (int i=0; i < components.length; i++)
    {
      if (components[i] instanceof JSeparator)
      {
        Dimension d = components[i].getPreferredSize();
        // total += Math.min(d.width, d.height);
        total += (orientation == HORIZONTAL ? d.width : d.height);
      }
      else total += componentLength;
    }

    int gaps = Math.max(0, spacing * (components.length - 1));
    total += gaps;

    return total;
  }


  /**
   * Calculates the preferred "length" of this layout for the provided
   * components.
   */
  private int calculatePreferredLength(Component[] components,
                    int orientation, int spacing)
  {
    int total = 0;
    Dimension d = null;

    for (int i=0; i < components.length; i++)
    {
      d = components[i].getPreferredSize();
//      if (components[i] instanceof JSeparator)
//      {
//        total += Math.min(d.width, d.height);
//      }
//
//      else
        total += (orientation == HORIZONTAL ? d.width : d.height);
    }

    int gaps = Math.max(0, spacing * (components.length - 1));
    total += gaps;

    return total;
  }


  /**
   * Returns the preferred "depth" of this layout for the provided
   * components.
   */
  private int calculatePreferredDepth(Component[] components, int orientation)
  {
    if (orientation == HORIZONTAL) return getMaxPrefHeight(components);
    else if (orientation == VERTICAL) return getMaxPrefWidth(components);
    else return 0;
  }

  private int countSeparators(Component[] components)
  {
    int count = 0;
    for (int i=0; i < components.length; i++)
    {
      if (components[i] instanceof JSeparator) count++;
    }
    return count;
  }

}





Table Layout

    
/**
 * The utillib library.
 * More information is available at http://www.jinchess.ru/.
 * Copyright (C) 2002, 2003 Alexander Maryanovsky.
 * All rights reserved.
 *
 * The utillib library is free software; you can redistribute
 * it and/or modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * The utillib library 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 Lesser
 * General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with utillib library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager2;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.NoSuchElementException;
import java.util.Vector;

/**
 * A LayoutManager which lays out the components in a table-like structure.
 * Unlike <code>GridLayout</code>, the sizes of the rows and columns
 * are dynamic, although properly aligned. The cell sizes are determined
 * according to the preferred sizes of the components and each component is
 * sized to either its maximum size or the cell size. Components are positioned
 * within their cells according to their X and Y alignments.
 * When a new component is added, it is placed in the first empty cell, in
 * lexigraphic order. A new row is created if necessary.
 * To create an empty cell, simply add blank component.
 */
public class TableLayout implements LayoutManager2{

  /**
   * The amount of columns in the table.
   */
  private final int columnCount;

  /**
   * The gap between columns, in pixels.
   */
  private final int xGap;

  /**
   * The gap between rows, in pixels.
   */
  private final int yGap;

  /**
   * A Vector of rows where each row is a Component array holding the components
   * in that row.
   */
  private final Vector rows = new Vector();

  /**
   * Creates a new TableLayout with the specified amount of columns,
   * horizontal/vertical gaps between columns/cells.
   */
  public TableLayout(int columnCount, int xGap, int yGap){
    if (columnCount <= 0)
      throw new IllegalArgumentException("The amount of columns must be positive");
    if (xGap < 0)
      throw new IllegalArgumentException("The horizontal gap may not be negative: "+xGap);
    if (yGap < 0)
      throw new IllegalArgumentException("The vertical gap may not be negative: "+yGap);
    this.columnCount = columnCount;
    this.xGap = xGap;
    this.yGap = yGap;
  }

  /**
   * Creates a new TableLayout with the specified amount of columns.
   */
  public TableLayout(int columnCount){
    this(columnCount, 0, 0);
  }


  /**
   * Adds the specified component to the layout.
   */
  public void addLayoutComponent(Component component, Object constraints){
    synchronized(component.getTreeLock()){
      int rowCount = rows.size();
      for (int i = 0; i < rowCount; i++){
        Component [] row = (Component [])rows.elementAt(i);
        for (int j = 0; j < row.length; j++){
          if (row[j] == null){
            row[j] = component;
            return;
          }
        }
      }
      Component [] newRow = new Component[columnCount];
      newRow[0] = component;
      rows.addElement(newRow);
    }
  }

  /**
   * Throws an exception.
   */
  public void addLayoutComponent(String name, Component component){
    throw new UnsupportedOperationException("deprecated addLayoutComponent(String, Component)");
  }


  /**
   * Removes the specified component from the layout.
   */
  public void removeLayoutComponent(Component component){
    synchronized(component.getTreeLock()){
      int rowCount = rows.size();
      outer: for (int i = 0; i < rowCount; i++){
        Component [] row = (Component [])rows.elementAt(i);
        for (int j = 0; j < row.length; j++){
          if (row[j] == component){
            row[j] = null;
            break outer;
          }
        }
      }
      // Remove any empty rows at the end.
      for (int i = rowCount - 1; i >= 0; i--){
        Component [] row = (Component [])rows.elementAt(i);
        boolean isEmpty = true;
        for (int j = 0; j < row.length; j++){
          if (row[j] != null){
            isEmpty = false;
            break;
          }
        }
        if (isEmpty)
          rows.removeElementAt(i);
        else
          break;
      }
    }
  }


  /**
   * Returns a matrix of Dimension objects specifying the preferred sizes of the
   * components we are going to layout.
   */
  private Dimension [][] getPreferredSizes(Container parent){
    int rowCount = rows.size();
    Dimension [][] prefSizes = new Dimension[rowCount][columnCount];
    for (int i = 0; i < rowCount; i++){
      Component [] row = (Component [])rows.elementAt(i);
      for (int j = 0; j < columnCount; j++){
        Component component = row[j];
        // Can only happen on the last line when all the remaining components are null as well
        if (component == null) 
          break;
        if (component.getParent() != parent)
          throw new IllegalStateException("Bad parent specified");
        prefSizes[i][j] = component.getPreferredSize();
      }
    }
    return prefSizes;
  }

  /**
   * Calculates and returns a Pair where the first object is an array holding
   * the column widths of our layout and the second is the rowHeights.
   */
  private Pair calculateLayout(Dimension [][] prefSizes){
    int rowCount = rows.size();
    int [] columnWidths = new int[columnCount];
    int [] rowHeights = new int[rowCount];
    // Find the maximum preferred row heights and column widths.
    for (int i = 0; i < rowCount; i++){
      for (int j = 0; j < columnCount; j++){
        Dimension prefSize = prefSizes[i][j];
        // Can only happen on the last line when all the remaining components are null as well
        if (prefSize == null)
          break;
        columnWidths[j] = Math.max(columnWidths[j], prefSize.width);
        rowHeights[i] = Math.max(rowHeights[i], prefSize.height);
      }
    }
    return new Pair(columnWidths, rowHeights);
  }


  /**
   * Lays out the specified container. Throws an
   * <code>IllegalStateException</code> if any of the components added via the
   * <code>addLayoutComponent</code> method have a different parent than the
   * specified Container.
   */
  public void layoutContainer(Container parent){
    synchronized(parent.getTreeLock()){
      int rowCount = rows.size();
      Insets parentInsets = parent.getInsets();
      // Collect the preferred sizes.
      Dimension [][] prefSizes = getPreferredSizes(parent);
      Pair layout = calculateLayout(prefSizes);
      int [] columnWidths = (int [])layout.getFirst();
      int [] rowHeights = (int [])layout.getSecond();
      Dimension prefParentSize = calculatePreferredLayoutSize(parent, columnWidths, rowHeights);
      Dimension parentSize = parent.getSize();
      Dimension layoutSize = 
        new Dimension(parentSize.width - xGap*(rowCount - 1) - parentInsets.left - parentInsets.right,
                      parentSize.height - yGap*(columnCount - 1) - parentInsets.top - parentInsets.bottom);
      Dimension prefLayoutSize =
        new Dimension(prefParentSize.width - xGap*(rowCount - 1) - parentInsets.left - parentInsets.right,
                      prefParentSize.height - yGap*(columnCount - 1) - parentInsets.top - parentInsets.bottom);
      // Layout the components.
      int y = parentInsets.top;
      for (int i = 0; i < rowCount; i++){
        int x = parentInsets.left;
        int cellHeight = (rowHeights[i]*layoutSize.height)/prefLayoutSize.height;
        Component [] row = (Component [])rows.elementAt(i);
        for (int j = 0; j < row.length; j++){
          int cellWidth = (columnWidths[j]*layoutSize.width)/prefLayoutSize.width;
          Component component = row[j];
          // Can only happen on the last line when all the remaining components are null as well
          if (component == null)
            break;
          Dimension maxSize = component.getMaximumSize();
          int compWidth = Math.min(maxSize.width, cellWidth);
          int compHeight = Math.min(maxSize.height, cellHeight);
          int compX = x + (int)((cellWidth - compWidth)*component.getAlignmentX());
          int compY = y + (int)((cellHeight - compHeight)*component.getAlignmentY());
          component.setBounds(compX, compY, compWidth, compHeight);
          x += cellWidth + xGap;
        }
        y += cellHeight + yGap;
      }
    }
  }

  /**
   * We"re not caching anything yet, so this call is ignored.
   */
  public void invalidateLayout(Container parent){
  }

  /**
   * Returns the preferred layout for the specified parent container.
   */
  public Dimension preferredLayoutSize(Container parent){
    synchronized(parent.getTreeLock()){
      Dimension [][] prefSizes = getPreferredSizes(parent);
      Pair layout = calculateLayout(prefSizes);
      int [] columnWidths = (int [])layout.getFirst();
      int [] rowHeights = (int [])layout.getSecond();
      return calculatePreferredLayoutSize(parent, columnWidths, rowHeights);
    }
  }

  /**
   * Calculates the preferred layout size for the specified preferred column
   * widths and row heights.
   */
  private Dimension calculatePreferredLayoutSize(Container parent, int [] columnWidths, int [] rowHeights){
    int prefWidth = 0;
    int prefHeight = 0;
    for (int i = 0; i < columnWidths.length; i++)
      prefWidth += columnWidths[i];
    for (int i = 0; i < rowHeights.length; i++)
      prefHeight += rowHeights[i];
    // Add the gaps
    prefWidth += xGap*(columnWidths.length - 1);
    prefHeight += yGap*(rowHeights.length - 1);
    // Add parent insets
    Insets parentInsets = parent.getInsets();
    prefWidth += parentInsets.left + parentInsets.right;
    prefHeight += parentInsets.top + parentInsets.bottom;
    
    return new Dimension(prefWidth, prefHeight);
  }

  /**
   * Returns the same as <code>preferredLayoutSize</code>.
   */
  public Dimension minimumLayoutSize(Container parent){
    return preferredLayoutSize(parent);
  }


  /**
   * Returns a dimension with maximum possible values.
   */
  public Dimension maximumLayoutSize(Container parent){
    return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
  }

  /**
   * Returns <code>CENTER_ALIGNMENT</code>;
   */
  public float getLayoutAlignmentX(Container parent) {
    return Component.CENTER_ALIGNMENT;
  }

  /**
   * Returns <code>CENTER_ALIGNMENT</code>;
   */
  public float getLayoutAlignmentY(Container parent) {
    return Component.CENTER_ALIGNMENT;
  }

}
/**
 * The utillib library.
 * More information is available at http://www.jinchess.ru/.
 * Copyright (C) 2002 Alexander Maryanovsky.
 * All rights reserved.
 *
 * The utillib library is free software; you can redistribute
 * it and/or modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * The utillib library 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 Lesser
 * General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with utillib library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/**
 * A wrapper for any two other given objects.
 */
 final class Pair{
  
  /**
   * The first object.
   */
  private final Object first;


  /**
   * The second object.
   */
  private final Object second;


  /**
   * Creates a new <code>Pair</code> with the two given objects. Either of the
   * objects may be <code>null</code>.
   */
  public Pair(Object first, Object second){
    this.first = first;
    this.second = second;
  }


  /**
   * Returns the first object.
   */
  public Object getFirst(){
    return first;
  }


  /**
   * Returns the second object.
   */
  public Object getSecond(){
    return second;
  }


  /**
   * Returns a hashcode combined from the hashcodes of the two target objects.
   */
  public int hashCode(){
    int hash1 = (first == null ? 0 : first.hashCode());
    int hash2 = (second == null ? 0 : second.hashCode());
    return hash1^hash2;
  }


  /**
   * Returns true iff the given Object is a Pair, and its two objects are the
   * same as this one"s (comparison done via <code>Utilities.areEqual</code>)
   */
  public boolean equals(Object o){
    if (o == this)
      return true;
    if (!(o instanceof Pair))
      return false;
    Pair pair = (Pair)o;
    return Utilities.areEqual(pair.first, first) && Utilities.areEqual(pair.second, second);
  }
}
 /**
  * The utillib library.
  * More information is available at http://www.jinchess.ru/.
  * Copyright (C) 2002, 2003 Alexander Maryanovsky.
  * All rights reserved.
  *
  * The utillib library is free software; you can redistribute
  * it and/or modify it under the terms of the GNU Lesser General Public License
  * as published by the Free Software Foundation; either version 2 of the
  * License, or (at your option) any later version.
  *
  * The utillib library 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 Lesser
  * General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public License
  * along with utillib library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA
  */

 /**
  * A collection of general utility methods.
  */
  class Utilities{
   
   
   
   /**
    * A 0-length Object array.
    */
    
   public static final Object [] EMPTY_ARRAY = new Object[0];

   /**
    * A 0-length long array.
    */
    
   public static final long [] EMPTY_LONG_ARRAY = new long[0];

   /**
    * A 0-length int array.
    */
    
   public static final int [] EMPTY_INT_ARRAY = new int[0];
   
   
   /**
    * A 0-length short array.
    */
    
   public static final short [] EMPTY_SHORT_ARRAY = new short[0];
   
   /**
    * A 0-length byte array.
    */
    
   public static final byte [] EMPTY_BYTE_ARRAY = new byte[0];
   
   
   
   /**
    * A 0-length char array.
    */
    
   public static final char [] EMPTY_CHAR_ARRAY = new char[0];

   /**
    * A 0-length double array.
    */
    
   public static final double [] EMPTY_DOUBLE_ARRAY = new double[0];
   

   /**
    * A 0-length float array.
    */
    
   public static final float [] EMPTY_FLOAT_ARRAY = new float[0];

   /**
    * A 0-length String array.
    */
    
   public static final String [] EMPTY_STRING_ARRAY = new String[0];
   
   
   
   /**
    * An empty enumeration.
    */
   
   public static final Enumeration EMPTY_ENUM = new Enumeration(){
     public boolean hasMoreElements(){return false;}
     public Object nextElement(){throw new NoSuchElementException();}
   };
   
   
   /**
    * Returns <code>true</code> if the two specified objects are the same.
    * Returns <code>false</code> otherwise. To be considered the same, the two
    * references must either both be null or invoking <code>equals</code> on one
    * of them with the other must return <code>true</code>.
    */
   public static boolean areEqual(Object obj1, Object obj2){
     return (obj1 == obj2) || (obj1 == null ? false : obj1.equals(obj2));
   }


   /**
    * Maps the specified key to the specified value in the specified
    * <code>Hashtable</code>. If the specified value is <code>null</code> any
    * existing mapping of the specified key is removed from the
    * <code>Hashtable</code>. The old value mapped to the specified key
    * is returned, or <code>null</code> if no value was mapped to the key.
    */
   public static Object put(Hashtable table, Object key, Object value){
     return value == null ? table.remove(key) : table.put(key, value);
   }

   /**
    * Returns <code>true</code> if the specified object is an element of the
    * specified array. The specified array may not be <code>null</code>. The
    * specified object may be <code>null</code>, in which case this method will
    * return <code>true</code> iff one of the indices in the array is empty 
    * (contains <code>null</code>).
    */
   public static boolean contains(Object [] array, Object item){
     return (indexOf(array, item) != -1);
   }

   /**
    * Returns the index of the first occurrance of specified object in the
    * specified array, or -1 if the specified object is not an element of the
    * specified array. The specified object may be <code>null</code> in which
    * case the returned index will be the index of the first <code>null</code>
    * in the array.
    */
   public static int indexOf(Object [] array, Object item){
     if (array == null)
       throw new IllegalArgumentException("The specified array may not be null");
     for (int i = 0; i < array.length; i++)
       if (areEqual(item, array[i]))
         return i;
     return -1;
   }


   /**
    * Returns the index of the first occurrance of specified integer in the
    * specified array, or -1 if the specified integer is not an element of the
    * specified array.
    */
   public static int indexOf(int [] arr, int val){
     if (arr == null)
       throw new IllegalArgumentException("The specified array may not be null");
     for (int i = 0; i < arr.length; i++)
       if (arr[i] == val)
         return i;
     return -1;
   }
   
   
   /**
    * Converts the specified array into a string by appending all its elements
    * separated by a semicolon.
    */
   public static String arrayToString(Object [] arr){
     StringBuffer buf = new StringBuffer();
     for (int i = 0; i < arr.length; i++){
       buf.append(arr[i]);
       buf.append("; ");
     }
     if (arr.length > 0)
       buf.setLength(buf.length() - 2); // get rid of the extra "; "
     return buf.toString();
   }


   /**
    * Converts the specified <code>Hashtable</code> into a string by putting
    * each key and value on a separate line (separated by "\n") and an arrow
    * (" -> ") between them.
    */
   public static String hashtableToString(Hashtable hashtable){
     StringBuffer buf = new StringBuffer();
     Enumeration keys = hashtable.keys();
     while (keys.hasMoreElements()){
       Object key = keys.nextElement();
       Object value = hashtable.get(key);
       buf.append(key.toString());
       buf.append(" -> ");
       buf.append(value.toString());
       buf.append("\n");
     }
     return buf.toString();
   }


   /**
    * Returns the maximum element in the specified integer array.
    */
   public static int max(int [] arr){
     if (arr == null)
       throw new IllegalArgumentException("The specified array may not be null");
     if (arr.length == 0)
       throw new IllegalArgumentException("The specified array must have at least one element");
     int n = arr[0];
     for (int i = 1; i < arr.length; i++)
       if (arr[i] > n)
         n = arr[i];
     return n;
   }

   /**
    * Returns a hash code for the specified double value.
    */
   public static int hashCode(double val){
     return hashCode(Double.doubleToLongBits(val));
   }

   /**
    * Returns a hash code for the specified long value.
    */
   public static int hashCode(long val){
     return (int)(val ^ (val >>> 32));
   }
   
   
   
   /**
    * Returns the name of the package of the specified class.
    */
   
   public static String getPackageName(Class c){
     return getPackageName(c.getName());
   }
   
   
   
   /**
    * Returns the name of the package of the class with the specified (full) name.
    */
   
   public static String getPackageName(String className){
     int lastDotIndex = className.lastIndexOf(".");
     return lastDotIndex == -1 ? "" : className.substring(0, lastDotIndex);
   }
   
   
   
   /**
    * Returns the short name (excluding the package name) of the specified class. 
    */
   
   public static String getClassName(Class c){
     return getClassName(c.getName());
   }
   
   
   
   /**
    * Returns the short name (excluding the package name) of the class with the
    * specified fully qualified name.
    */
   
   public static String getClassName(String className){
     int lastDotIndex = className.lastIndexOf(".");
     return lastDotIndex == -1 ? className : className.substring(lastDotIndex + 1);
   }
   
   
   
 }





Table Layout implements LayoutManager2

    
/* Copyright (c) 2006, 2009, Carl Burch. License information is located in the
 * com.cburch.logisim.Main source code and at www.cburch.ru/logisim/. */
 
import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.LayoutManager2;
import java.util.ArrayList;
public class TableLayout implements LayoutManager2 {
    private int colCount;
    private ArrayList contents; // of Component[]
    private int curRow;
    private int curCol;
    private Dimension prefs;
    private int[] prefRow;
    private int[] prefCol;
    private double[] rowWeight;
    
    public TableLayout(int colCount) {
        this.colCount = colCount;
        this.contents = new ArrayList();
        this.curRow = 0;
        this.curCol = 0;
    }
    
    public void setRowWeight(int rowIndex, double weight) {
        if(weight < 0) {
            throw new IllegalArgumentException("weight must be nonnegative");
        }
        if(rowIndex < 0) {
            throw new IllegalArgumentException("row index must be nonnegative");
        }
        if((rowWeight == null || rowIndex >= rowWeight.length) && weight != 0.0) {
            double[] a = new double[rowIndex + 10];
            if(rowWeight != null) System.arraycopy(rowWeight, 0, a, 0, rowWeight.length);
            rowWeight = a;
        }
        rowWeight[rowIndex] = weight;
    }
    public void addLayoutComponent(String name, Component comp) {
        while(curRow >= contents.size()) {
            contents.add(new Component[colCount]);
        }
        Component[] rowContents = (Component[]) contents.get(curRow);
        rowContents[curCol] = comp;
        ++curCol;
        if(curCol == colCount) {
            ++curRow;
            curCol = 0;
        }
        prefs = null;
    }
    public void addLayoutComponent(Component comp, Object constraints) {
        if(constraints instanceof TableConstraints) {
            TableConstraints con = (TableConstraints) constraints;
            if(con.getRow() >= 0) curRow = con.getRow();
            if(con.getCol() >= 0) curCol = con.getCol();
        }
        addLayoutComponent("", comp);
    }
    public void removeLayoutComponent(Component comp) {
        for(int i = 0, n = contents.size(); i < n; i++) {
            Component[] row = (Component[]) contents.get(i);
            for(int j = 0; j < row.length; j++) {
                if(row[j] == comp) {
                    row[j] = null;
                    return;
                }
            }
        }
        prefs = null;
    }
    public Dimension preferredLayoutSize(Container parent) {
        if(prefs == null) {
            int[] prefCol = new int[colCount];
            int[] prefRow = new int[contents.size()]; 
            int height = 0;
            for(int i = 0; i < prefRow.length; i++) {
                Component[] row = (Component[]) contents.get(i);
                int rowHeight = 0;
                for(int j = 0; j < row.length; j++) {
                    if(row[j] != null) {
                        Dimension dim = row[j].getPreferredSize();
                        if(dim.height > rowHeight) rowHeight = dim.height;
                        if(dim.width > prefCol[j]) prefCol[j] = dim.width;
                    }
                }
                prefRow[i] = rowHeight;
                height += rowHeight;
            }
            int width = 0;
            for(int i = 0; i < prefCol.length; i++) {
                width += prefCol[i];
            }
            this.prefs = new Dimension(width, height);
            this.prefRow = prefRow;
            this.prefCol = prefCol;
        }
        return new Dimension(prefs);
    }
    public Dimension minimumLayoutSize(Container parent) {
        return preferredLayoutSize(parent);
    }
    public Dimension maximumLayoutSize(Container parent) {
        return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
    }
    public float getLayoutAlignmentX(Container parent) {
        return 0.5f;
    }
    public float getLayoutAlignmentY(Container parent) {
        return 0.5f;
    }
    public void layoutContainer(Container parent) {
        Dimension pref = preferredLayoutSize(parent);
        int[] prefRow = this.prefRow;
        int[] prefCol = this.prefCol;
        Dimension size = parent.getSize();
        
        double y0;
        int yRemaining = size.height - pref.height;
        double rowWeightTotal = 0.0;
        if(yRemaining != 0 && rowWeight != null) {
            for(int i = 0; i < rowWeight.length; i++) {
                rowWeightTotal += rowWeight[i];
            }
        }
        if(rowWeightTotal == 0.0 && yRemaining > 0) {
            y0 = yRemaining / 2.0;
        } else {
            y0 = 0;
        }
        
        int x0 = (size.width - pref.width) / 2;
        if(x0 < 0) x0 = 0;
        double y = y0;
        for(int i = 0, n = contents.size(); i < n; i++) {
            Component[] row = (Component[]) contents.get(i);
            int yRound = (int) (y + 0.5);
            int x = x0;
            for(int j = 0; j < row.length; j++) {
                Component comp = row[j];
                if(comp != null) {
                    row[j].setBounds(x, yRound, prefCol[j], prefRow[i]);
                }
                x += prefCol[j];
            }
            y += prefRow[i];
            if(rowWeightTotal > 0 && i < rowWeight.length) {
                y += yRemaining * rowWeight[i] / rowWeightTotal;
            }
        }
        
        
        // TODO Auto-generated method stub
        
    }
    public void invalidateLayout(Container parent) {
        prefs = null;
    }
}
/* Copyright (c) 2006, 2009, Carl Burch. License information is located in the
 * com.cburch.logisim.Main source code and at www.cburch.ru/logisim/. */
 class TableConstraints {
    public static TableConstraints at(int row, int col) {
        return new TableConstraints(row, col);
    }
    
    private int col;
    private int row;
    
    private TableConstraints(int row, int col) {
        this.col = col;
        this.row = row;
    }
    
    int getRow() {
        return row;
    }
    
    int getCol() {
        return col;
    }
}





Table layout manager

    

// Table layout manager, with the flexibility of GridBagLayout but the ease
// of use of HTML table declarations.
// See http://www.parallax.co.uk/~rolf/download/table.html
// Copyright (C) Rolf Howarth 1997, 1998 (rolf@parallax.co.uk)
// Permission to freely use, modify and distribute this code is given,
// provided this notice remains attached. This code is provided for
// educational use only and no warranty as to its suitability for any
// other purpose is made.
// Modification history
// 0.1  01 Nov 96  First version
// 1.0  17 Jan 97  Minor bug fix; added column weighting.
// 1.1  08 Apr 98  Don"t use methods deprecated in JDK1.1
// 1.2  16 Apr 98  Make own copy of Dimension objects as they"re not immutable
import java.awt.*;
import java.util.*;
// Private class to parse and store the options for a single table entry

/**
 * Table layout manager, with the flexibity of GridBagLayout but the ease of
 * use of HTML table declarations.
 *
 * <p>use like:   </br>
 *    new TableLayout(cols) </br>
 *    add(comp, new TableOption(..))  </br>
 *    ..
 * </p>
 */
public class TableLayout implements LayoutManager,LayoutManager2 {
  private Hashtable options = new Hashtable();
  private TableOption defaultOption;
  private int nrows=0, ncols=0;
  private int ncomponents=0;
  private Component[][] components=null;
  private int MinWidth=0, MinHeight=0, PrefWidth=0, PrefHeight=0;
  private int[] minWidth=null, minHeight=null, prefWidth=null, prefHeight=null;
  private int[] weight=null, columnWidth=null;
  private int hgap=0, vgap=0;
  /**
  * Construct a new table layout manager.
  * @param cols Number of columns, used when adding components to tell when to go to the next row
  * @param defaultAlignment Default defaultAlignment for cells if not specified at the time of adding the component
  * @param hgap Horizontal gap between cells and at edge (in pixels)
  * @param vgap Vertical gap between cells and at edge (in pixels)
  **/
  public TableLayout(int cols, String defaultAlignment, int hgap, int vgap) {
    this(cols, new TableOption(defaultAlignment),hgap,vgap);
  }
    public TableLayout(int cols, TableOption defaultAlignment, int hgap, int vgap) {
        this.ncols = cols;  // the number of columns is specified
    this.nrows = 0;   // the number of rows is calculated
        this.ruponents = new Component[cols][];
    this.defaultOption=defaultAlignment;
        this.hgap = hgap;
        this.vgap = vgap;
    }
  public TableLayout(int cols, String alignment)
  {
    this(cols, alignment, 0, 0);
  }
  public TableLayout(int cols)
  {
    this(cols, "", 0, 0);
  }
  public void addLayoutComponent(String alignment, Component comp)
  {
    options.put(comp, new TableOption(alignment));
  }
  public void removeLayoutComponent(Component comp)
  {
    options.remove(comp);
  }
  // Iterate through the components, counting the number of rows taking into account
  // row and column spanning, then initialise the components[c][r] matrix so that
  // we can retrieve the component at a particular row,column position.
  private void loadComponents(Container parent)
  {
    ncomponents = parent.getComponentCount();
    // If we haven"t allocated the right sized array for each column yet, do so now.
    // Note that the number of columns is fixed, but the number of rows is not know
    // and could in the worst case be up the number of components. Unfortunately this
    // means we need to allocate quite big arrays, but the alternative would require
    // complex multiple passes as we try to work out the effect of row spanning.
    if (components[0] == null || components[0].length < ncomponents)
    {
      for (int i=0; i<ncols; ++i)
        components[i] = new Component[ncomponents];
    }
    // Nullify the array
    for (int i=0; i<ncols; ++i)
    {
      for (int j=0; j<components[i].length; ++j)
        components[i][j] = null;
    }
    // fill the matrix with components, taking row/column spanning into account
    int row=0, col=0;
    for (int i=0; i<ncomponents; ++i)
    {
      // get the next component and its options
      Component comp = parent.getComponent(i);
      TableOption option = (TableOption) options.get(comp);
      if (option==null) option = defaultOption;
      // handle options to force us to column 0 or to skip columns
      if (option.forceColumn >= 0)
      {
        if (col > option.forceColumn)
          ++row;
        col = option.forceColumn;
      }
      col += option.skipColumns;
      if (col>=ncols) { ++row; col=0; }
      // skip over any cells that are already occupied
      while (components[col][row] != null)
      {
        ++col;
        if (col>=ncols) { ++row; col=0; }
      }
      // if using colspan, will we fit on this row?
      if (col+option.colSpan > ncols)
      {
        ++row;
        col = 0;
      }
      // for now, fill all the cells that are occupied by this component
      for (int c=0; c<option.colSpan; ++c)
        for (int r=0; r<option.rowSpan; ++r)
          components[col+c][row+r] = comp;
      // advance to the next cell, ready for the next component
      col += option.colSpan;
      if (col>=ncols) { ++row; col=0; }
    }
    // now we know how many rows there are
    if (col == 0)
      nrows = row;
    else
      nrows = row+1;
    // now we"ve positioned our components we can thin out the cells so
    // we only remember the top left corner of each component
    for (row=0; row<nrows; ++row)
    {
      for (col=0; col<ncols; ++col)
      {
        Component comp = components[col][row];
        for (int r=row; r<nrows && components[col][r]==comp; ++r)
        {
          for (int c=col; c<ncols && components[c][r]==comp; ++c)
          {
            if (r>row || c>col)
              components[c][r] = null;
          }
        }
      }
    }
  }
  private void measureComponents(Container parent)
  {
    // set basic metrics such as ncomponents & nrows, and load the components
    // into the components[][] array.
    loadComponents(parent);
    // allocate new arrays to store row and column preferred and min sizes, but
    // only if the old arrays aren"t big enough
    if (minWidth==null || minWidth.length<ncols)
    {
      minWidth = new int[ncols];
      prefWidth = new int[ncols];
      columnWidth = new int[ncols];
      weight = new int[ncols];
    }
    if (minHeight==null || minHeight.length<nrows)
    {
      minHeight = new int[nrows];
      prefHeight = new int[nrows];
    }
    int i;
    for (i=0; i<ncols; ++i)
    {
      minWidth[i] = 0;
      prefWidth[i] = 0;
    }
    for (i=0; i<nrows; ++i)
    {
      minHeight[i] = 0;
      prefHeight[i] = 0;
    }
    // measure the minimum and preferred size of each row and column
    for (int row=0; row<nrows; ++row)
    {
      for (int col=0; col<ncols; ++col)
      {
        Component comp = components[col][row];
        if (comp != null)
        {
          TableOption option = (TableOption) options.get(comp);
          if (option==null) option = defaultOption;
          Dimension minSize = new Dimension(comp.getMinimumSize());
          Dimension prefSize = new Dimension(comp.getPreferredSize());
          // enforce prefSize>=minSize
          if (prefSize.width < minSize.width)
            prefSize.width = minSize.width;
          if (prefSize.height < minSize.height)
            prefSize.height = minSize.height;
          // divide size across all the rows or columns being spanned
          minSize.width /= option.colSpan;
          minSize.height /= option.rowSpan;
          prefSize.width = (prefSize.width - hgap*(option.colSpan-1)) / option.colSpan;
          prefSize.height = (prefSize.height - vgap*(option.rowSpan-1)) / option.rowSpan;
          for (int c=0; c<option.colSpan; ++c)
          {
            if (minSize.width > minWidth[col+c])
              minWidth[col+c] = minSize.width;
            if (prefSize.width > prefWidth[col+c])
              prefWidth[col+c] = prefSize.width;
          }
          for (int r=0; r<option.rowSpan; ++r)
          {
            if (minSize.height > minHeight[row+r])
              minHeight[row+r] = minSize.height;
            if (prefSize.height > prefHeight[row+r])
              prefHeight[row+r] = prefSize.height;
          }
        }
      }
    }
    // add rows and columns to give total min and preferred size of whole grid
    MinWidth = 0;
    MinHeight = 0;
    PrefWidth = hgap;
    PrefHeight = vgap;
    for (i=0; i<ncols; ++i)
    {
      MinWidth += minWidth[i];
      PrefWidth += prefWidth[i] + hgap;
    }
    for (i=0; i<nrows; ++i)
    {
      MinHeight += minHeight[i];
      PrefHeight += prefHeight[i] + vgap;
    }
  }
  public Dimension minimumLayoutSize(Container parent)
  {
    Insets insets = parent.getInsets();
    measureComponents(parent);
    // System.out.println("Min Size: "+MinWidth+","+MinHeight);
    return new Dimension(insets.left + insets.right + MinWidth,
      insets.top + insets.bottom + MinHeight);
  }
  public Dimension preferredLayoutSize(Container parent)
  {
    Insets insets = parent.getInsets();
    measureComponents(parent);
    // System.out.println("Pref Size: "+PrefWidth+","+PrefHeight);
    // System.out.println("+ insets LR "+insets.left+"+"+insets.right+", TB "+insets.top+"+"+insets.bottom);
    return new Dimension(insets.left + insets.right + PrefWidth,
      insets.top + insets.bottom + PrefHeight);
  }
  public void layoutContainer(Container parent)
  {
    Insets insets = parent.getInsets();
    measureComponents(parent);
    int width = parent.getSize().width - (insets.left + insets.right);
    int height = parent.getSize().height - (insets.top + insets.bottom);
    // System.out.println("Resize "+width+","+height);
    // Decide whether to base our scaling on minimum or preferred sizes, or
    // a mixture of both, separately for width and height scaling.
    // This weighting also tells us how much of the hgap/vgap to use.
    double widthWeighting = 0.0;
    if (width >= PrefWidth || PrefWidth==MinWidth)
      widthWeighting = 1.0;
    else if (width <= MinWidth)
    {
      widthWeighting = 0.0;
      width = MinWidth;
    }
    else
      widthWeighting = (double)(width-MinWidth)/(double)(PrefWidth-MinWidth);
    double heightWeighting = 0.0;
    if (height >= PrefHeight || PrefHeight==MinHeight)
      heightWeighting = 1.0;
    else if (height <= MinHeight)
    {
      heightWeighting = 0.0;
      height = MinHeight;
    }
    else
      heightWeighting = (double)(height-MinHeight)/(double)(PrefHeight-MinHeight);
    // calculate scale factors to scale components to size of container, based
    // on weighted combination of minimum and preferred sizes
    double minWidthScale = (1.0 - widthWeighting) * width/MinWidth;
    //double prefWidthScale = widthWeighting * (width-hgap*(ncols+1))/(PrefWidth-hgap*(ncols+1));
    double minHeightScale = (1.0 - heightWeighting) * height/MinHeight;
    double prefHeightScale = heightWeighting * (height-vgap*(nrows+1))/(PrefHeight-vgap*(nrows+1));
    // only get the full amount of gap if we"re working to preferred size
    int vGap = (int) (vgap * heightWeighting);
    int hGap = (int) (hgap * widthWeighting);
    int y = insets.top + vGap;
    for (int c=0; c<ncols; ++c)
      weight[c] = prefWidth[c];
    for (int r=0; r<nrows; ++r)
    {
      int x = insets.left + hGap;
      int rowHeight = (int)(minHeight[r]*minHeightScale + prefHeight[r]*prefHeightScale);
      // Column padding can vary from row to row, so we need several
      // passes through the columns for each row:
      // First, work out the weighting that deterimines how we distribute column padding
      for (int c=0; c<ncols; ++c)
      {
        Component comp = components[c][r];
        if (comp != null)
        {
          TableOption option = (TableOption) options.get(comp);
          if (option==null) option = defaultOption;
          if (option.weight >= 0)
            weight[c] = option.weight;
          else if (option.weight == -1)
            weight[c] = prefWidth[c];
        }
      }
      int totalWeight = 0;
      for (int c=0; c<ncols; ++c)
        totalWeight += weight[c];
      int horizSurplus = width - hgap*(ncols+1) - PrefWidth;
      // Then work out column sizes, essentially preferred size + share of padding
      for (int c=0; c<ncols; ++c)
      {
        columnWidth[c] = (int) (minWidthScale * minWidth[c] + widthWeighting * prefWidth[c]);
        if (horizSurplus > 0 && totalWeight > 0)
          columnWidth[c] += (int) (widthWeighting * horizSurplus * weight[c] / totalWeight);
      }
      // Only now do we know enough to position all the columns within this row...
      for (int c=0; c<ncols; ++c)
      {
        Component comp = components[c][r];
        if (comp != null)
        {
          TableOption option = (TableOption) options.get(comp);
          if (option==null) option = defaultOption;
          // cell size may be bigger than row/column size due to spanning
          int cellHeight = rowHeight;
          int cellWidth = columnWidth[c];
          for (int i=1; i<option.colSpan; ++i)
            cellWidth += columnWidth[c+i];
          for (int i=1; i<option.rowSpan; ++i)
            cellHeight += (int)(minHeight[r+i]*minHeightScale + prefHeight[r+i]*prefHeightScale + vGap);
          Dimension d = new Dimension(comp.getPreferredSize());
          if (d.width > cellWidth || option.horizontal==TableOption.FILL)
            d.width = cellWidth;
          if (d.height > cellHeight || option.vertical==TableOption.FILL)
            d.height = cellHeight;
          int yoff = 0;
          if (option.vertical == TableOption.BOTTOM)
            yoff = cellHeight - d.height;
          else if (option.vertical == TableOption.CENTRE)
            yoff = (cellHeight - d.height) / 2;
          int xoff = 0;
          if (option.horizontal == TableOption.RIGHT)
            xoff = cellWidth - d.width;
          else if (option.horizontal == TableOption.CENTRE)
            xoff = (cellWidth - d.width) / 2;
          // System.out.println(" "+comp.getClass().getName()+" at ("+x+"+"+xoff+","+y+"+"+yoff+"), size "+d.width+","+d.height);
          comp.setBounds(x+xoff,y+yoff,d.width,d.height);
        }
        x += columnWidth[c] + hGap;
      }
      y += rowHeight + vGap;
    }
  }
    public void addLayoutComponent(Component comp, Object constraints) {
        if(constraints instanceof TableOption){
            options.put(comp, constraints);
        }
        else if(constraints==null){
            options.put(comp,defaultOption);
        }
        else throw new IllegalArgumentException("not a valid constraints object="+constraints);
    }
     /**
     * 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.
     * <p>
     * @return the value <code>0.5f</code> 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.
     * <p>
     * @return the value <code>0.5f</code> 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) {
    }
    /**
     * 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);
    }
}

class TableOption{
  public static final int CENTRE=1, FILL=2, LEFT=3, RIGHT=4, TOP=5, BOTTOM=6;
  int horizontal = CENTRE;
  int vertical = CENTRE;
  int rowSpan=1, colSpan=1, skipColumns=0, forceColumn=-1, weight=-2;
    /**
     *
     * @param horizontal one of CENTRE,FILL,LEFT,RIGHT,TOP,BOTTOM
     * @param vertical
     */
    public TableOption(int horizontal, int vertical) {
        this.horizontal = horizontal;
        this.vertical = vertical;
    }
    public TableOption(int horizontal, int vertical, int rowSpan, int colSpan) {
        this.horizontal = horizontal;
        this.vertical = vertical;
        this.rowSpan = rowSpan;
        this.colSpan = colSpan;
    }
    public TableOption(int horizontal, int vertical, int rowSpan, int colSpan, int skipColumns, int forceColumn, int weight) {
        this.horizontal = horizontal;
        this.vertical = vertical;
        this.rowSpan = rowSpan;
        this.colSpan = colSpan;
        this.skipColumns = skipColumns;
        this.forceColumn = forceColumn;
        this.weight = weight;
    }
  TableOption(String alignment) {
    StringTokenizer tk = new StringTokenizer(alignment, ",");
    while (tk.hasMoreTokens())
    {
      String token = tk.nextToken();
      boolean ok = false;
      int delim = token.indexOf("=");
      if (token.equals("NW") || token.equals("W") || token.equals("SW"))
        { horizontal = LEFT; ok=true; }
      if (token.equals("NE") || token.equals("E") || token.equals("SE"))
        { horizontal = RIGHT; ok=true; }
      if (token.equals("N") || token.equals("C") || token.equals("F"))
        { horizontal = CENTRE; ok=true; }
      if (token.equals("F") || token.equals("FH"))
        { horizontal = FILL; ok=true; }
      if (token.equals("N") || token.equals("NW") || token.equals("NE"))
        { vertical = TOP; ok=true; }
      if (token.equals("S") || token.equals("SW") || token.equals("SE"))
        { vertical = BOTTOM; ok=true; }
      if (token.equals("W") || token.equals("C") || token.equals("E"))
        { vertical = CENTRE; ok=true; }
      if (token.equals("F") || token.equals("FV"))
        { vertical = FILL; ok=true; }
      if (delim>0)
      {
        int val = Integer.parseInt(token.substring(delim+1));
        token = token.substring(0,delim);
        if (token.equals("CS") && val>0)
          { colSpan = val; ok=true; }
        else if (token.equals("RS") && val>0)
          { rowSpan = val; ok=true; }
        else if (token.equals("SKIP") && val>0)
          { skipColumns = val; ok=true; }
        else if (token.equals("COL"))
          { forceColumn = val; ok=true; }
        else if (token.equals("WT"))
          { weight = val; ok=true; }
      }
      if (!ok) throw new IllegalArgumentException("TableOption "+token);
    }
  }
}





Tile Layout

    

import java.awt.*;
import java.util.LinkedList;
import java.io.Serializable;
/*
 * Relative Component Layout Manager
 * Copyright (c) 1999 John Catherino
 * The cajo project: https://cajo.dev.java.net
 *
 * For issues or suggestions mailto:cajo@dev.java.net
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License, at version
 * 2.1 of the licence, or any later version published by the Free Software
 * Foundation.
 *
 * This program 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 Lesser General Public License for more details.
 *
 * You can receive a copy of the GNU Lesser General Public License from their
 * website, http://fsf.org/licenses/lgpl.html; or via snail mail, Free
 * Software Foundation Inc., 51 Franklin Street, Boston MA 02111-1301, USA
 */
/**
 * A rather unique LayoutManager. In addition to laying out components relative
 * to the container, it also supports layout relative to components <i>within</i>
 * the container. Its purpose is to support arbitrarily complex component
 * layouts, of an unlimited number of components, within a single container. It
 * can easily create complex layouts that would otherwise require many
 * subpanels, and multiple standard layout managers. It also can create layouts
 * that are completely <i>impossible</i>, with standard layout managers. These
 * features make this layout manager extremely flexible, and makes
 * advancedlayouts extremely fast. It just may be, the last and only
 * LayoutManager you"ll ever need.
 * <p>
 * 
 * Components can be laid out above, below, left, or right of either a
 * referenced component in the panel, or to the panel itself. Its width and
 * height can be specified with similar flexibility. Absolute and proportional
 * bounds are also supported. In typical use, one or more <i>"reference"</i>
 * tiles are laid, and the rest of the components are set relative to them.
 * <p>
 * 
 * Usage example:<blockquote><tt><pre>
 * panel.add(new JLabel(&quot;Label text:&quot;), new Object[]{
 *       new Integer(TileLayout.LEFTINDENT + TileLayout.NOOFFSET +
 *       TileLayout.PROPWIDTH + TileLayout.FULLHEIGHT), refComponent,
 *       new Insets(-5, 10, 5, 10), new Rectangle(0, 0, 333, 0)
 * // proportion rectangle 33.3%w
 *       });
 * </tt></pre>
 * 
 * </blockquote>
 * <p>
 * 
 * Up to four alignment constraints can be specified, their order does not
 * matter:
 * 
 * <p>
 * <ul>
 * <li> Positioning constants for indent, offset, width, and height
 * <li> A Component for placement relative to, otherwise the container
 * <li> A Rectangle for fixed and proportional component bounds
 * <li> Insets to trim the resulting component boundaries
 * </ul>
 * <p>
 * 
 * <u><i>Note</u>:</i> since the JRE <i>draws</i> components from last added
 * to first; the manager lays them out similarly. Therefore, in order to layout
 * relative to another component, the reference component must be added <u>after</u>
 * the dependent one. I know this can be a drag at first, but it becomes
 * critically important when components are laid out on top of others, or
 * overlapping. This is a <i>super cool</i> capability of this layout manager.
 * 
 * @version 1.0, 01-Nov-99 Initial release
 * @author John Catherino
 */
public final class TileLayout implements LayoutManager2, Serializable {
   private static final long serialVersionUID = 1L;
   private static final Dimension NONE  = new Dimension();
   private final LinkedList components  = new LinkedList();
   private final LinkedList constraints = new LinkedList();
   private void align(Dimension cont, Object cons[], Component comp) {
      int align = 0;
      Insets insets = null;
      Rectangle tile = null, fixd = null;
      if (cons != null) {
         for (int i = 0; i < cons.length; i++) { // gather constraints
            if (cons[i] != null) {
               if (cons[i] instanceof Rectangle) fixd = (Rectangle)cons[i];
               else if (cons[i] instanceof Insets) insets = (Insets)cons[i];
               else if (cons[i] instanceof Integer) align = ((Integer)cons[i]).intValue();
               else if (cons[i] instanceof Component) tile = ((Component)cons[i]).getBounds();
            }
         }
      }
      if (tile == null) tile = new Rectangle(cont);
      Rectangle pref = new Rectangle(tile.getLocation(), comp.getPreferredSize());
      // perform component positioning:
      if ((align & 0x004000) != 0) pref.width = fixd.width;
      else if ((align & 0x008000) != 0) pref.width = (tile.width * fixd.width + 500) / 1000;
      else if ((align & 0x010000) != 0) pref.width = tile.width;
      if ((align & 0x080000) != 0) pref.height = fixd.height;
      else if ((align & 0x100000) != 0) pref.height = (tile.height
            * fixd.height + 500) / 1000;
      else if ((align & 0x200000) != 0) pref.height = tile.height;
      if ((align & 0x000001) != 0) pref.x -= pref.width;
      else if ((align & 0x000002) != 0) pref.x += (tile.width - pref.width >> 1);
      else if ((align & 0x000004) != 0) pref.x += tile.width - pref.width;
      else if ((align & 0x000008) != 0) pref.x += tile.width;
      else if ((align & 0x000010) != 0) pref.x += fixd.x;
      else if ((align & 0x000020) != 0) pref.x += (tile.width * fixd.x + 500) / 1000;
      if ((align & 0x000040) != 0) pref.y -= pref.height;
      else if ((align & 0x000080) != 0) pref.y += (tile.height - pref.height >> 1);
      else if ((align & 0x000100) != 0) pref.y += tile.height - pref.height;
      else if ((align & 0x000200) != 0) pref.y += tile.height;
      else if ((align & 0x000400) != 0) pref.y += fixd.y;
      else if ((align & 0x000800) != 0) pref.y += (tile.height * fixd.y + 500) / 1000;
      if ((align & 0x001000) != 0) pref.setBounds(0, pref.y, pref.x
            + pref.width, pref.height);
      else if ((align & 0x002000) != 0) pref.width = cont.width - pref.x;
      if ((align & 0x020000) != 0) pref.setBounds(pref.x, 0, pref.width, pref.y
            + pref.height);
      else if ((align & 0x040000) != 0) pref.height = cont.height - pref.y;
      if (insets != null) { // apply insets, if any:
         pref.x += insets.left;
         pref.y += insets.top;
         pref.width -= insets.left + insets.right;
         pref.height -= insets.top + insets.bottom;
      }
      // Note: this can cause surprising results, so use it, if you dare. :-)
      // Honour component minimum size:
      Dimension d = comp.getMinimumSize();
      if (pref.width < d.width) pref.width = d.width;
      if (pref.height < d.height) pref.height = d.height;
      comp.setBounds(pref); // now the tile is set!
   }
   /**
    * This constant specifies placement of the component even with the left
    * border of the provided reference component, otherwise to the container
    * itself.
    */
   public static final int NOINDENT = 0x000000;
   /**
    * This constant specifies placement of the component with its right border
    * one pixel to the left of the provided reference component, otherwise to
    * the container itself.
    */
   public static final int LEFTINDENT = 0x000001;
   /**
    * This constant specifies placement of the component evenly between the left
    * and right borders of the provided reference component, otherwise to the
    * container itself.
    */
   public static final int CENTERINDENT = 0x000002;
   /**
    * This constant specifies placement of the component with its right border
    * evenly aligned with the right border of the provided reference component,
    * otherwise to the container itself.
    */
   public static final int FULLINDENT = 0x000004;
   /**
    * This constant specifies placement of the left border of the component one
    * pixel to the right of the provided reference component origin, otherwise
    * to the container itself.
    */
   public static final int RIGHTINDENT = 0x000008;
   /**
    * Used in conjunction with a Rectangle constraint, the x value represents
    * the desired component indent as a fixed number of pixels right of the
    * provided component origin, otherwise to the container itself.
    */
   public static final int FIXEDINDENT = 0x000010;
   /**
    * Used in conjunction with a Rectangle constraint, the x value represents
    * the desired component indent as a percentage (2000 = 200.0%) of a provided
    * component, otherwise to the container itself.
    */
   public static final int PROPINDENT = 0x000020;
   /**
    * This constant specifies placement of the component even with the top
    * border of the provided reference component, otherwise to the container
    * itself.
    */
   public static final int NOOFFSET = 0x000000;
   /**
    * This constant specifies placement of the component with its bottom border
    * one pixel above the provided reference component, otherwise to the
    * container itself.
    */
   public static final int TOPOFFSET = 0x000040;
   /**
    * This constant specifies placement of the component evenly between the top
    * and bottom borders of the provided reference component, otherwise to the
    * container itself.
    */
   public static final int CENTEROFFSET = 0x000080;
   /**
    * This constant specifies placement of the component with its bottom border
    * evenly aligned with the bottom border of the provided reference component,
    * otherwise to the container itself.
    */
   public static final int FULLOFFSET = 0x000100;
   /**
    * This constant specifies placement of the top border of the component one
    * pixel below the provided reference component origin, otherwise to the
    * container itself.
    */
   public static final int BOTTOMOFFSET = 0x000200;
   /**
    * Used in conjunction with a Rectangle constraint, the y value represents
    * the desired component offset as a fixed number of pixels below the
    * provided component origin, otherwise to the container itself.
    */
   public static final int FIXEDOFFSET = 0x000400;
   /**
    * Used in conjunction with a Rectangle constraint, the y value represents
    * the desired component offset as a percentage (2000 = 200.0%) of a provided
    * component, otherwise to the container itself.
    */
   public static final int PROPOFFSET = 0x000800;
   /**
    * This constant specifies that the component have its preferred width, as
    * returned by its getPreferredSize method.
    */
   public static final int PREFWIDTH = 0x000000;
   /**
    * This constant specifies that the component be made wide enough such that
    * given its computed right margin, its left margin will align with that of
    * its container.
    */
   public static final int CLAMPLEFT = 0x001000;
   /**
    * This constant specifies that the component be made wide enough such that
    * given its computed origin, its right margin will align with that of its
    * container.
    */
   public static final int CLAMPRIGHT = 0x002000;
   /**
    * Used in conjunction with a Rectangle constraint, the width value
    * represents the desired component width as a fixed number of pixels.
    */
   public static final int FIXEDWIDTH = 0x004000;
   /**
    * Used in conjunction with a Rectangle constraint, the width value
    * represents the desired component offset as a percentage (2000 = 200.0%) of
    * a provided component, otherwise to the container itself.
    */
   public static final int PROPWIDTH = 0x008000;
   /**
    * This constant specifies that the component be made exactly as wide as its
    * reference component, otherwise as the container itself.
    */
   public static final int FULLWIDTH = 0x010000;
   /**
    * This constant specifies that the component have its preferred height, as
    * returned by its getPreferredSize method.
    */
   public static final int PREFHEIGHT = 0x000000;
   /**
    * This constant specifies that the component be made high enough such that
    * given its computed bottom margin, its top margin will align with that of
    * its container.
    */
   public static final int CLAMPTOP = 0x020000;
   /**
    * This constant specifies that the component be made high enough such that
    * given its computed origin, its bottom margin will align with that of its
    * container.
    */
   public static final int CLAMPBOTTOM = 0x040000;
   /**
    * Used in conjunction with a Rectangle constraint, the height value
    * represents the desired component width as a fixed number of pixels.
    */
   public static final int FIXEDHEIGHT = 0x080000;
   /**
    * Used in conjunction with a Rectangle constraint, the height value
    * represents the desired component offset as a percentage (2000 = 200.0%) of
    * a provided component, otherwise to the container itself.
    */
   public static final int PROPHEIGHT = 0x100000;
   /**
    * This constant specifies that the component be made exactly as high as its
    * reference component, otherwise as the container itself.
    */
   public static final int FULLHEIGHT = 0x200000;
   /**
    * A frequently used position, used in conjunction with a reference
    * component, it will locate the component directly over, with the same width
    * and height.
    */
   public static final Integer ABOVE = new Integer(NOINDENT + TOPOFFSET
         + FULLWIDTH + FULLHEIGHT);
   /**
    * A frequently used position, used in conjunction with a reference
    * component, it will locate the component directly beneath, with the same
    * width and height.
    */
   public static final Integer BELOW = new Integer(NOINDENT + BOTTOMOFFSET
         + FULLWIDTH + FULLHEIGHT);
   /**
    * A frequently used position, used in conjunction with a reference
    * component, it will locate the component directly adjacent, to its right,
    * with the same width and height.
    */
   public static final Integer RIGHT = new Integer(RIGHTINDENT + NOOFFSET
         + FULLWIDTH + FULLHEIGHT);
   /**
    * A frequently used position, used in conjunction with a reference
    * component, it will locate the component directly adjacent, to its left,
    * with the same width and height.
    */
   public static final Integer LEFT = new Integer(LEFTINDENT + NOOFFSET
         + FULLWIDTH + FULLHEIGHT);
   /**
    * A frequently used position, it will render the component using the exact
    * size of the reference component, or container.
    */
   public static final Integer FULLSIZE = new Integer(NOINDENT + NOOFFSET
         + FULLWIDTH + FULLHEIGHT);
   /**
    * Nothing is performed in the constructor, it is bodyless.
    */
   public TileLayout() {}
   /**
    * The primary component addition method. Components are added for layout,
    * and its constraints are provided as an Object array. Up to 4 constraints
    * may be specified, and their order is not important. The following are the
    * applicable constraints:
    * <ul>
    * <p>
    * <li> Rectangle for fixed or proportional component bounds
    * <li> Insets to trim the final boundaries after computation
    * <li> Integer of TileLayout positioning constants
    * <li> Component for relative placement, instead of container
    * </ul>
    * 
    * @param comp The component to be laid out within the container.
    * @param cons An Object[] containing 1 or more constraints.
    */
   public void addLayoutComponent(Component comp, Object cons) {
      components.add(comp);
      constraints.add(cons);
   }
   /**
    * This method will make the added component exactly the same size as the
    * container itself. It is useful for adding wallpaper.
    * 
    * @param comp The component to fill the container.
    * @param name The name of the component, unused by TileLayout.
    */
   public void addLayoutComponent(String name, Component comp) {
      components.add(comp);
      constraints.add(new Object[]{ FULLSIZE });
   }
   /**
    * As expected, removes the component from the ordered layout list.
    */
   public void removeLayoutComponent(Component comp) {
      for (int i = 0; i < components.size(); i++) {
         if (components.get(i) == comp) {
            components.remove(i);
            constraints.remove(i);
            return;
         }
      }
      throw new IllegalArgumentException("Component not in container");
   }
   /**
    * Lays out the components, last added to first added, according to their
    * specified constraints.
    */
   public void layoutContainer(Container parent) {
      Dimension container = parent.getSize();
      for (int i = components.size() - 1; i >= 0; i--)
         align(container, (Object[])constraints.get(i),
            (Component)components.get(i));
   }
   /**
    * Bodyless implementation, as TileLayout uses no cached information.
    */
   public void invalidateLayout(Container target) {}
   /**
    * Indicate center alignment.
    */
   public float getLayoutAlignmentX(Container target) { return 0.5F; }
   /**
    * Indicate center alignment.
    */
   public float getLayoutAlignmentY(Container target) { return 0.5F; }
   /**
    * Indicates no minimum size.
    */
   public Dimension minimumLayoutSize(Container parent) { return NONE; }
   /**
    * Indicates no maximum size.
    */
   public Dimension maximumLayoutSize(Container parent) { return NONE; }
   /**
    * Indicates no preferred size.
    */
   public Dimension preferredLayoutSize(Container parent) { return NONE; }
}





Wrapper Layout

    
/*
    GNU LESSER GENERAL PUBLIC LICENSE
    Copyright (C) 2006 The Lobo Project
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.
    This library 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
    Lesser General Public License for more details.
    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    Contact info: lobochief@users.sourceforge.net
*/
/*
 * Created on Mar 19, 2005
 */
import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.LayoutManager;
/**
 * @author J. H. S.
 */
public class WrapperLayout implements LayoutManager {
    /* (non-Javadoc)
     * @see java.awt.LayoutManager#addLayoutComponent(java.lang.String, java.awt.ruponent)
     */
    public void addLayoutComponent(String arg0, Component arg1) {
    }
    /* (non-Javadoc)
     * @see java.awt.LayoutManager#removeLayoutComponent(java.awt.ruponent)
     */
    public void removeLayoutComponent(Component arg0) {
    }
    /* (non-Javadoc)
     * @see java.awt.LayoutManager#preferredLayoutSize(java.awt.Container)
     */
    public Dimension preferredLayoutSize(Container arg0) {
      java.awt.Insets insets = arg0.getInsets();
        int count = arg0.getComponentCount();
        if(count > 0) {
            Dimension d = arg0.getComponent(0).getPreferredSize();
            return new Dimension(d.width + insets.left + insets.right,
                           d.height + insets.top + insets.bottom);
        }
        else {
            return new Dimension(insets.left + insets.right, insets.top + insets.bottom);
        }
    }
    /* (non-Javadoc)
     * @see java.awt.LayoutManager#minimumLayoutSize(java.awt.Container)
     */
    public Dimension minimumLayoutSize(Container arg0) {
      java.awt.Insets insets = arg0.getInsets();
        int count = arg0.getComponentCount();
        if(count > 0) {
            Dimension d = arg0.getComponent(0).getMinimumSize();
            return new Dimension(d.width + insets.left + insets.right,
               d.height + insets.top + insets.bottom);
        }
        else {
            return new Dimension(insets.left + insets.right, insets.top + insets.bottom);
        }
    }
    /* (non-Javadoc)
     * @see java.awt.LayoutManager#layoutContainer(java.awt.Container)
     */
    public void layoutContainer(Container arg0) {
        int count = arg0.getComponentCount();
        if(count > 0) {
            Component child = arg0.getComponent(0); 
            java.awt.Insets insets = arg0.getInsets();
            child.setBounds(insets.left, insets.top, arg0.getWidth() - insets.left - insets.right, arg0.getHeight() - insets.top - insets.bottom);
        }
    }
    
    private static WrapperLayout instance = new WrapperLayout();
    
    public static WrapperLayout getInstance() {
      return instance;
    }
}





X Y Layout

    
//Revised from enhydra swing
import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager2;
import java.awt.Rectangle;
import java.io.Serializable;
import java.util.Hashtable;
public class XYLayout implements LayoutManager2, Serializable {
  private static final long serialVersionUID = 200L;
  int width;
  int height;
  Hashtable info;
  static final XYConstraints defaultConstraints = new XYConstraints();
  public XYLayout() {
    info = new Hashtable();
  }
  public XYLayout(int width, int height) {
    info = new Hashtable();
    this.width = width;
    this.height = height;
  }
  public int getWidth() {
    return width;
  }
  public void setWidth(int width) {
    this.width = width;
  }
  public int getHeight() {
    return height;
  }
  public void setHeight(int height) {
    this.height = height;
  }
  public String toString() {
    return String.valueOf(String.valueOf((new StringBuffer("XYLayout[width=")).append(width)
        .append(",height=").append(height).append("]")));
  }
  public void addLayoutComponent(String s, Component component1) {
  }
  public void removeLayoutComponent(Component component) {
    info.remove(component);
  }
  public Dimension preferredLayoutSize(Container target) {
    return getLayoutSize(target, true);
  }
  public Dimension minimumLayoutSize(Container target) {
    return getLayoutSize(target, false);
  }
  public void layoutContainer(Container target) {
    Insets insets = target.getInsets();
    int count = target.getComponentCount();
    for (int i = 0; i < count; i++) {
      Component component = target.getComponent(i);
      if (component.isVisible()) {
        Rectangle r = getComponentBounds(component, true);
        component.setBounds(insets.left + r.x, insets.top + r.y, r.width, r.height);
      }
    }
  }
  public void addLayoutComponent(Component component, Object constraints) {
    if (constraints instanceof XYConstraints)
      info.put(component, constraints);
  }
  public Dimension maximumLayoutSize(Container target) {
    return new Dimension(0x7fffffff, 0x7fffffff);
  }
  public float getLayoutAlignmentX(Container target) {
    return 0.5F;
  }
  public float getLayoutAlignmentY(Container target) {
    return 0.5F;
  }
  public void invalidateLayout(Container container) {
  }
  Rectangle getComponentBounds(Component component, boolean doPreferred) {
    XYConstraints constraints = (XYConstraints) info.get(component);
    if (constraints == null)
      constraints = defaultConstraints;
    Rectangle r = new Rectangle(constraints.x, constraints.y, constraints.width, constraints.height);
    if (r.width <= 0 || r.height <= 0) {
      Dimension d = doPreferred ? component.getPreferredSize() : component.getMinimumSize();
      if (r.width <= 0)
        r.width = d.width;
      if (r.height <= 0)
        r.height = d.height;
    }
    return r;
  }
  Dimension getLayoutSize(Container target, boolean doPreferred) {
    Dimension dim = new Dimension(0, 0);
    if (width <= 0 || height <= 0) {
      int count = target.getComponentCount();
      for (int i = 0; i < count; i++) {
        Component component = target.getComponent(i);
        if (component.isVisible()) {
          Rectangle r = getComponentBounds(component, doPreferred);
          dim.width = Math.max(dim.width, r.x + r.width);
          dim.height = Math.max(dim.height, r.y + r.height);
        }
      }
    }
    if (width > 0)
      dim.width = width;
    if (height > 0)
      dim.height = height;
    Insets insets = target.getInsets();
    dim.width += insets.left + insets.right;
    dim.height += insets.top + insets.bottom;
    return dim;
  }
}
class XYConstraints implements Cloneable, Serializable {
  int x;
  int y;
  int width;
  int height;
  public XYConstraints() {
    this(0, 0, 0, 0);
  }
  public XYConstraints(int x, int y, int width, int height) {
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
  }
  public int getX() {
    return x;
  }
  public void setX(int x) {
    this.x = x;
  }
  public int getY() {
    return y;
  }
  public void setY(int y) {
    this.y = y;
  }
  public int getWidth() {
    return width;
  }
  public void setWidth(int width) {
    this.width = width;
  }
  public int getHeight() {
    return height;
  }
  public void setHeight(int height) {
    this.height = height;
  }
  public int hashCode() {
    return x ^ y * 37 ^ width * 43 ^ height * 47;
  }
  public boolean equals(Object that) {
    if (that instanceof XYConstraints) {
      XYConstraints other = (XYConstraints) that;
      return other.x == x && other.y == y && other.width == width && other.height == height;
    } else {
      return false;
    }
  }
  public Object clone() {
    return new XYConstraints(x, y, width, height);
  }
  public String toString() {
    return String.valueOf(String.valueOf((new StringBuffer("XYConstraints[")).append(x).append(",")
        .append(y).append(",").append(width).append(",").append(height).append("]")));
  }
}