/*
 * Copyright 2006 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */
package javax.swing;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager2;
import java.util.*;
import static java.awt.Component.BaselineResizeBehavior;
import static javax.swing.LayoutStyle.ComponentPlacement;
import static javax.swing.SwingConstants.HORIZONTAL;
import static javax.swing.SwingConstants.VERTICAL;

/**
 * {@code GroupLayout} is a {@code LayoutManager} that hierarchically
 * groups components in order to position them in a {@code Container}.
 * {@code GroupLayout} is intended for use by builders, but may be
 * hand-coded as well.
 * Grouping is done by instances of the {@link Group Group} class. {@code
 * GroupLayout} supports two types of groups. A sequential group
 * positions its child elements sequentially, one after another. A
 * parallel group aligns its child elements in one of four ways.
 * <p>
 * Each group may contain any number of elements, where an element is
 * a {@code Group}, {@code Component}, or gap. A gap can be thought
 * of as an invisible component with a minimum, preferred and maximum
 * size. In addition {@code GroupLayout} supports a preferred gap,
 * whose value comes from {@code LayoutStyle}.
 * <p>
 * Elements are similar to a spring. Each element has a range as
 * specified by a minimum, preferred and maximum.  Gaps have either a
 * developer-specified range, or a range determined by {@code
 * LayoutStyle}. The range for {@code Component}s is determined from
 * the {@code Component}'s {@code getMinimumSize}, {@code
 * getPreferredSize} and {@code getMaximumSize} methods. In addition,
 * when adding {@code Component}s you may specify a particular range
 * to use instead of that from the component. The range for a {@code
 * Group} is determined by the type of group. A {@code ParallelGroup}'s
 * range is the maximum of the ranges of its elements. A {@code
 * SequentialGroup}'s range is the sum of the ranges of its elements.
 * <p>
 * {@code GroupLayout} treats each axis independently.  That is, there
 * is a group representing the horizontal axis, and a group
 * representing the vertical axis.  The horizontal group is
 * responsible for determining the minimum, preferred and maximum size
 * along the horizontal axis as well as setting the x and width of the
 * components contained in it. The vertical group is responsible for
 * determining the minimum, preferred and maximum size along the
 * vertical axis as well as setting the y and height of the
 * components contained in it. Each {@code Component} must exist in both
 * a horizontal and vertical group, otherwise an {@code IllegalStateException}
 * is thrown during layout, or when the minimum, preferred or
 * maximum size is requested.
 * <p>
 * The following diagram shows a sequential group along the horizontal
 * axis. The sequential group contains three components. A parallel group
 * was used along the vertical axis.
 * <p align="center">
 * <img src="doc-files/groupLayout.1.gif">
 * <p>
 * To reinforce that each axis is treated independently the diagram shows
 * the range of each group and element along each axis. The
 * range of each component has been projected onto the axes,
 * and the groups are rendered in blue (horizontal) and red (vertical).
 * For readability there is a gap between each of the elements in the
 * sequential group.
 * <p>
 * The sequential group along the horizontal axis is rendered as a solid
 * blue line. Notice the sequential group is the sum of the children elements
 * it contains.
 * <p>
 * Along the vertical axis the parallel group is the maximum of the height
 * of each of the components. As all three components have the same height,
 * the parallel group has the same height.
 * <p>
 * The following diagram shows the same three components, but with the
 * parallel group along the horizontal axis and the sequential group along
 * the vertical axis.
 * <p>
 * <p align="center">
 * <img src="doc-files/groupLayout.2.gif">
 * <p>
 * As {@code c1} is the largest of the three components, the parallel
 * group is sized to {@code c1}. As {@code c2} and {@code c3} are smaller
 * than {@code c1} they are aligned based on the alignment specified
 * for the component (if specified) or the default alignment of the
 * parallel group. In the diagram {@code c2} and {@code c3} were created
 * with an alignment of {@code LEADING}. If the component orientation were
 * right-to-left then {@code c2} and {@code c3} would be positioned on
 * the opposite side.
 * <p>
 * The following diagram shows a sequential group along both the horizontal
 * and vertical axis.
 * <p align="center">
 * <img src="doc-files/groupLayout.3.gif">
 * <p>
 * {@code GroupLayout} provides the ability to insert gaps between
 * {@code Component}s. The size of the gap is determined by an
 * instance of {@code LayoutStyle}. This may be turned on using the
 * {@code setAutoCreateGaps} method.  Similarly, you may use
 * the {@code setAutoCreateContainerGaps} method to insert gaps
 * between components that touch the edge of the parent container and the
 * container.
 * <p>
 * The following builds a panel consisting of two labels in
 * one column, followed by two textfields in the next column:
 * <pre>
 *   JComponent panel = ...;
 *   GroupLayout layout = new GroupLayout(panel);
 *   panel.setLayout(layout);
 *
 *   // Turn on automatically adding gaps between components
 *   layout.setAutoCreateGaps(true);
 *
 *   // Turn on automatically creating gaps between components that touch
 *   // the edge of the container and the container.
 *   layout.setAutoCreateContainerGaps(true);
 *
 *   // Create a sequential group for the horizontal axis.
 *
 *   GroupLayout.SequentialGroup hGroup = layout.createSequentialGroup();
 *
 *   // The sequential group in turn contains two parallel groups.
 *   // One parallel group contains the labels, the other the text fields.
 *   // Putting the labels in a parallel group along the horizontal axis
 *   // positions them at the same x location.
 *   //
 *   // Variable indentation is used to reinforce the level of grouping.
 *   hGroup.addGroup(layout.createParallelGroup().
 *            addComponent(label1).addComponent(label2));
 *   hGroup.addGroup(layout.createParallelGroup().
 *            addComponent(tf1).addComponent(tf2));
 *   layout.setHorizontalGroup(hGroup);
 *
 *   // Create a sequential group for the vertical axis.
 *   GroupLayout.SequentialGroup vGroup = layout.createSequentialGroup();
 *
 *   // The sequential group contains two parallel groups that align
 *   // the contents along the baseline. The first parallel group contains
 *   // the first label and text field, and the second parallel group contains
 *   // the second label and text field. By using a sequential group
 *   // the labels and text fields are positioned vertically after one another.
 *   vGroup.addGroup(layout.createParallelGroup(Alignment.BASELINE).
 *            addComponent(label1).addComponent(tf1));
 *   vGroup.addGroup(layout.createParallelGroup(Alignment.BASELINE).
 *            addComponent(label2).addComponent(tf2));
 *   layout.setVerticalGroup(vGroup);
 * </pre>
 * <p>
 * When run the following is produced.
 * <p align="center">
 * <img src="doc-files/groupLayout.example.png">
 * <p>
 * This layout consists of the following.
 * <ul><li>The horizontal axis consists of a sequential group containing two
 *         parallel groups.  The first parallel group contains the labels,
 *         and the second parallel group contains the text fields.
 *     <li>The vertical axis consists of a sequential group
 *         containing two parallel groups.  The parallel groups are configured
 *         to align their components along the baseline. The first parallel
 *         group contains the first label and first text field, and
 *         the second group consists of the second label and second
 *         text field.
 * </ul>
 * There are a couple of things to notice in this code:
 * <ul>
 *   <li>You need not explicitly add the components to the container; this
 *       is indirectly done by using one of the {@code add} methods of
 *       {@code Group}.
 *   <li>The various {@code add} methods return
 *       the caller.  This allows for easy chaining of invocations.  For
 *       example, {@code group.addComponent(label1).addComponent(label2);} is
 *       equivalent to
 *       {@code group.addComponent(label1); group.addComponent(label2);}.
 *   <li>There are no public constructors for {@code Group}s; instead
 *       use the create methods of {@code GroupLayout}.
 * </ul>
 *
 * @author Tomas Pavek
 * @author Jan Stola
 * @author Scott Violet
 * @since 1.6
 */
public class GroupLayout implements LayoutManager2 {
    // Used in size calculations
    private static final int MIN_SIZE = 0;

    private static final int PREF_SIZE = 1;

    private static final int MAX_SIZE = 2;

    // Used by prepare, indicates min, pref or max isn't going to be used.
    private static final int SPECIFIC_SIZE = 3;

    private static final int UNSET = Integer.MIN_VALUE;

    /**
     * Indicates the size from the component or gap should be used for a
     * particular range value.
     *
     * @see Group
     */
    public static final int DEFAULT_SIZE = -1;

    /**
     * Indicates the preferred size from the component or gap should
     * be used for a particular range value.
     *
     * @see Group
     */
    public static final int PREFERRED_SIZE = -2;

    // Whether or not we automatically try and create the preferred
    // padding between components.
    private boolean autocreatePadding;

    // Whether or not we automatically try and create the preferred
    // padding between components the touch the edge of the container and
    // the container.
    private boolean autocreateContainerPadding;

    /**
     * Group responsible for layout along the horizontal axis.  This is NOT
     * the user specified group, use getHorizontalGroup to dig that out.
     */
    private Group horizontalGroup;

    /**
     * Group responsible for layout along the vertical axis.  This is NOT
     * the user specified group, use getVerticalGroup to dig that out.
     */
    private Group verticalGroup;

    // Maps from Component to ComponentInfo.  This is used for tracking
    // information specific to a Component.
    private Map<Component,ComponentInfo> componentInfos;

    // Container we're doing layout for.
    private Container host;

    // Used by areParallelSiblings, cached to avoid excessive garbage.
    private Set<Spring> tmpParallelSet;

    // Indicates Springs have changed in some way since last change.
    private boolean springsChanged;

    // Indicates invalidateLayout has been invoked.
    private boolean isValid;

    // Whether or not any preferred padding (or container padding) springs
    // exist
    private boolean hasPreferredPaddingSprings;

    /**
     * The LayoutStyle instance to use, if null the sharedInstance is used.
     */
    private LayoutStyle layoutStyle;

    /**
     * If true, components that are not visible are treated as though they
     * aren't there.
     */
    private boolean honorsVisibility;


    /**
     * Enumeration of the possible ways {@code ParallelGroup} can align
     * its children.
     *
     * @see #createParallelGroup(Alignment)
     * @since 1.6
     */
    public enum Alignment {
        /**
         * Indicates the elements should be
         * aligned to the origin.  For the horizontal axis with a left to
         * right orientation this means aligned to the left edge. For the
         * vertical axis leading means aligned to the top edge.
         *
         * @see #createParallelGroup(Alignment)
         */
        LEADING,

        /**
         * Indicates the elements should be aligned to the end of the
         * region.  For the horizontal axis with a left to right
         * orientation this means aligned to the right edge. For the
         * vertical axis trailing means aligned to the bottom edge.
         *
         * @see #createParallelGroup(Alignment)
         */
        TRAILING,

        /**
         * Indicates the elements should be centered in
         * the region.
         *
         * @see #createParallelGroup(Alignment)
         */
        CENTER,

        /**
         * Indicates the elements should be aligned along
         * their baseline.
         *
         * @see #createParallelGroup(Alignment)
         * @see #createBaselineGroup(boolean,boolean)
         */
        BASELINE
    }


    private static void checkSize(int min, int pref, int max,
            boolean isComponentSpring) {
        checkResizeType(min, isComponentSpring);
        if (!isComponentSpring && pref < 0) {
            throw new IllegalArgumentException("Pref must be >= 0");
        } else if (isComponentSpring) {
            checkResizeType(pref, true);
        }
        checkResizeType(max, isComponentSpring);
        checkLessThan(min, pref);
        checkLessThan(pref, max);
    }

    private static void checkResizeType(int type, boolean isComponentSpring) {
        if (type < 0 && ((isComponentSpring && type != DEFAULT_SIZE &&
                type != PREFERRED_SIZE) ||
                (!isComponentSpring && type != PREFERRED_SIZE))) {
            throw new IllegalArgumentException("Invalid size");
        }
    }

    private static void checkLessThan(int min, int max) {
        if (min >= 0 && max >= 0 && min > max) {
            throw new IllegalArgumentException(
                    "Following is not met: min<=pref<=max");
        }
    }

    /**
     * Creates a {@code GroupLayout} for the specified {@code Container}.
     *
     * @param host the {@code Container} the {@code GroupLayout} is
     *        the {@code LayoutManager} for
     * @throws IllegalArgumentException if host is {@code null}
     */
    public GroupLayout(Container host) {
        if (host == null) {
            throw new IllegalArgumentException("Container must be non-null");
        }
        honorsVisibility = true;
        this.host = host;
        setHorizontalGroup(createParallelGroup(Alignment.LEADING, true));
        setVerticalGroup(createParallelGroup(Alignment.LEADING, true));
        componentInfos = new HashMap<Component,ComponentInfo>();
        tmpParallelSet = new HashSet<Spring>();
    }

    /**
     * Sets whether component visiblity is considered when sizing and
     * positioning components. A value of {@code true} indicates that
     * non-visible components should not be treated as part of the
     * layout. A value of {@code false} indicates that components should be
     * positioned and sized regardless of visibility.
     * <p>
     * A value of {@code false} is useful when the visibility of components
     * is dynamically adjusted and you don't want surrounding components and
     * the sizing to change.
     * <p>
     * The specified value is used for components that do not have an
     * explicit visibility specified.
     * <p>
     * The default is {@code true}.
     *
     * @param honorsVisibility whether component visiblity is considered when
     *                         sizing and positioning components
     * @see #setHonorsVisibility(Component,Boolean)
     */
    public void setHonorsVisibility(boolean honorsVisibility) {
        if (this.honorsVisibility != honorsVisibility) {
            this.honorsVisibility = honorsVisibility;
            springsChanged = true;
            isValid = false;
            invalidateHost();
        }
    }

    /**
     * Returns whether component visiblity is considered when sizing and
     * positioning components.
     *
     * @return whether component visiblity is considered when sizing and
     *         positioning components
     */
    public boolean getHonorsVisibility() {
        return honorsVisibility;
    }

    /**
     * Sets whether the component's visiblity is considered for
     * sizing and positioning. A value of {@code Boolean.TRUE}
     * indicates that if {@code component} is not visible it should
     * not be treated as part of the layout. A value of {@code false}
     * indicates that {@code component} is positioned and sized
     * regardless of it's visibility.  A value of {@code null}
     * indicates the value specified by the single argument method {@code
     * setHonorsVisibility} should be used.
     * <p>
     * If {@code component} is not a child of the {@code Container} this
     * {@code GroupLayout} is managine, it will be added to the
     * {@code Container}.
     *
     * @param component the component
     * @param honorsVisibility whether {@code component}'s visiblity should be
     *              considered for sizing and positioning
     * @throws IllegalArgumentException if {@code component} is {@code null}
     * @see #setHonorsVisibility(Component,Boolean)
     */
    public void setHonorsVisibility(Component component,
            Boolean honorsVisibility) {
        if (component == null) {
            throw new IllegalArgumentException("Component must be non-null");
        }
        getComponentInfo(component).setHonorsVisibility(honorsVisibility);
        springsChanged = true;
        isValid = false;
        invalidateHost();
    }

