* 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 = 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 < 0 and * not one of {@code PREFERRED_SIZE} or {@code DEFAULT_SIZE}, or * the following is not met (for specific values): {@code min} * <= {@code pref} <= {@code max}. * <p> * Similarly any methods that take a {@code Component} throw a * {@code IllegalArgumentException} if passed {@code null} and any methods * that take a {@code Group} throw an {@code NullPointerException} 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}. *Lines 1001–1500 of 3745. Previous lines Load more
* 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 = 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 < 0 and * not one of {@code PREFERRED_SIZE} or {@code DEFAULT_SIZE}, or * the following is not met (for specific values): {@code min} * <= {@code pref} <= {@code max}. * <p> * Similarly any methods that take a {@code Component} throw a * {@code IllegalArgumentException} if passed {@code null} and any methods * that take a {@code Group} throw an {@code NullPointerException} 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}. *