Source Code Cross Referenced for GroupLayout.java in  » IDE-Netbeans » cvsclient » org » jdesktop » layout » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Netbeans » cvsclient » org.jdesktop.layout 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003:         *
0004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * The contents of this file are subject to the terms of either the GNU
0007:         * General Public License Version 2 only ("GPL") or the Common
0008:         * Development and Distribution License("CDDL") (collectively, the
0009:         * "License"). You may not use this file except in compliance with the
0010:         * License. You can obtain a copy of the License at
0011:         * http://www.netbeans.org/cddl-gplv2.html
0012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013:         * specific language governing permissions and limitations under the
0014:         * License.  When distributing the software, include this License Header
0015:         * Notice in each file and include the License file at
0016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
0017:         * particular file as subject to the "Classpath" exception as provided
0018:         * by Sun in the GPL Version 2 section of the License file that
0019:         * accompanied this code. If applicable, add the following below the
0020:         * License Header, with the fields enclosed by brackets [] replaced by
0021:         * your own identifying information:
0022:         * "Portions Copyrighted [year] [name of copyright owner]"
0023:         *
0024:         * Contributor(s):
0025:         *
0026:         * The Original Software is NetBeans. The Initial Developer of the Original
0027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
0028:         * Microsystems, Inc. All Rights Reserved.
0029:         *
0030:         * If you wish your version of this file to be governed by only the CDDL
0031:         * or only the GPL Version 2, indicate your decision by adding
0032:         * "[Contributor] elects to include this software in this distribution
0033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034:         * single choice of license, a recipient has the option to distribute
0035:         * your version of this file under either the CDDL, the GPL Version 2 or
0036:         * to extend the choice of license to its licensees as provided above.
0037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
0038:         * Version 2 license, then the option applies only if the new code is
0039:         * made subject to such option by the copyright holder.
0040:         */
0041:
0042:        package org.jdesktop.layout;
0043:
0044:        import java.awt.Component;
0045:        import java.awt.Container;
0046:        import java.awt.Dimension;
0047:        import java.awt.Insets;
0048:        import java.awt.LayoutManager2;
0049:        import java.awt.Toolkit;
0050:        import java.util.*;
0051:
0052:        /**
0053:         * GroupLayout is a LayoutManager that hierarchically groups components to
0054:         * achieve common, and not so common, layouts.  Grouping is done by instances
0055:         * of the Group class.  GroupLayout supports two types of groups:
0056:         * <table>
0057:         *   <tr><td valign=top>Sequential:<td>A sequential group positions its child
0058:         *           elements sequentially, one after another.
0059:         *   <tr><td valign=top>Parallel:<td>A parallel group positions its child 
0060:         *           elements in the same space on top of each other.  Parallel groups 
0061:         *           can also align the child elements along their baseline.
0062:         * </table>
0063:         * Each Group can contain any number of child groups, Components or gaps.
0064:         * GroupLayout treats each axis independently.  That is, there is a group
0065:         * representing the horizontal axis, and a separate group representing the
0066:         * vertical axis.  The horizontal group is responsible for setting the x
0067:         * and width of its contents, where as the vertical group is responsible for
0068:         * setting the y and height of its contents.
0069:         * <p>
0070:         * The following code builds a simple layout consisting of two labels in
0071:         * one column, followed by two textfields in the next column:
0072:         * <pre>
0073:         *   JComponent panel = ...;
0074:         *   GroupLayout layout = new GroupLayout(panel);
0075:         *   panel.setLayout(layout);
0076:         *   layout.setAutocreateGaps(true);
0077:         *   layout.setAutocreateContainerGaps(true);
0078:         *   GroupLayout.SequentialGroup hGroup = layout.createSequentialGroup();
0079:         *   hGroup.add(layout.createParallelGroup().add(label1).add(label2)).
0080:         *          add(layout.createParallelGroup().add(tf1).add(tf2));
0081:         *   layout.setHorizontalGroup(hGroup);
0082:         *   GroupLayout.SequentialGroup vGroup = layout.createSequentialGroup();
0083:         *   vGroup.add(layout.createParallelGroup(GroupLayout.BASELINE).add(label1).add(tf1)).
0084:         *          add(layout.createParallelGroup(GroupLayout.BASELINE).add(label2).add(tf2));
0085:         *   layout.setVerticalGroup(vGroup);
0086:         * </pre>
0087:         * <p>
0088:         * This layout consists of the following:
0089:         * <ul><li>The horizontal axis consists of a sequential group containing two
0090:         *         parallel groups.  The first parallel group consists of the labels,
0091:         *         with the second parallel group consisting of the text fields.
0092:         *     <li>The vertical axis similarly consists of a sequential group
0093:         *         containing two parallel groups.  The parallel groups align their
0094:         *         contents along the baseline.  The first parallel group consists
0095:         *         of the first label and text field, and the second group consists
0096:         *         of the second label and text field.
0097:         * </ul>
0098:         * There are a couple of things to notice in this code:
0099:         * <ul>
0100:         *   <li>You need not explicitly add the components to the container, this
0101:         *       is indirectly done by using one of the <code>add</code> methods.
0102:         *   <li>The various <code>add</code> methods of <code>Groups</code> return
0103:         *       themselves.  This allows for easy chaining of invocations.  For
0104:         *       example, <code>group.add(label1).add(label2);</code> is equivalent to
0105:         *       <code>group.add(label1);group.add(label2);</code>.
0106:         *   <li>There are no public constructors for the Groups, instead
0107:         *       use the create methods of <code>GroupLayout</code>.
0108:         * </ul>
0109:         * GroupLayout offer the ability to automatically insert the appropriate gap
0110:         * between components.  This can be turned on using the
0111:         * <code>setAutocreateGaps()</code> method.  Similarly you can use
0112:         * the <code>setAutocreateContainerGaps()</code> method to insert gaps
0113:         * between the components and the container.
0114:         * 
0115:         * @version $Revision$
0116:         * @author Tomas Pavek
0117:         * @author Jan Stola
0118:         * @author Scott Violet
0119:         */
0120:        public class GroupLayout implements  LayoutManager2 {
0121:            // Used in size calculations
0122:            private static final int MIN_SIZE = 0;
0123:            private static final int PREF_SIZE = 1;
0124:            private static final int MAX_SIZE = 2;
0125:
0126:            private static final int UNSET = Integer.MIN_VALUE;
0127:
0128:            /**
0129:             * Possible argument when linking sizes of components.  Specifies the
0130:             * the two component should share the same size along the horizontal
0131:             * axis.
0132:             *
0133:             * @see #linkSize(java.awt.Component[],int)
0134:             */
0135:            public static final int HORIZONTAL = 1;
0136:
0137:            /**
0138:             * Possible argument when linking sizes of components.  Specifies the
0139:             * the two component should share the same size along the vertical
0140:             * axis.
0141:             *
0142:             * @see #linkSize(java.awt.Component[],int)
0143:             */
0144:            public static final int VERTICAL = 2;
0145:
0146:            private static final int NO_ALIGNMENT = 0;
0147:            /**
0148:             * Possible alignment type.  Indicates the elements should be
0149:             * aligned to the origin.  For the horizontal axis with a left to
0150:             * right orientation this means aligned to the left.
0151:             *
0152:             * @see #createParallelGroup(int)
0153:             */
0154:            public static final int LEADING = 1;
0155:            /**
0156:             * Possible alignment type.  Indicates the elements should be
0157:             * aligned to the end.  For the horizontal axis with a left to
0158:             * right orientation this means aligned to the right.
0159:             *
0160:             * @see #createParallelGroup(int)
0161:             */
0162:            public static final int TRAILING = 2;
0163:            /**
0164:             * Possible alignment type.  Indicates the elements should centered in
0165:             * the spaced provided.
0166:             *
0167:             * @see #createParallelGroup(int)
0168:             */
0169:            public static final int CENTER = 3;
0170:            /**
0171:             * Possible alignment type.  Indicates the elements should aligned along
0172:             * their baseline.
0173:             *
0174:             * @see #createParallelGroup(int)
0175:             */
0176:            public static final int BASELINE = 3;
0177:
0178:            /**
0179:             * Possible value for the add methods that takes a Component.
0180:             * Indicates the size from the component should be used.
0181:             */
0182:            public static final int DEFAULT_SIZE = -1;
0183:            /**
0184:             * Possible value for the add methods that takes a Component.
0185:             * Indicates the preferred size should be used.
0186:             */
0187:            public static final int PREFERRED_SIZE = -2;
0188:
0189:            // Whether or not we automatically try and create the preferred
0190:            // padding between components.
0191:            private boolean autocreatePadding;
0192:
0193:            // Whether or not we automatically try and create the preferred
0194:            // padding between containers
0195:            private boolean autocreateContainerPadding;
0196:
0197:            /**
0198:             * Group responsible for layout along the horizontal axis.  This is NOT
0199:             * the user specified group, use getHorizontalGroup to dig that out.
0200:             */
0201:            private Group horizontalGroup;
0202:            /**
0203:             * Group responsible for layout along the vertical axis.  This is NOT
0204:             * the user specified group, use getVerticalGroup to dig that out.
0205:             */
0206:            private Group verticalGroup;
0207:
0208:            // Maps from Component to ComponentInfo.  This is used for tracking
0209:            // information specific to a Component.
0210:            private Map componentInfos;
0211:
0212:            // Container we're doing layout for.
0213:            private Container host;
0214:
0215:            // Used by areParallelSiblings, cached to avoid excessive garbage.
0216:            private List parallelList;
0217:
0218:            // Indicates Springs have been added since last change.
0219:            private boolean springsAdded;
0220:
0221:            // Whether or not any preferred padding (or container padding) springs exist
0222:            private boolean hasPreferredPaddingSprings;
0223:
0224:            private static void checkSize(int min, int pref, int max,
0225:                    boolean isComponentSpring) {
0226:                checkResizeType(min, isComponentSpring);
0227:                if (!isComponentSpring && pref < 0) {
0228:                    throw new IllegalArgumentException("Pref must be >= 0");
0229:                }
0230:                checkResizeType(max, isComponentSpring);
0231:                checkLessThan(min, pref);
0232:                checkLessThan(min, max);
0233:                checkLessThan(pref, max);
0234:            }
0235:
0236:            private static void checkResizeType(int type,
0237:                    boolean isComponentSpring) {
0238:                if (type < 0
0239:                        && ((isComponentSpring && type != DEFAULT_SIZE && type != PREFERRED_SIZE) || (!isComponentSpring && type != PREFERRED_SIZE))) {
0240:                    throw new IllegalArgumentException("Invalid size");
0241:                }
0242:            }
0243:
0244:            private static void checkLessThan(int min, int max) {
0245:                if (min >= 0 && max >= 0 && min > max) {
0246:                    throw new IllegalArgumentException(
0247:                            "Following is not met: min<=pref<=max");
0248:                }
0249:            }
0250:
0251:            // Makes sure the alignment is one of the known values.
0252:            private static void checkAlignment(int alignment,
0253:                    boolean allowsBaseline) {
0254:                if (alignment == LEADING || alignment == TRAILING
0255:                        || alignment == CENTER) {
0256:                    return;
0257:                }
0258:                if (allowsBaseline && alignment != BASELINE) {
0259:                    throw new IllegalArgumentException(
0260:                            "Alignment must be one of:"
0261:                                    + "LEADING, TRAILING, CENTER or BASELINE");
0262:                }
0263:                throw new IllegalArgumentException("Alignment must be one of:"
0264:                        + "LEADING, TRAILING or CENTER");
0265:            }
0266:
0267:            /**
0268:             * Creates a GroupLayout for the specified JComponent.
0269:             *
0270:             * @param host the Container to layout
0271:             * @throws IllegalArgumentException if host is null
0272:             */
0273:            public GroupLayout(Container host) {
0274:                if (host == null) {
0275:                    throw new IllegalArgumentException(
0276:                            "Container must be non-null");
0277:                }
0278:                this .host = host;
0279:                setHorizontalGroup(createParallelGroup(LEADING, true));
0280:                setVerticalGroup(createParallelGroup(LEADING, true));
0281:                componentInfos = new HashMap();
0282:                autocreatePadding = false;
0283:                parallelList = new ArrayList();
0284:            }
0285:
0286:            /**
0287:             * Returns a textual description of this GroupLayout.  The return value
0288:             * is intended for debugging purposes only.
0289:             *
0290:             * @return textual description of this GroupLayout
0291:             **/
0292:            public String toString() {
0293:                StringBuffer buffer = new StringBuffer();
0294:                buffer.append("HORIZONTAL\n");
0295:                dump(buffer, horizontalGroup, "  ", HORIZONTAL);
0296:                buffer.append("\nVERTICAL\n");
0297:                dump(buffer, verticalGroup, "  ", VERTICAL);
0298:                return buffer.toString();
0299:            }
0300:
0301:            private void dump(StringBuffer buffer, Spring spring,
0302:                    String indent, int axis) {
0303:                String origin = "";
0304:                String padding = "";
0305:                if (spring instanceof  ComponentSpring) {
0306:                    ComponentSpring cSpring = (ComponentSpring) spring;
0307:                    origin = Integer.toString(cSpring.getOrigin()) + " ";
0308:                    String name = cSpring.getComponent().getName();
0309:                    if (name != null) {
0310:                        origin = "name=" + name + ", ";
0311:                    }
0312:                }
0313:                if (spring instanceof  AutopaddingSpring) {
0314:                    AutopaddingSpring paddingSpring = (AutopaddingSpring) spring;
0315:                    padding = ", userCreated=" + paddingSpring.getUserCreated()
0316:                            + ", matches="
0317:                            + paddingSpring.getMatchDescription();
0318:                }
0319:                buffer.append(indent + spring.getClass().getName() + " "
0320:                        + Integer.toHexString(spring.hashCode()) + " " + origin
0321:                        + ", size=" + spring.getSize() + ", alignment="
0322:                        + spring.getAlignment() + " prefs=["
0323:                        + spring.getMinimumSize(axis) + " "
0324:                        + spring.getPreferredSize(axis) + " "
0325:                        + spring.getMaximumSize(axis) + padding + "]\n");
0326:                if (spring instanceof  Group) {
0327:                    List springs = ((Group) spring).springs;
0328:                    indent += "  ";
0329:                    for (int counter = 0; counter < springs.size(); counter++) {
0330:                        dump(buffer, (Spring) springs.get(counter), indent,
0331:                                axis);
0332:                    }
0333:                }
0334:            }
0335:
0336:            /**
0337:             * Sets whether or not a gap between components 
0338:             * should automatically be created.  For example, if this is true
0339:             * and you add two components to a <code>SequentialGroup</code> a
0340:             * gap between the two will automatically be created.  The default
0341:             * is false.
0342:             *
0343:             * @param autocreatePadding whether or not to automatically created a gap
0344:             *        between components and the container
0345:             */
0346:            public void setAutocreateGaps(boolean autocreatePadding) {
0347:                this .autocreatePadding = autocreatePadding;
0348:            }
0349:
0350:            /**
0351:             * Returns true if gaps between components are automatically be created.
0352:             *
0353:             * @return true if gaps between components should automatically be created
0354:             */
0355:            public boolean getAutocreateGaps() {
0356:                return autocreatePadding;
0357:            }
0358:
0359:            /**
0360:             * Sets whether or not gaps between the container and the first/last
0361:             * components should automatically be created. The default
0362:             * is false.
0363:             *
0364:             * @param autocreatePadding whether or not to automatically create
0365:             *        gaps between the container and first/last components.
0366:             */
0367:            public void setAutocreateContainerGaps(boolean autocreatePadding) {
0368:                if (autocreatePadding != autocreateContainerPadding) {
0369:                    autocreateContainerPadding = autocreatePadding;
0370:                    horizontalGroup = createTopLevelGroup(getHorizontalGroup());
0371:                    verticalGroup = createTopLevelGroup(getVerticalGroup());
0372:                }
0373:            }
0374:
0375:            /**
0376:             * Returns whether or not gaps between the container and the
0377:             * first/last components should automatically be created. The default
0378:             * is false.
0379:             *
0380:             * @return whether or not the gaps between the container and the
0381:             *         first/last components should automatically be created
0382:             */
0383:            public boolean getAutocreateContainerGaps() {
0384:                return autocreateContainerPadding;
0385:            }
0386:
0387:            /**
0388:             * Sets the <code>Group</code> that is responsible for
0389:             * layout along the horizontal axis.
0390:             *
0391:             * @param group <code>Group</code> responsible for layout along
0392:             *          the horizontal axis
0393:             * @throws IllegalArgumentException if group is null
0394:             */
0395:            public void setHorizontalGroup(Group group) {
0396:                if (group == null) {
0397:                    throw new IllegalArgumentException("Group must be non-null");
0398:                }
0399:                horizontalGroup = createTopLevelGroup(group);
0400:            }
0401:
0402:            /**
0403:             * Returns the <code>Group</code> that is responsible for
0404:             * layout along the horizontal axis.
0405:             *
0406:             * @return <code>ParallelGroup</code> responsible for layout along
0407:             *          the horizontal axis.
0408:             */
0409:            public Group getHorizontalGroup() {
0410:                int index = 0;
0411:                if (horizontalGroup.springs.size() > 1) {
0412:                    index = 1;
0413:                }
0414:                return (Group) horizontalGroup.springs.get(index);
0415:            }
0416:
0417:            /**
0418:             * Sets the <code>Group</code> that is responsible for
0419:             * layout along the vertical axis.
0420:             *
0421:             * @param group <code>Group</code> responsible for layout along
0422:             *          the vertical axis.
0423:             * @throws IllegalArgumentException if group is null.
0424:             */
0425:            public void setVerticalGroup(Group group) {
0426:                if (group == null) {
0427:                    throw new IllegalArgumentException("Group must be non-null");
0428:                }
0429:                verticalGroup = createTopLevelGroup(group);
0430:            }
0431:
0432:            /**
0433:             * Returns the <code>ParallelGroup</code> that is responsible for
0434:             * layout along the vertical axis.
0435:             *
0436:             * @return <code>ParallelGroup</code> responsible for layout along
0437:             *          the vertical axis.
0438:             */
0439:            public Group getVerticalGroup() {
0440:                int index = 0;
0441:                if (verticalGroup.springs.size() > 1) {
0442:                    index = 1;
0443:                }
0444:                return (Group) verticalGroup.springs.get(index);
0445:            }
0446:
0447:            /**
0448:             * Wraps the user specified group in a sequential group.  If 
0449:             * container gaps should be generate the necessary springs are
0450:             * added.
0451:             */
0452:            private Group createTopLevelGroup(Group specifiedGroup) {
0453:                SequentialGroup group = createSequentialGroup();
0454:                if (getAutocreateContainerGaps()) {
0455:                    group.addSpring(new ContainerAutopaddingSpring());
0456:                    group.add(specifiedGroup);
0457:                    group.addSpring(new ContainerAutopaddingSpring());
0458:                } else {
0459:                    group.add(specifiedGroup);
0460:                }
0461:                return group;
0462:            }
0463:
0464:            /**
0465:             * Creates and returns a <code>SequentialGroup</code>.
0466:             *
0467:             * @return a new <code>SequentialGroup</code>
0468:             */
0469:            public SequentialGroup createSequentialGroup() {
0470:                return new SequentialGroup();
0471:            }
0472:
0473:            /**
0474:             * Creates and returns a <code>ParallelGroup</code> with a
0475:             * <code>LEADING</code> alignment.  This is a cover method for the more
0476:             * general <code>createParallelGroup(int)</code> method.
0477:             *
0478:             * @return a new ParallelGroup
0479:             * @see #createParallelGroup(int)
0480:             */
0481:            public ParallelGroup createParallelGroup() {
0482:                return createParallelGroup(LEADING);
0483:            }
0484:
0485:            /**
0486:             * Creates and returns an <code>ParallelGroup</code>.  The alignment
0487:             * specifies how children elements should be positioned when the
0488:             * the parallel group is given more space than necessary.  For example,
0489:             * if a ParallelGroup with an alignment of TRAILING is given 100 pixels
0490:             * and a child only needs 50 pixels, the child will be positioned at the
0491:             * position 50.
0492:             *
0493:             * @param alignment alignment for the elements of the Group, one
0494:             *        of <code>LEADING</code>, <code>TRAILING</code>,
0495:             *        <code>CENTER</code> or <code>BASELINE</code>.
0496:             * @throws IllegalArgumentException if alignment is not one of
0497:             *         <code>LEADING</code>, <code>TRAILING</code>,
0498:             *         <code>CENTER</code> or <code>BASELINE</code>
0499:             * @return a new <code>ParallelGroup</code>
0500:             */
0501:            public ParallelGroup createParallelGroup(int alignment) {
0502:                return createParallelGroup(alignment, true);
0503:            }
0504:
0505:            /**
0506:             * Creates and returns an <code>ParallelGroup</code>.  The alignment
0507:             * specifies how children elements should be positioned when the
0508:             * the parallel group is given more space than necessary.  For example,
0509:             * if a ParallelGroup with an alignment of TRAILING is given 100 pixels
0510:             * and a child only needs 50 pixels, the child will be positioned at the
0511:             * position 50.
0512:             *
0513:             * @param alignment alignment for the elements of the Group, one
0514:             *        of <code>LEADING</code>, <code>TRAILING</code>,
0515:             *        <code>CENTER</code> or <code>BASELINE</code>.
0516:             * @param resizable whether or not the group is resizable.  If the group
0517:             *        is not resizable the min/max size will be the same as the
0518:             *        preferred.
0519:             * @throws IllegalArgumentException if alignment is not one of
0520:             *         <code>LEADING</code>, <code>TRAILING</code>,
0521:             *         <code>CENTER</code> or <code>BASELINE</code>
0522:             * @return a new <code>ParallelGroup</code>
0523:             */
0524:            public ParallelGroup createParallelGroup(int alignment,
0525:                    boolean resizable) {
0526:                if (alignment == BASELINE) {
0527:                    return new BaselineGroup(resizable);
0528:                }
0529:                return new ParallelGroup(alignment, resizable);
0530:            }
0531:
0532:            /**
0533:             * Forces the set of components to have the same size.
0534:             * This can be used multiple times to force
0535:             * any number of components to share the same size.
0536:             * <p>
0537:             * Linked Components are not be resizable.
0538:             *
0539:             * @param components Components to force to have same size.
0540:             * @throws IllegalArgumentException if <code>components</code> is
0541:             *         null, or contains null.
0542:             */
0543:            public void linkSize(Component[] components) {
0544:                linkSize(components, HORIZONTAL | VERTICAL);
0545:            }
0546:
0547:            /**
0548:             * Forces the set of components to have the same size.
0549:             * This can be used multiple times to force
0550:             * any number of components to share the same size.
0551:             * <p>
0552:             * Linked Components are not be resizable.
0553:             *
0554:             * @param components Components to force to have same size.
0555:             * @param axis Axis to bind size, one of HORIZONTAL, VERTICAL or
0556:             *             HORIZONTAL | VERTICAL
0557:             * @throws IllegalArgumentException if <code>components</code> is
0558:             *         null, or contains null.
0559:             * @throws IllegalArgumentException if <code>axis</code> does not
0560:             *         contain <code>HORIZONTAL</code> or <code>VERTICAL</code>
0561:             */
0562:            public void linkSize(Component[] components, int axis) {
0563:                if (components == null) {
0564:                    throw new IllegalArgumentException(
0565:                            "Components must be non-null");
0566:                }
0567:                boolean horizontal = ((axis & HORIZONTAL) == HORIZONTAL);
0568:                boolean vertical = ((axis & VERTICAL) == VERTICAL);
0569:                if (!vertical && !horizontal) {
0570:                    throw new IllegalArgumentException(
0571:                            "Axis must contain HORIZONTAL or VERTICAL");
0572:                }
0573:                for (int counter = components.length - 1; counter >= 0; counter--) {
0574:                    Component c = components[counter];
0575:                    if (components[counter] == null) {
0576:                        throw new IllegalArgumentException(
0577:                                "Components must be non-null");
0578:                    }
0579:                    // Force the component to be added
0580:                    getComponentInfo(c);
0581:                }
0582:                if (horizontal) {
0583:                    linkSize0(components, HORIZONTAL);
0584:                }
0585:                if (vertical) {
0586:                    linkSize0(components, VERTICAL);
0587:                }
0588:            }
0589:
0590:            private void linkSize0(Component[] components, int axis) {
0591:                ComponentInfo master = getComponentInfo(
0592:                        components[components.length - 1])
0593:                        .getMasterComponentInfo(axis);
0594:                for (int counter = components.length - 2; counter >= 0; counter--) {
0595:                    master
0596:                            .addChild(getComponentInfo(components[counter]),
0597:                                    axis);
0598:                }
0599:            }
0600:
0601:            /**
0602:             * Removes an existing component replacing it with the specified component.
0603:             *
0604:             * @param existingComponent the Component that should be removed and
0605:             *        replaced with newComponent
0606:             * @param newComponent the Component to put in existingComponents place
0607:             * @throws IllegalArgumentException is either of the Components are null or
0608:             *         if existingComponent is not being managed by this layout manager
0609:             */
0610:            public void replace(Component existingComponent,
0611:                    Component newComponent) {
0612:                if (existingComponent == null || newComponent == null) {
0613:                    throw new IllegalArgumentException(
0614:                            "Components must be non-null");
0615:                }
0616:                ComponentInfo info = (ComponentInfo) componentInfos
0617:                        .remove(existingComponent);
0618:                if (info == null) {
0619:                    throw new IllegalArgumentException(
0620:                            "Component must already exist");
0621:                }
0622:                host.remove(existingComponent);
0623:                host.add(newComponent);
0624:                info.setComponent(newComponent);
0625:                componentInfos.put(newComponent, info);
0626:                invalidateLayout(host);
0627:            }
0628:
0629:            //
0630:            // LayoutManager
0631:            //
0632:            /**
0633:             * Notification that a <code>Component</code> has been added to
0634:             * the parent container.  Developers should not invoke this method
0635:             * directly, instead you should use one of the <code>Group</code>
0636:             * methods to add a <code>Component</code>.
0637:             *
0638:             * @param name the string to be associated with the component
0639:             * @param component the <code>Component</code> to be added
0640:             */
0641:            public void addLayoutComponent(String name, Component component) {
0642:            }
0643:
0644:            /**
0645:             * Notification that a <code>Component</code> has been removed from
0646:             * the parent container.  You should not invoke this method
0647:             * directly, instead invoke <code>remove</code> on the parent
0648:             * <code>Container</code>.
0649:             *
0650:             * @param comp the component to be removed
0651:             * @see java.awt.Component#remove
0652:             */
0653:            public void removeLayoutComponent(Component comp) {
0654:            }
0655:
0656:            /**
0657:             * Returns the preferred size for the specified container.
0658:             *
0659:             * @param parent the container to return size for
0660:             * @throws IllegalArgumentException if <code>parent</code> is not
0661:             *         the same <code>Container</code> that this was created with
0662:             * @throws IllegalStateException if any of the components added to
0663:             *         this layout are not in both a horizontal and vertical group
0664:             * @see java.awt.Container#getPreferredSize
0665:             */
0666:            public Dimension preferredLayoutSize(Container parent) {
0667:                checkParent(parent);
0668:                prepare(PREF_SIZE);
0669:                return adjustSize(horizontalGroup.getPreferredSize(HORIZONTAL),
0670:                        verticalGroup.getPreferredSize(VERTICAL));
0671:            }
0672:
0673:            /**
0674:             * Returns the minimum size for the specified container.
0675:             *
0676:             * @param parent the container to return size for
0677:             * @throws IllegalArgumentException if <code>parent</code> is not
0678:             *         the same <code>Container</code> that this was created with
0679:             * @throws IllegalStateException if any of the components added to
0680:             *         this layout are not in both a horizontal and vertical group
0681:             * @see java.awt.Container#getMinimumSize
0682:             */
0683:            public Dimension minimumLayoutSize(Container parent) {
0684:                checkParent(parent);
0685:                prepare(MIN_SIZE);
0686:                return adjustSize(horizontalGroup.getMinimumSize(HORIZONTAL),
0687:                        verticalGroup.getMinimumSize(VERTICAL));
0688:            }
0689:
0690:            /**
0691:             * Lays out the specified container.
0692:             *
0693:             * @param parent the container to be laid out
0694:             * @throws IllegalStateException if any of the components added to
0695:             *         this layout are not in both a horizontal and vertical group
0696:             */
0697:            public void layoutContainer(Container parent) {
0698:                prepare();
0699:                Insets insets = parent.getInsets();
0700:
0701:                if (getAutocreateGaps() || getAutocreateContainerGaps()
0702:                        || hasPreferredPaddingSprings) {
0703:                    resetAutopadding(horizontalGroup, HORIZONTAL, -1, 0, parent
0704:                            .getWidth()
0705:                            - insets.left - insets.right);
0706:                    resetAutopadding(verticalGroup, VERTICAL, -1, 0, parent
0707:                            .getHeight()
0708:                            - insets.top - insets.bottom);
0709:                }
0710:                horizontalGroup.setSize(HORIZONTAL, 0, parent.getWidth()
0711:                        - insets.left - insets.right);
0712:                verticalGroup.setSize(VERTICAL, 0, parent.getHeight()
0713:                        - insets.top - insets.bottom);
0714:
0715:                Iterator componentInfo = componentInfos.values().iterator();
0716:                while (componentInfo.hasNext()) {
0717:                    ComponentInfo info = (ComponentInfo) componentInfo.next();
0718:                    Component c = info.getComponent();
0719:                    info.setBounds(insets);
0720:                }
0721:            }
0722:
0723:            //
0724:            // LayoutManager2
0725:            //
0726:            /**
0727:             * Notification that a <code>Component</code> has been added to
0728:             * the parent container.  You should not invoke this method
0729:             * directly, instead you should use one of the <code>Group</code>
0730:             * methods to add a <code>Component</code>.
0731:             *
0732:             * @param component The component added
0733:             * @param constraints Description of where to place the component.
0734:             */
0735:            public void addLayoutComponent(Component component,
0736:                    Object constraints) {
0737:            }
0738:
0739:            /**
0740:             * Returns the maximum size for the specified container.
0741:             *
0742:             * @param parent the container to return size for
0743:             * @throws IllegalArgumentException if <code>parent</code> is not
0744:             *         the same <code>Container</code> that this was created with
0745:             * @throws IllegalStateException if any of the components added to
0746:             *         this layout are not in both a horizontal and vertical group
0747:             * @see java.awt.Container#getMaximumSize
0748:             */
0749:            public Dimension maximumLayoutSize(Container parent) {
0750:                checkParent(parent);
0751:                prepare(MAX_SIZE);
0752:                return adjustSize(horizontalGroup.getMaximumSize(HORIZONTAL),
0753:                        verticalGroup.getMaximumSize(VERTICAL));
0754:            }
0755:
0756:            /**
0757:             * Returns the alignment along the x axis.  This specifies how
0758:             * the component would like to be aligned relative to other
0759:             * components.  The value should be a number between 0 and 1
0760:             * where 0 represents alignment along the origin, 1 is aligned
0761:             * the furthest away from the origin, 0.5 is centered, etc.
0762:             *
0763:             * @param parent Container hosting this LayoutManager
0764:             * @throws IllegalArgumentException if <code>parent</code> is not
0765:             *         the same <code>Container</code> that this was created with
0766:             * @return alignment
0767:             */
0768:            public float getLayoutAlignmentX(Container parent) {
0769:                checkParent(parent);
0770:                return .5f;
0771:            }
0772:
0773:            /**
0774:             * Returns the alignment along the y axis.  This specifies how
0775:             * the component would like to be aligned relative to other
0776:             * components.  The value should be a number between 0 and 1
0777:             * where 0 represents alignment along the origin, 1 is aligned
0778:             * the furthest away from the origin, 0.5 is centered, etc.
0779:             *
0780:             * @param parent Container hosting this LayoutManager
0781:             * @throws IllegalArgumentException if <code>parent</code> is not
0782:             *         the same <code>Container</code> that this was created with
0783:             * @return alignment
0784:             */
0785:            public float getLayoutAlignmentY(Container parent) {
0786:                checkParent(parent);
0787:                return .5f;
0788:            }
0789:
0790:            /**
0791:             * Invalidates the layout, indicating that if the layout manager
0792:             * has cached information it should be discarded.
0793:             *
0794:             * @param parent Container hosting this LayoutManager
0795:             * @throws IllegalArgumentException if <code>parent</code> is not
0796:             *         the same <code>Container</code> that this was created with
0797:             */
0798:            public void invalidateLayout(Container parent) {
0799:                checkParent(parent);
0800:                // invalidateLayout is called from Container.invalidate, which
0801:                // does NOT grab the treelock.  All other methods do.  To make sure
0802:                // there aren't any possible threading problems we grab the tree lock
0803:                // here.
0804:                synchronized (parent.getTreeLock()) {
0805:                    horizontalGroup.setSize(HORIZONTAL, UNSET, UNSET);
0806:                    verticalGroup.setSize(VERTICAL, UNSET, UNSET);
0807:                    for (Iterator cis = componentInfos.values().iterator(); cis
0808:                            .hasNext();) {
0809:                        ComponentInfo ci = (ComponentInfo) cis.next();
0810:                        ci.clear();
0811:                    }
0812:                }
0813:            }
0814:
0815:            private void resetAutopadding(Group group, int axis, int sizeType,
0816:                    int origin, int size) {
0817:                group.resetAutopadding();
0818:                switch (sizeType) {
0819:                case MIN_SIZE:
0820:                    size = group.getMinimumSize(axis);
0821:                    break;
0822:                case PREF_SIZE:
0823:                    size = group.getPreferredSize(axis);
0824:                    break;
0825:                case MAX_SIZE:
0826:                    size = group.getMaximumSize(axis);
0827:                    break;
0828:                }
0829:                group.setSize(axis, origin, size);
0830:                group.calculateAutopadding(axis);
0831:            }
0832:
0833:            private void prepare(int sizeType) {
0834:                prepare();
0835:                if (getAutocreateGaps() || getAutocreateContainerGaps()
0836:                        || hasPreferredPaddingSprings) {
0837:                    resetAutopadding(horizontalGroup, HORIZONTAL, sizeType, 0,
0838:                            0);
0839:                    resetAutopadding(verticalGroup, VERTICAL, sizeType, 0, 0);
0840:                }
0841:
0842:            }
0843:
0844:            private void prepare() {
0845:                if (springsAdded) {
0846:                    registerComponents(horizontalGroup, HORIZONTAL);
0847:                    registerComponents(verticalGroup, VERTICAL);
0848:                    checkComponents();
0849:                    horizontalGroup.removeAutopadding();
0850:                    verticalGroup.removeAutopadding();
0851:                    if (getAutocreateGaps()) {
0852:                        adjustAutopadding(true);
0853:                    } else if (hasPreferredPaddingSprings
0854:                            || getAutocreateContainerGaps()) {
0855:                        adjustAutopadding(false);
0856:                    }
0857:                    springsAdded = false;
0858:                }
0859:            }
0860:
0861:            private void checkComponents() {
0862:                Iterator infos = componentInfos.values().iterator();
0863:                while (infos.hasNext()) {
0864:                    ComponentInfo info = (ComponentInfo) infos.next();
0865:                    if (info.horizontalSpring == null) {
0866:                        throw new IllegalStateException(info.component
0867:                                + " is not attached to a horizontal group");
0868:                    }
0869:                    if (info.verticalSpring == null) {
0870:                        throw new IllegalStateException(info.component
0871:                                + " is not attached to a vertical group");
0872:                    }
0873:                }
0874:            }
0875:
0876:            private void registerComponents(Group group, int axis) {
0877:                List springs = group.springs;
0878:                for (int counter = springs.size() - 1; counter >= 0; counter--) {
0879:                    Spring spring = (Spring) springs.get(counter);
0880:                    if (spring instanceof  ComponentSpring) {
0881:                        ((ComponentSpring) spring).installIfNecessary(axis);
0882:                    } else if (spring instanceof  Group) {
0883:                        registerComponents((Group) spring, axis);
0884:                    }
0885:                }
0886:            }
0887:
0888:            private Dimension adjustSize(int width, int height) {
0889:                Insets insets = host.getInsets();
0890:                return new Dimension(width + insets.left + insets.right, height
0891:                        + insets.top + insets.bottom);
0892:            }
0893:
0894:            private void checkParent(Container parent) {
0895:                if (parent != host) {
0896:                    throw new IllegalArgumentException(
0897:                            "GroupLayout can only be used with one Container at a time");
0898:                }
0899:            }
0900:
0901:            /**
0902:             * Returns the <code>ComponentInfo</code> for the specified Component.
0903:             */
0904:            private ComponentInfo getComponentInfo(Component component) {
0905:                ComponentInfo info = (ComponentInfo) componentInfos
0906:                        .get(component);
0907:                if (info == null) {
0908:                    componentInfos.put(component, new ComponentInfo(component));
0909:                    host.add(component);
0910:                }
0911:                return info;
0912:            }
0913:
0914:            /**
0915:             * Adjusts the autopadding springs for the horizontal and vertical
0916:             * groups.  If <code>insert</code> is true this will insert auto padding
0917:             * springs, otherwise this will only adjust the springs that
0918:             * comprise auto preferred padding springs.
0919:             */
0920:            private void adjustAutopadding(boolean insert) {
0921:                horizontalGroup.insertAutopadding(HORIZONTAL, new ArrayList(1),
0922:                        new ArrayList(1), new ArrayList(1), new ArrayList(1),
0923:                        insert);
0924:                verticalGroup.insertAutopadding(VERTICAL, new ArrayList(1),
0925:                        new ArrayList(1), new ArrayList(1), new ArrayList(1),
0926:                        insert);
0927:            }
0928:
0929:            /**
0930:             * Returns true if the two Components have a common ParallelGroup ancestor
0931:             * along the particular axis.
0932:             */
0933:            private boolean areParallelSiblings(Component source,
0934:                    Component target, int axis) {
0935:                ComponentInfo sourceInfo = getComponentInfo(source);
0936:                ComponentInfo targetInfo = getComponentInfo(target);
0937:                Spring sourceSpring;
0938:                Spring targetSpring;
0939:                if (axis == HORIZONTAL) {
0940:                    sourceSpring = sourceInfo.horizontalSpring;
0941:                    targetSpring = targetInfo.horizontalSpring;
0942:                } else {
0943:                    sourceSpring = sourceInfo.verticalSpring;
0944:                    targetSpring = targetInfo.verticalSpring;
0945:                }
0946:                List sourcePath = parallelList;
0947:                sourcePath.clear();
0948:                Spring spring = sourceSpring.getParent();
0949:                while (spring != null) {
0950:                    sourcePath.add(spring);
0951:                    spring = spring.getParent();
0952:                }
0953:                spring = targetSpring.getParent();
0954:                while (spring != null) {
0955:                    if (sourcePath.contains(spring)) {
0956:                        while (spring != null) {
0957:                            if (spring instanceof  ParallelGroup) {
0958:                                return true;
0959:                            }
0960:                            spring = spring.getParent();
0961:                        }
0962:                        return false;
0963:                    }
0964:                    spring = spring.getParent();
0965:                }
0966:                return false;
0967:            }
0968:
0969:            /**
0970:             * Spring consists of a range: min, pref and max a value some where in
0971:             * the middle of that and a location.  Subclasses must override
0972:             * methods to get the min/max/pref and will likely want to override
0973:             * the <code>setSize</code> method.  Spring automatically caches the
0974:             * min/max/pref.  If the min/pref/max has internally changes, or needs
0975:             * to be updated you must invoked clear.
0976:             */
0977:            abstract class Spring {
0978:                private int size;
0979:                private int min;
0980:                private int max;
0981:                private int pref;
0982:                private Spring parent;
0983:
0984:                private int alignment;
0985:
0986:                Spring() {
0987:                    min = pref = max = UNSET;
0988:                }
0989:
0990:                abstract int getMinimumSize0(int axis);
0991:
0992:                abstract int getPreferredSize0(int axis);
0993:
0994:                abstract int getMaximumSize0(int axis);
0995:
0996:                /**
0997:                 * Sets the parent of this Spring.
0998:                 */
0999:                void setParent(Spring parent) {
1000:                    this .parent = parent;
1001:                }
1002:
1003:                /**
1004:                 * Returns the parent of this spring.
1005:                 */
1006:                Spring getParent() {
1007:                    return parent;
1008:                }
1009:
1010:                // This is here purely as a conveniance for ParallelGroup to avoid
1011:                // having to track alignment separately.
1012:                void setAlignment(int alignment) {
1013:                    checkAlignment(alignment, false);
1014:                    this .alignment = alignment;
1015:                }
1016:
1017:                int getAlignment() {
1018:                    return alignment;
1019:                }
1020:
1021:                /**
1022:                 * Returns the minimum size.
1023:                 */
1024:                final int getMinimumSize(int axis) {
1025:                    if (min == UNSET) {
1026:                        min = constrain(getMinimumSize0(axis));
1027:                    }
1028:                    return min;
1029:                }
1030:
1031:                /**
1032:                 * Returns the preferred size.
1033:                 */
1034:                final int getPreferredSize(int axis) {
1035:                    if (pref == UNSET) {
1036:                        pref = constrain(getPreferredSize0(axis));
1037:                    }
1038:                    return pref;
1039:                }
1040:
1041:                /**
1042:                 * Returns the maximum size.
1043:                 */
1044:                final int getMaximumSize(int axis) {
1045:                    if (max == UNSET) {
1046:                        max = constrain(getMaximumSize0(axis));
1047:                    }
1048:                    return max;
1049:                }
1050:
1051:                /**
1052:                 * Resets the cached min/max/pref.
1053:                 */
1054:                void clear() {
1055:                    size = min = pref = max = UNSET;
1056:                }
1057:
1058:                /**
1059:                 * Sets the value and location of the spring.  Subclasses
1060:                 * will want to invoke super, then do any additional sizing.
1061:                 *
1062:                 * @param axis HORIZONTAL or VERTICAL
1063:                 * @param origin of this Spring
1064:                 * @param size of the Spring.  If size is UNSET, this invokes
1065:                 *        clear.
1066:                 */
1067:                void setSize(int axis, int origin, int size) {
1068:                    this .size = size;
1069:                    if (size == UNSET) {
1070:                        clear();
1071:                    }
1072:                }
1073:
1074:                /**
1075:                 * Returns the current size.
1076:                 */
1077:                int getSize() {
1078:                    return size;
1079:                }
1080:
1081:                int constrain(int value) {
1082:                    return Math.min(value, Short.MAX_VALUE);
1083:                }
1084:            }
1085:
1086:            /**
1087:             * Group provides for commonality between the two types of operations
1088:             * supported by <code>GroupLayout</code>: laying out components one
1089:             * after another (<code>SequentialGroup</code>) or layout on top
1090:             * of each other (<code>ParallelGroup</code>). Use one of
1091:             * <code>createSequentialGroup</code> or
1092:             * <code>createParallelGroup</code> to create one.
1093:             */
1094:            public abstract class Group extends Spring {
1095:                // private int origin;
1096:                // private int size;
1097:                List springs;
1098:
1099:                Group() {
1100:                    springs = new ArrayList();
1101:                }
1102:
1103:                int indexOf(Spring spring) {
1104:                    return springs.indexOf(spring);
1105:                }
1106:
1107:                /**
1108:                 * Adds the Spring to the list of <code>Spring</code>s and returns
1109:                 * the receiver.
1110:                 */
1111:                Group addSpring(Spring spring, int index) {
1112:                    springs.add(spring);
1113:                    spring.setParent(this );
1114:                    if (!(spring instanceof  AutopaddingSpring)) {
1115:                        springsAdded = true;
1116:                    }
1117:                    return this ;
1118:                }
1119:
1120:                /**
1121:                 * Adds the Spring to the list of <code>Spring</code>s and returns
1122:                 * the receiver.
1123:                 */
1124:                Group addSpring(Spring spring) {
1125:                    addSpring(spring, springs.size());
1126:                    return this ;
1127:                }
1128:
1129:                //
1130:                // Spring methods
1131:                //
1132:
1133:                void setParent(Spring parent) {
1134:                    super .setParent(parent);
1135:                    for (int counter = springs.size() - 1; counter >= 0; counter--) {
1136:                        ((Spring) springs.get(counter)).setParent(this );
1137:                    }
1138:                }
1139:
1140:                void setSize(int axis, int origin, int size) {
1141:                    super .setSize(axis, origin, size);
1142:                    if (size == UNSET) {
1143:                        for (int counter = springs.size() - 1; counter >= 0; counter--) {
1144:                            getSpring(counter).setSize(axis, origin, size);
1145:                        }
1146:                    } else {
1147:                        setSize0(axis, origin, size);
1148:                    }
1149:                }
1150:
1151:                /**
1152:                 * This is invoked from <code>setSize</code> if passed a value
1153:                 * other than UNSET.
1154:                 */
1155:                abstract void setSize0(int axis, int origin, int size);
1156:
1157:                int getMinimumSize0(int axis) {
1158:                    return calculateSize(axis, MIN_SIZE);
1159:                }
1160:
1161:                int getPreferredSize0(int axis) {
1162:                    return calculateSize(axis, PREF_SIZE);
1163:                }
1164:
1165:                int getMaximumSize0(int axis) {
1166:                    return calculateSize(axis, MAX_SIZE);
1167:                }
1168:
1169:                /**
1170:                 * Used to compute how the two values representing two springs
1171:                 * will be combined.  For example, a group that layed things out
1172:                 * one after the next would return <code>a + b</code>.
1173:                 */
1174:                abstract int operator(int a, int b);
1175:
1176:                /**
1177:                 * Calculates the specified size.  This is called from
1178:                 * one of the <code>getMinimumSize0</code>,
1179:                 * <code>getPreferredSize0</code> or
1180:                 * <code>getMaximumSize0</code> methods.  This will invoke
1181:                 * to <code>operator</code> to combine the values.
1182:                 */
1183:                int calculateSize(int axis, int type) {
1184:                    int count = springs.size();
1185:                    if (count == 0) {
1186:                        return 0;
1187:                    }
1188:                    if (count == 1) {
1189:                        return getSize(getSpring(0), axis, type);
1190:                    }
1191:                    int size = constrain(operator(getSize(getSpring(0), axis,
1192:                            type), getSize(getSpring(1), axis, type)));
1193:                    for (int counter = 2; counter < count; counter++) {
1194:                        size = constrain(operator(size, getSize(
1195:                                getSpring(counter), axis, type)));
1196:                    }
1197:                    return size;
1198:                }
1199:
1200:                Spring getSpring(int index) {
1201:                    return (Spring) springs.get(index);
1202:                }
1203:
1204:                int getSize(Spring spring, int axis, int type) {
1205:                    switch (type) {
1206:                    case MIN_SIZE:
1207:                        return spring.getMinimumSize(axis);
1208:                    case PREF_SIZE:
1209:                        return spring.getPreferredSize(axis);
1210:                    case MAX_SIZE:
1211:                        return spring.getMaximumSize(axis);
1212:                    }
1213:                    return 0;
1214:                }
1215:
1216:                // Padding
1217:                /**
1218:                 * Adjusts the autopadding springs in this group and its children.
1219:                 * If <code>insert</code> is true this will insert auto padding
1220:                 * springs, otherwise this will only adjust the springs that
1221:                 * comprise auto preferred padding springs.
1222:                 *
1223:                 * @param axis the axis of the springs; HORIZONTAL or VERTICAL
1224:                 * @param leadingPadding List of AutopaddingSprings that occur before
1225:                 *                       this Group
1226:                 * @param trailingPadding any trailing autopadding springs are added
1227:                 *                        to this on exit
1228:                 * @param leading List of ComponentSprings that occur before this Group
1229:                 * @param trailing any trailing ComponentSpring are added to this
1230:                 *                 List
1231:                 * @param insert Whether or not to insert AutopaddingSprings or just
1232:                 *               adjust any existing AutopaddingSprings.
1233:                 */
1234:                abstract void insertAutopadding(int axis, List leadingPadding,
1235:                        List trailingPadding, List leading, List trailing,
1236:                        boolean insert);
1237:
1238:                /**
1239:                 * Removes any AutopaddingSprings.
1240:                 */
1241:                void removeAutopadding() {
1242:                    for (int counter = springs.size() - 1; counter >= 0; counter--) {
1243:                        Spring spring = (Spring) springs.get(counter);
1244:                        if (spring instanceof  AutopaddingSpring) {
1245:                            if (((AutopaddingSpring) spring).getUserCreated()) {
1246:                                ((AutopaddingSpring) spring).reset();
1247:                            } else {
1248:                                springs.remove(counter);
1249:                            }
1250:                        } else if (spring instanceof  Group) {
1251:                            ((Group) spring).removeAutopadding();
1252:                        }
1253:                    }
1254:                }
1255:
1256:                void resetAutopadding() {
1257:                    // Clear cached pref/min/max.
1258:                    clear();
1259:                    for (int counter = springs.size() - 1; counter >= 0; counter--) {
1260:                        Spring spring = (Spring) springs.get(counter);
1261:                        if (spring instanceof  AutopaddingSpring) {
1262:                            ((AutopaddingSpring) spring).clear();
1263:                        } else if (spring instanceof  Group) {
1264:                            ((Group) spring).resetAutopadding();
1265:                        }
1266:                    }
1267:                }
1268:
1269:                void calculateAutopadding(int axis) {
1270:                    for (int counter = springs.size() - 1; counter >= 0; counter--) {
1271:                        Spring spring = (Spring) springs.get(counter);
1272:                        if (spring instanceof  AutopaddingSpring) {
1273:                            // Force size to be reset.
1274:                            spring.clear();
1275:                            ((AutopaddingSpring) spring).calculatePadding(axis);
1276:                        } else if (spring instanceof  Group) {
1277:                            ((Group) spring).calculateAutopadding(axis);
1278:                        }
1279:                    }
1280:                    // Clear cached pref/min/max.
1281:                    clear();
1282:                }
1283:            }
1284:
1285:            /**
1286:             * A <code>Group</code> that lays out its elements sequentially, one
1287:             * after another.  This class has no public constructor, use the
1288:             * <code>createSequentialGroup</code> method to create one.
1289:             *
1290:             * @see #createSequentialGroup()
1291:             */
1292:            public class SequentialGroup extends Group {
1293:                SequentialGroup() {
1294:                }
1295:
1296:                /**
1297:                 * Adds the specified <code>Group</code> to this
1298:                 * <code>SequentialGroup</code>
1299:                 *
1300:                 * @param group the Group to add
1301:                 * @return this Group
1302:                 */
1303:                public SequentialGroup add(Group group) {
1304:                    return (SequentialGroup) addSpring(group);
1305:                }
1306:
1307:                /**
1308:                 * Adds the specified Component.  If the Component's min/max
1309:                 * are different from its pref than the component will be resizable.
1310:                 *
1311:                 * @param component the Component to add
1312:                 * @return this <code>SequentialGroup</code>
1313:                 */
1314:                public SequentialGroup add(Component component) {
1315:                    return add(component, DEFAULT_SIZE, DEFAULT_SIZE,
1316:                            DEFAULT_SIZE);
1317:                }
1318:
1319:                /**
1320:                 * Adds the specified <code>Component</code>.  Min, pref and max
1321:                 * can be absolute values, or they can be one of
1322:                 * <code>DEFAULT_SIZE</code> or <code>PREFERRED_SIZE</code>.  For
1323:                 * example, the following:
1324:                 * <pre>
1325:                 *   add(component, PREFERRED_SIZE, PREFERRED_SIZE, 1000);
1326:                 * </pre>
1327:                 * Forces a max of 1000, with the min and preferred equalling that
1328:                 * of the preferred size of <code>component</code>.
1329:                 *
1330:                 * @param component the Component to add
1331:                 * @param min the minimum size
1332:                 * @param pref the preferred size
1333:                 * @param max the maximum size
1334:                 * @throws IllegalArgumentException if min, pref or max are
1335:                 *         not positive and not one of PREFERRED_SIZE or DEFAULT_SIZE
1336:                 * @return this <code>SequentialGroup</code>
1337:                 */
1338:                public SequentialGroup add(Component component, int min,
1339:                        int pref, int max) {
1340:                    return (SequentialGroup) addSpring(new ComponentSpring(
1341:                            component, min, pref, max));
1342:                }
1343:
1344:                /**
1345:                 * Adds a rigid gap.
1346:                 *
1347:                 * @param pref the size of the gap
1348:                 * @throws IllegalArgumentException if min < 0 or pref < 0 or max < 0
1349:                 *         or the following is not meant min <= pref <= max
1350:                 * @return this <code>SequentialGroup</code>
1351:                 */
1352:                public SequentialGroup add(int pref) {
1353:                    return add(pref, pref, pref);
1354:                }
1355:
1356:                /**
1357:                 * Adds a gap with the specified size.
1358:                 *
1359:                 * @param min the minimum size of the gap, or PREFERRED_SIZE
1360:                 * @param pref the preferred size of the gap
1361:                 * @param max the maximum size of the gap, or PREFERRED_SIZE
1362:                 * @throws IllegalArgumentException if min < 0 or pref < 0 or max < 0
1363:                 *         or the following is not meant min <= pref <= max
1364:                 * @return this <code>SequentialGroup</code>
1365:                 */
1366:                public SequentialGroup add(int min, int pref, int max) {
1367:                    return (SequentialGroup) addSpring(new GapSpring(min, pref,
1368:                            max));
1369:                }
1370:
1371:                /**
1372:                 * Adds an element representing the preferred gap between the two
1373:                 * components.
1374:                 * 
1375:                 * @param comp1 the first component
1376:                 * @param comp2 the second component
1377:                 * @param type the type of gap; one of the constants defined by
1378:                 *        LayoutStyle
1379:                 * @return this <code>SequentialGroup</code>
1380:                 * @throws IllegalArgumentException if <code>type</code> is not a
1381:                 *         valid LayoutStyle constant
1382:                 * @see LayoutStyle
1383:                 */
1384:                public SequentialGroup addPreferredGap(Component comp1,
1385:                        Component comp2, int type) {
1386:                    return addPreferredGap(comp1, comp2, type, false);
1387:                }
1388:
1389:                /**
1390:                 * Adds an element representing the preferred gap between the two
1391:                 * components.
1392:                 * 
1393:                 * @param comp1 the first component
1394:                 * @param comp2 the second component
1395:                 * @param type the type of gap; one of the constants defined by
1396:                 *        LayoutStyle
1397:                 * @param canGrow true if the gap can grow if more
1398:                 *                space is available
1399:                 * @return this <code>SequentialGroup</code>
1400:                 * @throws IllegalArgumentException if <code>type</code> is not a
1401:                 *         valid LayoutStyle constant
1402:                 * @see LayoutStyle
1403:                 */
1404:                public SequentialGroup addPreferredGap(Component comp1,
1405:                        Component comp2, int type, boolean canGrow) {
1406:                    if (type != LayoutStyle.RELATED
1407:                            && type != LayoutStyle.UNRELATED
1408:                            && type != LayoutStyle.INDENT) {
1409:                        throw new IllegalArgumentException(
1410:                                "Invalid type argument");
1411:                    }
1412:                    return (SequentialGroup) addSpring(new PaddingSpring(comp1,
1413:                            comp2, type, canGrow));
1414:                }
1415:
1416:                /**
1417:                 * Adds an element representing the preferred gap between the
1418:                 * nearest components.  That is, during layout the neighboring
1419:                 * components are found, and the min, pref and max of this
1420:                 * element is set based on the preferred gap between the
1421:                 * components.  If no neighboring components are found the
1422:                 * min, pref and max are set to 0.
1423:                 * 
1424:                 * @param type the type of gap; one of the LayoutStyle constants
1425:                 * @return this SequentialGroup
1426:                 * @throws IllegalArgumentException if type is not one of
1427:                 *         <code>LayoutStyle.RELATED</code> or
1428:                 *         <code>LayoutStyle.UNRELATED</code>
1429:                 * @see LayoutStyle
1430:                 */
1431:                public SequentialGroup addPreferredGap(int type) {
1432:                    return addPreferredGap(type, DEFAULT_SIZE, DEFAULT_SIZE);
1433:                }
1434:
1435:                /**
1436:                 * Adds an element for the preferred gap between the
1437:                 * nearest components.  That is, during layout the neighboring
1438:                 * components are found, and the min of this
1439:                 * element is set based on the preferred gap between the
1440:                 * components.  If no neighboring components are found the
1441:                 * min is set to 0.  This method allows you to specify the
1442:                 * preferred and maximum size by way of the <code>pref</code>
1443:                 * and <code>max</code> arguments.  These can either be a
1444:                 * value &gt;= 0, in which case the preferred or max is the max
1445:                 * of the argument and the preferred gap, of DEFAULT_VALUE in
1446:                 * which case the value is the same as the preferred gap.
1447:                 * 
1448:                 * @param type the type of gap; one of LayoutStyle.RELATED or
1449:                 *        LayoutStyle.UNRELATED
1450:                 * @param pref the preferred size; one of DEFAULT_SIZE or a value > 0
1451:                 * @param max the maximum size; one of DEFAULT_SIZE, PREFERRED_SIZE
1452:                 *        or a value > 0
1453:                 * @return this SequentialGroup
1454:                 * @throws IllegalArgumentException if type is not one of
1455:                 *         <code>LayoutStyle.RELATED</code> or
1456:                 *         <code>LayoutStyle.UNRELATED</code> or pref/max is
1457:                 *         != DEFAULT_SIZE and < 0, or pref > max
1458:                 * @see LayoutStyle
1459:                 */
1460:                public SequentialGroup addPreferredGap(int type, int pref,
1461:                        int max) {
1462:                    if (type != LayoutStyle.RELATED
1463:                            && type != LayoutStyle.UNRELATED) {
1464:                        throw new IllegalArgumentException(
1465:                                "Padding type must be one of Padding.RELATED or Padding.UNRELATED");
1466:                    }
1467:                    if ((pref < 0 && pref != DEFAULT_SIZE)
1468:                            || (max < 0 && max != DEFAULT_SIZE && max != PREFERRED_SIZE)
1469:                            || (pref >= 0 && max >= 0 && pref > max)) {
1470:                        throw new IllegalArgumentException(
1471:                                "Pref and max must be either DEFAULT_VALUE or >= 0 and pref <= max");
1472:                    }
1473:                    hasPreferredPaddingSprings = true;
1474:                    return (SequentialGroup) addSpring(new AutopaddingSpring(
1475:                            type, pref, max));
1476:                }
1477:
1478:                /**
1479:                 * Adds an element representing the preferred gap between one edge
1480:                 * of the container and the next/previous Component.  This will have
1481:                 * no effect if the next/previous element is not a Component and does
1482:                 * not touch one edge of the parent container. 
1483:                 *
1484:                 * @return this <code>SequentialGroup</code>.
1485:                 */
1486:                public SequentialGroup addContainerGap() {
1487:                    return addContainerGap(DEFAULT_SIZE, DEFAULT_SIZE);
1488:                }
1489:
1490:                /**
1491:                 * Adds an element representing the preferred gap between one edge
1492:                 * of the container and the next/previous Component.  This will have
1493:                 * no effect if the next/previous element is not a Component and does
1494:                 * not touch one edge of the parent container. 
1495:                 *
1496:                 * @param pref the preferred size; one of DEFAULT_SIZE or a value > 0
1497:                 * @param max the maximum size; one of DEFAULT_SIZE, PREFERRED_SIZE
1498:                 *        or a value > 0.
1499:                 * @throws IllegalArgumentException if pref/max is
1500:                 *         != DEFAULT_SIZE and < 0, or pref > max
1501:                 * @return this <code>SequentialGroup</code>
1502:                 */
1503:                public SequentialGroup addContainerGap(int pref, int max) {
1504:                    if ((pref < 0 && pref != DEFAULT_SIZE)
1505:                            || (max < 0 && max != DEFAULT_SIZE && max != PREFERRED_SIZE)
1506:                            || (pref >= 0 && max >= 0 && pref > max)) {
1507:                        throw new IllegalArgumentException(
1508:                                "Pref and max must be either DEFAULT_VALUE or >= 0 and pref <= max");
1509:                    }
1510:                    hasPreferredPaddingSprings = true;
1511:                    return (SequentialGroup) addSpring(new ContainerAutopaddingSpring(
1512:                            pref, max));
1513:                }
1514:
1515:                int operator(int a, int b) {
1516:                    return constrain(a) + constrain(b);
1517:                }
1518:
1519:                void setSize0(int axis, int origin, int size) {
1520:                    int pref = getPreferredSize(axis);
1521:                    if ((size - pref) == 0) {
1522:                        for (int counter = 0, max = springs.size(); counter < max; counter++) {
1523:                            Spring spring = getSpring(counter);
1524:                            int springPref = spring.getPreferredSize(axis);
1525:                            spring.setSize(axis, origin, springPref);
1526:                            origin += springPref;
1527:                        }
1528:                    } else if (springs.size() == 1) {
1529:                        Spring spring = getSpring(0);
1530:                        spring.setSize(axis, origin, Math.min(size, spring
1531:                                .getMaximumSize(axis)));
1532:                    } else if (springs.size() > 1) {
1533:                        // Adjust between min/pref
1534:                        resize(axis, origin, size);
1535:                    }
1536:                }
1537:
1538:                private void resize(int axis, int origin, int size) {
1539:                    int delta = size - getPreferredSize(axis);
1540:                    boolean useMin = (delta < 0);
1541:                    int springCount = springs.size();
1542:                    if (useMin) {
1543:                        delta *= -1;
1544:                    }
1545:
1546:                    // First pass, sort the resizable springs into resizable
1547:                    List resizable = buildResizableList(axis, useMin);
1548:                    int resizableCount = resizable.size();
1549:
1550:                    if (resizableCount > 0) {
1551:                        int sDelta = delta / resizableCount;
1552:                        int slop = delta - sDelta * resizableCount;
1553:                        int[] sizes = new int[springCount];
1554:                        int sign = useMin ? -1 : 1;
1555:                        // Second pass, accumulate the resulting deltas (relative to
1556:                        // preferred) into sizes.
1557:                        for (int counter = 0; counter < resizableCount; counter++) {
1558:                            SpringDelta springDelta = (SpringDelta) resizable
1559:                                    .get(counter);
1560:                            if ((counter + 1) == resizableCount) {
1561:                                sDelta += slop;
1562:                            }
1563:                            springDelta.delta = Math.min(sDelta,
1564:                                    springDelta.delta);
1565:                            delta -= springDelta.delta;
1566:                            if (springDelta.delta != sDelta
1567:                                    && counter + 1 < resizableCount) {
1568:                                // Spring didn't take all the space, reset how much
1569:                                // each spring will get.
1570:                                sDelta = delta / (resizableCount - counter - 1);
1571:                                slop = delta - sDelta
1572:                                        * (resizableCount - counter - 1);
1573:                            }
1574:                            Spring spring = getSpring(springDelta.index);
1575:                            sizes[springDelta.index] = sign * springDelta.delta;
1576:                        }
1577:
1578:                        // And finally set the size of each spring
1579:                        for (int counter = 0; counter < springCount; counter++) {
1580:                            Spring spring = getSpring(counter);
1581:                            int sSize = spring.getPreferredSize(axis)
1582:                                    + sizes[counter];
1583:                            spring.setSize(axis, origin, sSize);
1584:                            origin += sSize;
1585:                        }
1586:                    } else {
1587:                        // Nothing resizable, use the min or max of each of the
1588:                        // springs.
1589:                        for (int counter = 0; counter < springCount; counter++) {
1590:                            Spring spring = getSpring(counter);
1591:                            int sSize;
1592:                            if (useMin) {
1593:                                sSize = spring.getMinimumSize(axis);
1594:                            } else {
1595:                                sSize = spring.getMaximumSize(axis);
1596:                            }
1597:                            spring.setSize(axis, origin, sSize);
1598:                            origin += sSize;
1599:                        }
1600:                    }
1601:                }
1602:
1603:                /**
1604:                 * Returns the sorted list of SpringDelta's for the current set of
1605:                 * Springs.
1606:                 */
1607:                private List buildResizableList(int axis, boolean useMin) {
1608:                    // First pass, figure out what is resizable
1609:                    int size = springs.size();
1610:                    List sorted = new ArrayList(size);
1611:                    for (int counter = 0; counter < size; counter++) {
1612:                        Spring spring = getSpring(counter);
1613:                        int sDelta;
1614:                        if (useMin) {
1615:                            sDelta = spring.getPreferredSize(axis)
1616:                                    - spring.getMinimumSize(axis);
1617:                        } else {
1618:                            sDelta = spring.getMaximumSize(axis)
1619:                                    - spring.getPreferredSize(axis);
1620:                        }
1621:                        if (sDelta > 0) {
1622:                            sorted.add(new SpringDelta(counter, sDelta));
1623:                        }
1624:                    }
1625:                    Collections.sort(sorted);
1626:                    return sorted;
1627:                }
1628:
1629:                /**
1630:                 * Returns an AutopaddingSpring, or null, at the specified index.
1631:                 * If the Spring at index is an AutopaddingSpring and user created
1632:                 * it will be returned.  Otherwise if insert is true this will
1633:                 * create and AutopaddingSpring and insert it.  If insert is false
1634:                 * null will be returned.
1635:                 */
1636:                private AutopaddingSpring getNextAutopadding(int index,
1637:                        boolean insert) {
1638:                    Spring spring = getSpring(index);
1639:                    if (spring instanceof  AutopaddingSpring
1640:                            && ((AutopaddingSpring) spring).getUserCreated()) {
1641:                        return (AutopaddingSpring) spring;
1642:                    }
1643:                    if (insert) {
1644:                        AutopaddingSpring autoSpring = new AutopaddingSpring();
1645:                        springs.add(index, autoSpring);
1646:                        return autoSpring;
1647:                    }
1648:                    return null;
1649:                }
1650:
1651:                void insertAutopadding(int axis, List leadingPadding,
1652:                        List trailingPadding, List leading, List trailing,
1653:                        boolean insert) {
1654:                    List newLeadingPadding = new ArrayList(leadingPadding);
1655:                    List newTrailingPadding = new ArrayList(1);
1656:                    List newLeading = new ArrayList(leading);
1657:                    List newTrailing = null;
1658:                    for (int counter = 0; counter < springs.size(); counter++) {
1659:                        Spring spring = getSpring(counter);
1660:                        if (spring instanceof  AutopaddingSpring) {
1661:                            AutopaddingSpring padding = (AutopaddingSpring) spring;
1662:                            padding.setSources(newLeading);
1663:                            newLeading.clear();
1664:                            if (counter + 1 == springs.size()) {
1665:                                if (!(padding instanceof  ContainerAutopaddingSpring)) {
1666:                                    trailingPadding.add(padding);
1667:                                }
1668:                            } else {
1669:                                newLeadingPadding.clear();
1670:                                newLeadingPadding.add(padding);
1671:                            }
1672:                        } else {
1673:                            if (newLeading.size() > 0 && insert) {
1674:                                AutopaddingSpring padding = new AutopaddingSpring();
1675:                                // Force this to be revisted by decrementing counter
1676:                                // and breaking
1677:                                springs.add(counter--, padding);
1678:                                continue;
1679:                            }
1680:                            if (spring instanceof  ComponentSpring) {
1681:                                ComponentSpring cSpring = (ComponentSpring) spring;
1682:                                for (int i = 0; i < newLeadingPadding.size(); i++) {
1683:                                    ((AutopaddingSpring) newLeadingPadding
1684:                                            .get(i)).add(cSpring, axis);
1685:                                }
1686:                                newLeading.clear();
1687:                                newLeadingPadding.clear();
1688:                                if (counter + 1 == springs.size()) {
1689:                                    trailing.add(cSpring);
1690:                                } else {
1691:                                    newLeading.add(cSpring);
1692:                                }
1693:                            } else if (spring instanceof  Group) {
1694:                                if (newTrailing == null) {
1695:                                    newTrailing = new ArrayList(1);
1696:                                } else {
1697:                                    newTrailing.clear();
1698:                                }
1699:                                newTrailingPadding.clear();
1700:                                ((Group) spring).insertAutopadding(axis,
1701:                                        newLeadingPadding, newTrailingPadding,
1702:                                        newLeading, newTrailing, insert);
1703:                                newLeading.clear();
1704:                                newLeadingPadding.clear();
1705:                                if (counter + 1 == springs.size()) {
1706:                                    trailing.addAll(newTrailing);
1707:                                    trailingPadding.addAll(newTrailingPadding);
1708:                                } else {
1709:                                    newLeading.addAll(newTrailing);
1710:                                    newLeadingPadding
1711:                                            .addAll(newTrailingPadding);
1712:                                }
1713:                            } else {
1714:                                newLeadingPadding.clear();
1715:                                newLeading.clear();
1716:                            }
1717:                        }
1718:                    }
1719:                }
1720:            }
1721:
1722:            /**
1723:             * Used in figuring out how much space to give resizable springs.
1724:             */
1725:            private static class SpringDelta implements  Comparable {
1726:                // Original index.
1727:                public int index;
1728:                // Delta, one of pref - min or max - pref.
1729:                public int delta;
1730:
1731:                public SpringDelta(int index, int delta) {
1732:                    this .index = index;
1733:                    this .delta = delta;
1734:                }
1735:
1736:                public int compareTo(Object o) {
1737:                    return delta - ((SpringDelta) o).delta;
1738:                }
1739:
1740:                public String toString() {
1741:                    return super .toString() + "[index=" + index + ", delta="
1742:                            + delta + "]";
1743:                }
1744:            }
1745:
1746:            /**
1747:             * A <code>Group</code> that lays out its elements on top of each
1748:             * other.  If a child element is smaller than the provided space it
1749:             * is aligned based on the alignment of the child (if specified) or
1750:             * on the alignment of the ParallelGroup.
1751:             *
1752:             * @see #createParallelGroup()
1753:             */
1754:            public class ParallelGroup extends Group {
1755:                // How children are layed out.
1756:                private int childAlignment;
1757:                // Whether or not we're resizable.
1758:                private boolean resizable;
1759:
1760:                ParallelGroup(int childAlignment, boolean resizable) {
1761:                    checkAlignment(childAlignment, true);
1762:                    this .childAlignment = childAlignment;
1763:                    this .resizable = resizable;
1764:                }
1765:
1766:                /**
1767:                 * Adds the specified <code>Group</code>.
1768:                 *
1769:                 * @param group the Group to add
1770:                 * @return this Group
1771:                 */
1772:                public ParallelGroup add(Group group) {
1773:                    return (ParallelGroup) addSpring(group);
1774:                }
1775:
1776:                /**
1777:                 * Adds the specified Component.  If the Component's min/max
1778:                 * are different from its pref than the component will be resizable.
1779:                 *
1780:                 * @param component the Component to add
1781:                 * @return this <code>ParallelGroup</code>
1782:                 */
1783:                public ParallelGroup add(Component component) {
1784:                    return add(component, DEFAULT_SIZE, DEFAULT_SIZE,
1785:                            DEFAULT_SIZE);
1786:                }
1787:
1788:                /**
1789:                 * Adds the specified <code>Component</code>.  Min, pref and max
1790:                 * can be absolute values, or they can be one of
1791:                 * <code>DEFAULT_SIZE</code> or <code>PREFERRED_SIZE</code>.  For
1792:                 * example, the following:
1793:                 * <pre>
1794:                 *   add(component, PREFERRED_SIZE, PREFERRED_SIZE, 1000);
1795:                 * </pre>
1796:                 * Forces a max of 1000, with the min and preferred equalling that
1797:                 * of the preferred size of <code>component</code>.
1798:                 *
1799:                 * @param component the Component to add
1800:                 * @param min the minimum size
1801:                 * @param pref the preferred size
1802:                 * @param max the maximum size
1803:                 * @throws IllegalArgumentException if min, pref or max are
1804:                 *         not positive and not one of PREFERRED_SIZE or DEFAULT_SIZE.
1805:                 * @return this <code>SequentialGroup</code>
1806:                 */
1807:                public ParallelGroup add(Component component, int min,
1808:                        int pref, int max) {
1809:                    return (ParallelGroup) addSpring(new ComponentSpring(
1810:                            component, min, pref, max));
1811:                }
1812:
1813:                /**
1814:                 * Adds a rigid gap.
1815:                 *
1816:                 * @param pref the size of the gap
1817:                 * @throws IllegalArgumentException if min < 0 or pref < 0 or max < 0
1818:                 *         or the following is not meant min <= pref <= max.
1819:                 * @return this <code>ParallelGroup</code>
1820:                 */
1821:                public ParallelGroup add(int pref) {
1822:                    return add(pref, pref, pref);
1823:                }
1824:
1825:                /**
1826:                 * Adds a gap with the specified size.
1827:                 *
1828:                 * @param min the minimum size of the gap
1829:                 * @param pref the preferred size of the gap
1830:                 * @param max the maximum size of the gap
1831:                 * @throws IllegalArgumentException if min < 0 or pref < 0 or max < 0
1832:                 *         or the following is not meant min <= pref <= max.
1833:                 * @return this <code>ParallelGroup</code>
1834:                 */
1835:                public ParallelGroup add(int min, int pref, int max) {
1836:                    return (ParallelGroup) addSpring(new GapSpring(min, pref,
1837:                            max));
1838:                }
1839:
1840:                /**
1841:                 * Adds the specified <code>Group</code> as a child of this group.
1842:                 *
1843:                 * @param alignment the alignment of the Group.
1844:                 * @param group the Group to add
1845:                 * @return this <code>ParallelGroup</code>
1846:                 * @throws IllegalArgumentException if alignment is not one of
1847:                 *         <code>LEADING</code>, <code>TRAILING</code> or
1848:                 *         <code>CENTER</code>
1849:                 */
1850:                public ParallelGroup add(int alignment, Group group) {
1851:                    group.setAlignment(alignment);
1852:                    return (ParallelGroup) addSpring(group);
1853:                }
1854:
1855:                /**
1856:                 * Adds the specified Component.  If the Component's min/max
1857:                 * are different from its pref than the component will be resizable.
1858:                 *
1859:                 * @param alignment the alignment for the component
1860:                 * @param component the Component to add
1861:                 * @return this <code>Group</code>
1862:                 * @throws IllegalArgumentException if alignment is not one of
1863:                 *         <code>LEADING</code>, <code>TRAILING</code> or
1864:                 *         <code>CENTER</code>
1865:                 */
1866:                public ParallelGroup add(int alignment, Component component) {
1867:                    return add(alignment, component, DEFAULT_SIZE,
1868:                            DEFAULT_SIZE, DEFAULT_SIZE);
1869:                }
1870:
1871:                /**
1872:                 * Adds the specified <code>Component</code>.  Min, pref and max
1873:                 * can be absolute values, or they can be one of
1874:                 * <code>DEFAULT_SIZE</code> or <code>PREFERRED_SIZE</code>.  For
1875:                 * example, the following:
1876:                 * <pre>
1877:                 *   add(component, PREFERRED_SIZE, PREFERRED_SIZE, 1000);
1878:                 * </pre>
1879:                 * Forces a max of 1000, with the min and preferred equalling that
1880:                 * of the preferred size of <code>component</code>.
1881:                 *
1882:                 * @param alignment the alignment for the component.
1883:                 * @param component the Component to add
1884:                 * @param min the minimum size
1885:                 * @param pref the preferred size
1886:                 * @param max the maximum size
1887:                 * @throws IllegalArgumentException if min, pref or max are
1888:                 *         not positive and not one of PREFERRED_SIZE or DEFAULT_SIZE.
1889:                 * @return this <code>Group</code>
1890:                 */
1891:                public ParallelGroup add(int alignment, Component component,
1892:                        int min, int pref, int max) {
1893:                    ComponentSpring spring = new ComponentSpring(component,
1894:                            min, pref, max);
1895:                    spring.setAlignment(alignment);
1896:                    return (ParallelGroup) addSpring(spring);
1897:                }
1898:
1899:                boolean isResizable() {
1900:                    return resizable;
1901:                }
1902:
1903:                int operator(int a, int b) {
1904:                    return Math.max(a, b);
1905:                }
1906:
1907:                int getMinimumSize0(int axis) {
1908:                    if (!isResizable()) {
1909:                        return getPreferredSize(axis);
1910:                    }
1911:                    return super .getMinimumSize0(axis);
1912:                }
1913:
1914:                int getMaximumSize0(int axis) {
1915:                    if (!isResizable()) {
1916:                        return getPreferredSize(axis);
1917:                    }
1918:                    return super .getMaximumSize0(axis);
1919:                }
1920:
1921:                void setSize0(int axis, int origin, int size) {
1922:                    int alignment = childAlignment;
1923:                    if (alignment == BASELINE) {
1924:                        // Not having the axis in the constructor forces us
1925:                        // to do this.
1926:                        alignment = LEADING;
1927:                    }
1928:                    for (int counter = 0, max = springs.size(); counter < max; counter++) {
1929:                        Spring spring = getSpring(counter);
1930:                        int sAlignment = spring.getAlignment();
1931:                        int springSize = Math.min(size, spring
1932:                                .getMaximumSize(axis));
1933:                        if (sAlignment == NO_ALIGNMENT) {
1934:                            sAlignment = alignment;
1935:                        }
1936:                        switch (sAlignment) {
1937:                        case TRAILING:
1938:                            spring.setSize(axis, origin + size - springSize,
1939:                                    springSize);
1940:                            break;
1941:                        case CENTER:
1942:                            spring.setSize(axis, origin + (size - springSize)
1943:                                    / 2, springSize);
1944:                            break;
1945:                        default: // LEADING or NO_ALIGNMENT
1946:                            spring.setSize(axis, origin, springSize);
1947:                            break;
1948:                        }
1949:                    }
1950:                }
1951:
1952:                void insertAutopadding(int axis, List leadingPadding,
1953:                        List trailingPadding, List leading, List trailing,
1954:                        boolean insert) {
1955:                    for (int counter = 0; counter < springs.size(); counter++) {
1956:                        Spring spring = getSpring(counter);
1957:                        if (spring instanceof  ComponentSpring) {
1958:                            for (int i = 0; i < leadingPadding.size(); i++) {
1959:                                ((AutopaddingSpring) leadingPadding.get(i))
1960:                                        .add((ComponentSpring) spring, axis);
1961:                            }
1962:                            trailing.add(spring);
1963:                        } else if (spring instanceof  Group) {
1964:                            ((Group) spring).insertAutopadding(axis,
1965:                                    leadingPadding, trailingPadding, leading,
1966:                                    trailing, insert);
1967:                        } else if (spring instanceof  AutopaddingSpring) {
1968:                            trailingPadding.add(spring);
1969:                        }
1970:                    }
1971:                }
1972:            }
1973:
1974:            /**
1975:             * An extension of <code>ParallelGroup</code> that aligns its
1976:             * constituent <code>Spring</code>s along the baseline.
1977:             */
1978:            private class BaselineGroup extends ParallelGroup {
1979:                //
1980:                // This class aligns all components that have a baseline along
1981:                // the baseline.  Any components that do not have a baseline are
1982:                // centered.  Addititionally components that have a baseline
1983:                // will NOT be resized!
1984:                //
1985:                private boolean allSpringsHaveBaseline;
1986:                private int prefAscent;
1987:                private int prefDescent;
1988:
1989:                BaselineGroup(boolean resizable) {
1990:                    super (LEADING, resizable);
1991:                    prefAscent = prefDescent = -1;
1992:                }
1993:
1994:                void setSize(int axis, int origin, int size) {
1995:                    if (size == UNSET) {
1996:                        prefAscent = prefDescent = -1;
1997:                    }
1998:                    super .setSize(axis, origin, size);
1999:                }
2000:
2001:                void setSize0(int axis, int origin, int size) {
2002:                    if (axis == HORIZONTAL || prefAscent == -1) {
2003:                        super .setSize0(axis, origin, size);
2004:                    } else {
2005:                        // do baseline layout
2006:                        baselineLayout(origin, size);
2007:                    }
2008:                }
2009:
2010:                int calculateSize(int axis, int type) {
2011:                    if (springs.size() < 2 || axis != VERTICAL) {
2012:                        return super .calculateSize(axis, type);
2013:                    }
2014:                    if (prefAscent == -1) {
2015:                        calculateBaseline();
2016:                    }
2017:                    if (allSpringsHaveBaseline) {
2018:                        return prefAscent + prefDescent;
2019:                    }
2020:                    return Math.max(prefAscent + prefDescent, super 
2021:                            .calculateSize(axis, type));
2022:                }
2023:
2024:                /**
2025:                 * Calculates the baseline of children Springs that have a baseline.
2026:                 * The results are stored in prefAscent & prefDescent.  If all
2027:                 * child springs have a baseline <code>allSpringsHaveBaseline</code>
2028:                 * is set to true.
2029:                 */
2030:                private void calculateBaseline() {
2031:                    // calculate baseline
2032:                    prefAscent = 0;
2033:                    prefDescent = 0;
2034:                    allSpringsHaveBaseline = true;
2035:                    for (int counter = springs.size() - 1; counter >= 0; counter--) {
2036:                        Spring spring = getSpring(counter);
2037:                        int baseline = -1;
2038:                        if (spring instanceof  ComponentSpring) {
2039:                            baseline = ((ComponentSpring) spring).getBaseline();
2040:                            if (baseline >= 0) {
2041:                                prefAscent = Math.max(prefAscent, baseline);
2042:                                prefDescent = Math.max(prefDescent, spring
2043:                                        .getPreferredSize(VERTICAL)
2044:                                        - baseline);
2045:                            }
2046:                        }
2047:                        if (baseline < 0) {
2048:                            allSpringsHaveBaseline = false;
2049:                        }
2050:                    }
2051:                }
2052:
2053:                /**
2054:                 * Lays out springs that have a baseline along the baseline.  All
2055:                 * others are centered.
2056:                 */
2057:                private void baselineLayout(int origin, int size) {
2058:                    for (int counter = 0, max = springs.size(); counter < max; counter++) {
2059:                        Spring spring = getSpring(counter);
2060:                        int baseline = -1;
2061:                        if (spring instanceof  ComponentSpring) {
2062:                            baseline = ((ComponentSpring) spring).getBaseline();
2063:                            if (baseline >= 0) {
2064:                                spring.setSize(VERTICAL, origin + prefAscent
2065:                                        - baseline, spring
2066:                                        .getPreferredSize(VERTICAL));
2067:                            }
2068:                        }
2069:                        if (baseline < 0) {
2070:                            // PENDING: do we want to offer up alternative alignments
2071:                            // here?
2072:                            int sSize = Math.min(spring
2073:                                    .getMaximumSize(VERTICAL), size);
2074:                            spring.setSize(VERTICAL, origin + (size - sSize)
2075:                                    / 2, sSize);
2076:                        }
2077:                    }
2078:                }
2079:            }
2080:
2081:            /**
2082:             * A Spring representing one axis of a Component.
2083:             * There are three ways to configure this:
2084:             * <ul>
2085:             * <li>Use the pref/min/max from the component
2086:             * <li>Use the pref from the component and fix the min to 0 or max
2087:             *     to a big number.
2088:             * <li>Force the min/max/pref to be a certain value.
2089:             * If the Component's size is to be linked to another components than
2090:             * the min/max/pref all come from the ComponentInfo.
2091:             */
2092:            class ComponentSpring extends Spring {
2093:                private Component component;
2094:                private int origin;
2095:
2096:                private int min;
2097:                private int pref;
2098:                private int max;
2099:
2100:                // Baseline for the component.
2101:                private int baseline = -1;
2102:
2103:                // Whether or not the size has been requested yet.
2104:                private boolean installed;
2105:
2106:                private ComponentSpring(Component component, int min, int pref,
2107:                        int max) {
2108:                    this .component = component;
2109:
2110:                    checkSize(min, pref, max, true);
2111:
2112:                    this .min = min;
2113:                    this .max = max;
2114:                    this .pref = pref;
2115:
2116:                    getComponentInfo(component);
2117:                }
2118:
2119:                int getMinimumSize0(int axis) {
2120:                    if (isLinked(axis)) {
2121:                        return getLinkSize(axis, MIN_SIZE);
2122:                    }
2123:                    return getMinimumSize1(axis);
2124:                }
2125:
2126:                int getMinimumSize1(int axis) {
2127:                    if (min >= 0) {
2128:                        return min;
2129:                    }
2130:                    if (min == PREFERRED_SIZE) {
2131:                        return getPreferredSize1(axis);
2132:                    }
2133:                    return getSizeAlongAxis(axis, component.getMinimumSize());
2134:                }
2135:
2136:                int getPreferredSize0(int axis) {
2137:                    if (isLinked(axis)) {
2138:                        return getLinkSize(axis, PREF_SIZE);
2139:                    }
2140:                    return Math.max(getMinimumSize(axis),
2141:                            getPreferredSize1(axis));
2142:                }
2143:
2144:                int getPreferredSize1(int axis) {
2145:                    if (pref >= 0) {
2146:                        return pref;
2147:                    }
2148:                    return getSizeAlongAxis(axis, component.getPreferredSize());
2149:                }
2150:
2151:                int getMaximumSize0(int axis) {
2152:                    if (isLinked(axis)) {
2153:                        return getLinkSize(axis, MAX_SIZE);
2154:                    }
2155:                    return Math
2156:                            .max(getMinimumSize(axis), getMaximumSize1(axis));
2157:                }
2158:
2159:                int getMaximumSize1(int axis) {
2160:                    if (max >= 0) {
2161:                        return max;
2162:                    }
2163:                    if (max == PREFERRED_SIZE) {
2164:                        return getPreferredSize1(axis);
2165:                    }
2166:                    return getSizeAlongAxis(axis, component.getMaximumSize());
2167:                }
2168:
2169:                private int getSizeAlongAxis(int axis, Dimension size) {
2170:                    return (axis == HORIZONTAL) ? size.width : size.height;
2171:                }
2172:
2173:                private int getLinkSize(int axis, int type) {
2174:                    ComponentInfo ci = getComponentInfo(component);
2175:                    return ci.getSize(axis, type);
2176:                }
2177:
2178:                void setSize(int axis, int origin, int size) {
2179:                    super .setSize(axis, origin, size);
2180:                    this .origin = origin;
2181:                    if (size == UNSET) {
2182:                        baseline = -1;
2183:                    }
2184:                }
2185:
2186:                int getOrigin() {
2187:                    return origin;
2188:                }
2189:
2190:                void setComponent(Component component) {
2191:                    this .component = component;
2192:                }
2193:
2194:                Component getComponent() {
2195:                    return component;
2196:                }
2197:
2198:                int getBaseline() {
2199:                    if (baseline == -1 && (component instanceof  Component)) {
2200:                        Spring horizontalSpring = getComponentInfo(component).horizontalSpring;
2201:                        int width;
2202:                        if (horizontalSpring != null) {
2203:                            width = horizontalSpring.getSize();
2204:                        } else {
2205:                            width = component.getPreferredSize().width;
2206:                        }
2207:                        baseline = Baseline.getBaseline((Component) component,
2208:                                width, getPreferredSize(VERTICAL));
2209:                    }
2210:                    return baseline;
2211:                }
2212:
2213:                private boolean isLinked(int axis) {
2214:                    return getComponentInfo(component).isLinked(axis);
2215:                }
2216:
2217:                void installIfNecessary(int axis) {
2218:                    if (!installed) {
2219:                        installed = true;
2220:                        if (axis == HORIZONTAL) {
2221:                            getComponentInfo(component).horizontalSpring = this ;
2222:                        } else {
2223:                            getComponentInfo(component).verticalSpring = this ;
2224:                        }
2225:                    }
2226:                }
2227:            }
2228:
2229:            /**
2230:             * Spring representing the preferred distance between two components.
2231:             */
2232:            class PaddingSpring extends Spring {
2233:                private Component source;
2234:                private Component target;
2235:                private int type;
2236:                private boolean canGrow;
2237:
2238:                PaddingSpring(Component source, Component target, int type,
2239:                        boolean canGrow) {
2240:                    this .source = source;
2241:                    this .target = target;
2242:                    this .type = type;
2243:                    this .canGrow = canGrow;
2244:                }
2245:
2246:                int getMinimumSize0(int axis) {
2247:                    return getPadding(axis);
2248:                }
2249:
2250:                int getPreferredSize0(int axis) {
2251:                    return getPadding(axis);
2252:                }
2253:
2254:                int getMaximumSize0(int axis) {
2255:                    if (canGrow) {
2256:                        return Short.MAX_VALUE;
2257:                    }
2258:                    return getPadding(axis);
2259:                }
2260:
2261:                private int getPadding(int axis) {
2262:                    int position;
2263:                    if (axis == HORIZONTAL) {
2264:                        position = 3;//SwingConstants.EAST;
2265:                    } else {
2266:                        position = 5;//SwingConstants.SOUTH;
2267:                    }
2268:                    return LayoutStyle.getSharedInstance().getPreferredGap(
2269:                            source, target, type, position, host);
2270:                }
2271:            }
2272:
2273:            /**
2274:             * Spring represented a certain amount of space.
2275:             */
2276:            class GapSpring extends Spring {
2277:                private int min;
2278:                private int pref;
2279:                private int max;
2280:
2281:                GapSpring(int min, int pref, int max) {
2282:                    checkSize(min, pref, max, false);
2283:                    this .min = min;
2284:                    this .pref = pref;
2285:                    this .max = max;
2286:                }
2287:
2288:                int getMinimumSize0(int axis) {
2289:                    if (min == PREFERRED_SIZE) {
2290:                        return getPreferredSize(axis);
2291:                    }
2292:                    return min;
2293:                }
2294:
2295:                int getPreferredSize0(int axis) {
2296:                    return pref;
2297:                }
2298:
2299:                int getMaximumSize0(int axis) {
2300:                    if (max == PREFERRED_SIZE) {
2301:                        return getPreferredSize(axis);
2302:                    }
2303:                    return max;
2304:                }
2305:            }
2306:
2307:            /**
2308:             * Spring reprensenting the distance between any number of sources and
2309:             * targets.  The targets and sources are computed during layout.  An
2310:             * instance of this can either be dynamically created when
2311:             * autocreatePadding is true, or explicitly created by the developer.
2312:             */
2313:            private class AutopaddingSpring extends Spring {
2314:                List sources;
2315:                ComponentSpring source;
2316:                private List matches;
2317:                int size;
2318:                int lastSize;
2319:                private int pref;
2320:                private int max;
2321:                private int type;
2322:                private boolean userCreated;
2323:
2324:                private AutopaddingSpring() {
2325:                    this .pref = PREFERRED_SIZE;
2326:                    this .max = PREFERRED_SIZE;
2327:                    this .type = LayoutStyle.RELATED;
2328:                }
2329:
2330:                AutopaddingSpring(int pref, int max) {
2331:                    this .pref = pref;
2332:                    this .max = max;
2333:                }
2334:
2335:                AutopaddingSpring(int type, int pref, int max) {
2336:                    this .type = type;
2337:                    this .pref = pref;
2338:                    this .max = max;
2339:                    this .userCreated = true;
2340:                }
2341:
2342:                public void setSource(ComponentSpring source) {
2343:                    this .source = source;
2344:                }
2345:
2346:                public void setSources(List sources) {
2347:                    this .sources = new ArrayList(sources.size());
2348:                    this .sources.addAll(sources);
2349:                }
2350:
2351:                public void setUserCreated(boolean userCreated) {
2352:                    this .userCreated = userCreated;
2353:                }
2354:
2355:                public boolean getUserCreated() {
2356:                    return userCreated;
2357:                }
2358:
2359:                void clear() {
2360:                    lastSize = getSize();
2361:                    super .clear();
2362:                    size = 0;
2363:                }
2364:
2365:                public void reset() {
2366:                    size = 0;
2367:                    sources = null;
2368:                    source = null;
2369:                    matches = null;
2370:                }
2371:
2372:                public void calculatePadding(int axis) {
2373:                    size = 0;
2374:                    int maxPadding = 0;
2375:                    if (matches != null) {
2376:                        LayoutStyle p = LayoutStyle.getSharedInstance();
2377:                        // PENDING: rtl
2378:                        int position = (axis == HORIZONTAL) ? 3 : 5;
2379:                        for (int i = matches.size() - 1; i >= 0; i--) {
2380:                            AutopaddingMatch match = (AutopaddingMatch) matches
2381:                                    .get(i);
2382:                            maxPadding = Math.max(maxPadding, calculatePadding(
2383:                                    p, position, match.source, match.target));
2384:                        }
2385:                    }
2386:                    if (lastSize != UNSET) {
2387:                        size += Math.min(maxPadding, lastSize);
2388:                    }
2389:                }
2390:
2391:                private int calculatePadding(LayoutStyle p, int position,
2392:                        ComponentSpring source, ComponentSpring target) {
2393:                    int delta = target.getOrigin()
2394:                            - (source.getOrigin() + source.getSize());
2395:                    if (delta >= 0) {
2396:                        int padding;
2397:                        if ((source.getComponent() instanceof  Component)
2398:                                && (target.getComponent() instanceof  Component)) {
2399:                            padding = p.getPreferredGap((Component) source
2400:                                    .getComponent(), (Component) target
2401:                                    .getComponent(), type, position, host);
2402:                        } else {
2403:                            padding = 10;
2404:                        }
2405:                        if (padding > delta) {
2406:                            size = Math.max(size, padding - delta);
2407:                        }
2408:                        return padding;
2409:                    }
2410:                    return 0;
2411:                }
2412:
2413:                public void add(ComponentSpring spring, int axis) {
2414:                    int oAxis = (axis == HORIZONTAL) ? VERTICAL : HORIZONTAL;
2415:                    if (source != null) {
2416:                        if (areParallelSiblings(source.getComponent(), spring
2417:                                .getComponent(), oAxis)) {
2418:                            addMatch(source, spring);
2419:                        }
2420:                    } else {
2421:                        Component component = spring.getComponent();
2422:                        for (int counter = sources.size() - 1; counter >= 0; counter--) {
2423:                            ComponentSpring source = (ComponentSpring) sources
2424:                                    .get(counter);
2425:                            if (areParallelSiblings(source.getComponent(),
2426:                                    component, oAxis)) {
2427:                                addMatch(source, spring);
2428:                            }
2429:                        }
2430:                    }
2431:                }
2432:
2433:                private void addMatch(ComponentSpring source,
2434:                        ComponentSpring target) {
2435:                    if (matches == null) {
2436:                        matches = new ArrayList(1);
2437:                    }
2438:                    matches.add(new AutopaddingMatch(source, target));
2439:                }
2440:
2441:                int getMinimumSize0(int axis) {
2442:                    return size;
2443:                }
2444:
2445:                int getPreferredSize0(int axis) {
2446:                    if (pref == PREFERRED_SIZE || pref == DEFAULT_SIZE) {
2447:                        return size;
2448:                    }
2449:                    return Math.max(size, pref);
2450:                }
2451:
2452:                int getMaximumSize0(int axis) {
2453:                    if (max >= 0) {
2454:                        return Math.max(getPreferredSize(axis), max);
2455:                    }
2456:                    return size;
2457:                }
2458:
2459:                String getMatchDescription() {
2460:                    return (matches == null) ? "" : matches.toString();
2461:                }
2462:
2463:                public String toString() {
2464:                    return super .toString() + getMatchDescription();
2465:                }
2466:            }
2467:
2468:            /**
2469:             * Represents two springs that should have autopadding inserted between
2470:             * them.
2471:             */
2472:            private static class AutopaddingMatch {
2473:                public ComponentSpring source;
2474:                public ComponentSpring target;
2475:
2476:                AutopaddingMatch(ComponentSpring source, ComponentSpring target) {
2477:                    this .source = source;
2478:                    this .target = target;
2479:                }
2480:
2481:                private String toString(ComponentSpring spring) {
2482:                    return spring.getComponent().getName();
2483:                }
2484:
2485:                public String toString() {
2486:                    return "[" + toString(source) + "-" + toString(target)
2487:                            + "]";
2488:                }
2489:            }
2490:
2491:            /**
2492:             * An extension of AutopaddingSpring used for container level padding.
2493:             */
2494:            private class ContainerAutopaddingSpring extends AutopaddingSpring {
2495:                private List targets;
2496:
2497:                ContainerAutopaddingSpring() {
2498:                    super ();
2499:                    setUserCreated(true);
2500:                }
2501:
2502:                ContainerAutopaddingSpring(int pref, int max) {
2503:                    super (pref, max);
2504:                    setUserCreated(true);
2505:                }
2506:
2507:                public void add(ComponentSpring spring, int axis) {
2508:                    if (targets == null) {
2509:                        targets = new ArrayList(1);
2510:                    }
2511:                    targets.add(spring);
2512:                }
2513:
2514:                public void calculatePadding(int axis) {
2515:                    LayoutStyle p = LayoutStyle.getSharedInstance();
2516:                    int maxPadding = 0;
2517:                    size = 0;
2518:                    if (targets != null) {
2519:                        // Indicates leading
2520:                        // PENDING: rtl
2521:                        int position = (axis == HORIZONTAL) ? 7 : 1;
2522:                        for (int i = targets.size() - 1; i >= 0; i--) {
2523:                            ComponentSpring targetSpring = (ComponentSpring) targets
2524:                                    .get(i);
2525:                            int padding = 10;
2526:                            if (targetSpring.getComponent() instanceof  Component) {
2527:                                padding = p
2528:                                        .getContainerGap(
2529:                                                (Component) targetSpring
2530:                                                        .getComponent(),
2531:                                                position, host);
2532:                                maxPadding = Math.max(padding, maxPadding);
2533:                                padding -= targetSpring.getOrigin();
2534:                            } else {
2535:                                maxPadding = Math.max(padding, maxPadding);
2536:                            }
2537:                            size = Math.max(size, padding);
2538:                        }
2539:                    } else {
2540:                        // Trailing
2541:                        // PENDING: rtl
2542:                        int position = (axis == HORIZONTAL) ? 3 : 5;
2543:                        if (sources != null) {
2544:                            for (int i = sources.size() - 1; i >= 0; i--) {
2545:                                ComponentSpring sourceSpring = (ComponentSpring) sources
2546:                                        .get(i);
2547:                                maxPadding = Math.max(maxPadding, updateSize(p,
2548:                                        sourceSpring, position));
2549:                            }
2550:                        } else if (source != null) {
2551:                            maxPadding = updateSize(p, source, position);
2552:                        }
2553:                    }
2554:                    if (lastSize != UNSET) {
2555:                        size += Math.min(maxPadding, lastSize);
2556:                    }
2557:                }
2558:
2559:                private int updateSize(LayoutStyle p,
2560:                        ComponentSpring sourceSpring, int position) {
2561:                    int padding = 10;
2562:                    if (sourceSpring.getComponent() instanceof  Component) {
2563:                        padding = p.getContainerGap((Component) sourceSpring
2564:                                .getComponent(), position, host);
2565:                    }
2566:                    int delta = Math
2567:                            .max(0, getParent().getSize()
2568:                                    - sourceSpring.getSize()
2569:                                    - sourceSpring.getOrigin());
2570:                    size = Math.max(size, padding - delta);
2571:                    return padding;
2572:                }
2573:
2574:                String getMatchDescription() {
2575:                    if (targets != null) {
2576:                        return "leading: " + targets.toString();
2577:                    }
2578:                    if (sources != null) {
2579:                        return "trailing: " + sources.toString();
2580:                    }
2581:                    return "--";
2582:                }
2583:            }
2584:
2585:            /**
2586:             * Tracks the horizontal/vertical Springs for a Component.
2587:             * This class is also used to handle Springs that have their sizes
2588:             * linked.
2589:             */
2590:            private static class ComponentInfo {
2591:                // Component being layed out
2592:                private Component component;
2593:
2594:                ComponentSpring horizontalSpring;
2595:                ComponentSpring verticalSpring;
2596:
2597:                // If there is a chain of components that share the
2598:                // same size this will be the master CI.  If this is the
2599:                // masterCI, masterCI == this.
2600:                private ComponentInfo horizontalMaster;
2601:                private ComponentInfo verticalMaster;
2602:                // If we're the master, this is the dependant ComponentInfos
2603:                private List horizontalDependants;
2604:                private List verticalDependants;
2605:                // If we're the masterCI this gives the min/pref/max size of all
2606:                // children.  This is indexed by one of the size operators.  Horizontal
2607:                // first, then vertical.
2608:                private int[] horizontalSizes;
2609:                private int[] verticalSizes;
2610:
2611:                ComponentInfo(Component component) {
2612:                    this .component = component;
2613:                    clear();
2614:                }
2615:
2616:                public void setBounds(Insets insets) {
2617:                    int x = 0;
2618:                    int y = 0;
2619:                    int w = 0;
2620:                    int h = 0;
2621:
2622:                    if (horizontalSpring != null) {
2623:                        x = horizontalSpring.getOrigin();
2624:                        w = horizontalSpring.getSize();
2625:                    }
2626:                    if (verticalSpring != null) {
2627:                        y = verticalSpring.getOrigin();
2628:                        h = verticalSpring.getSize();
2629:                    }
2630:                    /* TODO fix up
2631:                     * There is problem, that right (also bottom sometimes) is not
2632:                     * well aligned. The magic constant 2 ensures that componets are 2px from
2633:                     * bottom and right. The side effect is, that user can not put component to full screen size.
2634:                     */
2635:                    Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
2636:                    if (x + insets.left + w + insets.right + 2 > d.width) {
2637:                        w = d.width - (insets.left + insets.right + x + 2);
2638:                    }
2639:                    if (y + insets.top + h + insets.bottom + 2 > d.height) {
2640:                        h = d.height - (insets.top + insets.bottom + y + 2);
2641:                    }
2642:                    //end fix up
2643:                    component.setBounds(x + insets.left, y + insets.top, w, h);
2644:                }
2645:
2646:                public void setComponent(Component component) {
2647:                    this .component = component;
2648:                    if (horizontalSpring != null) {
2649:                        horizontalSpring.setComponent(component);
2650:                    }
2651:                    if (verticalSpring != null) {
2652:                        verticalSpring.setComponent(component);
2653:                    }
2654:                }
2655:
2656:                public Component getComponent() {
2657:                    return component;
2658:                }
2659:
2660:                /**
2661:                 * Returns true if this component has its size linked to
2662:                 * other components.
2663:                 */
2664:                public boolean isLinked(int axis) {
2665:                    if (axis == HORIZONTAL) {
2666:                        return horizontalMaster != null;
2667:                    }
2668:                    return (verticalMaster != null);
2669:                }
2670:
2671:                public ComponentInfo getMasterComponentInfo(int axis) {
2672:                    if (axis == HORIZONTAL) {
2673:                        if (horizontalMaster == null) {
2674:                            horizontalMaster = this ;
2675:                            horizontalDependants = new ArrayList(1);
2676:                            horizontalDependants.add(this );
2677:                            horizontalSizes = new int[3];
2678:                            clear();
2679:                        }
2680:                        return horizontalMaster;
2681:                    } else {
2682:                        if (verticalMaster == null) {
2683:                            verticalMaster = this ;
2684:                            verticalDependants = new ArrayList(1);
2685:                            verticalDependants.add(this );
2686:                            verticalSizes = new int[3];
2687:                            clear();
2688:                        }
2689:                        return verticalMaster;
2690:                    }
2691:                }
2692:
2693:                public void addChild(ComponentInfo child, int axis) {
2694:                    if (axis == HORIZONTAL) {
2695:                        addChild0(child, HORIZONTAL);
2696:                    } else {
2697:                        addChild0(child, VERTICAL);
2698:                    }
2699:                }
2700:
2701:                private void addChild0(ComponentInfo child, int axis) {
2702:                    if (axis == HORIZONTAL) {
2703:                        if (child.horizontalMaster == child) {
2704:                            // Child is already marked as a master, subsume all it's
2705:                            // children and reset it's master to us.
2706:                            horizontalDependants
2707:                                    .addAll(child.horizontalDependants);
2708:                            child.horizontalDependants = null;
2709:                            child.horizontalSizes = null;
2710:                        } else {
2711:                            // Child isn't a master.
2712:                            horizontalDependants.add(child);
2713:                        }
2714:                        child.horizontalMaster = this ;
2715:                    } else {
2716:                        if (child.verticalMaster == child) {
2717:                            // Child is already marked as a master, subsume all it's
2718:                            // children and reset it's master to us.
2719:                            verticalDependants.addAll(child.verticalDependants);
2720:                            child.verticalDependants = null;
2721:                            child.verticalSizes = null;
2722:                        } else {
2723:                            // Child isn't a master.
2724:                            verticalDependants.add(child);
2725:                        }
2726:                        child.verticalMaster = this ;
2727:                    }
2728:                }
2729:
2730:                public void clear() {
2731:                    clear(horizontalSizes);
2732:                    clear(verticalSizes);
2733:                }
2734:
2735:                private void clear(int[] sizes) {
2736:                    if (sizes != null) {
2737:                        for (int counter = sizes.length - 1; counter >= 0; counter--) {
2738:                            sizes[counter] = UNSET;
2739:                        }
2740:                    }
2741:                }
2742:
2743:                // NOTE:
2744:                // There is a lot of code that follows relating to the type of
2745:                // size being requested (min/pref/max).  It's currently ignored
2746:                // because we can't deal with resizable components that are linked.
2747:                // I've left the code in place in case we come up with a way to
2748:                // solve resizing linked components.
2749:                int getSize(int axis, int type) {
2750:                    int sizes[] = null;
2751:                    List dependants = null;
2752:                    if (axis == HORIZONTAL) {
2753:                        if (horizontalMaster != this ) {
2754:                            return horizontalMaster.getSize(axis, type);
2755:                        }
2756:                        sizes = horizontalSizes;
2757:                        dependants = horizontalDependants;
2758:                    } else if (axis == VERTICAL) {
2759:                        if (verticalMaster != this ) {
2760:                            return verticalMaster.getSize(axis, type);
2761:                        }
2762:                        sizes = verticalSizes;
2763:                        dependants = verticalDependants;
2764:                    }
2765:                    if (sizes[type] == UNSET) {
2766:                        sizes[type] = calcSize(dependants, axis, type);
2767:                    }
2768:                    return sizes[type];
2769:                }
2770:
2771:                private int calcSize(List dependants, int axis, int type) {
2772:                    int count = dependants.size() - 1;
2773:                    int size = getSize(dependants, axis, type, count--);
2774:                    while (count >= 0) {
2775:                        size = Math.max(size, getSize(dependants, axis, type,
2776:                                count--));
2777:                    }
2778:                    return size;
2779:                }
2780:
2781:                private int getSize(List dependants, int axis, int type,
2782:                        int index) {
2783:                    ComponentInfo ci = (ComponentInfo) dependants.get(index);
2784:                    ComponentSpring spring;
2785:                    if (axis == HORIZONTAL) {
2786:                        spring = ci.horizontalSpring;
2787:                    } else {
2788:                        spring = ci.verticalSpring;
2789:                    }
2790:                    return spring.getPreferredSize1(axis);
2791:                    //            switch(type) {
2792:                    //                case MIN_SIZE:
2793:                    //                    return spring.getMinimumSize1(axis);
2794:                    //                case PREF_SIZE:
2795:                    //                    return spring.getPreferredSize1(axis);
2796:                    //                default:
2797:                    //                    return spring.getMaximumSize1(axis);
2798:                    //            }
2799:                }
2800:            }
2801:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.