GroupLayout.java
上传用户:haobig99
上传日期:2022-06-15
资源大小:369k
文件大小:130k
源码类别:

J2ME

开发平台:

Java

  1.                 throw new IllegalArgumentException(
  2.                         "Pref and max must be either DEFAULT_SIZE, " +
  3.                         "PREFERRED_SIZE, or >= 0 and pref <= max");
  4.             }
  5.             hasPreferredPaddingSprings = true;
  6.             return (SequentialGroup)addSpring(new AutopaddingSpring(
  7.                                        type, pref, max));
  8.         }
  9.         
  10.         /**
  11.          * Adds an element representing the preferred gap between one edge
  12.          * of the container and the next/previous Component.  This will have
  13.          * no effect if the next/previous element is not a Component and does
  14.          * not touch one edge of the parent container. 
  15.          *
  16.          * @return this <code>SequentialGroup</code>.
  17.          */
  18.         public SequentialGroup addContainerGap() {
  19.             return addContainerGap(DEFAULT_SIZE, DEFAULT_SIZE);
  20.         }
  21.         
  22.         /**
  23.          * Adds an element representing the preferred gap between one edge
  24.          * of the container and the next/previous Component.  This will have
  25.          * no effect if the next/previous element is not a Component and does
  26.          * not touch one edge of the parent container. 
  27.          *
  28.          * @param pref the preferred size; one of DEFAULT_SIZE or a value > 0
  29.          * @param max the maximum size; one of DEFAULT_SIZE, PREFERRED_SIZE
  30.          *        or a value > 0.
  31.          * @throws IllegalArgumentException if pref/max is
  32.          *         != DEFAULT_SIZE and < 0, or pref > max
  33.          * @return this <code>SequentialGroup</code>
  34.          */
  35.         public SequentialGroup addContainerGap(int pref, int max) {
  36.             if ((pref < 0 && pref != DEFAULT_SIZE) ||
  37.                     (max < 0 && max != DEFAULT_SIZE && max != PREFERRED_SIZE) ||
  38.                     (pref >= 0 && max >= 0 && pref > max)) {
  39.                 throw new IllegalArgumentException(
  40.                         "Pref and max must be either DEFAULT_VALUE or >= 0 and pref <= max");
  41.             }
  42.             hasPreferredPaddingSprings = true;
  43.             return (SequentialGroup)addSpring(
  44.                     new ContainerAutopaddingSpring(pref, max));
  45.         }
  46.         
  47.         int operator(int a, int b) {
  48.             return constrain(a) + constrain(b);
  49.         }
  50.         
  51.         void setValidSize(int axis, int origin, int size) {
  52.             int pref = getPreferredSize(axis);
  53.             if (size == pref) {
  54.                 for (int counter = 0, max = springs.size(); counter < max;
  55.                 counter++) {
  56.                     Spring spring = getSpring(counter);
  57.                     int springPref = spring.getPreferredSize(axis);
  58.                     spring.setSize(axis, origin, springPref);
  59.                     origin += springPref;
  60.                 }
  61.             } else if (springs.size() == 1) {
  62.                 Spring spring = getSpring(0);
  63.                 spring.setSize(axis, origin, Math.min(
  64.                         Math.max(size, spring.getMinimumSize(axis)),
  65.                         spring.getMaximumSize(axis)));
  66.             } else if (springs.size() > 1) {
  67.                 // Adjust between min/pref
  68.                 setValidSizeNotPreferred(axis, origin, size);
  69.             }
  70.         }
  71.         
  72.         private void setValidSizeNotPreferred(int axis, int origin, int size) {
  73.             int delta = size - getPreferredSize(axis);
  74.             //assert delta != 0;
  75.             boolean useMin = (delta < 0);
  76.             int springCount = springs.size();
  77.             if (useMin) {
  78.                 delta *= -1;
  79.             }
  80.             
  81.             // The following algorithm if used for resizing springs:
  82.             // 1. Calculate the resizability of each spring (pref - min or
  83.             //    max - pref) into a list.
  84.             // 2. Sort the list in ascending order
  85.             // 3. Iterate through each of the resizable Springs, attempting
  86.             //    to give them (pref - size) / resizeCount
  87.             // 4. For any Springs that can not accommodate that much space
  88.             //    add the remainder back to the amount to distribute and
  89.             //    recalculate how must space the remaining springs will get.
  90.             // 5. Set the size of the springs.
  91.             // First pass, sort the resizable springs into resizable
  92.             Vector resizable = buildResizableList(axis, useMin);
  93.             int resizableCount = resizable.size();
  94.             
  95.             if (resizableCount > 0) {
  96.                 // How much we would like to give each Spring.
  97.                 int sDelta = delta / resizableCount;
  98.                 // Remaining space.
  99.                 int slop = delta - sDelta * resizableCount;
  100.                 int[] sizes = new int[springCount];
  101.                 int sign = useMin ? -1 : 1;
  102.                 // Second pass, accumulate the resulting deltas (relative to
  103.                 // preferred) into sizes.
  104.                 for (int counter = 0; counter < resizableCount; counter++) {
  105.                     SpringDelta springDelta = (SpringDelta)resizable.
  106.                             elementAt(counter);
  107.                     if ((counter + 1) == resizableCount) {
  108.                         sDelta += slop;
  109.                     }
  110.                     springDelta.delta = Math.min(sDelta, springDelta.delta);
  111.                     delta -= springDelta.delta;
  112.                     if (springDelta.delta != sDelta && counter + 1 <
  113.                             resizableCount) {
  114.                         // Spring didn't take all the space, reset how much
  115.                         // each spring will get.
  116.                         sDelta = delta / (resizableCount - counter - 1);
  117.                         slop = delta - sDelta * (resizableCount - counter - 1);
  118.                     }
  119.                     sizes[springDelta.index] = sign * springDelta.delta;
  120.                 }
  121.                 
  122.                 // And finally set the size of each spring
  123.                 for (int counter = 0; counter < springCount; counter++) {
  124.                     Spring spring = getSpring(counter);
  125.                     int sSize = spring.getPreferredSize(axis) + sizes[counter];
  126.                     spring.setSize(axis, origin, sSize);
  127.                     origin += sSize;
  128.                 }
  129.             } else {
  130.                 // Nothing resizable, use the min or max of each of the
  131.                 // springs.
  132.                 for (int counter = 0; counter < springCount; counter++) {
  133.                     Spring spring = getSpring(counter);
  134.                     int sSize;
  135.                     if (useMin) {
  136.                         sSize = spring.getMinimumSize(axis);
  137.                     } else {
  138.                         sSize = spring.getMaximumSize(axis);
  139.                     }
  140.                     spring.setSize(axis, origin, sSize);
  141.                     origin += sSize;
  142.                 }
  143.             }
  144.         }
  145.         
  146.         /**
  147.          * Returns the sorted list of SpringDelta's for the current set of
  148.          * Springs.
  149.          */
  150.         private Vector buildResizableList(int axis, boolean useMin) {
  151.             // First pass, figure out what is resizable
  152.             int size = springs.size();
  153.             Vector sorted = new Vector(size);
  154.             for (int counter = 0; counter < size; counter++) {
  155.                 Spring spring = getSpring(counter);
  156.                 int sDelta;
  157.                 if (useMin) {
  158.                     sDelta = spring.getPreferredSize(axis) -
  159.                             spring.getMinimumSize(axis);
  160.                 } else {
  161.                     sDelta = spring.getMaximumSize(axis) -
  162.                             spring.getPreferredSize(axis);
  163.                 }
  164.                 if (sDelta > 0) {
  165.                     sorted.addElement(new SpringDelta(counter, sDelta));
  166.                 }
  167.             }
  168.             //size = sorted.size();
  169.             
  170.             // insertion sort for a relatively small vector
  171.     for (int i = 0 ; i < 0 ; i++) {
  172. for (int j = i; j > 0 && ((SpringDelta)sorted.elementAt(j-1)).compareTo(sorted.elementAt(j)) > 0 ; j--) {
  173.                     Object a = sorted.elementAt(j-1);
  174.                     Object b = sorted.elementAt(j);
  175.     sorted.setElementAt(b, j - 1);
  176.     sorted.setElementAt(a, j);
  177.                 }
  178.             }
  179.             return sorted;
  180.         }
  181.         
  182.         private int indexOfNextNonZeroSpring(int index, boolean treatAutopaddingAsZeroSized) {
  183.             while (index < springs.size()) {
  184.                 Spring spring = (Spring)springs.elementAt(index);
  185.                 if (!((Spring)spring).willHaveZeroSize(treatAutopaddingAsZeroSized)) {
  186.                     return index;
  187.                 }
  188.                 index++;
  189.             }
  190.             return index;
  191.         }
  192.         void insertAutopadding(int axis, Vector leadingPadding,
  193.                 Vector trailingPadding, Vector leading, Vector trailing,
  194.                 boolean insert) {
  195.             Vector newLeadingPadding = create(leadingPadding);
  196.             Vector newTrailingPadding = new Vector(1);
  197.             Vector newLeading = create(leading);
  198.             Vector newTrailing = null;
  199.             int counter = 0;
  200.             // Warning, this must use springs.size, as it may change during the
  201.             // loop.
  202.             while (counter < springs.size()) {
  203.                 Spring spring = getSpring(counter);
  204.                 if (spring instanceof AutopaddingSpring) {
  205.                     if (newLeadingPadding.size() == 0) {
  206.                         AutopaddingSpring padding = (AutopaddingSpring)spring;
  207.                         padding.setSources(newLeading);
  208.                         newLeading.removeAllElements();
  209.                         int nextCounter = indexOfNextNonZeroSpring(counter + 1, true);
  210.                         if (nextCounter == springs.size()) {
  211.                             // Last spring in the list, add it to trailingPadding.
  212.                             if (!(padding instanceof ContainerAutopaddingSpring)) {
  213.                                 trailingPadding.addElement(padding);
  214.                             }
  215.                         } else {
  216.                             newLeadingPadding.removeAllElements();
  217.                             newLeadingPadding.addElement(padding);
  218.                         }
  219.                         counter = nextCounter;
  220.                     } else {
  221.                         counter = indexOfNextNonZeroSpring(counter + 1, true);
  222.                     }
  223.                 } else {
  224.                     // Not a padding spring
  225.                     if (newLeading.size() > 0 && insert) {
  226.                         // There's leading ComponentSprings, create an
  227.                         // autopadding spring.
  228.                         AutopaddingSpring padding = new AutopaddingSpring();
  229.                         // Force the newly created spring to be considered
  230.                         // by NOT incrementing counter
  231.                         springs.insertElementAt(padding, counter);
  232.                         continue;
  233.                     }
  234.                     if (spring instanceof ComponentSpring) {
  235.                         // Spring is a Component, make it the target of any
  236.                         // leading AutopaddingSpring.
  237.                         ComponentSpring cSpring = (ComponentSpring)spring;
  238.                         if (!cSpring.isVisible()) {
  239.                             counter++;
  240.                             continue;
  241.                         }
  242.                         for (int i = 0; i < newLeadingPadding.size(); i++) {
  243.                             ((AutopaddingSpring)newLeadingPadding.elementAt(i)).
  244.                                     addTarget(cSpring, axis);
  245.                         }
  246.                         newLeading.removeAllElements();
  247.                         newLeadingPadding.removeAllElements();
  248.                         int nextCounter = indexOfNextNonZeroSpring(counter + 1, false);
  249.                         if (nextCounter == springs.size()) {
  250.                             // Last Spring, add it to trailing
  251.                             trailing.addElement(cSpring);
  252.                         } else {
  253.                             // Not that last Spring, add it to leading
  254.                             newLeading.addElement(cSpring);
  255.                         }
  256.                         counter = nextCounter;
  257.                     } else if (spring instanceof Group) {
  258.                         // Forward call to child Group
  259.                         if (newTrailing == null) {
  260.                             newTrailing = new Vector(1);
  261.                         } else {
  262.                             newTrailing.removeAllElements();
  263.                         }
  264.                         newTrailingPadding.removeAllElements();
  265.                         ((Group)spring).insertAutopadding(axis, newLeadingPadding,
  266.                                 newTrailingPadding, newLeading, newTrailing,
  267.                                 insert);
  268.                         newLeading.removeAllElements();
  269.                         newLeadingPadding.removeAllElements();
  270.                         int nextCounter = indexOfNextNonZeroSpring(counter + 1, 
  271.                                 newTrailing.size() == 0);
  272.                         if (nextCounter == springs.size()) {
  273.                             addAll(trailing, newTrailing);
  274.                             addAll(trailingPadding, newTrailingPadding);
  275.                         } else {
  276.                             addAll(newLeading, newTrailing);
  277.                             addAll(newLeadingPadding, newTrailingPadding);
  278.                         }
  279.                         counter = nextCounter;
  280.                     } else {
  281.                         // Gap
  282.                         newLeadingPadding.removeAllElements();
  283.                         newLeading.removeAllElements();
  284.                         counter++;
  285.                     }
  286.                 }
  287.             }
  288.         }
  289.         
  290.         int getBaseline() {
  291.             if (baselineSpring != null) {
  292.                 int baseline = baselineSpring.getBaseline();
  293.                 if (baseline >= 0) {
  294.                     int size = 0;
  295.                     for (int i = 0, max = springs.size(); i < max; i++) {
  296.                         Spring spring = getSpring(i);
  297.                         if (spring == baselineSpring) {
  298.                             return size + baseline;
  299.                         } else {
  300.                             size += spring.getPreferredSize(VERTICAL);
  301.                         }
  302.                     }
  303.                 }
  304.             }
  305.             return -1;
  306.         }
  307.         
  308.         int getBaselineResizeBehavior() {
  309.             if (isResizable(VERTICAL)) {
  310.                 if (!baselineSpring.isResizable(VERTICAL)) {
  311.                     // Spring to use for baseline isn't resizable. In this case
  312.                     // baseline resize behavior can be determined based on how
  313.                     // preceeding springs resize.
  314.                     boolean leadingResizable = false;
  315.                     for (int i = 0, max = springs.size(); i < max; i++) {
  316.                         Spring spring = getSpring(i);
  317.                         if (spring == baselineSpring) {
  318.                             break;
  319.                         } else if (spring.isResizable(VERTICAL)) {
  320.                             leadingResizable = true;
  321.                             break;
  322.                         }
  323.                     }
  324.                     boolean trailingResizable = false;
  325.                     for (int i = springs.size() - 1; i >= 0; i--) {
  326.                         Spring spring = getSpring(i);
  327.                         if (spring == baselineSpring) {
  328.                             break;
  329.                         }
  330.                         if (spring.isResizable(VERTICAL)) {
  331.                             trailingResizable = true;
  332.                             break;
  333.                         }
  334.                     }
  335.                     if (leadingResizable && !trailingResizable) {
  336.                         return Component.BRB_CONSTANT_DESCENT;
  337.                     } else if (!leadingResizable && trailingResizable) {
  338.                         return Component.BRB_CONSTANT_ASCENT;
  339.                     }
  340.                     // If we get here, both leading and trailing springs are
  341.                     // resizable. Fall through to OTHER.
  342.                 } else {
  343.                     int brb = baselineSpring.getBaselineResizeBehavior();
  344.                     if (brb == Component.BRB_CONSTANT_ASCENT) {
  345.                         for (int i = 0, max = springs.size(); i < max; i++) {
  346.                             Spring spring = getSpring(i);
  347.                             if (spring == baselineSpring) {
  348.                                 return Component.BRB_CONSTANT_ASCENT;
  349.                             }
  350.                             if (spring.isResizable(VERTICAL)) {
  351.                                 return Component.BRB_OTHER;
  352.                             }
  353.                         }
  354.                     } else if (brb == Component.BRB_CONSTANT_DESCENT) {
  355.                         for (int i = springs.size() - 1; i >= 0; i--) {
  356.                             Spring spring = getSpring(i);
  357.                             if (spring == baselineSpring) {
  358.                                 return Component.BRB_CONSTANT_DESCENT;
  359.                             }
  360.                             if (spring.isResizable(VERTICAL)) {
  361.                                 return Component.BRB_OTHER;
  362.                             }
  363.                         }
  364.                     }
  365.                 }
  366.                 return Component.BRB_OTHER;
  367.             }
  368.             // Not resizable, treat as constant_ascent
  369.             return Component.BRB_CONSTANT_ASCENT;
  370.         }
  371.     }
  372.     
  373.     
  374.     /**
  375.      * Used in figuring out how much space to give resizable springs.
  376.      */
  377.     private static final class SpringDelta  {
  378.         // Original index.
  379.         public final int index;
  380.         // Delta, one of pref - min or max - pref.
  381.         public int delta;
  382.         
  383.         public SpringDelta(int index, int delta) {
  384.             this.index = index;
  385.             this.delta = delta;
  386.         }
  387.         
  388.         public int compareTo(Object o) {
  389.             return delta - ((SpringDelta)o).delta;
  390.         }
  391.         
  392.         public String toString() {
  393.             return super.toString() + "[index=" + index + ", delta=" +
  394.                     delta + "]";
  395.         }
  396.     }
  397.     
  398.     
  399.     /**
  400.      * A <code>Group</code> that lays out its elements on top of each
  401.      * other.  If a child element is smaller than the provided space it
  402.      * is aligned based on the alignment of the child (if specified) or
  403.      * on the alignment of the ParallelGroup.
  404.      *
  405.      * @see #createParallelGroup()
  406.      */
  407.     public class ParallelGroup extends Group {
  408.         // How children are layed out.
  409.         private final int childAlignment;
  410.         // Whether or not we're resizable.
  411.         private final boolean resizable;
  412.         
  413.         ParallelGroup(int childAlignment, boolean resizable) {
  414.             this.childAlignment = childAlignment;
  415.             this.resizable = resizable;
  416.         }
  417.         
  418.         /**
  419.          * Adds the specified <code>Group</code>.
  420.          *
  421.          * @param group the Group to add
  422.          * @return this Group
  423.          */
  424.         public ParallelGroup add(Group group) {
  425.             return (ParallelGroup)addSpring(group);
  426.         }
  427.         
  428.         /**
  429.          * Adds the specified Component.  If the Component's min/max
  430.          * are different from its pref than the component will be resizable.
  431.          *
  432.          * @param component the Component to add
  433.          * @return this <code>ParallelGroup</code>
  434.          */
  435.         public ParallelGroup add(Component component) {
  436.             return add(component, DEFAULT_SIZE, DEFAULT_SIZE, DEFAULT_SIZE);
  437.         }
  438.         
  439.         /**
  440.          * Adds the specified <code>Component</code>.  Min, pref and max
  441.          * can be absolute values, or they can be one of
  442.          * <code>DEFAULT_SIZE</code> or <code>PREFERRED_SIZE</code>.  For
  443.          * example, the following:
  444.          * <pre>
  445.          *   add(component, PREFERRED_SIZE, PREFERRED_SIZE, 1000);
  446.          * </pre>
  447.          * Forces a max of 1000, with the min and preferred equalling that
  448.          * of the preferred size of <code>component</code>.
  449.          *
  450.          * @param component the Component to add
  451.          * @param min the minimum size
  452.          * @param pref the preferred size
  453.          * @param max the maximum size
  454.          * @throws IllegalArgumentException if min, pref or max are
  455.          *         not positive and not one of PREFERRED_SIZE or DEFAULT_SIZE.
  456.          * @return this <code>SequentialGroup</code>
  457.          */
  458.         public ParallelGroup add(Component component, int min, int pref,
  459.                 int max) {
  460.             return (ParallelGroup)addSpring(new ComponentSpring(
  461.                     component, min, pref, max));
  462.         }
  463.         
  464.         /**
  465.          * Adds a rigid gap.
  466.          *
  467.          * @param pref the size of the gap
  468.          * @throws IllegalArgumentException if min < 0 or pref < 0 or max < 0
  469.          *         or the following is not meant min <= pref <= max.
  470.          * @return this <code>ParallelGroup</code>
  471.          */
  472.         public ParallelGroup add(int pref) {
  473.             return add(pref, pref, pref);
  474.         }
  475.         
  476.         /**
  477.          * Adds a gap with the specified size.
  478.          *
  479.          * @param min the minimum size of the gap
  480.          * @param pref the preferred size of the gap
  481.          * @param max the maximum size of the gap
  482.          * @throws IllegalArgumentException if min < 0 or pref < 0 or max < 0
  483.          *         or the following is not meant min <= pref <= max.
  484.          * @return this <code>ParallelGroup</code>
  485.          */
  486.         public ParallelGroup add(int min, int pref, int max) {
  487.             return (ParallelGroup)addSpring(new GapSpring(min, pref, max));
  488.         }
  489.         
  490.         /**
  491.          * Adds the specified <code>Group</code> as a child of this group.
  492.          *
  493.          * @param alignment the alignment of the Group.
  494.          * @param group the Group to add
  495.          * @return this <code>ParallelGroup</code>
  496.          * @throws IllegalArgumentException if alignment is not one of
  497.          *         <code>LEADING</code>, <code>TRAILING</code> or
  498.          *         <code>CENTER</code>
  499.          */
  500.         public ParallelGroup add(int alignment, Group group) {
  501.             checkChildAlignment(alignment);
  502.             group.setAlignment(alignment);
  503.             return (ParallelGroup)addSpring(group);
  504.         }
  505.         
  506.         /**
  507.          * Adds the specified Component.  If the Component's min/max
  508.          * are different from its pref than the component will be resizable.
  509.          *
  510.          * @param alignment the alignment for the component
  511.          * @param component the Component to add
  512.          * @return this <code>Group</code>
  513.          * @throws IllegalArgumentException if alignment is not one of
  514.          *         <code>LEADING</code>, <code>TRAILING</code> or
  515.          *         <code>CENTER</code>
  516.          */
  517.         public ParallelGroup add(int alignment, Component component) {
  518.             return add(alignment, component, DEFAULT_SIZE, DEFAULT_SIZE,
  519.                     DEFAULT_SIZE);
  520.         }
  521.         
  522.         /**
  523.          * Adds the specified <code>Component</code>.  Min, pref and max
  524.          * can be absolute values, or they can be one of
  525.          * <code>DEFAULT_SIZE</code> or <code>PREFERRED_SIZE</code>.  For
  526.          * example, the following:
  527.          * <pre>
  528.          *   add(component, PREFERRED_SIZE, PREFERRED_SIZE, 1000);
  529.          * </pre>
  530.          * Forces a max of 1000, with the min and preferred equalling that
  531.          * of the preferred size of <code>component</code>.
  532.          *
  533.          * @param alignment the alignment for the component.
  534.          * @param component the Component to add
  535.          * @param min the minimum size
  536.          * @param pref the preferred size
  537.          * @param max the maximum size
  538.          * @throws IllegalArgumentException if min, pref or max are
  539.          *         not positive and not one of PREFERRED_SIZE or DEFAULT_SIZE.
  540.          * @return this <code>Group</code>
  541.          */
  542.         public ParallelGroup add(int alignment, Component component, int min,
  543.                 int pref, int max) {
  544.             checkChildAlignment(alignment);
  545.             ComponentSpring spring = new ComponentSpring(component,
  546.                     min, pref, max);
  547.             spring.setAlignment(alignment);
  548.             return (ParallelGroup)addSpring(spring);
  549.         }
  550.         
  551.         boolean isResizable() {
  552.             return resizable;
  553.         }
  554.         
  555.         int operator(int a, int b) {
  556.             return Math.max(a, b);
  557.         }
  558.         
  559.         int calculateMinimumSize(int axis) {
  560.             if (!isResizable()) {
  561.                 return getPreferredSize(axis);
  562.             }
  563.             return super.calculateMinimumSize(axis);
  564.         }
  565.         
  566.         int calculateMaximumSize(int axis) {
  567.             if (!isResizable()) {
  568.                 return getPreferredSize(axis);
  569.             }
  570.             return super.calculateMaximumSize(axis);
  571.         }
  572.         
  573.         void setValidSize(int axis, int origin, int size) {
  574.             for (int i = 0, max = springs.size(); i < max; i++) {
  575.                 setChildSize(getSpring(i), axis, origin, size);
  576.             }
  577.         }
  578.         
  579.         void setChildSize(Spring spring, int axis, int origin, int size) {
  580.             int alignment = spring.getAlignment();
  581.             int springSize = Math.min(
  582.                     Math.max(spring.getMinimumSize(axis), size),
  583.                     spring.getMaximumSize(axis));
  584.             if (alignment == NO_ALIGNMENT) {
  585.                 alignment = childAlignment;
  586.             }
  587.             switch (alignment) {
  588.                 case TRAILING:
  589.                     spring.setSize(axis, origin + size - springSize,
  590.                             springSize);
  591.                     break;
  592.                 case CENTER:
  593.                     spring.setSize(axis, origin +
  594.                             (size - springSize) / 2,springSize);
  595.                     break;
  596.                 default: // LEADING, or BASELINE
  597.                     spring.setSize(axis, origin, springSize);
  598.                     break;
  599.             }
  600.         }
  601.         
  602.         void insertAutopadding(int axis, Vector leadingPadding,
  603.                 Vector trailingPadding, Vector leading, Vector trailing,
  604.                 boolean insert) {
  605.             for (int counter = 0, max = springs.size(); counter < max; counter++) {
  606.                 Spring spring = getSpring(counter);
  607.                 if (spring instanceof ComponentSpring) {
  608.                     if (((ComponentSpring)spring).isVisible()) {
  609.                         for (int i = 0; i < leadingPadding.size(); i++) {
  610.                             ((AutopaddingSpring)leadingPadding.elementAt(i)).addTarget(
  611.                                     (ComponentSpring)spring, axis);
  612.                         }
  613.                         trailing.addElement(spring);
  614.                     }
  615.                 } else if (spring instanceof Group) {
  616.                     ((Group)spring).insertAutopadding(axis, leadingPadding,
  617.                             trailingPadding, leading, trailing, insert);
  618.                 } else if (spring instanceof AutopaddingSpring) {
  619.                     ((AutopaddingSpring)spring).setSources(leading);
  620.                     trailingPadding.addElement(spring);
  621.                 }
  622.             }
  623.         }
  624.         private void checkChildAlignment(int alignment) {
  625.             boolean allowsBaseline = (this instanceof BaselineGroup);
  626.             if (!allowsBaseline && alignment == BASELINE) {
  627.                 throw new IllegalArgumentException("Alignment must be one of:" +
  628.                         "LEADING, TRAILING or CENTER");
  629.             }
  630.             if (alignment != CENTER && alignment != BASELINE &&
  631.                     alignment != LEADING && alignment != TRAILING) {
  632.                 throw new IllegalArgumentException("Alignment must be one of:" +
  633.                         "LEADING, TRAILING or CENTER");
  634.             }
  635.         }
  636.     }
  637.     
  638.     
  639.     /**
  640.      * An extension of <code>ParallelGroup</code> that aligns its
  641.      * constituent <code>Spring</code>s along the baseline.
  642.      */
  643.     private class BaselineGroup extends ParallelGroup {
  644.         // Whether or not all child springs have a baseline
  645.         private boolean allSpringsHaveBaseline;
  646.         // max(spring.getBaseline()) of all springs aligned along the baseline
  647.         // that have a baseline
  648.         private int prefAscent;
  649.         // max(spring.getPreferredSize().height - spring.getBaseline()) of all
  650.         // springs aligned along the baseline that have a baseline
  651.         private int prefDescent;
  652.         // Whether baselineAnchoredToTop was explicitly set
  653.         private boolean baselineAnchorSet;
  654.         // Whether the baseline is anchored to the top or the bottom.
  655.         // If anchored to the top the baseline is always at prefAscent,
  656.         // otherwise the baseline is at (height - prefDescent)
  657.         private boolean baselineAnchoredToTop;
  658.         
  659.         // Whether or not the baseline has been calculated.
  660.         private boolean calcedBaseline;
  661.         
  662.         BaselineGroup(boolean resizable) {
  663.             super(LEADING, resizable);
  664.             prefAscent = prefDescent = -1;
  665.             calcedBaseline = false;
  666.         }
  667.         
  668.         BaselineGroup(boolean resizable, boolean baselineAnchoredToTop) {
  669.             this(resizable);
  670.             this.baselineAnchoredToTop = baselineAnchoredToTop;
  671.             baselineAnchorSet = true;
  672.         }
  673.         
  674.         void unset() {
  675.             super.unset();
  676.             prefAscent = prefDescent = -1;
  677.             calcedBaseline = false;
  678.         }
  679.         
  680.         void setValidSize(int axis, int origin, int size) {
  681.             checkAxis(axis);
  682.             if (prefAscent == -1) {
  683.                 super.setValidSize(axis, origin, size);
  684.             } else {
  685.                 // do baseline layout
  686.                 baselineLayout(origin, size);
  687.             }
  688.         }
  689.         
  690.         int calculateSize(int axis, int type) {
  691.             checkAxis(axis);
  692.             if (!calcedBaseline) {
  693.                 calculateBaselineAndResizeBehavior();
  694.             }
  695.             if (type == MIN_SIZE) {
  696.                 return calculateMinSize();
  697.             }
  698.             if (type == MAX_SIZE) {
  699.                 return calculateMaxSize();
  700.             }
  701.             if (allSpringsHaveBaseline) {
  702.                 return prefAscent + prefDescent;
  703.             }
  704.             return Math.max(prefAscent + prefDescent,
  705.                     super.calculateSize(axis, type));
  706.         }
  707.         
  708.         private void calculateBaselineAndResizeBehavior() {
  709.             // calculate baseline
  710.             prefAscent = 0;
  711.             prefDescent = 0;
  712.             int baselineSpringCount = 0;
  713.             int resizeBehavior = 0;
  714.             for (int counter = springs.size() - 1; counter >= 0; counter--) {
  715.                 Spring spring = getSpring(counter);
  716.                 if (spring.getAlignment() == NO_ALIGNMENT ||
  717.                         spring.getAlignment() == BASELINE) {
  718.                     int baseline = spring.getBaseline();
  719.                     if (baseline >= 0) {
  720.                         if (spring.isResizable(VERTICAL)) {
  721.                             int brb = spring.
  722.                                     getBaselineResizeBehavior();
  723.                             if (resizeBehavior == 0) {
  724.                                 resizeBehavior = brb;
  725.                             } else if (brb != resizeBehavior) {
  726.                                 resizeBehavior = Component.BRB_CONSTANT_ASCENT;
  727.                             }
  728.                         }
  729.                         prefAscent = Math.max(prefAscent, baseline);
  730.                         prefDescent = Math.max(prefDescent, spring.
  731.                                 getPreferredSize(VERTICAL) - baseline);
  732.                         baselineSpringCount++;
  733.                     }
  734.                 }
  735.             }
  736.             if (!baselineAnchorSet) {
  737.                 if (resizeBehavior == Component.BRB_CONSTANT_DESCENT){
  738.                     this.baselineAnchoredToTop = false;
  739.                 } else {
  740.                     this.baselineAnchoredToTop = true;
  741.                 }
  742.             }
  743.             allSpringsHaveBaseline = (baselineSpringCount == springs.size());
  744.             calcedBaseline = true;
  745.         }
  746.         
  747.         private int calculateMaxSize() {
  748.             int maxAscent = prefAscent;
  749.             int maxDescent = prefDescent;
  750.             int nonBaselineMax = 0;
  751.             for (int counter = springs.size() - 1; counter >= 0; counter--) {
  752.                 Spring spring = getSpring(counter);
  753.                 int baseline;
  754.                 int springMax = spring.getMaximumSize(VERTICAL);
  755.                 if ((spring.getAlignment() == NO_ALIGNMENT ||
  756.                         spring.getAlignment() == BASELINE) &&
  757.                         (baseline = spring.getBaseline()) >= 0) {
  758.                     int springPref = spring.getPreferredSize(VERTICAL);
  759.                     if (springPref != springMax) {
  760.                         switch (spring.getBaselineResizeBehavior()) {
  761.                             case Component.BRB_CONSTANT_ASCENT:
  762.                                 if (baselineAnchoredToTop) {
  763.                                     maxDescent = Math.max(maxDescent,
  764.                                             springMax - baseline);
  765.                                 }
  766.                                 break;
  767.                             case Component.BRB_CONSTANT_DESCENT:
  768.                                 if (!baselineAnchoredToTop) {
  769.                                     maxAscent = Math.max(maxAscent,
  770.                                             springMax - springPref + baseline);
  771.                                 }
  772.                                 break;
  773.                             default: // CENTER_OFFSET and OTHER, not resizable
  774.                                 break;
  775.                         }
  776.                     }
  777.                 } else {
  778.                     // Not aligned along the baseline, or no baseline.
  779.                     nonBaselineMax = Math.max(nonBaselineMax, springMax);
  780.                 }
  781.             }
  782.             return Math.max(nonBaselineMax, maxAscent + maxDescent);
  783.         }
  784.         
  785.         private int calculateMinSize() {
  786.             int minAscent = 0;
  787.             int minDescent = 0;
  788.             int nonBaselineMin = 0;
  789.             if (baselineAnchoredToTop) {
  790.                 minAscent = prefAscent;
  791.             } else {
  792.                 minDescent = prefDescent;
  793.             }
  794.             for (int counter = springs.size() - 1; counter >= 0; counter--) {
  795.                 Spring spring = getSpring(counter);
  796.                 int springMin = spring.getMinimumSize(VERTICAL);
  797.                 int baseline;
  798.                 if ((spring.getAlignment() == NO_ALIGNMENT ||
  799.                         spring.getAlignment() == BASELINE) &&
  800.                         (baseline = spring.getBaseline()) >= 0) {
  801.                     int springPref = spring.getPreferredSize(VERTICAL);
  802.                     switch (spring.getBaselineResizeBehavior()) {
  803.                         case Component.BRB_CONSTANT_ASCENT:
  804.                             if (baselineAnchoredToTop) {
  805.                                 minDescent = Math.max(springMin - baseline,
  806.                                         minDescent);
  807.                             } else {
  808.                                 minAscent = Math.max(baseline, minAscent);
  809.                             }
  810.                             break;
  811.                         case Component.BRB_CONSTANT_DESCENT:
  812.                             if (!baselineAnchoredToTop) {
  813.                                 minAscent = Math.max(
  814.                                         baseline - (springPref - springMin),
  815.                                         minAscent);
  816.                             } else {
  817.                                 minDescent = Math.max(springPref - baseline,
  818.                                         minDescent);
  819.                             }
  820.                             break;
  821.                         default:
  822.                             // CENTER_OFFSET and OTHER are !resizable, use
  823.                             // the preferred size.
  824.                             minAscent = Math.max(baseline, minAscent);
  825.                             minDescent = Math.max(springPref - baseline,
  826.                                     minDescent);
  827.                             break;
  828.                     }
  829.                 } else {
  830.                     // Not aligned along the baseline, or no baseline.
  831.                     nonBaselineMin = Math.max(nonBaselineMin, springMin);
  832.                 }
  833.             }
  834.             return Math.max(nonBaselineMin, minAscent + minDescent);
  835.         }
  836.         /**
  837.          * Lays out springs that have a baseline along the baseline.  All
  838.          * others are centered.
  839.          */
  840.         private void baselineLayout(int origin, int size) {
  841.             int ascent;
  842.             int descent;
  843.             if (baselineAnchoredToTop) {
  844.                 ascent = prefAscent;
  845.                 descent = size - ascent;
  846.             } else {
  847.                 ascent = size - prefDescent;
  848.                 descent = prefDescent;
  849.             }
  850.             for (int counter = springs.size() - 1; counter >= 0; counter--) {
  851.                 Spring spring = getSpring(counter);
  852.                 int alignment = spring.getAlignment();
  853.                 if (alignment == NO_ALIGNMENT || alignment == BASELINE) {
  854.                     int baseline = spring.getBaseline();
  855.                     if (baseline >= 0) {
  856.                         int springMax = spring.getMaximumSize(VERTICAL);
  857.                         int springPref = spring.getPreferredSize(VERTICAL);
  858.                         int height = springPref;
  859.                         int y;
  860.                         switch(spring.getBaselineResizeBehavior()) {
  861.                             case Component.BRB_CONSTANT_ASCENT:
  862.                                 y = origin + ascent - baseline;
  863.                                 height = Math.min(descent, springMax -
  864.                                         baseline) + baseline;
  865.                                 break;
  866.                             case Component.BRB_CONSTANT_DESCENT:
  867.                                 height = Math.min(ascent, springMax -
  868.                                         springPref + baseline) +
  869.                                         (springPref - baseline);
  870.                                 y = origin + ascent +
  871.                                         (springPref - baseline) - height;
  872.                                 break;
  873.                             default: // CENTER_OFFSET & OTHER, not resizable
  874.                                 y = origin + ascent - baseline;
  875.                                 break;
  876.                         }
  877.                         spring.setSize(VERTICAL, y, height);
  878.                     } else {
  879.                         setChildSize(spring, VERTICAL, origin, size);
  880.                     }
  881.                 } else {
  882.                     setChildSize(spring, VERTICAL, origin, size);
  883.                 }
  884.             }
  885.         }
  886.         
  887.         int getBaseline() {
  888.             if (springs.size() > 1) {
  889.                 // Force the baseline to be calculated
  890.                 getPreferredSize(VERTICAL);
  891.                 return prefAscent;
  892.             } else if (springs.size() == 1) {
  893.                 return getSpring(0).getBaseline();
  894.             }
  895.             return -1;
  896.         }
  897.         
  898.         int getBaselineResizeBehavior() {
  899.             if (springs.size() == 1) {
  900.                 return getSpring(0).getBaselineResizeBehavior();
  901.             }
  902.             if (baselineAnchoredToTop) {
  903.                 return Component.BRB_CONSTANT_ASCENT;
  904.             }
  905.             return Component.BRB_CONSTANT_DESCENT;
  906.         }
  907.         
  908.         // If the axis is VERTICAL, throws an IllegalStateException
  909.         private void checkAxis(int axis) {
  910.             if (axis == HORIZONTAL) {
  911.                 throw new IllegalStateException(
  912.                         "Baseline must be used along vertical axis");
  913.             }
  914.         }
  915.     }
  916.     
  917.     
  918.     /**
  919.      * A Spring representing one axis of a Component.
  920.      * There are three ways to configure this:
  921.      * <ul>
  922.      * <li>Use the pref/min/max from the component
  923.      * <li>Use the pref from the component and fix the min to 0 or max
  924.      *     to a big number.
  925.      * <li>Force the min/max/pref to be a certain value.
  926.      * If the Component's size is to be linked to another components than
  927.      * the min/max/pref all come from the ComponentInfo.
  928.      */
  929.     private final class ComponentSpring extends Spring {
  930.         private Component component;
  931.         private int origin;
  932.         
  933.         // min/pref/max are either a value >= 0 or one of
  934.         // DEFAULT_SIZE or PREFERRED_SIZE
  935.         private final int min;
  936.         private final int pref;
  937.         private final int max;
  938.         
  939.         // Baseline for the component.
  940.         private int baseline = -1;
  941.         
  942.         // Whether or not the size has been requested yet.
  943.         private boolean installed;
  944.         
  945.         private ComponentSpring(Component component, int min, int pref,
  946.                 int max) {
  947.             this.component = component;
  948.             if (component == null) {
  949.                 throw new IllegalArgumentException(
  950.                         "Component must be non-null");
  951.             }
  952.             checkSize(min, pref, max, true);
  953.             
  954.             this.min = min;
  955.             this.max = max;
  956.             this.pref = pref;
  957.             
  958.             // getComponentInfo makes sure component is a child of the
  959.             // Container GroupLayout is the LayoutManager for.
  960.             getComponentInfo(component);
  961.         }
  962.         
  963.         int calculateMinimumSize(int axis) {
  964.             if (isLinked(axis)) {
  965.                 return getLinkSize(axis, MIN_SIZE);
  966.             }
  967.             return calculateNonlinkedMinimumSize(axis);
  968.         }
  969.         
  970.         int calculatePreferredSize(int axis) {
  971.             if (isLinked(axis)) {
  972.                 return getLinkSize(axis, PREF_SIZE);
  973.             }
  974.             int min = getMinimumSize(axis);
  975.             int pref = calculateNonlinkedPreferredSize(axis);
  976.             int max = getMaximumSize(axis);
  977.             return Math.min(max, Math.max(min, pref));
  978.         }
  979.         
  980.         int calculateMaximumSize(int axis) {
  981.             if (isLinked(axis)) {
  982.                 return getLinkSize(axis, MAX_SIZE);
  983.             }
  984.             return Math.max(getMinimumSize(axis),
  985.                     calculateNonlinkedMaximumSize(axis));
  986.         }
  987.         
  988.         boolean isVisible() {
  989.             return getComponentInfo(getComponent()).isVisible();
  990.         }
  991.         
  992.         int calculateNonlinkedMinimumSize(int axis) {
  993.             if (!isVisible()) {
  994.                 return 0;
  995.             }
  996.             if (min >= 0) {
  997.                 return min;
  998.             }
  999.             if (min == PREFERRED_SIZE) {
  1000.                 return calculateNonlinkedPreferredSize(axis);
  1001.             }
  1002.             //assert (min == DEFAULT_SIZE);
  1003.             //return getSizeAlongAxis(axis, component.getMinimumSize());
  1004.             // Do we need this if we don't support minimum size?
  1005.             return getSizeAlongAxis(axis, component.getPreferredSize());
  1006.         }
  1007.         
  1008.         int calculateNonlinkedPreferredSize(int axis) {
  1009.             if (!isVisible()) {
  1010.                 return 0;
  1011.             }
  1012.             if (pref >= 0) {
  1013.                 return pref;
  1014.             }
  1015.             //assert (pref == DEFAULT_SIZE || pref == PREFERRED_SIZE);
  1016.             return getSizeAlongAxis(axis, component.getPreferredSize());
  1017.         }
  1018.         
  1019.         int calculateNonlinkedMaximumSize(int axis) {
  1020.             if (!isVisible()) {
  1021.                 return 0;
  1022.             }
  1023.             if (max >= 0) {
  1024.                 return max;
  1025.             }
  1026.             if (max == PREFERRED_SIZE) {
  1027.                 return calculateNonlinkedPreferredSize(axis);
  1028.             }
  1029.             //assert (max == DEFAULT_SIZE);
  1030.             //return getSizeAlongAxis(axis, component.getMaximumSize());
  1031.             return getSizeAlongAxis(axis, component.getPreferredSize());
  1032.         }
  1033.         
  1034.         private int getSizeAlongAxis(int axis, Dimension size) {
  1035.             return (axis == HORIZONTAL) ? size.getWidth() : size.getHeight();
  1036.         }
  1037.         
  1038.         private int getLinkSize(int axis, int type) {
  1039.             if (!isVisible()) {
  1040.                 return 0;
  1041.             }
  1042.             ComponentInfo ci = getComponentInfo(component);
  1043.             return ci.getLinkSize(axis, type);
  1044.         }
  1045.         
  1046.         void setSize(int axis, int origin, int size) {
  1047.             super.setSize(axis, origin, size);
  1048.             this.origin = origin;
  1049.             if (size == UNSET) {
  1050.                 baseline = -1;
  1051.             }
  1052.         }
  1053.         
  1054.         int getOrigin() {
  1055.             return origin;
  1056.         }
  1057.         
  1058.         void setComponent(Component component) {
  1059.             this.component = component;
  1060.         }
  1061.         
  1062.         Component getComponent() {
  1063.             return component;
  1064.         }
  1065.         
  1066.         int getBaseline() {
  1067.             if (baseline == -1) {
  1068.                 Spring horizontalSpring = getComponentInfo(component).
  1069.                         horizontalSpring;
  1070.                 int width = horizontalSpring.getPreferredSize(HORIZONTAL);
  1071.                 int height = getPreferredSize(VERTICAL);
  1072.                 if (width > 0 && height > 0) {
  1073.                     baseline = component.getBaseline(width, height);
  1074.                 }
  1075.             }
  1076.             return baseline;
  1077.         }
  1078.         
  1079.         int getBaselineResizeBehavior() {
  1080.             return getComponent().getBaselineResizeBehavior();
  1081.         }
  1082.         private boolean isLinked(int axis) {
  1083.             return getComponentInfo(component).isLinked(axis);
  1084.         }
  1085.         
  1086.         void installIfNecessary(int axis) {
  1087.             if (!installed) {
  1088.                 installed = true;
  1089.                 if (axis == HORIZONTAL) {
  1090.                     getComponentInfo(component).horizontalSpring = this;
  1091.                 } else {
  1092.                     getComponentInfo(component).verticalSpring = this;
  1093.                 }
  1094.             }
  1095.         }
  1096.         boolean willHaveZeroSize(boolean treatAutopaddingAsZeroSized) {
  1097.             return !isVisible();
  1098.         }
  1099.     }
  1100.     
  1101.     /**
  1102.      * Spring representing the preferred distance between two components.
  1103.      */
  1104.     private final class PaddingSpring extends Spring {
  1105.         private final Component source;
  1106.         private final Component target;
  1107.         private final int type;
  1108.         private final boolean canGrow;
  1109.         
  1110.         PaddingSpring(Component source, Component target, int type,
  1111.                 boolean canGrow) {
  1112.             this.source = source;
  1113.             this.target = target;
  1114.             this.type = type;
  1115.             this.canGrow = canGrow;
  1116.         }
  1117.         
  1118.         int calculateMinimumSize(int axis) {
  1119.             return getPadding(axis);
  1120.         }
  1121.         
  1122.         int calculatePreferredSize(int axis) {
  1123.             return getPadding(axis);
  1124.         }
  1125.         
  1126.         int calculateMaximumSize(int axis) {
  1127.             if (canGrow) {
  1128.                 return Short.MAX_VALUE;
  1129.             }
  1130.             return getPadding(axis);
  1131.         }
  1132.         
  1133.         private int getPadding(int axis) {
  1134.             int position;
  1135.             if (axis == HORIZONTAL) {
  1136.                 position = EAST;
  1137.             } else {
  1138.                 position = SOUTH;
  1139.             }
  1140.             return getLayoutStyle0().getPreferredGap(source,
  1141.                     target, type, position, host);
  1142.         }
  1143.         boolean willHaveZeroSize(boolean treatAutopaddingAsZeroSized) {
  1144.             return false;
  1145.         }
  1146.     }
  1147.     
  1148.     
  1149.     /**
  1150.      * Spring represented a certain amount of space.
  1151.      */
  1152.     private final class GapSpring extends Spring {
  1153.         private final int min;
  1154.         private final int pref;
  1155.         private final int max;
  1156.         
  1157.         GapSpring(int min, int pref, int max) {
  1158.             checkSize(min, pref, max, false);
  1159.             this.min = min;
  1160.             this.pref = pref;
  1161.             this.max = max;
  1162.         }
  1163.         int calculateMinimumSize(int axis) {
  1164.             if (min == PREFERRED_SIZE) {
  1165.                 return getPreferredSize(axis);
  1166.             }
  1167.             return min;
  1168.         }
  1169.         
  1170.         int calculatePreferredSize(int axis) {
  1171.             return pref;
  1172.         }
  1173.         
  1174.         int calculateMaximumSize(int axis) {
  1175.             if (max == PREFERRED_SIZE) {
  1176.                 return getPreferredSize(axis);
  1177.             }
  1178.             return max;
  1179.         }
  1180.         boolean willHaveZeroSize(boolean treatAutopaddingAsZeroSized) {
  1181.             return false;
  1182.         }
  1183.     }
  1184.     
  1185.     
  1186.     /**
  1187.      * Spring reprensenting the distance between any number of sources and
  1188.      * targets.  The targets and sources are computed during layout.  An
  1189.      * instance of this can either be dynamically created when
  1190.      * autocreatePadding is true, or explicitly created by the developer.
  1191.      */
  1192.     private class AutopaddingSpring extends Spring {
  1193.         Vector sources;
  1194.         ComponentSpring source;
  1195.         private Vector matches;
  1196.         int size;
  1197.         int lastSize;
  1198.         private final int pref;
  1199.         private final int max;
  1200.         private int type;
  1201.         private boolean userCreated;
  1202.         
  1203.         private AutopaddingSpring() {
  1204.             this.pref = PREFERRED_SIZE;
  1205.             this.max = PREFERRED_SIZE;
  1206.             this.type = LayoutStyle.RELATED;
  1207.         }
  1208.         AutopaddingSpring(int pref, int max) {
  1209.             this.pref = pref;
  1210.             this.max = max;
  1211.         }
  1212.         
  1213.         AutopaddingSpring(int type, int pref, int max) {
  1214.             this.type = type;
  1215.             this.pref = pref;
  1216.             this.max = max;
  1217.             this.userCreated = true;
  1218.         }
  1219.         
  1220.         public void setSource(ComponentSpring source) {
  1221.             this.source = source;
  1222.         }
  1223.         
  1224.         public void setSources(Vector sources) {
  1225.             this.sources = create(sources);
  1226.         }
  1227.         
  1228.         public void setUserCreated(boolean userCreated) {
  1229.             this.userCreated = userCreated;
  1230.         }
  1231.         
  1232.         public boolean getUserCreated() {
  1233.             return userCreated;
  1234.         }
  1235.         
  1236.         void unset() {
  1237.             lastSize = getSize();
  1238.             super.unset();
  1239.             size = 0;
  1240.         }
  1241.         
  1242.         public void reset() {
  1243.             size = 0;
  1244.             sources = null;
  1245.             source = null;
  1246.             matches = null;
  1247.         }
  1248.         
  1249.         public void calculatePadding(int axis) {
  1250.             size = UNSET;
  1251.             int maxPadding = UNSET;
  1252.             if (matches != null) {
  1253.                 LayoutStyle p = getLayoutStyle0();
  1254.                 int position;
  1255.                 if (axis == HORIZONTAL) {
  1256.                     if (isLeftToRight()) {
  1257.                         position = EAST;
  1258.                     } else {
  1259.                         position = WEST;
  1260.                     }
  1261.                 } else {
  1262.                     position = SOUTH;
  1263.                 }
  1264.                 for (int i = matches.size() - 1; i >= 0; i--) {
  1265.                     AutopaddingMatch match = (AutopaddingMatch)matches.elementAt(i);
  1266.                     maxPadding = Math.max(maxPadding,
  1267.                             calculatePadding(p, position, match.source,
  1268.                             match.target));
  1269.                 }
  1270.             }
  1271.             if (size == UNSET) {
  1272.                 size = 0;
  1273.             }
  1274.             if (maxPadding == UNSET) {
  1275.                 maxPadding = 0;
  1276.             }
  1277.             if (lastSize != UNSET) {
  1278.                 size += Math.min(maxPadding, lastSize);
  1279.             }
  1280.         }
  1281.         
  1282.         private int calculatePadding(LayoutStyle p, int position,
  1283.                 ComponentSpring source,
  1284.                 ComponentSpring target) {
  1285.             int delta = target.getOrigin() - (source.getOrigin() +
  1286.                     source.getSize());
  1287.             if (delta >= 0) {
  1288.                 int padding = p.getPreferredGap(source.getComponent(),
  1289.                         target.getComponent(), type, position, host);
  1290.                 if (padding > delta) {
  1291.                     size = Math.max(size, padding - delta);
  1292.                 }
  1293.                 return padding;
  1294.             }
  1295.             return 0;
  1296.         }
  1297.         
  1298.         public void addTarget(ComponentSpring spring, int axis) {
  1299.             int oAxis = (axis == HORIZONTAL) ? VERTICAL : HORIZONTAL;
  1300.             if (source != null) {
  1301.                 if (areParallelSiblings(source.getComponent(),
  1302.                         spring.getComponent(), oAxis)) {
  1303.                     addValidTarget(source, spring);
  1304.                 }
  1305.             } else {
  1306.                 Component component = spring.getComponent();
  1307.                 for (int counter = sources.size() - 1; counter >= 0; counter--){
  1308.                     ComponentSpring source = (ComponentSpring)sources.
  1309.                             elementAt(counter);
  1310.                     if (areParallelSiblings(source.getComponent(),
  1311.                             component, oAxis)) {
  1312.                         addValidTarget(source, spring);
  1313.                     }
  1314.                 }
  1315.             }
  1316.         }
  1317.         
  1318.         private void addValidTarget(ComponentSpring source,
  1319.                 ComponentSpring target) {
  1320.             if (matches == null) {
  1321.                 matches = new Vector(1);
  1322.             }
  1323.             matches.addElement(new AutopaddingMatch(source, target));
  1324.         }
  1325.         
  1326.         int calculateMinimumSize(int axis) {
  1327.             return size;
  1328.         }
  1329.         
  1330.         int calculatePreferredSize(int axis) {
  1331.             if (pref == PREFERRED_SIZE || pref == DEFAULT_SIZE) {
  1332.                 return size;
  1333.             }
  1334.             return Math.max(size, pref);
  1335.         }
  1336.         
  1337.         int calculateMaximumSize(int axis) {
  1338.             if (max >= 0) {
  1339.                 return Math.max(getPreferredSize(axis), max);
  1340.             }
  1341.             return size;
  1342.         }
  1343.   
  1344.         String getMatchDescription() {
  1345.             return (matches == null) ? "" : matches.toString();
  1346.         }
  1347.         
  1348.         public String toString() {
  1349.             return super.toString() + getMatchDescription();
  1350.         }
  1351.         boolean willHaveZeroSize(boolean treatAutopaddingAsZeroSized) {
  1352.             return treatAutopaddingAsZeroSized;
  1353.         }
  1354.     }
  1355.     
  1356.     
  1357.     /**
  1358.      * Represents two springs that should have autopadding inserted between
  1359.      * them.
  1360.      */
  1361.     private final static class AutopaddingMatch {
  1362.         public final ComponentSpring source;
  1363.         public final ComponentSpring target;
  1364.         AutopaddingMatch(ComponentSpring source, ComponentSpring target) {
  1365.             this.source = source;
  1366.             this.target = target;
  1367.         }
  1368.         
  1369.         private String toString(ComponentSpring spring) {
  1370.             return spring.getComponent().toString();
  1371.         }
  1372.         public String toString() {
  1373.             return "[" + toString(source) + "-" + toString(target) + "]";
  1374.         }
  1375.     }
  1376.     
  1377.     
  1378.     /**
  1379.      * An extension of AutopaddingSpring used for container level padding.
  1380.      */
  1381.     private class ContainerAutopaddingSpring extends AutopaddingSpring {
  1382.         private Vector targets;
  1383.         
  1384.         ContainerAutopaddingSpring() {
  1385.             super();
  1386.             setUserCreated(true);
  1387.         }
  1388.         ContainerAutopaddingSpring(int pref, int max) {
  1389.             super(pref, max);
  1390.             setUserCreated(true);
  1391.         }
  1392.         public void addTarget(ComponentSpring spring, int axis) {
  1393.             if (targets == null) {
  1394.                 targets = new Vector(1);
  1395.             }
  1396.             targets.addElement(spring);
  1397.         }
  1398.         public void calculatePadding(int axis) {
  1399.             LayoutStyle p = getLayoutStyle0();
  1400.             int maxPadding = 0;
  1401.             int position;
  1402.             size = 0;
  1403.             if (targets != null) {
  1404.                 // Leading
  1405.                 if (axis == HORIZONTAL) {
  1406.                     if (isLeftToRight()) {
  1407.                         position = WEST;
  1408.                     } else {
  1409.                         position = EAST;
  1410.                     }
  1411.                 } else {
  1412.                     position = SOUTH;
  1413.                 }
  1414.                 for (int i = targets.size() - 1; i >= 0; i--) {
  1415.                     ComponentSpring targetSpring = (ComponentSpring)targets.
  1416.                                                                     elementAt(i);
  1417.                     int padding = p.getContainerGap(
  1418.                                 targetSpring.getComponent(),
  1419.                                 position, host);
  1420.                     maxPadding = Math.max(padding, maxPadding);
  1421.                     padding -= targetSpring.getOrigin();
  1422.                     size = Math.max(size, padding);
  1423.                 }
  1424.             }
  1425.             else {
  1426.                 // Trailing
  1427.                 if (axis == HORIZONTAL) {
  1428.                     if (isLeftToRight()) {
  1429.                         position = EAST;
  1430.                     } else {
  1431.                         position = WEST;
  1432.                     }
  1433.                 } else {
  1434.                     position = SOUTH;
  1435.                 }
  1436.                 if (sources != null) {
  1437.                     for (int i = sources.size() - 1; i >= 0; i--) {
  1438.                         ComponentSpring sourceSpring = (ComponentSpring)sources.
  1439.                                 elementAt(i);
  1440.                         maxPadding = Math.max(maxPadding,
  1441.                                 updateSize(p, sourceSpring, position));
  1442.                     }
  1443.                 }
  1444.                 else if (source != null) {
  1445.                     maxPadding = updateSize(p, source, position);
  1446.                 }
  1447.             }
  1448.             if (lastSize != UNSET) {
  1449.                 size += Math.min(maxPadding, lastSize);
  1450.             }
  1451.         }
  1452.         private int updateSize(LayoutStyle p, ComponentSpring sourceSpring,
  1453.                 int position) {
  1454.             int padding = p.getContainerGap(
  1455.                         sourceSpring.getComponent(), position,
  1456.                         host);
  1457.             int delta = Math.max(0, getParent().getSize() -
  1458.                     sourceSpring.getSize() - sourceSpring.getOrigin());
  1459.             size = Math.max(size, padding - delta);
  1460.             return padding;
  1461.         }
  1462.         
  1463.         String getMatchDescription() {
  1464.             if (targets != null) {
  1465.                 return "leading: " + targets.toString();
  1466.             }
  1467.             if (sources != null) {
  1468.                 return "trailing: " + sources.toString();
  1469.             }
  1470.             return "--";
  1471.         }
  1472. }
  1473.     
  1474.     // LinkInfo contains the set of ComponentInfosthat are linked along a
  1475.     // particular axis.
  1476.     private static final class LinkInfo {
  1477.         private final int axis;
  1478.         private final Vector linked;
  1479.         private int size;
  1480.         
  1481.         LinkInfo(int axis) {
  1482.             linked = new Vector();
  1483.             size = UNSET;
  1484.             this.axis = axis;
  1485.         }
  1486.         
  1487.         public void add(ComponentInfo child) {
  1488.             LinkInfo childMaster = child.getLinkInfo(axis, false);
  1489.             if (childMaster == null) {
  1490.                 linked.addElement(child);
  1491.                 child.setLinkInfo(axis, this);
  1492.             } else if (childMaster != this) {
  1493.                 addAll(linked, childMaster.linked);
  1494.                 for (int i = 0; i < childMaster.linked.size(); i++) {
  1495.                     ComponentInfo childInfo = (ComponentInfo)childMaster.linked.elementAt(i);
  1496.                     childInfo.setLinkInfo(axis, this);
  1497.                 }
  1498.             }
  1499.             clearCachedSize();
  1500.         }
  1501.         
  1502.         public void remove(ComponentInfo info) {
  1503.             linked.removeElement(info);
  1504.             info.setLinkInfo(axis, null);
  1505.             if (linked.size() == 1) {
  1506.                 ((ComponentInfo)linked.elementAt(0)).setLinkInfo(axis, null);
  1507.             }
  1508.             clearCachedSize();
  1509.         }
  1510.         
  1511.         public void clearCachedSize() {
  1512.             size = UNSET;
  1513.         }
  1514.         
  1515.         public int getSize(int axis) {
  1516.             if (size == UNSET) {
  1517.                 size = calculateLinkedSize(axis);
  1518.             }
  1519.             return size;
  1520.         }
  1521.         
  1522.         private int calculateLinkedSize(int axis) {
  1523.             int size = 0;
  1524.             for (int i = 0; i < linked.size(); i++) {
  1525.                 ComponentInfo info = (ComponentInfo)linked.elementAt(i);
  1526.                 ComponentSpring spring;
  1527.                 if (axis == HORIZONTAL) {
  1528.                     spring = info.horizontalSpring;
  1529.                 } else {
  1530.                     //assert (axis == VERTICAL);
  1531.                     spring = info.verticalSpring;
  1532.                 }
  1533.                 size = Math.max(size,
  1534.                         spring.calculateNonlinkedPreferredSize(axis));
  1535.             }
  1536.             return size;
  1537.         }
  1538.     }
  1539.     
  1540.     /**
  1541.      * Tracks the horizontal/vertical Springs for a Component.
  1542.      * This class is also used to handle Springs that have their sizes
  1543.      * linked.
  1544.      */
  1545.     private final class ComponentInfo {
  1546.         // Component being layed out
  1547.         private Component component;
  1548.         
  1549.         ComponentSpring horizontalSpring;
  1550.         ComponentSpring verticalSpring;
  1551.         
  1552.         // If the component's size is linked to other components, the
  1553.         // horizontalMaster and/or verticalMaster reference the group of
  1554.         // linked components.
  1555.         private LinkInfo horizontalMaster;
  1556.         private LinkInfo verticalMaster;
  1557.         private boolean visible;
  1558.         private Boolean honorsVisibility;
  1559.         
  1560.         ComponentInfo(Component component) {
  1561.             this.component = component;
  1562.             updateVisibility();
  1563.         }
  1564.         
  1565.         public void dispose() {
  1566.             // Remove horizontal/vertical springs
  1567.             removeSpring(horizontalSpring);
  1568.             horizontalSpring = null;
  1569.             removeSpring(verticalSpring);
  1570.             verticalSpring = null;
  1571.             // Clean up links
  1572.             if (horizontalMaster != null) {
  1573.                 horizontalMaster.remove(this);
  1574.             }
  1575.             if (verticalMaster != null) {
  1576.                 verticalMaster.remove(this);
  1577.             }
  1578.         }
  1579.         
  1580.         void setHonorsVisibility(Boolean honorsVisibility) {
  1581.             this.honorsVisibility = honorsVisibility;
  1582.         }
  1583.         private void removeSpring(Spring spring) {
  1584.             if (spring != null) {
  1585.                 ((Group)spring.getParent()).springs.removeElement(spring);
  1586.             }
  1587.         }
  1588.         
  1589.         public boolean isVisible() {
  1590.             return visible;
  1591.         }
  1592.         
  1593.         /**
  1594.          * Updates the cached visibility.
  1595.          *
  1596.          * @return true if the visibility changed
  1597.          */
  1598.         boolean updateVisibility() {
  1599.             boolean honorsVisibility;
  1600.             if (this.honorsVisibility == null) {
  1601.                 honorsVisibility = GroupLayout.this.getHonorsVisibility();
  1602.             } else {
  1603.                 honorsVisibility = this.honorsVisibility.booleanValue();
  1604.             }
  1605.             boolean newVisible = (honorsVisibility) ?
  1606.                 component.isVisible() : true;
  1607.             if (visible != newVisible) {
  1608.                 visible = newVisible;
  1609.                 return true;
  1610.             }
  1611.             return false;
  1612.         }
  1613.         
  1614.         public void setBounds(int insetX, int insetY, int parentWidth, boolean ltr) {
  1615.             int x = horizontalSpring.getOrigin();
  1616.             int w = horizontalSpring.getSize();
  1617.             int y = verticalSpring.getOrigin();
  1618.             int h = verticalSpring.getSize();
  1619.             
  1620.             if (!ltr) {
  1621.                 x = parentWidth - x - w;
  1622.             }
  1623.             component.setX(x + insetX);
  1624.             component.setY(y + insetY);
  1625.             component.setWidth(w);
  1626.             component.setHeight(h);
  1627.         }
  1628.         
  1629.         public void setComponent(Component component) {
  1630.             this.component = component;
  1631.             if (horizontalSpring != null) {
  1632.                 horizontalSpring.setComponent(component);
  1633.             }
  1634.             if (verticalSpring != null) {
  1635.                 verticalSpring.setComponent(component);
  1636.             }
  1637.         }
  1638.         
  1639.         public Component getComponent() {
  1640.             return component;
  1641.         }
  1642.         
  1643.         /**
  1644.          * Returns true if this component has its size linked to
  1645.          * other components.
  1646.          */
  1647.         public boolean isLinked(int axis) {
  1648.             if (axis == HORIZONTAL) {
  1649.                 return horizontalMaster != null;
  1650.             }
  1651.             //assert (axis == VERTICAL);
  1652.             return (verticalMaster != null);
  1653.         }
  1654.         
  1655.         private void setLinkInfo(int axis, LinkInfo linkInfo) {
  1656.             if (axis == HORIZONTAL) {
  1657.                 horizontalMaster = linkInfo;
  1658.             } else {
  1659.                 //assert (axis == VERTICAL);
  1660.                 verticalMaster = linkInfo;
  1661.             }
  1662.         }
  1663.         
  1664.         public LinkInfo getLinkInfo(int axis) {
  1665.             return getLinkInfo(axis, true);
  1666.         }
  1667.         
  1668.         private LinkInfo getLinkInfo(int axis, boolean create) {
  1669.             if (axis == HORIZONTAL) {
  1670.                 if (horizontalMaster == null && create) {
  1671.                     // horizontalMaster field is directly set by adding
  1672.                     // us to the LinkInfo.
  1673.                     new LinkInfo(HORIZONTAL).add(this);
  1674.                 }
  1675.                 return horizontalMaster;
  1676.             } else {
  1677.                 //assert (axis == VERTICAL);
  1678.                 if (verticalMaster == null && create) {
  1679.                     // verticalMaster field is directly set by adding
  1680.                     // us to the LinkInfo.
  1681.                     new LinkInfo(VERTICAL).add(this);
  1682.                 }
  1683.                 return verticalMaster;
  1684.             }
  1685.         }
  1686.         public void clearCachedSize() {
  1687.             if (horizontalMaster != null) {
  1688.                 horizontalMaster.clearCachedSize();
  1689.             }
  1690.             if (verticalMaster != null) {
  1691.                 verticalMaster.clearCachedSize();
  1692.             }
  1693.         }
  1694.         
  1695.         int getLinkSize(int axis, int type) {
  1696.             if (axis == HORIZONTAL) {
  1697.                 return horizontalMaster.getSize(axis);
  1698.             } else {
  1699.                 //assert (axis == VERTICAL);
  1700.                 return verticalMaster.getSize(axis);
  1701.             }
  1702.         }
  1703.     }
  1704. }