    /**
     * Sets whether a gap between components should automatically be
     * created.  For example, if this is {@code true} and you add two
     * components to a {@code SequentialGroup} a gap between the
     * two components is automatically be created.  The default is
     * {@code false}.
     *
     * @param autoCreatePadding whether a gap between components is
     *        automatically created
     */
    public void setAutoCreateGaps(boolean autoCreatePadding) {
        if (this.autocreatePadding != autoCreatePadding) {
            this.autocreatePadding = autoCreatePadding;
            invalidateHost();
        }
    }

    /**
     * Returns {@code true} if gaps between components are automatically
     * created.
     *
     * @return {@code true} if gaps between components are automatically
     *         created
     */
    public boolean getAutoCreateGaps() {
        return autocreatePadding;
    }

    /**
     * Sets whether a gap between the container and components that
     * touch the border of the container should automatically be
     * created. The default is {@code false}.
     *
     * @param autoCreateContainerPadding whether a gap between the container and
     *        components that touch the border of the container should
     *        automatically be created
     */
    public void setAutoCreateContainerGaps(boolean autoCreateContainerPadding){
        if (this.autocreateContainerPadding != autoCreateContainerPadding) {
            this.autocreateContainerPadding = autoCreateContainerPadding;
            horizontalGroup = createTopLevelGroup(getHorizontalGroup());
            verticalGroup = createTopLevelGroup(getVerticalGroup());
            invalidateHost();
        }
    }

    /**
     * Returns {@code true} if gaps between the container and components that
     * border the container are automatically created.
     *
     * @return {@code true} if gaps between the container and components that
     *         border the container are automatically created
     */
    public boolean getAutoCreateContainerGaps() {
        return autocreateContainerPadding;
    }

    /**
     * Sets the {@code Group} that positions and sizes
     * components along the horizontal axis.
     *
     * @param group the {@code Group} that positions and sizes
     *        components along the horizontal axis
     * @throws IllegalArgumentException if group is {@code null}
     */
    public void setHorizontalGroup(Group group) {
        if (group == null) {
            throw new IllegalArgumentException("Group must be non-null");
        }
        horizontalGroup = createTopLevelGroup(group);
        invalidateHost();
    }

    /**
     * Returns the {@code Group} that positions and sizes components
     * along the horizontal axis.
     *
     * @return the {@code Group} responsible for positioning and
     *         sizing component along the horizontal axis
     */
    private Group getHorizontalGroup() {
        int index = 0;
        if (horizontalGroup.springs.size() > 1) {
            index = 1;
        }
        return (Group)horizontalGroup.springs.get(index);
    }

    /**
     * Sets the {@code Group} that positions and sizes
     * components along the vertical axis.
     *
     * @param group the {@code Group} that positions and sizes
     *        components along the vertical axis
     * @throws IllegalArgumentException if group is {@code null}
     */
    public void setVerticalGroup(Group group) {
        if (group == null) {
            throw new IllegalArgumentException("Group must be non-null");
        }
        verticalGroup = createTopLevelGroup(group);
        invalidateHost();
    }

    /**
     * Returns the {@code Group} that positions and sizes components
     * along the vertical axis.
     *
     * @return the {@code Group} responsible for positioning and
     *         sizing component along the vertical axis
     */
    private Group getVerticalGroup() {
        int index = 0;
        if (verticalGroup.springs.size() > 1) {
            index = 1;
        }
        return (Group)verticalGroup.springs.get(index);
    }

    /**
     * Wraps the user specified group in a sequential group.  If
     * container gaps should be generated the necessary springs are
     * added.
     */
    private Group createTopLevelGroup(Group specifiedGroup) {
        SequentialGroup group = createSequentialGroup();
        if (getAutoCreateContainerGaps()) {
            group.addSpring(new ContainerAutoPreferredGapSpring());
            group.addGroup(specifiedGroup);
            group.addSpring(new ContainerAutoPreferredGapSpring());
        } else {
            group.addGroup(specifiedGroup);
        }
        return group;
    }

    /**
     * Creates and returns a {@code SequentialGroup}.
     *
     * @return a new {@code SequentialGroup}
     */
    public SequentialGroup createSequentialGroup() {
        return new SequentialGroup();
    }

    /**
     * Creates and returns a {@code ParallelGroup} with an alignment of
     * {@code Alignment.LEADING}.  This is a cover method for the more
     * general {@code createParallelGroup(Alignment)} method.
     *
     * @return a new {@code ParallelGroup}
     * @see #createParallelGroup(Alignment)
     */
    public ParallelGroup createParallelGroup() {
        return createParallelGroup(Alignment.LEADING);
    }

    /**
     * Creates and returns a {@code ParallelGroup} with the specified
     * alignment.  This is a cover method for the more general {@code
     * createParallelGroup(Alignment,boolean)} method with {@code true}
     * supplied for the second argument.
     *
     * @param alignment the alignment for the elements of the group
     * @throws IllegalArgumentException if {@code alignment} is {@code null}
     * @return a new {@code ParallelGroup}
     * @see #createBaselineGroup
     * @see ParallelGroup
     */
    public ParallelGroup createParallelGroup(Alignment alignment) {
        return createParallelGroup(alignment, true);
    }

    /**
     * Creates and returns a {@code ParallelGroup} with the specified
     * alignment and resize behavior. The {@code
     * alignment} argument specifies how children elements are
     * positioned that do not fill the group. For example, if a {@code
     * ParallelGroup} with an alignment of {@code TRAILING} is given
     * 100 and a child only needs 50, the child is
     * positioned at the position 50 (with a component orientation of
     * left-to-right).
     * <p>
     * Baseline alignment is only useful when used along the vertical
     * axis. A {@code ParallelGroup} created with a baseline alignment
     * along the horizontal axis is treated as {@code LEADING}.
     * <p>
     * Refer to {@link GroupLayout.ParallelGroup ParallelGroup} for details on
     * the behavior of baseline groups.
     *
     * @param alignment the alignment for the elements of the group
     * @param resizable {@code true} if the group is resizable; if the group
     *        is not resizable the preferred size is used for the
     *        minimum and maximum size of the group
     * @throws IllegalArgumentException if {@code alignment} is {@code null}
     * @return a new {@code ParallelGroup}
     * @see #createBaselineGroup
     * @see GroupLayout.ParallelGroup
     */
    public ParallelGroup createParallelGroup(Alignment alignment,
            boolean resizable){
        if (alignment == Alignment.BASELINE) {
            return new BaselineGroup(resizable);
        }
        return new ParallelGroup(alignment, resizable);
    }

    /**
     * Creates and returns a {@code ParallelGroup} that aligns it's
     * elements along the baseline.
     *
     * @param resizable whether the group is resizable
     * @param anchorBaselineToTop whether the baseline is anchored to
     *        the top or bottom of the group
     * @see #createBaselineGroup
     * @see ParallelGroup
     */
    public ParallelGroup createBaselineGroup(boolean resizable,
            boolean anchorBaselineToTop) {
        return new BaselineGroup(resizable, anchorBaselineToTop);
    }

    /**
     * Forces the specified components to have the same size
     * regardless of their preferred, minimum or maximum sizes. Components that
     * are linked are given the maximum of the preferred size of each of
     * the linked components. For example, if you link two components with
     * a preferred width of 10 and 20, both components are given a width of 20.
     * <p>
     * This can be used multiple times to force any number of
     * components to share the same size.
     * <p>
     * Linked Components are not be resizable.
     *
     * @param components the {@code Component}s that are to have the same size
     * @throws IllegalArgumentException if {@code components} is
     *         {@code null}, or contains {@code null}
     * @see #linkSize(int,Component[])
     */
    public void linkSize(Component... components) {
        linkSize(SwingConstants.HORIZONTAL, components);
        linkSize(SwingConstants.VERTICAL, components);
    }

    /**
     * Forces the specified components to have the same size along the
     * specified axis regardless of their preferred, minimum or
     * maximum sizes. Components that are linked are given the maximum
     * of the preferred size of each of the linked components. For
     * example, if you link two components along the horizontal axis
     * and the preferred width is 10 and 20, both components are given
     * a width of 20.
     * <p>
     * This can be used multiple times to force any number of
     * components to share the same size.
     * <p>
     * Linked {@code Component}s are not be resizable.
     *
     * @param components the {@code Component}s that are to have the same size
     * @param axis the axis to link the size along; one of
     *             {@code SwingConstants.HORIZONTAL} or
     *             {@code SwingConstans.VERTICAL}
     * @throws IllegalArgumentException if {@code components} is
     *         {@code null}, or contains {@code null}; or {@code axis}
     *          is not {@code SwingConstants.HORIZONTAL} or
     *          {@code SwingConstants.VERTICAL}
     */
    public void linkSize(int axis, Component... components) {
        if (components == null) {
            throw new IllegalArgumentException("Components must be non-null");
        }
        for (int counter = components.length - 1; counter >= 0; counter--) {
            Component c = components[counter];
            if (components[counter] == null) {
                throw new IllegalArgumentException(
                        "Components must be non-null");
            }
            // Force the component to be added
            getComponentInfo(c);
        }
        int glAxis;
        if (axis == SwingConstants.HORIZONTAL) {
            glAxis = HORIZONTAL;
        } else if (axis == SwingConstants.VERTICAL) {
            glAxis = VERTICAL;
        } else {
            throw new IllegalArgumentException("Axis must be one of " +
                    "SwingConstants.HORIZONTAL or SwingConstants.VERTICAL");
        }
        LinkInfo master = getComponentInfo(
                components[components.length - 1]).getLinkInfo(glAxis);
        for (int counter = components.length - 2; counter >= 0; counter--) {
            master.add(getComponentInfo(components[counter]));
        }
        invalidateHost();
    }

    /**
     * Replaces an existing component with a new one.
     *
     * @param existingComponent the component that should be removed
     *        and replaced with {@code newComponent}
     * @param newComponent the component to put in
     *        {@code existingComponent}'s place
     * @throws IllegalArgumentException if either of the components are
     *         {@code null} or {@code existingComponent} is not being managed
     *         by this layout manager
     */
    public void replace(Component existingComponent, Component newComponent) {
        if (existingComponent == null || newComponent == null) {
            throw new IllegalArgumentException("Components must be non-null");
        }
        // Make sure all the components have been registered, otherwise we may
        // not update the correct Springs.
        if (springsChanged) {
            registerComponents(horizontalGroup, HORIZONTAL);
            registerComponents(verticalGroup, VERTICAL);
        }
        ComponentInfo info = componentInfos.remove(existingComponent);
        if (info == null) {
            throw new IllegalArgumentException("Component must already exist");
        }
        host.remove(existingComponent);
        if (newComponent.getParent() != host) {
            host.add(newComponent);
        }
        info.setComponent(newComponent);
        componentInfos.put(newComponent, info);
        invalidateHost();
    }

    /**
     * Sets the {@code LayoutStyle} used to calculate the preferred
     * gaps between components. A value of {@code null} indicates the
     * shared instance of {@code LayoutStyle} should be used.
     *
     * @param layoutStyle the {@code LayoutStyle} to use
     * @see LayoutStyle
     */
    public void setLayoutStyle(LayoutStyle layoutStyle) {
        this.layoutStyle = layoutStyle;
        invalidateHost();
    }

    /**
     * Returns the {@code LayoutStyle} used for calculating the preferred
     * gap between components. This returns the value specified to
     * {@code setLayoutStyle}, which may be {@code null}.
     *
     * @return the {@code LayoutStyle} used for calculating the preferred
     *         gap between components
     */
    public LayoutStyle getLayoutStyle() {
        return layoutStyle;
    }

    private LayoutStyle getLayoutStyle0() {
        LayoutStyle layoutStyle = getLayoutStyle();
        if (layoutStyle == null) {
            layoutStyle = LayoutStyle.getInstance();
        }
        return layoutStyle;
    }

    private void invalidateHost() {
        if (host instanceof JComponent) {
            ((JComponent)host).revalidate();
        } else {
            host.invalidate();
        }
        host.repaint();
    }

    //
    // LayoutManager
    //
    /**
     * Notification that a {@code Component} has been added to
     * the parent container.  You should not invoke this method
     * directly, instead you should use one of the {@code Group}
     * methods to add a {@code Component}.
     *
     * @param name the string to be associated with the component
     * @param component the {@code Component} to be added
     */
    public void addLayoutComponent(String name, Component component) {
    }

    /**
     * Notification that a {@code Component} has been removed from
     * the parent container.  You should not invoke this method
     * directly, instead invoke {@code remove} on the parent
     * {@code Container}.
     *
     * @param component the component to be removed
     * @see java.awt.Component#remove
     */
    public void removeLayoutComponent(Component component) {
        ComponentInfo info = componentInfos.remove(component);
        if (info != null) {
            info.dispose();
            springsChanged = true;
            isValid = false;
        }
    }

    /**
     * Returns the preferred size for the specified container.
     *
     * @param parent the container to return the preferred size for
     * @return the preferred size for {@code parent}
     * @throws IllegalArgumentException if {@code parent} is not
     *         the same {@code Container} this was created with
     * @throws IllegalStateException if any of the components added to
     *         this layout are not in both a horizontal and vertical group
     * @see java.awt.Container#getPreferredSize
     */
    public Dimension preferredLayoutSize(Container parent) {
        checkParent(parent);
        prepare(PREF_SIZE);
        return adjustSize(horizontalGroup.getPreferredSize(HORIZONTAL),
                verticalGroup.getPreferredSize(VERTICAL));
    }

    /**
     * Returns the minimum size for the specified container.
     *
     * @param parent the container to return the size for
     * @return the minimum size for {@code parent}
     * @throws IllegalArgumentException if {@code parent} is not
     *         the same {@code Container} that this was created with
     * @throws IllegalStateException if any of the components added to
     *         this layout are not in both a horizontal and vertical group
     * @see java.awt.Container#getMinimumSize
     */
    public Dimension minimumLayoutSize(Container parent) {
        checkParent(parent);
        prepare(MIN_SIZE);
        return adjustSize(horizontalGroup.getMinimumSize(HORIZONTAL),
                verticalGroup.getMinimumSize(VERTICAL));
    }

