(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); } Lines 2001–2500 of 3745. Previous lines Load more
(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); }