    /**
     * Lays out the specified container.
     *
     * @param parent the container to be laid out
     * @throws IllegalStateException if any of the components added to
     *         this layout are not in both a horizontal and vertical group
     */
    public void layoutContainer(Container parent) {
        // Step 1: Prepare for layout.
        prepare(SPECIFIC_SIZE);
        Insets insets = parent.getInsets();
        int width = parent.getWidth() - insets.left - insets.right;
        int height = parent.getHeight() - insets.top - insets.bottom;
        boolean ltr = isLeftToRight();
        if (getAutoCreateGaps() || getAutoCreateContainerGaps() ||
                hasPreferredPaddingSprings) {
            // Step 2: Calculate autopadding springs
            calculateAutopadding(horizontalGroup, HORIZONTAL, SPECIFIC_SIZE, 0,
                    width);
            calculateAutopadding(verticalGroup, VERTICAL, SPECIFIC_SIZE, 0,
                    height);
        }
        // Step 3: set the size of the groups.
        horizontalGroup.setSize(HORIZONTAL, 0, width);
        verticalGroup.setSize(VERTICAL, 0, height);
        // Step 4: apply the size to the components.
        for (ComponentInfo info : componentInfos.values()) {
            info.setBounds(insets, width, ltr);
        }
    }

    //
    // LayoutManager2
    //
    /**
     * Notification that a {@code Component} has been added to
     * the parent container.  You should not invoke this method
     * directly, instead you should use one of the {@code Group}
     * methods to add a {@code Component}.
     *
     * @param component the component added
     * @param constraints description of where to place the component
     */
    public void addLayoutComponent(Component component, Object constraints) {
    }

    /**
     * Returns the maximum size for the specified container.
     *
     * @param parent the container to return the size for
     * @return the maximum size for {@code parent}
     * @throws IllegalArgumentException if {@code parent} is not
     *         the same {@code Container} that this was created with
     * @throws IllegalStateException if any of the components added to
     *         this layout are not in both a horizontal and vertical group
     * @see java.awt.Container#getMaximumSize
     */
    public Dimension maximumLayoutSize(Container parent) {
        checkParent(parent);
        prepare(MAX_SIZE);
        return adjustSize(horizontalGroup.getMaximumSize(HORIZONTAL),
                verticalGroup.getMaximumSize(VERTICAL));
    }

    /**
     * Returns the alignment along the x axis.  This specifies how
     * the component would like to be aligned relative to other
     * components.  The value should be a number between 0 and 1
     * where 0 represents alignment along the origin, 1 is aligned
     * the furthest away from the origin, 0.5 is centered, etc.
     *
     * @param parent the {@code Container} hosting this {@code LayoutManager}
     * @throws IllegalArgumentException if {@code parent} is not
     *         the same {@code Container} that this was created with
     * @return the alignment; this implementation returns {@code .5}
     */
    public float getLayoutAlignmentX(Container parent) {
        checkParent(parent);
        return .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.
     *
     * @param parent the {@code Container} hosting this {@code LayoutManager}
     * @throws IllegalArgumentException if {@code parent} is not
     *         the same {@code Container} that this was created with
     * @return alignment; this implementation returns {@code .5}
     */
    public float getLayoutAlignmentY(Container parent) {
        checkParent(parent);
        return .5f;
    }

    /**
     * Invalidates the layout, indicating that if the layout manager
     * has cached information it should be discarded.
     *
     * @param parent the {@code Container} hosting this LayoutManager
     * @throws IllegalArgumentException if {@code parent} is not
     *         the same {@code Container} that this was created with
     */
    public void invalidateLayout(Container parent) {
        checkParent(parent);
        // invalidateLayout is called from Container.invalidate, which
        // does NOT grab the treelock.  All other methods do.  To make sure
        // there aren't any possible threading problems we grab the tree lock
        // here.
        synchronized(parent.getTreeLock()) {
            isValid = false;
        }
    }

    private void prepare(int sizeType) {
        boolean visChanged = false;
        // Step 1: If not-valid, clear springs and update visibility.
        if (!isValid) {
            isValid = true;
            horizontalGroup.setSize(HORIZONTAL, UNSET, UNSET);
            verticalGroup.setSize(VERTICAL, UNSET, UNSET);
            for (ComponentInfo ci : componentInfos.values()) {
                if (ci.updateVisibility()) {
                    visChanged = true;
                }
                ci.clearCachedSize();
            }
        }
        // Step 2: Make sure components are bound to ComponentInfos
        if (springsChanged) {
            registerComponents(horizontalGroup, HORIZONTAL);
            registerComponents(verticalGroup, VERTICAL);
        }
        // Step 3: Adjust the autopadding. This removes existing
        // autopadding, then recalculates where it should go.
        if (springsChanged || visChanged) {
            checkComponents();
            horizontalGroup.removeAutopadding();
            verticalGroup.removeAutopadding();
            if (getAutoCreateGaps()) {
                insertAutopadding(true);
            } else if (hasPreferredPaddingSprings ||
                    getAutoCreateContainerGaps()) {
                insertAutopadding(false);
            }
            springsChanged = false;
        }
        // Step 4: (for min/pref/max size calculations only) calculate the
        // autopadding. This invokes for unsetting the calculated values, then
        // recalculating them.
        // If sizeType == SPECIFIC_SIZE, it indicates we're doing layout, this
        // step will be done later on.
        if (sizeType != SPECIFIC_SIZE && (getAutoCreateGaps() ||
                getAutoCreateContainerGaps() || hasPreferredPaddingSprings)) {
            calculateAutopadding(horizontalGroup, HORIZONTAL, sizeType, 0, 0);
            calculateAutopadding(verticalGroup, VERTICAL, sizeType, 0, 0);
        }
    }

    private void calculateAutopadding(Group group, int axis, int sizeType,
            int origin, int size) {
        group.unsetAutopadding();
        switch(sizeType) {
            case MIN_SIZE:
                size = group.getMinimumSize(axis);
                break;
            case PREF_SIZE:
                size = group.getPreferredSize(axis);
                break;
            case MAX_SIZE:
                size = group.getMaximumSize(axis);
                break;
            default:
                break;
        }
        group.setSize(axis, origin, size);
        group.calculateAutopadding(axis);
    }

    private void checkComponents() {
        for (ComponentInfo info : componentInfos.values()) {
            if (info.horizontalSpring == null) {
                throw new IllegalStateException(info.component +
                        " is not attached to a horizontal group");
            }
            if (info.verticalSpring == null) {
                throw new IllegalStateException(info.component +
                        " is not attached to a vertical group");
            }
        }
    }

    private void registerComponents(Group group, int axis) {
        List<Spring> springs = group.springs;
        for (int counter = springs.size() - 1; counter >= 0; counter--) {
            Spring spring = springs.get(counter);
            if (spring instanceof ComponentSpring) {
                ((ComponentSpring)spring).installIfNecessary(axis);
            } else if (spring instanceof Group) {
                registerComponents((Group)spring, axis);
            }
        }
    }

    private Dimension adjustSize(int width, int height) {
        Insets insets = host.getInsets();
        return new Dimension(width + insets.left + insets.right,
                height + insets.top + insets.bottom);
    }

    private void checkParent(Container parent) {
        if (parent != host) {
            throw new IllegalArgumentException(
                    "GroupLayout can only be used with one Container at a time");
        }
    }

    /**
     * Returns the {@code ComponentInfo} for the specified Component,
     * creating one if necessary.
     */
    private ComponentInfo getComponentInfo(Component component) {
        ComponentInfo info = (ComponentInfo)componentInfos.get(component);
        if (info == null) {
            info = new ComponentInfo(component);
            componentInfos.put(component, info);
            if (component.getParent() != host) {
                host.add(component);
            }
        }
        return info;
    }

    /**
     * Adjusts the autopadding springs for the horizontal and vertical
     * groups.  If {@code insert} is {@code true} this will insert auto padding
     * springs, otherwise this will only adjust the springs that
     * comprise auto preferred padding springs.
     */
    private void insertAutopadding(boolean insert) {
        horizontalGroup.insertAutopadding(HORIZONTAL,
                new ArrayList<AutoPreferredGapSpring>(1),
                new ArrayList<AutoPreferredGapSpring>(1),
                new ArrayList<ComponentSpring>(1),
                new ArrayList<ComponentSpring>(1), insert);
        verticalGroup.insertAutopadding(VERTICAL,
                new ArrayList<AutoPreferredGapSpring>(1),
                new ArrayList<AutoPreferredGapSpring>(1),
                new ArrayList<ComponentSpring>(1),
                new ArrayList<ComponentSpring>(1), insert);
    }

    /**
     * Returns {@code true} if the two Components have a common ParallelGroup
     * ancestor along the particular axis.
     */
    private boolean areParallelSiblings(Component source, Component target,
            int axis) {
        ComponentInfo sourceInfo = getComponentInfo(source);
        ComponentInfo targetInfo = getComponentInfo(target);
        Spring sourceSpring;
        Spring targetSpring;
        if (axis == HORIZONTAL) {
            sourceSpring = sourceInfo.horizontalSpring;
            targetSpring = targetInfo.horizontalSpring;
        } else {
            sourceSpring = sourceInfo.verticalSpring;
            targetSpring = targetInfo.verticalSpring;
        }
        Set<Spring> sourcePath = tmpParallelSet;
        sourcePath.clear();
        Spring spring = sourceSpring.getParent();
        while (spring != null) {
            sourcePath.add(spring);
            spring = spring.getParent();
        }
        spring = targetSpring.getParent();
        while (spring != null) {
            if (sourcePath.contains(spring)) {
                sourcePath.clear();
                while (spring != null) {
                    if (spring instanceof ParallelGroup) {
                        return true;
                    }
                    spring = spring.getParent();
                }
                return false;
            }
            spring = spring.getParent();
        }
        sourcePath.clear();
        return false;
    }

    private boolean isLeftToRight() {
        return host.getComponentOrientation().isLeftToRight();
    }

    /**
     * Returns a string representation of this {@code GroupLayout}.
     * This method is intended to be used for debugging purposes,
     * and the content and format of the returned string may vary
     * between implementations.
     *
     * @return a string representation of this {@code GroupLayout}
     **/
    public String toString() {
        if (springsChanged) {
            registerComponents(horizontalGroup, HORIZONTAL);
            registerComponents(verticalGroup, VERTICAL);
        }
        StringBuffer buffer = new StringBuffer();
        buffer.append("HORIZONTAL\n");
        createSpringDescription(buffer, horizontalGroup, "  ", HORIZONTAL);
        buffer.append("\nVERTICAL\n");
        createSpringDescription(buffer, verticalGroup, "  ", VERTICAL);
        return buffer.toString();
    }

    private void createSpringDescription(StringBuffer buffer, Spring spring,
            String indent, int axis) {
        String origin = "";
        String padding = "";
        if (spring instanceof ComponentSpring) {
            ComponentSpring cSpring = (ComponentSpring)spring;
            origin = Integer.toString(cSpring.getOrigin()) + " ";
            String name = cSpring.getComponent().getName();
            if (name != null) {
                origin = "name=" + name + ", ";
            }
        }
        if (spring instanceof AutoPreferredGapSpring) {
            AutoPreferredGapSpring paddingSpring =
                    (AutoPreferredGapSpring)spring;
            padding = ", userCreated=" + paddingSpring.getUserCreated() +
                    ", matches=" + paddingSpring.getMatchDescription();
        }
        buffer.append(indent + spring.getClass().getName() + " " +
                Integer.toHexString(spring.hashCode()) + " " +
                origin +
                ", size=" + spring.getSize() +
                ", alignment=" + spring.getAlignment() +
                " prefs=[" + spring.getMinimumSize(axis) +
                " " + spring.getPreferredSize(axis) +
                " " + spring.getMaximumSize(axis) +
                padding + "]\n");
        if (spring instanceof Group) {
            List<Spring> springs = ((Group)spring).springs;
            indent += "  ";
            for (int counter = 0; counter < springs.size(); counter++) {
                createSpringDescription(buffer, springs.get(counter), indent,
                        axis);
            }
        }
    }


    /**
     * Spring consists of a range: min, pref and max, a value some where in
     * the middle of that, and a location. Spring caches the
     * min/max/pref.  If the min/pref/max has internally changes, or needs
     * to be updated you must invoke clear.
     */
    private abstract class Spring {
        private int size;
        private int min;
        private int max;
        private int pref;
        private Spring parent;

        private Alignment alignment;

        Spring() {
            min = pref = max = UNSET;
        }

        /**
         * Calculates and returns the minimum size.
         *
         * @param axis the axis of layout; one of HORIZONTAL or VERTICAL
         * @return the minimum size
         */
        abstract int calculateMinimumSize(int axis);

        /**
         * Calculates and returns the preferred size.
         *
         * @param axis the axis of layout; one of HORIZONTAL or VERTICAL
         * @return the preferred size
         */
        abstract int calculatePreferredSize(int axis);

        /**
         * Calculates and returns the minimum size.
         *
         * @param axis the axis of layout; one of HORIZONTAL or VERTICAL
         * @return the minimum size
         */
        abstract int calculateMaximumSize(int axis);

        /**
         * Sets the parent of this Spring.
         */
        void setParent(Spring parent) {
            this.parent = parent;
        }

        /**
         * Returns the parent of this spring.
         */
        Spring getParent() {
            return parent;
        }

        // This is here purely as a conveniance for ParallelGroup to avoid
        // having to track alignment separately.
        void setAlignment(Alignment alignment) {
            this.alignment = alignment;
        }

        /**
         * Alignment for this Spring, this may be null.
         */
        Alignment getAlignment() {
            return alignment;
        }

        /**
         * Returns the minimum size.
         */
        final int getMinimumSize(int axis) {
            if (min == UNSET) {
                min = constrain(calculateMinimumSize(axis));
            }
            return min;
        }

        /**
         * Returns the preferred size.
         */
        final int getPreferredSize(int axis) {
            if (pref == UNSET) {
                pref = constrain(calculatePreferredSize(axis));
            }
            return pref;
        }

        /**
         * Returns the maximum size.
         */
        final int getMaximumSize(int axis) {
            if (max == UNSET) {
                max = constrain(calculateMaximumSize(axis));
            }
            return max;
        }

        /**
         * Sets the value and location of the spring.  Subclasses
         * will want to invoke super, then do any additional sizing.
         *
         * @param axis HORIZONTAL or VERTICAL
         * @param origin of this Spring
         * @param size of the Spring.  If size is UNSET, this invokes
         *        clear.
         */
        void setSize(int axis, int origin, int size) {
            this.size = size;
            if (size == UNSET) {
                unset();
            }
        }

        /**
         * Resets the cached min/max/pref.
         */
        void unset() {
            size = min = pref = max = UNSET;
        }

        /**
         * Returns the current size.
         */
        int getSize() {
            return size;
        }

        int constrain(int value) {
            return Math.min(value, Short.MAX_VALUE);
        }

        int getBaseline() {
            return -1;
        }

        BaselineResizeBehavior getBaselineResizeBehavior() {
            return BaselineResizeBehavior.OTHER;
        }

        final boolean isResizable(int axis) {
            int min = getMinimumSize(axis);
            int pref = getPreferredSize(axis);
            return (min != pref || pref != getMaximumSize(axis));
        }

        /**
         * Returns {@code true} if this spring will ALWAYS have a zero
         * size. This should NOT check the current size, rather it's
         * meant to quickly test if this Spring will always have a
         * zero size.
         *
         * @param treatAutopaddingAsZeroSized if {@code true}, auto padding
         *        springs should be treated as having a size of {@code 0}
         * @return {@code true} if this spring will have a zero size,
         *         {@code false} otherwise
         */
        abstract boolean willHaveZeroSize(boolean treatAutopaddingAsZeroSized);
    }

    /**
     * {@code Group} provides the basis for the two types of
     * operations supported by {@code GroupLayout}: laying out
     * components one after another ({@link SequentialGroup SequentialGroup})
     * or aligned ({@link ParallelGroup ParallelGroup}). {@code Group} and
     * its subclasses have no public constructor; to create one use
     * one of {@code createSequentialGroup} or
     * {@code createParallelGroup}. Additionally, taking a {@code Group}
     * created from one {@code GroupLayout} and using it with another
     * will produce undefined results.
     * <p>
     * Various methods in {@code Group} and its subclasses allow you
     * to explicitly specify the range. The arguments to these methods
     * can take two forms, either a value greater than or equal to 0,
     * or one of {@code DEFAULT_SIZE} or {@code PREFERRED_SIZE}. A
     * value greater than or equal to {@code 0} indicates a specific
     * size. {@code DEFAULT_SIZE} indicates the corresponding size
     * from the component should be used.  For example, if {@code
     * DEFAULT_SIZE} is passed as the minimum size argument, the
     * minimum size is obtained from invoking {@code getMinimumSize}
     * on the component. Likewise, {@code PREFERRED_SIZE} indicates
     * the value from {@code getPreferredSize} should be used.
     * The following example adds {@code myComponent} to {@code group}
     * with specific values for the range. That is, the minimum is
     * explicitly specified as 100, preferred as 200, and maximum as
     * 300.
     * <pre>
     *   group.addComponent(myComponent, 100, 200, 300);
     * </pre>
     * The following example adds {@code myComponent} to {@code group} using
     * a combination of the forms. The minimum size is forced to be the
     * same as the preferred size, the preferred size is determined by
     * using {@code myComponent.getPreferredSize} and the maximum is
     * determined by invoking {@code getMaximumSize} on the component.
     * <pre>
     *   group.addComponent(myComponent, GroupLayout.PREFERRED_SIZE,
     *             GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE);
     * </pre>
     * <p>
     * Unless otherwise specified all the methods of {@code Group} and
     * its subclasses that allow you to specify a range throw an
     * {@code IllegalArgumentException} if passed an invalid range. An
     * invalid range is one in which any of the values are &lt; 0 and
     * not one of {@code PREFERRED_SIZE} or {@code DEFAULT_SIZE}, or
     * the following is not met (for specific values): {@code min}
     * &lt;= {@code pref} &lt;= {@code max}.
     * <p>
     * Similarly any methods that take a {@code Component} throw a
     * {@code NullPointerException} if passed {@code null} and any methods
     * that take a {@code Group} throw an {@code IllegalArgumentException} if
     * passed {@code null}.
     *
     * @see #createSequentialGroup
     * @see #createParallelGroup
     * @since 1.6
     */
    public abstract class Group extends Spring {
        // private int origin;
        // private int size;
        List<Spring> springs;

        Group() {
            springs = new ArrayList<Spring>();
        }

        /**
         * Adds a {@code Group} to this {@code Group}.
         *
         * @param group the {@code Group} to add
         * @return this {@code Group}
         */
        public Group addGroup(Group group) {
            return addSpring(group);
        }

        /**
         * Adds a {@code Component} to this {@code Group}.
         *
         * @param component the {@code Component} to add
         * @return this {@code Group}
         */
        public Group addComponent(Component component) {
            return addComponent(component, DEFAULT_SIZE, DEFAULT_SIZE,
                    DEFAULT_SIZE);
        }

        /**
         * Adds a {@code Component} to this {@code Group}
         * with the specified size.
         *
         * @param component the {@code Component} to add
         * @param min the minimum size or one of {@code DEFAULT_SIZE} or
         *            {@code PREFERRED_SIZE}
         * @param pref the preferred size or one of {@code DEFAULT_SIZE} or
         *            {@code PREFERRED_SIZE}
         * @param max the maximum size or one of {@code DEFAULT_SIZE} or
         *            {@code PREFERRED_SIZE}
         * @return this {@code Group}
         */
        public Group addComponent(Component component, int min, int pref,
                int max) {
            return addSpring(new ComponentSpring(component, min, pref, max));
        }

        /**
         * Adds a rigid gap to this {@code Group}.
         *
         * @param size the size of the gap
         * @return this {@code Group}
         * @throws IllegalArgumentException if {@code size} is less than
         *         {@code 0}
         */
        public Group addGap(int size) {
            return addGap(size, size, size);
        }

        /**
         * Adds a gap to this {@code Group} with the specified size.
         *
         * @param min the minimum size of the gap
         * @param pref the preferred size of the gap
         * @param max the maximum size of the gap
         * @throws IllegalArgumentException if any of the values are
         *         less than {@code 0}
         * @return this {@code Group}
         */
        public Group addGap(int min, int pref, int max) {
            return addSpring(new GapSpring(min, pref, max));
        }

        Spring getSpring(int index) {
            return springs.get(index);
        }

        int indexOf(Spring spring) {
            return springs.indexOf(spring);
        }

        /**
         * Adds the Spring to the list of {@code Spring}s and returns
         * the receiver.
         */
        Group addSpring(Spring spring) {
            springs.add(spring);
            spring.setParent(this);
            if (!(spring instanceof AutoPreferredGapSpring) ||
                    !((AutoPreferredGapSpring)spring).getUserCreated()) {
                springsChanged = true;
            }
            return this;
        }

        //
        // Spring methods
        //

        void setSize(int axis, int origin, int size) {
            super.setSize(axis, origin, size);
            if (size == UNSET) {
                for (int counter = springs.size() - 1; counter >= 0;
                counter--) {
                    getSpring(counter).setSize(axis, origin, size);
                }
            } else {
                setValidSize(axis, origin, size);
            }
        }

        /**
         * This is invoked from {@code setSize} if passed a value
         * other than UNSET.
         */
        abstract void setValidSize(int axis, int origin, int size);

        int calculateMinimumSize(int axis) {
            return calculateSize(axis, MIN_SIZE);
        }

        int calculatePreferredSize(int axis) {
            return calculateSize(axis, PREF_SIZE);
        }

        int calculateMaximumSize(int axis) {
            return calculateSize(axis, MAX_SIZE);
        }

        /**
         * Calculates the specified size.  This is called from
         * one of the {@code getMinimumSize0},
         * {@code getPreferredSize0} or
         * {@code getMaximumSize0} methods.  This will invoke
         * to {@code operator} to combine the values.
         */
        int calculateSize(int axis, int type) {
            int count = springs.size();
            if (count == 0) {
                return 0;
            }
            if (count == 1) {
                return getSpringSize(getSpring(0), axis, type);
            }
            int size = constrain(operator(getSpringSize(getSpring(0), axis,
                    type), getSpringSize(getSpring(1), axis, type)));
            for (int counter = 2; counter < count; counter++) {
                size = constrain(operator(size, getSpringSize(
                        getSpring(counter), axis, type)));
            }
            return size;
        }

        int getSpringSize(Spring spring, int axis, int type) {
            switch(type) {
                case MIN_SIZE:
                    return spring.getMinimumSize(axis);
                case PREF_SIZE:
                    return spring.getPreferredSize(axis);
                case MAX_SIZE:
                    return spring.getMaximumSize(axis);
            }
            assert false;
            return 0;
        }

        /**
         * Used to compute how the two values representing two springs
         * will be combined.  For example, a group that layed things out
         * one after the next would return {@code a + b}.
         */
        abstract int operator(int a, int b);

        //
        // Padding
        //

        /**
         * Adjusts the autopadding springs in this group and its children.
         * If {@code insert} is true this will insert auto padding
         * springs, otherwise this will only adjust the springs that
         * comprise auto preferred padding springs.
         *
         * @param axis the axis of the springs; HORIZONTAL or VERTICAL
         * @param leadingPadding List of AutopaddingSprings that occur before
         *                       this Group
         * @param trailingPadding any trailing autopadding springs are added
         *                        to this on exit
         * @param leading List of ComponentSprings that occur before this Group
         * @param trailing any trailing ComponentSpring are added to this
         *                 List
         * @param insert Whether or not to insert AutopaddingSprings or just
         *               adjust any existing AutopaddingSprings.
         */
        abstract void insertAutopadding(int axis,
                List<AutoPreferredGapSpring> leadingPadding,
                List<AutoPreferredGapSpring> trailingPadding,
                List<ComponentSpring> leading, List<ComponentSpring> trailing,
                boolean insert);

        /**
         * Removes any AutopaddingSprings for this Group and its children.
         */
        void removeAutopadding() {
            unset();
            for (int counter = springs.size() - 1; counter >= 0; counter--) {
                Spring spring = springs.get(counter);
                if (spring instanceof AutoPreferredGapSpring) {
                    if (((AutoPreferredGapSpring)spring).getUserCreated()) {
                        ((AutoPreferredGapSpring)spring).reset();
                    } else {
                        springs.remove(counter);
                    }
                } else if (spring instanceof Group) {
                    ((Group)spring).removeAutopadding();
                }
            }
        }

        void unsetAutopadding() {
            // Clear cached pref/min/max.
            unset();
            for (int counter = springs.size() - 1; counter >= 0; counter--) {
                Spring spring = springs.get(counter);
                if (spring instanceof AutoPreferredGapSpring) {
                    ((AutoPreferredGapSpring)spring).unset();
                } else if (spring instanceof Group) {
                    ((Group)spring).unsetAutopadding();
                }
            }
        }

        void calculateAutopadding(int axis) {
            for (int counter = springs.size() - 1; counter >= 0; counter--) {
                Spring spring = springs.get(counter);
                if (spring instanceof AutoPreferredGapSpring) {
                    // Force size to be reset.
                    spring.unset();
                    ((AutoPreferredGapSpring)spring).calculatePadding(axis);
                } else if (spring instanceof Group) {
                    ((Group)spring).calculateAutopadding(axis);
                }
            }
            // Clear cached pref/min/max.
            unset();
        }

        @Override
        boolean willHaveZeroSize(boolean treatAutopaddingAsZeroSized) {
            for (int i = springs.size() - 1; i >= 0; i--) {
                Spring spring = springs.get(i);
                if (!spring.willHaveZeroSize(treatAutopaddingAsZeroSized)) {
                    return false;
                }
            }
            return true;
        }
    }


    /**
     * A {@code Group} that positions and sizes its elements
     * sequentially, one after another.  This class has no public
     * constructor, use the {@code createSequentialGroup} method
     * to create one.
     * <p>
     * In order to align a {@code SequentialGroup} along the baseline
     * of a baseline aligned {@code ParallelGroup} you need to specify
     * which of the elements of the {@code SequentialGroup} is used to
     * determine the baseline.  The element used to calculate the
     * baseline is specified using one of the {@code add} methods that
     * take a {@code boolean}. The last element added with a value of
     * {@code true} for {@code useAsBaseline} is used to calculate the
     * baseline.
     *
     * @see #createSequentialGroup
     * @since 1.6
     */
    public class SequentialGroup extends Group {
        private Spring baselineSpring;

        SequentialGroup() {
        }

        /**
         * {@inheritDoc}
         */
        public SequentialGroup addGroup(Group group) {
            return (SequentialGroup)super.addGroup(group);
        }

        /**
         * Adds a {@code Group} to this {@code Group}.
         *
         * @param group the {@code Group} to add
         * @param useAsBaseline whether the specified {@code Group} should
         *        be used to calculate the baseline for this {@code Group}
         * @return this {@code Group}
         */
        public SequentialGroup addGroup(boolean useAsBaseline, Group group) {
            super.addGroup(group);
            if (useAsBaseline) {
                baselineSpring = group;
            }
            return this;
        }

        /**
         * {@inheritDoc}
         */
        public SequentialGroup addComponent(Component component) {
            return (SequentialGroup)super.addComponent(component);
        }

        /**
         * Adds a {@code Component} to this {@code Group}.
         *
         * @param useAsBaseline whether the specified {@code Component} should
         *        be used to calculate the baseline for this {@code Group}
         * @param component the {@code Component} to add
         * @return this {@code Group}
         */
        public SequentialGroup addComponent(boolean useAsBaseline,
                Component component) {
            super.addComponent(component);
            if (useAsBaseline) {
                baselineSpring = springs.get(springs.size() - 1);
            }
            return this;
        }

        /**
         * {@inheritDoc}
         */
        public SequentialGroup addComponent(Component component, int min,
                int pref, int max) {
            return (SequentialGroup)super.addComponent(
                    component, min, pref, max);
        }

        /**
         * Adds a {@code Component} to this {@code Group}
         * with the specified size.
         *
         * @param useAsBaseline whether the specified {@code Component} should
         *        be used to calculate the baseline for this {@code Group}
         * @param component the {@code Component} to add
         * @param min the minimum size or one of {@code DEFAULT_SIZE} or
         *            {@code PREFERRED_SIZE}
         * @param pref the preferred size or one of {@code DEFAULT_SIZE} or
         *            {@code PREFERRED_SIZE}
         * @param max the maximum size or one of {@code DEFAULT_SIZE} or
         *            {@code PREFERRED_SIZE}
         * @return this {@code Group}
         */
        public SequentialGroup addComponent(boolean useAsBaseline,
                Component component, int min, int pref, int max) {
            super.addComponent(component, min, pref, max);
            if (useAsBaseline) {
                baselineSpring = springs.get(springs.size() - 1);
            }
            return this;
        }

        /**
         * {@inheritDoc}
         */
        public SequentialGroup addGap(int size) {
            return (SequentialGroup)super.addGap(size);
        }

        /**
         * {@inheritDoc}
         */
        public SequentialGroup addGap(int min, int pref, int max) {
            return (SequentialGroup)super.addGap(min, pref, max);
        }

        /**
         * Adds an element representing the preferred gap between two
         * components. The element created to represent the gap is not
         * resizable.
         *
         * @param comp1 the first component
         * @param comp2 the second component
         * @param type the type of gap; one of the constants defined by
         *        {@code LayoutStyle}
         * @return this {@code SequentialGroup}
         * @throws IllegalArgumentException if {@code type}, {@code comp1} or
         *         {@code comp2} is {@code null}
         * @see LayoutStyle
         */
        public SequentialGroup addPreferredGap(JComponent comp1,
                JComponent comp2, ComponentPlacement type) {
            return addPreferredGap(comp1, comp2, type, DEFAULT_SIZE,
                    PREFERRED_SIZE);
        }

        /**
         * Adds an element representing the preferred gap between two
         * components.
         *
         * @param comp1 the first component
         * @param comp2 the second component
         * @param type the type of gap
         * @param pref the preferred size of the grap; one of
         *        {@code DEFAULT_SIZE} or a value &gt;= 0
         * @param max the maximum size of the gap; one of
         *        {@code DEFAULT_SIZE}, {@code PREFERRED_SIZE}
         *        or a value &gt;= 0
         * @return this {@code SequentialGroup}
         * @throws IllegalArgumentException if {@code type}, {@code comp1} or
         *         {@code comp2} is {@code null}
         * @see LayoutStyle
         */
        public SequentialGroup addPreferredGap(JComponent comp1,
                JComponent comp2, ComponentPlacement type, int pref,
                int max) {
            if (type == null) {
                throw new IllegalArgumentException("Type must be non-null");
            }
            if (comp1 == null || comp2 == null) {
                throw new IllegalArgumentException(
                        "Components must be non-null");
            }
            checkPreferredGapValues(pref, max);
            return (SequentialGroup)addSpring(new PreferredGapSpring(
                    comp1, comp2, type, pref, max));
        }

        /**
         * Adds an element representing the preferred gap between the
         * nearest components.  During layout, neighboring
         * components are found, and the size of the added gap is set
         * based on the preferred gap between the components.  If no
         * neighboring components are found the gap has a size of {@code 0}.
         * <p>
         * The element created to represent the gap is not
         * resizable.
         *
         * @param type the type of gap; one of
         *        {@code LayoutStyle.ComponentPlacement.RELATED} or
         *        {@code LayoutStyle.ComponentPlacement.UNRELATED}
         * @return this {@code SequentialGroup}
         * @see LayoutStyle
         * @throws IllegalArgumentException if {@code type} is not one of
         *         {@code LayoutStyle.ComponentPlacement.RELATED} or
         *         {@code LayoutStyle.ComponentPlacement.UNRELATED}
         */
        public SequentialGroup addPreferredGap(ComponentPlacement type) {
            return addPreferredGap(type, DEFAULT_SIZE, DEFAULT_SIZE);
        }

        /**
         * Adds an element representing the preferred gap between the
         * nearest components.  During layout, neighboring
         * components are found, and the minimum of this
         * gap is set based on the size of the preferred gap between the
         * neighboring components.  If no neighboring components are found the
         * minimum size is set to 0.
         *
         * @param type the type of gap; one of
         *        {@code LayoutStyle.ComponentPlacement.RELATED} or
         *        {@code LayoutStyle.ComponentPlacement.UNRELATED}
         * @param pref the preferred size of the grap; one of
         *        {@code DEFAULT_SIZE} or a value &gt;= 0
         * @param max the maximum size of the gap; one of
         *        {@code DEFAULT_SIZE}, {@code PREFERRED_SIZE}
         *        or a value &gt;= 0
         * @return this {@code SequentialGroup}
         * @throws IllegalArgumentException if {@code type} is not one of
         *         {@code LayoutStyle.ComponentPlacement.RELATED} or
         *         {@code LayoutStyle.ComponentPlacement.UNRELATED}
         * @see LayoutStyle
         */
        public SequentialGroup addPreferredGap(ComponentPlacement type,
                int pref, int max) {
            if (type != ComponentPlacement.RELATED &&
                    type != ComponentPlacement.UNRELATED) {
                throw new IllegalArgumentException(
                        "Type must be one of " +
                        "LayoutStyle.ComponentPlacement.RELATED or " +
                        "LayoutStyle.ComponentPlacement.UNRELATED");
            }
            checkPreferredGapValues(pref, max);
            hasPreferredPaddingSprings = true;
            return (SequentialGroup)addSpring(new AutoPreferredGapSpring(
                    type, pref, max));
        }

        /**
         * Adds an element representing the preferred gap between an edge
         * the container and components that touch the border of the
         * container. This has no effect if the added gap does not
         * touch an edge of the parent container.
         * <p>
         * The element created to represent the gap is not
         * resizable.
         *
         * @return this {@code SequentialGroup}
         */
        public SequentialGroup addContainerGap() {
            return addContainerGap(DEFAULT_SIZE, DEFAULT_SIZE);
        }

        /**
         * Adds an element representing the preferred gap between one
         * edge of the container and the next or previous {@code
         * Component} with the specified size. This has no
         * effect if the next or previous element is not a {@code
         * Component} and does not touch one edge of the parent
         * container.
         *
         * @param pref the preferred size; one of {@code DEFAULT_SIZE} or a
         *              value &gt;= 0
         * @param max the maximum size; one of {@code DEFAULT_SIZE},
         *        {@code PREFERRED_SIZE} or a value &gt;= 0
         * @return this {@code SequentialGroup}
         */
        public SequentialGroup addContainerGap(int pref, int max) {
            if ((pref < 0 && pref != DEFAULT_SIZE) ||
                    (max < 0 && max != DEFAULT_SIZE && max != PREFERRED_SIZE)||
                    (pref >= 0 && max >= 0 && pref > max)) {
                throw new IllegalArgumentException(
                        "Pref and max must be either DEFAULT_VALUE " +
                        "or >= 0 and pref <= max");
            }
            hasPreferredPaddingSprings = true;
            return (SequentialGroup)addSpring(
                    new ContainerAutoPreferredGapSpring(pref, max));
        }

        int operator(int a, int b) {
            return constrain(a) + constrain(b);
        }

        void setValidSize(int axis, int origin, int size) {
            int pref = getPreferredSize(axis);
            if (size == pref) {
                // Layout at preferred size
                for (Spring spring : springs) {
                    int springPref = spring.getPreferredSize(axis);
                    spring.setSize(axis, origin, springPref);
                    origin += springPref;
                }
            } else if (springs.size() == 1) {
                Spring spring = getSpring(0);
                spring.setSize(axis, origin, Math.min(
                        Math.max(size, spring.getMinimumSize(axis)),
                        spring.getMaximumSize(axis)));
            } else if (springs.size() > 1) {
                // Adjust between min/pref
                setValidSizeNotPreferred(axis, origin, size);
            }
        }

        private void setValidSizeNotPreferred(int axis, int origin, int size) {
            int delta = size - getPreferredSize(axis);
            assert delta != 0;
            boolean useMin = (delta < 0);
            int springCount = springs.size();
            if (useMin) {
                delta *= -1;
            }

            // The following algorithm if used for resizing springs:
            // 1. Calculate the resizability of each spring (pref - min or
            //    max - pref) into a list.
            // 2. Sort the list in ascending order
            // 3. Iterate through each of the resizable Springs, attempting
            //    to give them (pref - size) / resizeCount
            // 4. For any Springs that can not accomodate that much space
            //    add the remainder back to the amount to distribute and
            //    recalculate how must space the remaining springs will get.
            // 5. Set the size of the springs.

            // First pass, sort the resizable springs into the List resizable
            List<SpringDelta> resizable = buildResizableList(axis, useMin);
            int resizableCount = resizable.size();

            if (resizableCount > 0) {
                // How much we would like to give each Spring.
                int sDelta = delta / resizableCount;
                // Remaining space.
                int slop = delta - sDelta * resizableCount;
                int[] sizes = new int[springCount];
                int sign = useMin ? -1 : 1;
                // Second pass, accumulate the resulting deltas (relative to
                // preferred) into sizes.
                for (int counter = 0; counter < resizableCount; counter++) {
                    SpringDelta springDelta = resizable.get(counter);
                    if ((counter + 1) == resizableCount) {
                        sDelta += slop;
                    }
                    springDelta.delta = Math.min(sDelta, springDelta.delta);
                    delta -= springDelta.delta;
                    if (springDelta.delta != sDelta && counter + 1 <
                            resizableCount) {
                        // Spring didn't take all the space, reset how much
                        // each spring will get.
                        sDelta = delta / (resizableCount - counter - 1);
                        slop = delta - sDelta * (resizableCount - counter - 1);
                    }
                    sizes[springDelta.index] = sign * springDelta.delta;
                }

                // And finally set the size of each spring
                for (int counter = 0; counter < springCount; counter++) {
                    Spring spring = getSpring(counter);
                    int sSize = spring.getPreferredSize(axis) + sizes[counter];
                    spring.setSize(axis, origin, sSize);
                    origin += sSize;
                }
            } else {
                // Nothing resizable, use the min or max of each of the
                // springs.
                for (int counter = 0; counter < springCount; counter++) {
                    Spring spring = getSpring(counter);
                    int sSize;
                    if (useMin) {
                        sSize = spring.getMinimumSize(axis);
                    } else {
                        sSize = spring.getMaximumSize(axis);
                    }
                    spring.setSize(axis, origin, sSize);
                    origin += sSize;
                }
            }
        }

        /**
         * Returns the sorted list of SpringDelta's for the current set of
         * Springs. The list is ordered based on the amount of flexibility of
         * the springs.
         */
        private List<SpringDelta> buildResizableList(int axis,
                boolean useMin) {
            // First pass, figure out what is resizable
            int size = springs.size();
            List<SpringDelta> sorted = new ArrayList<SpringDelta>(size);
            for (int counter = 0; counter < size; counter++) {
                Spring spring = getSpring(counter);
                int sDelta;
                if (useMin) {
                    sDelta = spring.getPreferredSize(axis) -
                            spring.getMinimumSize(axis);
                } else {
                    sDelta = spring.getMaximumSize(axis) -
                            spring.getPreferredSize(axis);
                }
                if (sDelta > 0) {
                    sorted.add(new SpringDelta(counter, sDelta));
                }
            }
            Collections.sort(sorted);
            return sorted;
        }

        private int indexOfNextNonZeroSpring(
                int index, boolean treatAutopaddingAsZeroSized) {
            while (index < springs.size()) {
                Spring spring = springs.get(index);
                if (!spring.willHaveZeroSize(treatAutopaddingAsZeroSized)) {
                    return index;
                }
                index++;
            }
            return index;
        }

        @Override
        void insertAutopadding(int axis,
                List<AutoPreferredGapSpring> leadingPadding,
                List<AutoPreferredGapSpring> trailingPadding,
                List<ComponentSpring> leading, List<ComponentSpring> trailing,
                boolean insert) {
            List<AutoPreferredGapSpring> newLeadingPadding =
                    new ArrayList<AutoPreferredGapSpring>(leadingPadding);
            List<AutoPreferredGapSpring> newTrailingPadding =
                    new ArrayList<AutoPreferredGapSpring>(1);
            List<ComponentSpring> newLeading =
                    new ArrayList<ComponentSpring>(leading);
            List<ComponentSpring> newTrailing = null;
            int counter = 0;
            // Warning, this must use springs.size, as it may change during the
            // loop.
            while (counter < springs.size()) {
                Spring spring = getSpring(counter);
                if (spring instanceof AutoPreferredGapSpring) {
                    if (newLeadingPadding.size() == 0) {
                        // Autopadding spring. Set the sources of the
                        // autopadding spring based on newLeading.
                        AutoPreferredGapSpring padding =
                            (AutoPreferredGapSpring)spring;
                        padding.setSources(newLeading);
                        newLeading.clear();
                        counter = indexOfNextNonZeroSpring(counter + 1, true);
                        if (counter == springs.size()) {
                            // Last spring in the list, add it to
                            // trailingPadding.
                            if (!(padding instanceof
                                  ContainerAutoPreferredGapSpring)) {
                                trailingPadding.add(padding);
                            }
                        } else {
                            newLeadingPadding.clear();
                            newLeadingPadding.add(padding);
                        }
                    } else {
                        counter = indexOfNextNonZeroSpring(counter + 1, true);
                    }
                } else {
                    // Not a padding spring
                    if (newLeading.size() > 0 && insert) {
                        // There's leading ComponentSprings, create an
                        // autopadding spring.
                        AutoPreferredGapSpring padding =
                                new AutoPreferredGapSpring();
                        // Force the newly created spring to be considered
                        // by NOT incrementing counter
                        springs.add(counter, padding);
                        continue;
                    }
                    if (spring instanceof ComponentSpring) {
                        // Spring is a Component, make it the target of any
                        // leading AutopaddingSpring.
                        ComponentSpring cSpring = (ComponentSpring)spring;
                        if (!cSpring.isVisible()) {
                            counter++;
                            continue;
                        }
                        for (AutoPreferredGapSpring gapSpring : newLeadingPadding) {
                            gapSpring.addTarget(cSpring, axis);
                        }
                        newLeading.clear();
                        newLeadingPadding.clear();
                        counter = indexOfNextNonZeroSpring(counter + 1, false);
                        if (counter == springs.size()) {
                            // Last Spring, add it to trailing
                            trailing.add(cSpring);
                        } else {
                            // Not that last Spring, add it to leading
                            newLeading.add(cSpring);
                        }
                    } else if (spring instanceof Group) {
                        // Forward call to child Group
                        if (newTrailing == null) {
                            newTrailing = new ArrayList<ComponentSpring>(1);
                        } else {
                            newTrailing.clear();
                        }
                        newTrailingPadding.clear();
                        ((Group)spring).insertAutopadding(axis,
                                newLeadingPadding, newTrailingPadding,
                                newLeading, newTrailing, insert);
                        newLeading.clear();
                        newLeadingPadding.clear();
                        counter = indexOfNextNonZeroSpring(
                                    counter + 1, (newTrailing.size() == 0));
                        if (counter == springs.size()) {
                            trailing.addAll(newTrailing);
                            trailingPadding.addAll(newTrailingPadding);
                        } else {
                            newLeading.addAll(newTrailing);
                            newLeadingPadding.addAll(newTrailingPadding);
                        }
                    } else {
                        // Gap
                        newLeadingPadding.clear();
                        newLeading.clear();
                        counter++;
                    }
                }
            }
        }

        int getBaseline() {
            if (baselineSpring != null) {
                int baseline = baselineSpring.getBaseline();
                if (baseline >= 0) {
                    int size = 0;
                    for (Spring spring : springs) {
                        if (spring == baselineSpring) {
                            return size + baseline;
                        } else {
                            size += spring.getPreferredSize(VERTICAL);
                        }
                    }
                }
            }
            return -1;
        }

        BaselineResizeBehavior getBaselineResizeBehavior() {
            if (isResizable(VERTICAL)) {
                if (!baselineSpring.isResizable(VERTICAL)) {
                    // Spring to use for baseline isn't resizable. In this case
                    // baseline resize behavior can be determined based on how
                    // preceeding springs resize.
                    boolean leadingResizable = false;
                    for (Spring spring : springs) {
                        if (spring == baselineSpring) {
                            break;
                        } else if (spring.isResizable(VERTICAL)) {
                            leadingResizable = true;
                            break;
                        }
                    }
                    boolean trailingResizable = false;
                    for (int i = springs.size() - 1; i >= 0; i--) {
                        Spring spring = springs.get(i);
                        if (spring == baselineSpring) {
                            break;
                        }
                        if (spring.isResizable(VERTICAL)) {
                            trailingResizable = true;
                            break;
                        }
                    }
                    if (leadingResizable && !trailingResizable) {
                        return BaselineResizeBehavior.CONSTANT_DESCENT;
                    } else if (!leadingResizable && trailingResizable) {
                        return BaselineResizeBehavior.CONSTANT_ASCENT;
                    }
                    // If we get here, both leading and trailing springs are
                    // resizable. Fall through to OTHER.
                } else {
                    BaselineResizeBehavior brb = baselineSpring.getBaselineResizeBehavior();
                    if (brb == BaselineResizeBehavior.CONSTANT_ASCENT) {
                        for (Spring spring : springs) {
                            if (spring == baselineSpring) {
                                return BaselineResizeBehavior.CONSTANT_ASCENT;
                            }
                            if (spring.isResizable(VERTICAL)) {
                                return BaselineResizeBehavior.OTHER;
                            }
                        }
                    } else if (brb == BaselineResizeBehavior.CONSTANT_DESCENT) {
                        for (int i = springs.size() - 1; i >= 0; i--) {
                            Spring spring = springs.get(i);
                            if (spring == baselineSpring) {
                                return BaselineResizeBehavior.CONSTANT_DESCENT;
                            }
                            if (spring.isResizable(VERTICAL)) {
                                return BaselineResizeBehavior.OTHER;
                            }
                        }
                    }
                }
                return BaselineResizeBehavior.OTHER;
            }
            // Not resizable, treat as constant_ascent
            return BaselineResizeBehavior.CONSTANT_ASCENT;
        }

        private void checkPreferredGapValues(int pref, int max) {
            if ((pref < 0 && pref != DEFAULT_SIZE && pref != PREFERRED_SIZE) ||
                    (max < 0 && max != DEFAULT_SIZE && max != PREFERRED_SIZE)||
                    (pref >= 0 && max >= 0 && pref > max)) {
                throw new IllegalArgumentException(
                        "Pref and max must be either DEFAULT_SIZE, " +
                        "PREFERRED_SIZE, or >= 0 and pref <= max");
            }
        }
    }


    /**
     * Used by SequentialGroup in calculating resizability of springs.
     */
    private static final class SpringDelta implements Comparable<SpringDelta> {
        // Original index.
        public final int index;
        // Delta, one of pref - min or max - pref.
        public int delta;

        public SpringDelta(int index, int delta) {
            this.index = index;
            this.delta = delta;
        }

        public int compareTo(SpringDelta o) {
            return delta - o.delta;
        }

        public String toString() {
            return super.toString() + "[index=" + index + ", delta=" +
                    delta + "]";
        }
    }


    /**
     * A {@code Group} that aligns and sizes it's children.
     * {@code ParallelGroup} aligns it's children in
     * four possible ways: along the baseline, centered, anchored to the
     * leading edge, or anchored to the trailing edge.
     * <h3>Baseline</h3>
     * A {@code ParallelGroup} that aligns it's children along the
     * baseline must first decide where the baseline is
     * anchored. The baseline can either be anchored to the top, or
     * anchored to the bottom of the group. That is, the distance between the
     * baseline and the beginning of the group can be a constant
     * distance, or the distance between the end of the group and the
     * baseline can be a constant distance. The possible choices
     * correspond to the {@code BaselineResizeBehavior} constants
     * {@link
     * java.awt.Component.BaselineResizeBehavior#CONSTANT_ASCENT CONSTANT_ASCENT} and
     * {@link
     * java.awt.Component.BaselineResizeBehavior#CONSTANT_DESCENT CONSTANT_DESCENT}.
     * <p>
     * The baseline anchor may be explicitly specified by the
     * {@code createBaselineGroup} method, or determined based on the elements.
     * If not explicitly specified, the baseline will be anchored to
     * the bottom if all the elements with a baseline, and that are
     * aligned to the baseline, have a baseline resize behavior of
     * {@code CONSTANT_DESCENT}; otherwise the baseline is anchored to the top
     * of the group.
     * <p>
     * Elements aligned to the baseline are resizable if they have have
     * a baseline resize behavior of {@code CONSTANT_ASCENT} or
     * {@code CONSTANT_DESCENT}. Elements with a baseline resize
     * behavior of {@code OTHER} or {@code CENTER_OFFSET} are not resizable.
     * <p>
     * The baseline is calculated based on the preferred height of each
     * of the elements that have a baseline. The baseline is
     * calculated using the following algorithm:
     * {@code max(maxNonBaselineHeight, maxAscent + maxDescent)}, where the
     * {@code maxNonBaselineHeight} is the maximum height of all elements
     * that do not have a baseline, or are not aligned along the baseline.
     * {@code maxAscent} is the maximum ascent (baseline) of all elements that
     * have a baseline and are aligned along the baseline.
     * {@code maxDescent} is the maximum descent (preferred height - baseline)
     * of all elements that have a baseline and are aligned along the baseline.
     * <p>
     * A {@code ParallelGroup} that aligns it's elements along the baseline
     * is only useful along the vertical axis. If you create a
     * baseline group and use it along the horizontal axis an
     * {@code IllegalStateException} is thrown when you ask
     * {@code GroupLayout} for the minimum, preferred or maximum size or
     * attempt to layout the components.
     * <p>
     * Elements that are not aligned to the baseline and smaller than the size
     * of the {@code ParallelGroup} are positioned in one of three
     * ways: centered, anchored to the leading edge, or anchored to the
     * trailing edge.
     *
     * <h3>Non-baseline {@code ParallelGroup}</h3>
     * {@code ParallelGroup}s created with an alignment other than
     * {@code BASELINE} align elements that are smaller than the size
     * of the group in one of three ways: centered, anchored to the
     * leading edge, or anchored to the trailing edge.
     * <p>
     * The leading edge is based on the axis and {@code
     * ComponentOrientation}.  For the vertical axis the top edge is
     * always the leading edge, and the bottom edge is always the
     * trailing edge. When the {@code ComponentOrientation} is {@code
     * LEFT_TO_RIGHT}, the leading edge is the left edge and the
     * trailing edge the right edge. A {@code ComponentOrientation} of
     * {@code RIGHT_TO_LEFT} flips the left and right edges. Child
     * elements are aligned based on the specified alignment the
     * element was added with. If you do not specify an alignment, the
     * alignment specified for the {@code ParallelGroup} is used.
     * <p>
     * To align elements along the baseline you {@code createBaselineGroup},
     * or {@code createParallelGroup} with an alignment of {@code BASELINE}.
     * If the group was not created with a baseline alignment, and you attempt
     * to add an element specifying a baseline alignment, an
     * {@code IllegalArgumentException} is thrown.
     *
     * @see #createParallelGroup()
     * @see #createBaselineGroup(boolean,boolean)
     * @since 1.6
     */
    public class ParallelGroup extends Group {
        // How children are layed out.
        private final Alignment childAlignment;
        // Whether or not we're resizable.
        private final boolean resizable;

        ParallelGroup(Alignment childAlignment, boolean resizable) {
            this.childAlignment = childAlignment;
            this.resizable = resizable;
        }

        /**
         * {@inheritDoc}
         */
        public ParallelGroup addGroup(Group group) {
            return (ParallelGroup)super.addGroup(group);
        }

        /**
         * {@inheritDoc}
         */
        public ParallelGroup addComponent(Component component) {
            return (ParallelGroup)super.addComponent(component);
        }

        /**
         * {@inheritDoc}
         */
        public ParallelGroup addComponent(Component component, int min, int pref,
                int max) {
            return (ParallelGroup)super.addComponent(component, min, pref, max);
        }

        /**
         * {@inheritDoc}
         */
        public ParallelGroup addGap(int pref) {
            return (ParallelGroup)super.addGap(pref);
        }

        /**
         * {@inheritDoc}
         */
        public ParallelGroup addGap(int min, int pref, int max) {
            return (ParallelGroup)super.addGap(min, pref, max);
        }

        /**
         * Adds a {@code Group} to this {@code ParallelGroup} with the
         * specified alignment. If the child is smaller than the
         * {@code Group} it is aligned based on the specified
         * alignment.
         *
         * @param alignment the alignment
         * @param group the {@code Group} to add
         * @return this {@code ParallelGroup}
         * @throws IllegalArgumentException if {@code alignment} is
         *         {@code null}
         */
        public ParallelGroup addGroup(Alignment alignment, Group group) {
            checkChildAlignment(alignment);
            group.setAlignment(alignment);
            return (ParallelGroup)addSpring(group);
        }

        /**
         * Adds a {@code Component} to this {@code ParallelGroup} with
         * the specified alignment.
         *
         * @param alignment the alignment
         * @param component the {@code Component} to add
         * @return this {@code Group}
         * @throws IllegalArgumentException if {@code alignment} is
         *         {@code null}
         */
        public ParallelGroup addComponent(Component component,
                Alignment alignment) {
            return addComponent(component, alignment, DEFAULT_SIZE, DEFAULT_SIZE,
                    DEFAULT_SIZE);
        }

        /**
         * Adds a {@code Component} to this {@code ParallelGroup} with the
         * specified alignment and size.
         *
         * @param alignment the alignment
         * @param component the {@code Component} to add
         * @param min the minimum size
         * @param pref the preferred size
         * @param max the maximum size
         * @throws IllegalArgumentException if {@code alignment} is
         *         {@code null}
         * @return this {@code Group}
         */
        public ParallelGroup addComponent(Component component,
                Alignment alignment, int min, int pref, int max) {
            checkChildAlignment(alignment);
            ComponentSpring spring = new ComponentSpring(component,
                    min, pref, max);
            spring.setAlignment(alignment);
            return (ParallelGroup)addSpring(spring);
        }

        boolean isResizable() {
            return resizable;
        }

        int operator(int a, int b) {
            return Math.max(a, b);
        }

        int calculateMinimumSize(int axis) {
            if (!isResizable()) {
                return getPreferredSize(axis);
            }
            return super.calculateMinimumSize(axis);
        }

        int calculateMaximumSize(int axis) {
            if (!isResizable()) {
                return getPreferredSize(axis);
            }
            return super.calculateMaximumSize(axis);
        }

        void setValidSize(int axis, int origin, int size) {
            for (Spring spring : springs) {
                setChildSize(spring, axis, origin, size);
            }
        }

        void setChildSize(Spring spring, int axis, int origin, int size) {
            Alignment alignment = spring.getAlignment();
            int springSize = Math.min(
                    Math.max(spring.getMinimumSize(axis), size),
                    spring.getMaximumSize(axis));
            if (alignment == null) {
                alignment = childAlignment;
            }
            switch (alignment) {
                case TRAILING:
                    spring.setSize(axis, origin + size - springSize,
                            springSize);
                    break;
                case CENTER:
                    spring.setSize(axis, origin +
                            (size - springSize) / 2,springSize);
                    break;
                default: // LEADING, or BASELINE
                    spring.setSize(axis, origin, springSize);
                    break;
            }
        }

        @Override
        void insertAutopadding(int axis,
                List<AutoPreferredGapSpring> leadingPadding,
                List<AutoPreferredGapSpring> trailingPadding,
                List<ComponentSpring> leading, List<ComponentSpring> trailing,
                boolean insert) {
            for (Spring spring : springs) {
                if (spring instanceof ComponentSpring) {
                    if (((ComponentSpring)spring).isVisible()) {
                        for (AutoPreferredGapSpring gapSpring :
                                 leadingPadding) {
                            gapSpring.addTarget((ComponentSpring)spring, axis);
                        }
                        trailing.add((ComponentSpring)spring);
                    }
                } else if (spring instanceof Group) {
                    ((Group)spring).insertAutopadding(axis, leadingPadding,
                            trailingPadding, leading, trailing, insert);
                } else if (spring instanceof AutoPreferredGapSpring) {
                    ((AutoPreferredGapSpring)spring).setSources(leading);
                    trailingPadding.add((AutoPreferredGapSpring)spring);
                }
            }
        }

        private void checkChildAlignment(Alignment alignment) {
            checkChildAlignment(alignment, (this instanceof BaselineGroup));
        }

        private void checkChildAlignment(Alignment alignment,
                boolean allowsBaseline) {
            if (alignment == null) {
                throw new IllegalArgumentException("Alignment must be non-null");
            }
            if (!allowsBaseline && alignment == Alignment.BASELINE) {
                throw new IllegalArgumentException("Alignment must be one of:" +
                        "LEADING, TRAILING or CENTER");
            }
        }
    }


    /**
     * An extension of {@code ParallelGroup} that aligns its
     * constituent {@code Spring}s along the baseline.
     */
    private class BaselineGroup extends ParallelGroup {
        // Whether or not all child springs have a baseline
        private boolean allSpringsHaveBaseline;

        // max(spring.getBaseline()) of all springs aligned along the baseline
        // that have a baseline
        private int prefAscent;

        // max(spring.getPreferredSize().height - spring.getBaseline()) of all
        // springs aligned along the baseline that have a baseline
        private int prefDescent;

        // Whether baselineAnchoredToTop was explicitly set
        private boolean baselineAnchorSet;

        // Whether the baseline is anchored to the top or the bottom.
        // If anchored to the top the baseline is always at prefAscent,
        // otherwise the baseline is at (height - prefDescent)
        private boolean baselineAnchoredToTop;

        // Whether or not the baseline has been calculated.
        private boolean calcedBaseline;

        BaselineGroup(boolean resizable) {
            super(Alignment.LEADING, resizable);
            prefAscent = prefDescent = -1;
            calcedBaseline = false;
        }

        BaselineGroup(boolean resizable, boolean baselineAnchoredToTop) {
            this(resizable);
            this.baselineAnchoredToTop = baselineAnchoredToTop;
            baselineAnchorSet = true;
        }

        void unset() {
            super.unset();
            prefAscent = prefDescent = -1;
            calcedBaseline = false;
        }

        void setValidSize(int axis, int origin, int size) {
            checkAxis(axis);
            if (prefAscent == -1) {
                super.setValidSize(axis, origin, size);
            } else {
                // do baseline layout
                baselineLayout(origin, size);
            }
        }

        int calculateSize(int axis, int type) {
            checkAxis(axis);
            if (!calcedBaseline) {
                calculateBaselineAndResizeBehavior();
            }
            if (type == MIN_SIZE) {
                return calculateMinSize();
            }
            if (type == MAX_SIZE) {
                return calculateMaxSize();
            }
            if (allSpringsHaveBaseline) {
                return prefAscent + prefDescent;
            }
            return Math.max(prefAscent + prefDescent,
                    super.calculateSize(axis, type));
        }

        private void calculateBaselineAndResizeBehavior() {
            // calculate baseline
            prefAscent = 0;
            prefDescent = 0;
            int baselineSpringCount = 0;
            BaselineResizeBehavior resizeBehavior = null;
            for (Spring spring : springs) {
                if (spring.getAlignment() == null ||
                        spring.getAlignment() == Alignment.BASELINE) {
                    int baseline = spring.getBaseline();
                    if (baseline >= 0) {
                        if (spring.isResizable(VERTICAL)) {
                            BaselineResizeBehavior brb = spring.
                                    getBaselineResizeBehavior();
                            if (resizeBehavior == null) {
                                resizeBehavior = brb;
                            } else if (brb != resizeBehavior) {
                                resizeBehavior = BaselineResizeBehavior.
                                        CONSTANT_ASCENT;
                            }
                        }
                        prefAscent = Math.max(prefAscent, baseline);
                        prefDescent = Math.max(prefDescent, spring.
                                getPreferredSize(VERTICAL) - baseline);
                        baselineSpringCount++;
                    }
                }
            }
            if (!baselineAnchorSet) {
                if (resizeBehavior == BaselineResizeBehavior.CONSTANT_DESCENT){
                    this.baselineAnchoredToTop = false;
                } else {
                    this.baselineAnchoredToTop = true;
                }
            }
            allSpringsHaveBaseline = (baselineSpringCount == springs.size());
            calcedBaseline = true;
        }

        private int calculateMaxSize() {
            int maxAscent = prefAscent;
            int maxDescent = prefDescent;
            int nonBaselineMax = 0;
            for (Spring spring : springs) {
                int baseline;
                int springMax = spring.getMaximumSize(VERTICAL);
                if ((spring.getAlignment() == null ||
                        spring.getAlignment() == Alignment.BASELINE) &&
                        (baseline = spring.getBaseline()) >= 0) {
                    int springPref = spring.getPreferredSize(VERTICAL);
                    if (springPref != springMax) {
                        switch (spring.getBaselineResizeBehavior()) {
                            case CONSTANT_ASCENT:
                                if (baselineAnchoredToTop) {
                                    maxDescent = Math.max(maxDescent,
                                            springMax - baseline);
                                }
                                break;
                            case CONSTANT_DESCENT:
                                if (!baselineAnchoredToTop) {
                                    maxAscent = Math.max(maxAscent,
                                            springMax - springPref + baseline);
                                }
                                break;
                            default: // CENTER_OFFSET and OTHER, not resizable
                                break;
                        }
                    }
                } else {
                    // Not aligned along the baseline, or no baseline.
                    nonBaselineMax = Math.max(nonBaselineMax, springMax);
                }
            }
            return Math.max(nonBaselineMax, maxAscent + maxDescent);
        }

        private int calculateMinSize() {
            int minAscent = 0;
            int minDescent = 0;
            int nonBaselineMin = 0;
            if (baselineAnchoredToTop) {
                minAscent = prefAscent;
            } else {
                minDescent = prefDescent;
            }
            for (Spring spring : springs) {
                int springMin = spring.getMinimumSize(VERTICAL);
                int baseline;
                if ((spring.getAlignment() == null ||
                        spring.getAlignment() == Alignment.BASELINE) &&
                        (baseline = spring.getBaseline()) >= 0) {
                    int springPref = spring.getPreferredSize(VERTICAL);
                    BaselineResizeBehavior brb = spring.
                            getBaselineResizeBehavior();
                    switch (brb) {
                        case CONSTANT_ASCENT:
                            if (baselineAnchoredToTop) {
                                minDescent = Math.max(springMin - baseline,
                                        minDescent);
                            } else {
                                minAscent = Math.max(baseline, minAscent);
                            }
                            break;
                        case CONSTANT_DESCENT:
                            if (!baselineAnchoredToTop) {
                                minAscent = Math.max(
                                        baseline - (springPref - springMin),
                                        minAscent);
                            } else {
                                minDescent = Math.max(springPref - baseline,
                                        minDescent);
                            }
                            break;
                        default:
                            // CENTER_OFFSET and OTHER are !resizable, use
                            // the preferred size.
                            minAscent = Math.max(baseline, minAscent);
                            minDescent = Math.max(springPref - baseline,
                                    minDescent);
                            break;
                    }
                } else {
                    // Not aligned along the baseline, or no baseline.
                    nonBaselineMin = Math.max(nonBaselineMin, springMin);
                }
            }
            return Math.max(nonBaselineMin, minAscent + minDescent);
        }

        /**
         * Lays out springs that have a baseline along the baseline.  All
         * others are centered.
         */
        private void baselineLayout(int origin, int size) {
            int ascent;
            int descent;
            if (baselineAnchoredToTop) {
                ascent = prefAscent;
                descent = size - ascent;
            } else {
                ascent = size - prefDescent;
                descent = prefDescent;
            }
            for (Spring spring : springs) {
                Alignment alignment = spring.getAlignment();
                if (alignment == null || alignment == Alignment.BASELINE) {
                    int baseline = spring.getBaseline();
                    if (baseline >= 0) {
                        int springMax = spring.getMaximumSize(VERTICAL);
                        int springPref = spring.getPreferredSize(VERTICAL);
                        int height = springPref;
                        int y;
                        switch(spring.getBaselineResizeBehavior()) {
                            case CONSTANT_ASCENT:
                                y = origin + ascent - baseline;
                                height = Math.min(descent, springMax -
                                        baseline) + baseline;
                                break;
                            case CONSTANT_DESCENT:
                                height = Math.min(ascent, springMax -
                                        springPref + baseline) +
                                        (springPref - baseline);
                                y = origin + ascent +
                                        (springPref - baseline) - height;
                                break;
                            default: // CENTER_OFFSET & OTHER, not resizable
                                y = origin + ascent - baseline;
                                break;
                        }
                        spring.setSize(VERTICAL, y, height);
                    } else {
                        setChildSize(spring, VERTICAL, origin, size);
                    }
                } else {
                    setChildSize(spring, VERTICAL, origin, size);
                }
            }
        }

        int getBaseline() {
            if (springs.size() > 1) {
                // Force the baseline to be calculated
                getPreferredSize(VERTICAL);
                return prefAscent;
            } else if (springs.size() == 1) {
                return springs.get(0).getBaseline();
            }
            return -1;
        }

        BaselineResizeBehavior getBaselineResizeBehavior() {
            if (springs.size() == 1) {
                return springs.get(0).getBaselineResizeBehavior();
            }
            if (baselineAnchoredToTop) {
                return BaselineResizeBehavior.CONSTANT_ASCENT;
            }
            return BaselineResizeBehavior.CONSTANT_DESCENT;
        }

        // If the axis is VERTICAL, throws an IllegalStateException
        private void checkAxis(int axis) {
            if (axis == HORIZONTAL) {
                throw new IllegalStateException(
                        "Baseline must be used along vertical axis");
            }
        }
    }


    private final class ComponentSpring extends Spring {
        private Component component;
        private int origin;

        // min/pref/max are either a value >= 0 or one of
        // DEFAULT_SIZE or PREFERRED_SIZE
        private final int min;
        private final int pref;
        private final int max;

        // Baseline for the component, computed as necessary.
        private int baseline = -1;

        // Whether or not the size has been requested yet.
        private boolean installed;

        private ComponentSpring(Component component, int min, int pref,
                int max) {
            this.component = component;
            if (component == null) {
                throw new IllegalArgumentException(
                        "Component must be non-null");
            }

            checkSize(min, pref, max, true);

            this.min = min;
            this.max = max;
            this.pref = pref;

            // getComponentInfo makes sure component is a child of the
            // Container GroupLayout is the LayoutManager for.
            getComponentInfo(component);
        }

        int calculateMinimumSize(int axis) {
            if (isLinked(axis)) {
                return getLinkSize(axis, MIN_SIZE);
            }
            return calculateNonlinkedMinimumSize(axis);
        }

        int calculatePreferredSize(int axis) {
            if (isLinked(axis)) {
                return getLinkSize(axis, PREF_SIZE);
            }
            int min = getMinimumSize(axis);
            int pref = calculateNonlinkedPreferredSize(axis);
            int max = getMaximumSize(axis);
            return Math.min(max, Math.max(min, pref));
        }

        int calculateMaximumSize(int axis) {
            if (isLinked(axis)) {
                return getLinkSize(axis, MAX_SIZE);
            }
            return Math.max(getMinimumSize(axis),
                    calculateNonlinkedMaximumSize(axis));
        }

        boolean isVisible() {
            return getComponentInfo(getComponent()).isVisible();
        }

        int calculateNonlinkedMinimumSize(int axis) {
            if (!isVisible()) {
                return 0;
            }
            if (min >= 0) {
                return min;
            }
            if (min == PREFERRED_SIZE) {
                return calculateNonlinkedPreferredSize(axis);
            }
            assert (min == DEFAULT_SIZE);
            return getSizeAlongAxis(axis, component.getMinimumSize());
        }

        int calculateNonlinkedPreferredSize(int axis) {
            if (!isVisible()) {
                return 0;
            }
            if (pref >= 0) {
                return pref;
            }
            assert (pref == DEFAULT_SIZE || pref == PREFERRED_SIZE);
            return getSizeAlongAxis(axis, component.getPreferredSize());
        }

        int calculateNonlinkedMaximumSize(int axis) {
            if (!isVisible()) {
                return 0;
            }
            if (max >= 0) {
                return max;
            }
            if (max == PREFERRED_SIZE) {
                return calculateNonlinkedPreferredSize(axis);
            }
            assert (max == DEFAULT_SIZE);
            return getSizeAlongAxis(axis, component.getMaximumSize());
        }

        private int getSizeAlongAxis(int axis, Dimension size) {
            return (axis == HORIZONTAL) ? size.width : size.height;
        }

        private int getLinkSize(int axis, int type) {
            if (!isVisible()) {
                return 0;
            }
            ComponentInfo ci = getComponentInfo(component);
            return ci.getLinkSize(axis, type);
        }

        void setSize(int axis, int origin, int size) {
            super.setSize(axis, origin, size);
            this.origin = origin;
            if (size == UNSET) {
                baseline = -1;
            }
        }

        int getOrigin() {
            return origin;
        }

        void setComponent(Component component) {
            this.component = component;
        }

        Component getComponent() {
            return component;
        }

        int getBaseline() {
            if (baseline == -1) {
                Spring horizontalSpring = getComponentInfo(component).
                        horizontalSpring;
                int width = horizontalSpring.getPreferredSize(HORIZONTAL);
                int height = getPreferredSize(VERTICAL);
                if (width > 0 && height > 0) {
                    baseline = component.getBaseline(width, height);
                }
            }
            return baseline;
        }

        BaselineResizeBehavior getBaselineResizeBehavior() {
            return getComponent().getBaselineResizeBehavior();
        }

        private boolean isLinked(int axis) {
            return getComponentInfo(component).isLinked(axis);
        }

        void installIfNecessary(int axis) {
            if (!installed) {
                installed = true;
                if (axis == HORIZONTAL) {
                    getComponentInfo(component).horizontalSpring = this;
                } else {
                    getComponentInfo(component).verticalSpring = this;
                }
            }
        }

        @Override
        boolean willHaveZeroSize(boolean treatAutopaddingAsZeroSized) {
            return !isVisible();
        }
    }


    /**
     * Spring representing the preferred distance between two components.
     */
    private class PreferredGapSpring extends Spring {
        private final JComponent source;
        private final JComponent target;
        private final ComponentPlacement type;
        private final int pref;
        private final int max;

        PreferredGapSpring(JComponent source, JComponent target,
                ComponentPlacement type, int pref, int max) {
            this.source = source;
            this.target = target;
            this.type = type;
            this.pref = pref;
            this.max = max;
        }

        int calculateMinimumSize(int axis) {
            return getPadding(axis);
        }

        int calculatePreferredSize(int axis) {
            if (pref == DEFAULT_SIZE || pref == PREFERRED_SIZE) {
                return getMinimumSize(axis);
            }
            int min = getMinimumSize(axis);
            int max = getMaximumSize(axis);
            return Math.min(max, Math.max(min, pref));
        }

        int calculateMaximumSize(int axis) {
            if (max == PREFERRED_SIZE || max == DEFAULT_SIZE) {
                return getPadding(axis);
            }
            return Math.max(getMinimumSize(axis), max);
        }

        private int getPadding(int axis) {
            int position;
            if (axis == HORIZONTAL) {
                position = SwingConstants.EAST;
            } else {
                position = SwingConstants.SOUTH;
            }
            return getLayoutStyle0().getPreferredGap(source,
                    target, type, position, host);
        }

        @Override
        boolean willHaveZeroSize(boolean treatAutopaddingAsZeroSized) {
            return false;
        }
    }


    /**
     * Spring represented a certain amount of space.
     */
    private class GapSpring extends Spring {
        private final int min;
        private final int pref;
        private final int max;

        GapSpring(int min, int pref, int max) {
            checkSize(min, pref, max, false);
            this.min = min;
            this.pref = pref;
            this.max = max;
        }

        int calculateMinimumSize(int axis) {
            if (min == PREFERRED_SIZE) {
                return getPreferredSize(axis);
            }
            return min;
        }

        int calculatePreferredSize(int axis) {
            return pref;
        }

        int calculateMaximumSize(int axis) {
            if (max == PREFERRED_SIZE) {
                return getPreferredSize(axis);
            }
            return max;
        }

        @Override
        boolean willHaveZeroSize(boolean treatAutopaddingAsZeroSized) {
            return false;
        }
    }


    /**
     * Spring reprensenting the distance between any number of sources and
     * targets.  The targets and sources are computed during layout.  An
     * instance of this can either be dynamically created when
     * autocreatePadding is true, or explicitly created by the developer.
     */
    private class AutoPreferredGapSpring extends Spring {
        List<ComponentSpring> sources;
        ComponentSpring source;
        private List<AutoPreferredGapMatch> matches;
        int size;
        int lastSize;
        private final int pref;
        private final int max;
        // Type of gap
        private ComponentPlacement type;
        private boolean userCreated;

        private AutoPreferredGapSpring() {
            this.pref = PREFERRED_SIZE;
            this.max = PREFERRED_SIZE;
            this.type = ComponentPlacement.RELATED;
        }

        AutoPreferredGapSpring(int pref, int max) {
            this.pref = pref;
            this.max = max;
        }

        AutoPreferredGapSpring(ComponentPlacement type, int pref, int max) {
            this.type = type;
            this.pref = pref;
            this.max = max;
            this.userCreated = true;
        }

        public void setSource(ComponentSpring source) {
            this.source = source;
        }

        public void setSources(List<ComponentSpring> sources) {
            this.sources = new ArrayList<ComponentSpring>(sources);
        }

        public void setUserCreated(boolean userCreated) {
            this.userCreated = userCreated;
        }

        public boolean getUserCreated() {
            return userCreated;
        }

        void unset() {
            lastSize = getSize();
            super.unset();
            size = 0;
        }

        public void reset() {
            size = 0;
            sources = null;
            source = null;
            matches = null;
        }

        public void calculatePadding(int axis) {
            size = UNSET;
            int maxPadding = UNSET;
            if (matches != null) {
                LayoutStyle p = getLayoutStyle0();
                int position;
                if (axis == HORIZONTAL) {
                    if (isLeftToRight()) {
                        position = SwingConstants.EAST;
                    } else {
                        position = SwingConstants.WEST;
                    }
                } else {
                    position = SwingConstants.SOUTH;
                }
                for (int i = matches.size() - 1; i >= 0; i--) {
                    AutoPreferredGapMatch match = matches.get(i);
                    maxPadding = Math.max(maxPadding,
                            calculatePadding(p, position, match.source,
                            match.target));
                }
            }
            if (size == UNSET) {
                size = 0;
            }
            if (maxPadding == UNSET) {
                maxPadding = 0;
            }
            if (lastSize != UNSET) {
                size += Math.min(maxPadding, lastSize);
            }
        }

        private int calculatePadding(LayoutStyle p, int position,
                ComponentSpring source,
                ComponentSpring target) {
            int delta = target.getOrigin() - (source.getOrigin() +
                    source.getSize());
            if (delta >= 0) {
                int padding;
                if ((source.getComponent() instanceof JComponent) &&
                        (target.getComponent() instanceof JComponent)) {
                    padding = p.getPreferredGap(
                            (JComponent)source.getComponent(),
                            (JComponent)target.getComponent(), type, position,
                            host);
                } else {
                    padding = 10;
                }
                if (padding > delta) {
                    size = Math.max(size, padding - delta);
                }
                return padding;
            }
            return 0;
        }

        public void addTarget(ComponentSpring spring, int axis) {
            int oAxis = (axis == HORIZONTAL) ? VERTICAL : HORIZONTAL;
            if (source != null) {
                if (areParallelSiblings(source.getComponent(),
                        spring.getComponent(), oAxis)) {
                    addValidTarget(source, spring);
                }
            } else {
                Component component = spring.getComponent();
                for (int counter = sources.size() - 1; counter >= 0;
                         counter--){
                    ComponentSpring source = sources.get(counter);
                    if (areParallelSiblings(source.getComponent(),
                            component, oAxis)) {
                        addValidTarget(source, spring);
                    }
                }
            }
        }

        private void addValidTarget(ComponentSpring source,
                ComponentSpring target) {
            if (matches == null) {
                matches = new ArrayList<AutoPreferredGapMatch>(1);
            }
            matches.add(new AutoPreferredGapMatch(source, target));
        }

        int calculateMinimumSize(int axis) {
            return size;
        }

        int calculatePreferredSize(int axis) {
            if (pref == PREFERRED_SIZE || pref == DEFAULT_SIZE) {
                return size;
            }
            return Math.max(size, pref);
        }

        int calculateMaximumSize(int axis) {
            if (max >= 0) {
                return Math.max(getPreferredSize(axis), max);
            }
            return size;
        }

        String getMatchDescription() {
            return (matches == null) ? "" : matches.toString();
        }

        public String toString() {
            return super.toString() + getMatchDescription();
        }

        @Override
        boolean willHaveZeroSize(boolean treatAutopaddingAsZeroSized) {
            return treatAutopaddingAsZeroSized;
        }
    }


    /**
     * Represents two springs that should have autopadding inserted between
     * them.
     */
    private final static class AutoPreferredGapMatch {
        public final ComponentSpring source;
        public final ComponentSpring target;

        AutoPreferredGapMatch(ComponentSpring source, ComponentSpring target) {
            this.source = source;
            this.target = target;
        }

        private String toString(ComponentSpring spring) {
            return spring.getComponent().getName();
        }

        public String toString() {
            return "[" + toString(source) + "-" + toString(target) + "]";
        }
    }


    /**
     * An extension of AutopaddingSpring used for container level padding.
     */
    private class ContainerAutoPreferredGapSpring extends
            AutoPreferredGapSpring {
        private List<ComponentSpring> targets;

        ContainerAutoPreferredGapSpring() {
            super();
            setUserCreated(true);
        }

        ContainerAutoPreferredGapSpring(int pref, int max) {
            super(pref, max);
            setUserCreated(true);
        }

        public void addTarget(ComponentSpring spring, int axis) {
            if (targets == null) {
                targets = new ArrayList<ComponentSpring>(1);
            }
            targets.add(spring);
        }

        public void calculatePadding(int axis) {
            LayoutStyle p = getLayoutStyle0();
            int maxPadding = 0;
            int position;
            size = 0;
            if (targets != null) {
                // Leading
                if (axis == HORIZONTAL) {
                    if (isLeftToRight()) {
                        position = SwingConstants.WEST;
                    } else {
                        position = SwingConstants.EAST;
                    }
                } else {
                    position = SwingConstants.SOUTH;
                }
                for (int i = targets.size() - 1; i >= 0; i--) {
                    ComponentSpring targetSpring = targets.get(i);
                    int padding = 10;
                    if (targetSpring.getComponent() instanceof JComponent) {
                        padding = p.getContainerGap(
                                (JComponent)targetSpring.getComponent(),
                                position, host);
                        maxPadding = Math.max(padding, maxPadding);
                        padding -= targetSpring.getOrigin();
                    } else {
                        maxPadding = Math.max(padding, maxPadding);
                    }
                    size = Math.max(size, padding);
                }
            } else {
                // Trailing
                if (axis == HORIZONTAL) {
                    if (isLeftToRight()) {
                        position = SwingConstants.EAST;
                    } else {
                        position = SwingConstants.WEST;
                    }
                } else {
                    position = SwingConstants.SOUTH;
                }
                if (sources != null) {
                    for (int i = sources.size() - 1; i >= 0; i--) {
                        ComponentSpring sourceSpring = sources.get(i);
                        maxPadding = Math.max(maxPadding,
                                updateSize(p, sourceSpring, position));
                    }
                } else if (source != null) {
                    maxPadding = updateSize(p, source, position);
                }
            }
            if (lastSize != UNSET) {
                size += Math.min(maxPadding, lastSize);
            }
        }

        private int updateSize(LayoutStyle p, ComponentSpring sourceSpring,
                int position) {
            int padding = 10;
            if (sourceSpring.getComponent() instanceof JComponent) {
                padding = p.getContainerGap(
                        (JComponent)sourceSpring.getComponent(), position,
                        host);
            }
            int delta = Math.max(0, getParent().getSize() -
                    sourceSpring.getSize() - sourceSpring.getOrigin());
            size = Math.max(size, padding - delta);
            return padding;
        }

        String getMatchDescription() {
            if (targets != null) {
                return "leading: " + targets.toString();
            }
            if (sources != null) {
                return "trailing: " + sources.toString();
            }
            return "--";
        }
    }


    // LinkInfo contains the set of ComponentInfosthat are linked along a
    // particular axis.
    private static class LinkInfo {
        private final int axis;
        private final List<ComponentInfo> linked;
        private int size;

        LinkInfo(int axis) {
            linked = new ArrayList<ComponentInfo>();
            size = UNSET;
            this.axis = axis;
        }

        public void add(ComponentInfo child) {
            LinkInfo childMaster = child.getLinkInfo(axis, false);
            if (childMaster == null) {
                linked.add(child);
                child.setLinkInfo(axis, this);
            } else if (childMaster != this) {
                linked.addAll(childMaster.linked);
                for (ComponentInfo childInfo : childMaster.linked) {
                    childInfo.setLinkInfo(axis, this);
                }
            }
            clearCachedSize();
        }

        public void remove(ComponentInfo info) {
            linked.remove(info);
            info.setLinkInfo(axis, null);
            if (linked.size() == 1) {
                linked.get(0).setLinkInfo(axis, null);
            }
            clearCachedSize();
        }

        public void clearCachedSize() {
            size = UNSET;
        }

        public int getSize(int axis) {
            if (size == UNSET) {
                size = calculateLinkedSize(axis);
            }
            return size;
        }

        private int calculateLinkedSize(int axis) {
            int size = 0;
            for (ComponentInfo info : linked) {
                ComponentSpring spring;
                if (axis == HORIZONTAL) {
                    spring = info.horizontalSpring;
                } else {
                    assert (axis == VERTICAL);
                    spring = info.verticalSpring;
                }
                size = Math.max(size,
                        spring.calculateNonlinkedPreferredSize(axis));
            }
            return size;
        }
    }

    /**
     * Tracks the horizontal/vertical Springs for a Component.
     * This class is also used to handle Springs that have their sizes
     * linked.
     */
    private class ComponentInfo {
        // Component being layed out
        private Component component;

        ComponentSpring horizontalSpring;
        ComponentSpring verticalSpring;

        // If the component's size is linked to other components, the
        // horizontalMaster and/or verticalMaster reference the group of
        // linked components.
        private LinkInfo horizontalMaster;
        private LinkInfo verticalMaster;

        private boolean visible;
        private Boolean honorsVisibility;

        ComponentInfo(Component component) {
            this.component = component;
            updateVisibility();
        }

        public void dispose() {
            // Remove horizontal/vertical springs
            removeSpring(horizontalSpring);
            horizontalSpring = null;
            removeSpring(verticalSpring);
            verticalSpring = null;
            // Clean up links
            if (horizontalMaster != null) {
                horizontalMaster.remove(this);
            }
            if (verticalMaster != null) {
                verticalMaster.remove(this);
            }
        }

        void setHonorsVisibility(Boolean honorsVisibility) {
            this.honorsVisibility = honorsVisibility;
        }

        private void removeSpring(Spring spring) {
            if (spring != null) {
                ((Group)spring.getParent()).springs.remove(spring);
            }
        }

        public boolean isVisible() {
            return visible;
        }

        /**
         * Updates the cached visibility.
         *
         * @return true if the visibility changed
         */
        boolean updateVisibility() {
            boolean honorsVisibility;
            if (this.honorsVisibility == null) {
                honorsVisibility = GroupLayout.this.getHonorsVisibility();
            } else {
                honorsVisibility = this.honorsVisibility;
            }
            boolean newVisible = (honorsVisibility) ?
                component.isVisible() : true;
            if (visible != newVisible) {
                visible = newVisible;
                return true;
            }
            return false;
        }

        public void setBounds(Insets insets, int parentWidth, boolean ltr) {
            int x = horizontalSpring.getOrigin();
            int w = horizontalSpring.getSize();
            int y = verticalSpring.getOrigin();
            int h = verticalSpring.getSize();

            if (!ltr) {
                x = parentWidth - x - w;
            }
            component.setBounds(x + insets.left, y + insets.top, w, h);
        }

        public void setComponent(Component component) {
            this.component = component;
            if (horizontalSpring != null) {
                horizontalSpring.setComponent(component);
            }
            if (verticalSpring != null) {
                verticalSpring.setComponent(component);
            }
        }

        public Component getComponent() {
            return component;
        }

        /**
         * Returns true if this component has its size linked to
         * other components.
         */
        public boolean isLinked(int axis) {
            if (axis == HORIZONTAL) {
                return horizontalMaster != null;
            }
            assert (axis == VERTICAL);
            return (verticalMaster != null);
        }

        private void setLinkInfo(int axis, LinkInfo linkInfo) {
            if (axis == HORIZONTAL) {
                horizontalMaster = linkInfo;
            } else {
                assert (axis == VERTICAL);
                verticalMaster = linkInfo;
            }
        }

        public LinkInfo getLinkInfo(int axis) {
            return getLinkInfo(axis, true);
        }

        private LinkInfo getLinkInfo(int axis, boolean create) {
            if (axis == HORIZONTAL) {
                if (horizontalMaster == null && create) {
                    // horizontalMaster field is directly set by adding
                    // us to the LinkInfo.
                    new LinkInfo(HORIZONTAL).add(this);
                }
                return horizontalMaster;
            } else {
                assert (axis == VERTICAL);
                if (verticalMaster == null && create) {
                    // verticalMaster field is directly set by adding
                    // us to the LinkInfo.
                    new LinkInfo(VERTICAL).add(this);
                }
                return verticalMaster;
            }
        }

        public void clearCachedSize() {
            if (horizontalMaster != null) {
                horizontalMaster.clearCachedSize();
            }
            if (verticalMaster != null) {
                verticalMaster.clearCachedSize();
            }
        }

        int getLinkSize(int axis, int type) {
            if (axis == HORIZONTAL) {
                return horizontalMaster.getSize(axis);
            } else {
                assert (axis == VERTICAL);
                return verticalMaster.getSize(axis);
            }
        }

    }
}
