Source Code Cross Referenced for ExtendedGridLayout.java in  » Swing-Library » jEdit » org » gjt » sp » jedit » gui » 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 » Swing Library » jEdit » org.gjt.sp.jedit.gui 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * ExtendedGridLayout.java - a grid layout manager with variable cell sizes
0003:         * that supports colspans and rowspans
0004:         * :tabSize=8:indentSize=8:noTabs=false:
0005:         * :folding=explicit:collapseFolds=1:
0006:         *
0007:         * Originally written by Björn Kautler for the jEdit project. This work has been
0008:         * placed into the public domain. You may use this work in any way and for any
0009:         * purpose you wish.
0010:         *
0011:         * THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, NOT EVEN THE
0012:         * IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE, ASSUMES
0013:         * _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE RESULTING FROM THE USE, MODIFICATION,
0014:         * OR REDISTRIBUTION OF THIS SOFTWARE.
0015:         */
0016:
0017:        package org.gjt.sp.jedit.gui;
0018:
0019:        import java.awt.Component;
0020:        import java.awt.Container;
0021:        import java.awt.Dimension;
0022:        import java.awt.Insets;
0023:        import java.awt.LayoutManager2;
0024:
0025:        import java.util.ArrayList;
0026:        import java.util.Arrays;
0027:        import java.util.HashSet;
0028:        import java.util.Hashtable;
0029:        import java.util.Iterator;
0030:        import java.util.List;
0031:        import java.util.ListIterator;
0032:        import java.util.Set;
0033:
0034:        import static java.awt.Component.CENTER_ALIGNMENT;
0035:
0036:        import static org.gjt.sp.jedit.gui.ExtendedGridLayoutConstraints.REMAINDER;
0037:
0038:        /**
0039:         * A layout manager that places components in a rectangular grid
0040:         * with variable cell sizes that supports colspans and rowspans.
0041:         * <p>
0042:         * The container is divided into rectangles, and each component is placed
0043:         * in a rectangular space defined by its colspan and rowspan.
0044:         * Each row is as large as the largest component in
0045:         * that row, and each column is as wide as the widest component in
0046:         * that column. </p>
0047:         * <p>
0048:         * This behavior is similar to 
0049:         * <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/awt/GridLayout.html">{@code java.awt.GridLayout}</a>
0050:         * but it supports different row heights and
0051:         * column widths for each row/column. </p>
0052:         * <p>
0053:         * For example, the following is a Dialog that lays out ten buttons
0054:         * exactly the same as in the example of the JavaDoc of
0055:         * <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/awt/GridBagLayout.html">{@code java.awt.GridBagLayout}</a>
0056:         * with the difference of vertical and horizontal gaps that can be configured:
0057:         * <hr>
0058:         * <blockquote><pre><font color="#000000">
0059:         * <font color="#000000">   1:</font><font color="#009966"><strong>import</strong></font> java.awt.Button;
0060:         * <font color="#000000">   2:</font><font color="#009966"><strong>import</strong></font> java.awt.Dimension;
0061:         * <font color="#000000">   3:</font>
0062:         * <font color="#000000">   4:</font><font color="#009966"><strong>import</strong></font> javax.swing.JDialog;
0063:         * <font color="#990066">   5:</font>
0064:         * <font color="#000000">   6:</font><font color="#009966"><strong>import</strong></font> org.gjt.sp.jedit.gui.ExtendedGridLayout;
0065:         * <font color="#000000">   7:</font><font color="#009966"><strong>import</strong></font> org.gjt.sp.jedit.gui.ExtendedGridLayoutConstraints;
0066:         * <font color="#000000">   8:</font>
0067:         * <font color="#000000">   9:</font><font color="#009966"><strong>import</strong></font> <font color="#006699"><strong>static</strong></font> org.gjt.sp.jedit.gui.ExtendedGridLayoutConstraints.REMAINDER;
0068:         * <font color="#990066">  10:</font>
0069:         * <font color="#000000">  11:</font><font color="#006699"><strong>public</strong></font> <font color="#0099ff"><strong>class</strong></font> ExampleDialog <font color="#006699"><strong>extends</strong></font> JDialog <font color="#000000"><strong>{</strong></font>
0070:         * <font color="#000000">  12:</font>    <font color="#006699"><strong>public</strong></font> <font color="#9966ff">ExampleDialog</font>() <font color="#000000"><strong>{</strong></font>
0071:         * <font color="#000000">  13:</font>        <font color="#cc00cc">super</font>(<font color="#cc00cc">null</font>,<font color="#ff00cc">&quot;</font><font color="#ff00cc">Example</font><font color="#ff00cc"> </font><font color="#ff00cc">Dialog</font><font color="#ff00cc">&quot;</font>,<font color="#cc00cc">true</font>);
0072:         * <font color="#000000">  14:</font>        <font color="#9966ff">setLayout</font>(<font color="#006699"><strong>new</strong></font> <font color="#9966ff">ExtendedGridLayout</font>(<font color="#ff0000">5</font>,<font color="#ff0000">5</font>,<font color="#006699"><strong>new</strong></font> <font color="#9966ff">Insets</font>(<font color="#ff0000">5</font>,<font color="#ff0000">5</font>,<font color="#ff0000">5</font>,<font color="#ff0000">5</font>)));
0073:         * <font color="#990066">  15:</font>        
0074:         * <font color="#000000">  16:</font>        <font color="#9966ff">add</font>(<font color="#9966ff">makeButton</font>(<font color="#ff00cc">&quot;</font><font color="#ff00cc">Button1</font><font color="#ff00cc">&quot;</font>));
0075:         * <font color="#000000">  17:</font>        <font color="#9966ff">add</font>(<font color="#9966ff">makeButton</font>(<font color="#ff00cc">&quot;</font><font color="#ff00cc">Button2</font><font color="#ff00cc">&quot;</font>));
0076:         * <font color="#000000">  18:</font>        <font color="#9966ff">add</font>(<font color="#9966ff">makeButton</font>(<font color="#ff00cc">&quot;</font><font color="#ff00cc">Button3</font><font color="#ff00cc">&quot;</font>));
0077:         * <font color="#000000">  19:</font>        <font color="#9966ff">add</font>(<font color="#9966ff">makeButton</font>(<font color="#ff00cc">&quot;</font><font color="#ff00cc">Button4</font><font color="#ff00cc">&quot;</font>));
0078:         * <font color="#990066">  20:</font>        Button button <font color="#000000"><strong>=</strong></font> <font color="#9966ff">makeButton</font>(<font color="#ff00cc">&quot;</font><font color="#ff00cc">Button5</font><font color="#ff00cc">&quot;</font>);
0079:         * <font color="#000000">  21:</font>        <font color="#9966ff">add</font>(button,<font color="#006699"><strong>new</strong></font> <font color="#9966ff">ExtendedGridLayoutConstraints</font>(<font color="#ff0000">1</font>,REMAINDER,<font color="#ff0000">1</font>,button));
0080:         * <font color="#000000">  22:</font>        button <font color="#000000"><strong>=</strong></font> <font color="#9966ff">makeButton</font>(<font color="#ff00cc">&quot;</font><font color="#ff00cc">Button6</font><font color="#ff00cc">&quot;</font>);
0081:         * <font color="#000000">  23:</font>        <font color="#9966ff">add</font>(button,<font color="#006699"><strong>new</strong></font> <font color="#9966ff">ExtendedGridLayoutConstraints</font>(<font color="#ff0000">2</font>,<font color="#ff0000">3</font>,<font color="#ff0000">1</font>,button));
0082:         * <font color="#000000">  24:</font>        button <font color="#000000"><strong>=</strong></font> <font color="#9966ff">makeButton</font>(<font color="#ff00cc">&quot;</font><font color="#ff00cc">Button7</font><font color="#ff00cc">&quot;</font>);
0083:         * <font color="#990066">  25:</font>        <font color="#9966ff">add</font>(button,<font color="#006699"><strong>new</strong></font> <font color="#9966ff">ExtendedGridLayoutConstraints</font>(<font color="#ff0000">2</font>,button));
0084:         * <font color="#000000">  26:</font>        button <font color="#000000"><strong>=</strong></font> <font color="#9966ff">makeButton</font>(<font color="#ff00cc">&quot;</font><font color="#ff00cc">Button8</font><font color="#ff00cc">&quot;</font>);
0085:         * <font color="#000000">  27:</font>        <font color="#9966ff">add</font>(button,<font color="#006699"><strong>new</strong></font> <font color="#9966ff">ExtendedGridLayoutConstraints</font>(<font color="#ff0000">3</font>,<font color="#ff0000">1</font>,<font color="#ff0000">2</font>,button));
0086:         * <font color="#000000">  28:</font>        button <font color="#000000"><strong>=</strong></font> <font color="#9966ff">makeButton</font>(<font color="#ff00cc">&quot;</font><font color="#ff00cc">Button9</font><font color="#ff00cc">&quot;</font>);
0087:         * <font color="#000000">  29:</font>        <font color="#9966ff">add</font>(button,<font color="#006699"><strong>new</strong></font> <font color="#9966ff">ExtendedGridLayoutConstraints</font>(<font color="#ff0000">3</font>,<font color="#ff0000">3</font>,<font color="#ff0000">1</font>,button));
0088:         * <font color="#990066">  30:</font>        button <font color="#000000"><strong>=</strong></font> <font color="#9966ff">makeButton</font>(<font color="#ff00cc">&quot;</font><font color="#ff00cc">Button10</font><font color="#ff00cc">&quot;</font>);
0089:         * <font color="#000000">  31:</font>        <font color="#9966ff">add</font>(button,<font color="#006699"><strong>new</strong></font> <font color="#9966ff">ExtendedGridLayoutConstraints</font>(<font color="#ff0000">4</font>,REMAINDER,<font color="#ff0000">1</font>,button));
0090:         * <font color="#000000">  32:</font>        
0091:         * <font color="#000000">  33:</font>        <font color="#9966ff">pack</font>();
0092:         * <font color="#000000">  34:</font>        <font color="#9966ff">setLocationRelativeTo</font>(<font color="#cc00cc">null</font>);
0093:         * <font color="#990066">  35:</font>        <font color="#9966ff">setVisible</font>(<font color="#cc00cc">true</font>);
0094:         * <font color="#000000">  36:</font>    <font color="#000000"><strong>}</strong></font>
0095:         * <font color="#000000">  37:</font>    
0096:         * <font color="#000000">  38:</font>    <font color="#006699"><strong>private</strong></font> Button <font color="#9966ff">makeButton</font>(String name) <font color="#000000"><strong>{</strong></font>
0097:         * <font color="#000000">  39:</font>        Button button <font color="#000000"><strong>=</strong></font> <font color="#006699"><strong>new</strong></font> <font color="#9966ff">Button</font>(name);
0098:         * <font color="#990066">  40:</font>        button.<font color="#9966ff">setMaximumSize</font>(<font color="#006699"><strong>new</strong></font> <font color="#9966ff">Dimension</font>(Integer.MAX_VALUE,Integer.MAX_VALUE));
0099:         * <font color="#000000">  41:</font>        <font color="#006699"><strong>return</strong></font> button;
0100:         * <font color="#000000">  42:</font>    <font color="#000000"><strong>}</strong></font>
0101:         * <font color="#000000">  43:</font><font color="#000000"><strong>}</strong></font>
0102:         * </font></pre></blockquote>
0103:         * <hr>
0104:         * If you use {@code REMAINDER} as colspan or rowspan then a component takes
0105:         * up the remaining space in that column or row. Any additional components in
0106:         * a row are ignored and not displayed. Additional components in a column are
0107:         * moved rightside. If a rowspan hits a colspan, the colspan ends and the
0108:         * rowspan takes precedence.
0109:         * <p>
0110:         * Components for which {@code isVisible() == false} are ignored. Because
0111:         * of this, components can be replaced "in-place" by adding two components next to
0112:         * each other, with different {@code isVisible()} values, and toggling the 
0113:         * {@code setVisible()} values of both when we wish to swap the currently
0114:         * visible component with the one that is hidden. </p>
0115:         *
0116:         * <p>
0117:         * If you want to reserve free space in a row inbetween components,  
0118:         * add a <a href="http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/Box.Filler.html">{@code javax.swing.Box.Filler}</a>
0119:         * to the layout if the free space is in the middle of a row,
0120:         * or just don't add components if the free space
0121:         * should be at the end of a row.</p>
0122:         * <p>
0123:         * If a row is taller, or a column is wider than the {@code maximumSize} of a component,
0124:         * the component is resized to its maximum size and aligned according to its
0125:         * {@code alignmentX} and {@code alignmentY} values. </p>
0126:         * <p>
0127:         * One instance of this class can be used to layout multiple
0128:         * containers at the same time. </p>
0129:         *
0130:         * @author Björn "Vampire" Kautler
0131:         * @version 1.0
0132:         * @see ExtendedGridLayoutConstraints
0133:         * @see <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/awt/Component.html"><code>java.awt.Component</code></a>
0134:         * @see <a href="http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/Box.Filler.html"><code>javax.swing.Box.Filler</code></a>
0135:         */
0136:        public class ExtendedGridLayout implements  LayoutManager2 {
0137:            /**
0138:             * This hashtable maintains the association between
0139:             * a component and its ExtendedGridLayoutConstraints.
0140:             * The Keys in {@code comptable} are the components and the
0141:             * values are the instances of {@code ExtendedGridLayoutConstraints}.
0142:             *
0143:             * @see ExtendedGridLayoutConstraints
0144:             */
0145:            private final Hashtable<Component, ExtendedGridLayoutConstraints> comptable;
0146:
0147:            /**
0148:             * Specifies the horizontal space between two columns.
0149:             * The default value is 0.
0150:             * 
0151:             * @see #distanceToBorders
0152:             * @see #vgap
0153:             */
0154:            private final int hgap;
0155:
0156:            /**
0157:             * Specifies the vertical space between two rows.
0158:             * The default value is 0.
0159:             * 
0160:             * @see #distanceToBorders
0161:             * @see #hgap
0162:             */
0163:            private final int vgap;
0164:
0165:            /**
0166:             * Specifies the gap between the grid and the borders of the parent container.
0167:             * The default value is 0 for all four borders.
0168:             * 
0169:             * @see #hgap
0170:             * @see #vgap
0171:             */
0172:            private final Insets distanceToBorders;
0173:
0174:            /**
0175:             * An enum to tell the {@code getSize()} method which size is requested.
0176:             * 
0177:             * @see #getSize()
0178:             */
0179:            private static enum LayoutSize {
0180:                MINIMUM, PREFERRED, MAXIMUM
0181:            }
0182:
0183:            /**
0184:             * Creates an extended grid layout manager with the specified horizontal
0185:             * and vertical gap, and the specified distance to the borders
0186:             * of the parent container.
0187:             * 
0188:             * @param hgap The horizontal space between two columns ({@literal >=0})
0189:             * @param vgap The vertical space between two rows ({@literal >=0})
0190:             * @param distanceToBorders The distances to the borders of the parent container
0191:             * @throws IllegalArgumentException if hgap {@literal < 0}
0192:             * @throws IllegalArgumentException if vgap {@literal < 0}
0193:             */
0194:            public ExtendedGridLayout(int hgap, int vgap,
0195:                    Insets distanceToBorders) {
0196:                if (hgap < 0) {
0197:                    throw new IllegalArgumentException(
0198:                            "hgap must be non-negative (" + hgap + ')');
0199:                }
0200:                if (vgap < 0) {
0201:                    throw new IllegalArgumentException(
0202:                            "vgap must be non-negative (" + vgap + ')');
0203:                }
0204:                this .hgap = hgap;
0205:                this .vgap = vgap;
0206:                this .distanceToBorders = (Insets) distanceToBorders.clone();
0207:                comptable = new Hashtable<Component, ExtendedGridLayoutConstraints>();
0208:            }
0209:
0210:            /**
0211:             * Creates an extended grid layout manager with zero horizontal
0212:             * and vertical gap, and zero distance to the borders
0213:             * of the parent container.
0214:             */
0215:            public ExtendedGridLayout() {
0216:                this (0, 0, new Insets(0, 0, 0, 0));
0217:            }
0218:
0219:            /**
0220:             * If the layout manager uses a per-component string,
0221:             * adds the component <code>component</code> to the layout,
0222:             * associating it with the string specified by <code>name</code>.
0223:             * 
0224:             * @param name      The string to be associated with the component.
0225:             *                  Has to be {@code null}, so that default constraints are used.
0226:             * @param component The component to be added
0227:             * @throws IllegalArgumentException if {@code name} is not {@code null}
0228:             * @see #addLayoutComponent(java.awt.Component, java.lang.Object)
0229:             */
0230:            public void addLayoutComponent(String name, Component component) {
0231:                addLayoutComponent(component, name);
0232:            }
0233:
0234:            /**
0235:             * Adds the specified component to the layout, using the specified
0236:             * constraints object.
0237:             * 
0238:             * @param component    The component to be added
0239:             * @param constraints  Where/how the component is added to the layout.
0240:             * @throws IllegalArgumentException if {@code constraints} is not an ExtendedGridLayoutConstraints object
0241:             * @throws IllegalArgumentException if {@code constraints} is a placeholder
0242:             * @throws IllegalArgumentException if {@code constraints} is not the right one for the component
0243:             * @see ExtendedGridLayoutConstraints
0244:             */
0245:            public void addLayoutComponent(Component component,
0246:                    Object constraints) {
0247:                if (null == constraints) {
0248:                    constraints = new ExtendedGridLayoutConstraints(component);
0249:                }
0250:                if (constraints instanceof  ExtendedGridLayoutConstraints) {
0251:                    ExtendedGridLayoutConstraints eglConstraints = (ExtendedGridLayoutConstraints) constraints;
0252:                    if (eglConstraints.isPlaceholder()) {
0253:                        throw new IllegalArgumentException(
0254:                                "constraints must not be a placeholder");
0255:                    } else if (component != eglConstraints.getComponent()) {
0256:                        throw new IllegalArgumentException(
0257:                                "constraints is not the right one for this component");
0258:                    }
0259:                    comptable.put(component, eglConstraints);
0260:                } else {
0261:                    throw new IllegalArgumentException(
0262:                            "constraints must not be an ExtendedGridLayoutConstraints object");
0263:                }
0264:            }
0265:
0266:            /**
0267:             * Retrieves the constraints for the specified {@code component}.
0268:             * If {@code component} is not in the {@code ExtendedGridLayout},
0269:             * a set of default {@code ExtendedGridLayoutConstraints} are returned.
0270:             * 
0271:             * @param component the {@code component} to be queried
0272:             * @return the contraints for the specified {@code component}
0273:             * @throws NullPointerException if {@code component} is {@code null}
0274:             * @see ExtendedGridLayoutConstraints
0275:             */
0276:            private ExtendedGridLayoutConstraints lookupConstraints(
0277:                    Component component) {
0278:                if (null == component) {
0279:                    throw new NullPointerException("component must not be null");
0280:                }
0281:                ExtendedGridLayoutConstraints constraints = comptable
0282:                        .get(component);
0283:                if (null == constraints) {
0284:                    constraints = new ExtendedGridLayoutConstraints(component);
0285:                    comptable.put(component, constraints);
0286:                }
0287:                return constraints;
0288:            }
0289:
0290:            /**
0291:             * Removes the specified component from the layout.
0292:             * 
0293:             * @param component The component to be removed
0294:             */
0295:            public void removeLayoutComponent(Component component) {
0296:                comptable.remove(component);
0297:            }
0298:
0299:            /**
0300:             * Returns the alignment along the X axis.  This specifies how
0301:             * the component would like to be aligned relative to other
0302:             * components.  The value should be a number between 0 and 1
0303:             * where 0 represents alignment along the origin, 1 is aligned
0304:             * the furthest away from the origin, 0.5 is centered, etc.
0305:             * 
0306:             * @param container The container for which the alignment should be returned
0307:             * @return {@code java.awt.Component.CENTER_ALIGNMENT}
0308:             */
0309:            public float getLayoutAlignmentX(Container container) {
0310:                return CENTER_ALIGNMENT;
0311:            }
0312:
0313:            /**
0314:             * Returns the alignment along the Y axis. This specifies how
0315:             * the component would like to be aligned relative to other
0316:             * components. The value should be a number between 0 and 1
0317:             * where 0 represents alignment along the origin, 1 is aligned
0318:             * the furthest away from the origin, 0.5 is centered, etc.
0319:             * 
0320:             * @param container The container for which the alignment should be returned
0321:             * @return {@code java.awt.Component.CENTER_ALIGNMENT}
0322:             */
0323:            public float getLayoutAlignmentY(Container container) {
0324:                return CENTER_ALIGNMENT;
0325:            }
0326:
0327:            /**
0328:             * Calculates the minimum size dimensions for the specified
0329:             * container, given the components it contains.
0330:             * 
0331:             * @param parent The component to be laid out
0332:             * @return The minimum size for the container
0333:             * @see #maximumLayoutSize
0334:             * @see #preferredLayoutSize
0335:             */
0336:            public Dimension minimumLayoutSize(Container parent) {
0337:                synchronized (parent.getTreeLock()) {
0338:                    List<List<ExtendedGridLayoutConstraints>> gridRows = new ArrayList<List<ExtendedGridLayoutConstraints>>();
0339:                    Set<ExtendedGridLayoutConstraints> colspans = new HashSet<ExtendedGridLayoutConstraints>();
0340:                    Set<ExtendedGridLayoutConstraints> rowspans = new HashSet<ExtendedGridLayoutConstraints>();
0341:                    Dimension gridSize = buildGrid(parent, gridRows, colspans,
0342:                            rowspans);
0343:                    return getSize(parent, LayoutSize.MINIMUM, false, gridSize,
0344:                            gridRows, colspans, rowspans, new int[0][0]);
0345:                }
0346:            }
0347:
0348:            /**
0349:             * Calculates the preferred size dimensions for the specified
0350:             * container, given the components it contains.
0351:             * 
0352:             * @param parent The container to be laid out
0353:             * @return The preferred size for the container
0354:             * @see #maximumLayoutSize
0355:             * @see #minimumLayoutSize
0356:             */
0357:            public Dimension preferredLayoutSize(Container parent) {
0358:                synchronized (parent.getTreeLock()) {
0359:                    List<List<ExtendedGridLayoutConstraints>> gridRows = new ArrayList<List<ExtendedGridLayoutConstraints>>();
0360:                    Set<ExtendedGridLayoutConstraints> colspans = new HashSet<ExtendedGridLayoutConstraints>();
0361:                    Set<ExtendedGridLayoutConstraints> rowspans = new HashSet<ExtendedGridLayoutConstraints>();
0362:                    Dimension gridSize = buildGrid(parent, gridRows, colspans,
0363:                            rowspans);
0364:                    return getSize(parent, LayoutSize.PREFERRED, false,
0365:                            gridSize, gridRows, colspans, rowspans,
0366:                            new int[0][0]);
0367:                }
0368:            }
0369:
0370:            /**
0371:             * Calculates the maximum size dimensions for the specified
0372:             * container, given the components it contains.
0373:             * 
0374:             * @param parent The container to be laid out
0375:             * @return The maximum size for the container
0376:             * @see #minimumLayoutSize
0377:             * @see #preferredLayoutSize
0378:             */
0379:            public Dimension maximumLayoutSize(Container parent) {
0380:                synchronized (parent.getTreeLock()) {
0381:                    List<List<ExtendedGridLayoutConstraints>> gridRows = new ArrayList<List<ExtendedGridLayoutConstraints>>();
0382:                    Set<ExtendedGridLayoutConstraints> colspans = new HashSet<ExtendedGridLayoutConstraints>();
0383:                    Set<ExtendedGridLayoutConstraints> rowspans = new HashSet<ExtendedGridLayoutConstraints>();
0384:                    Dimension gridSize = buildGrid(parent, gridRows, colspans,
0385:                            rowspans);
0386:                    return getSize(parent, LayoutSize.MAXIMUM, false, gridSize,
0387:                            gridRows, colspans, rowspans, new int[0][0]);
0388:                }
0389:            }
0390:
0391:            /**
0392:             * Invalidates the layout, indicating that if the layout manager
0393:             * has cached information it should be discarded.
0394:             * 
0395:             * @param container The container for which the cached information should be discarded
0396:             */
0397:            public void invalidateLayout(Container container) {
0398:            }
0399:
0400:            /**
0401:             * Lays out the specified container.
0402:             * 
0403:             * @param parent The container to be laid out 
0404:             */
0405:            public void layoutContainer(Container parent) {
0406:                synchronized (parent.getTreeLock()) {
0407:                    // Pass 1: build the grid
0408:                    List<List<ExtendedGridLayoutConstraints>> gridRows = new ArrayList<List<ExtendedGridLayoutConstraints>>();
0409:                    Set<ExtendedGridLayoutConstraints> colspans = new HashSet<ExtendedGridLayoutConstraints>();
0410:                    Set<ExtendedGridLayoutConstraints> rowspans = new HashSet<ExtendedGridLayoutConstraints>();
0411:                    Dimension gridSize = buildGrid(parent, gridRows, colspans,
0412:                            rowspans);
0413:
0414:                    // Pass 2: compute minimum, preferred and maximum column widths / row heights
0415:                    int[][] layoutSizes = new int[6][];
0416:                    Dimension preferredSize = getSize(parent,
0417:                            LayoutSize.PREFERRED, true, gridSize, gridRows,
0418:                            colspans, rowspans, layoutSizes);
0419:                    int[] minimumColWidths = layoutSizes[0];
0420:                    int[] minimumRowHeights = layoutSizes[1];
0421:                    int[] preferredColWidths = layoutSizes[2];
0422:                    int[] preferredRowHeights = layoutSizes[3];
0423:                    int[] maximumColWidths = layoutSizes[4];
0424:                    int[] maximumRowHeights = layoutSizes[5];
0425:
0426:                    // Pass 3: redistribute free space
0427:                    Dimension parentSize = parent.getSize();
0428:                    Insets insets = parent.getInsets();
0429:                    int freeWidth = parentSize.width - insets.left
0430:                            - insets.right - (gridSize.width - 1) * hgap
0431:                            - distanceToBorders.left - distanceToBorders.right;
0432:                    int freeHeight = parentSize.height - insets.top
0433:                            - insets.bottom - (gridSize.height - 1) * vgap
0434:                            - distanceToBorders.top - distanceToBorders.bottom;
0435:                    redistributeSpace(preferredSize.width, freeWidth, 0,
0436:                            gridSize.width, preferredColWidths,
0437:                            minimumColWidths, maximumColWidths);
0438:                    redistributeSpace(preferredSize.height, freeHeight, 0,
0439:                            gridSize.height, preferredRowHeights,
0440:                            minimumRowHeights, maximumRowHeights);
0441:
0442:                    // Pass 4: layout components
0443:                    for (int row = 0, y = insets.top + distanceToBorders.top; row < gridSize.height; y += preferredRowHeights[row]
0444:                            + vgap, row++) {
0445:                        List<ExtendedGridLayoutConstraints> gridRow = gridRows
0446:                                .get(row);
0447:                        for (int col = 0, x = insets.left
0448:                                + distanceToBorders.left; col < gridSize.width; x += preferredColWidths[col]
0449:                                + hgap, col++) {
0450:                            ExtendedGridLayoutConstraints cell = gridRow
0451:                                    .get(col);
0452:                            if ((null != cell) && (null != cell.getComponent())
0453:                                    && !cell.isPlaceholder()) {
0454:                                Component component = cell.getComponent();
0455:                                Dimension maxSize = component.getMaximumSize();
0456:                                int fromCol = cell.getCol();
0457:                                int colspan = cell.getEffectiveColspan();
0458:                                int toCol = fromCol + colspan;
0459:                                int width = 0;
0460:                                for (int col2 = fromCol; col2 < toCol; col2++) {
0461:                                    width += preferredColWidths[col2];
0462:                                }
0463:                                width += (colspan - 1) * hgap;
0464:                                int fromRow = cell.getRow();
0465:                                int rowspan = cell.getEffectiveRowspan();
0466:                                int toRow = fromRow + rowspan;
0467:                                int height = 0;
0468:                                for (int row2 = fromRow; row2 < toRow; row2++) {
0469:                                    height += preferredRowHeights[row2];
0470:                                }
0471:                                height += (rowspan - 1) * vgap;
0472:                                int xCorrection = 0;
0473:                                int yCorrection = 0;
0474:                                if (width > maxSize.width) {
0475:                                    xCorrection = (int) ((width - maxSize.width) * component
0476:                                            .getAlignmentX());
0477:                                    width = maxSize.width;
0478:                                }
0479:                                if (height > maxSize.height) {
0480:                                    yCorrection = (int) ((height - maxSize.height) * component
0481:                                            .getAlignmentY());
0482:                                    height = maxSize.height;
0483:                                }
0484:
0485:                                component.setBounds(x + xCorrection, y
0486:                                        + yCorrection, width, height);
0487:                            }
0488:                        }
0489:                    }
0490:                }
0491:            }
0492:
0493:            /**
0494:             * Redistributs free space (positive or negative) to all available
0495:             * columns or rows while taking elements maximum and minimum sizes into
0496:             * account if possible.
0497:             * 
0498:             * @param totalSize             The cumulated preferred sizes of the components
0499:             * @param freeSize              The available space for displaying components
0500:             *                              without any gaps between components or between
0501:             *                              the grid and the borders of the parent container
0502:             * @param start                 The start in the arrays of rows or columns inclusive
0503:             * @param stop                  The stop in the arrays of rows or columns exclusive
0504:             * @param preferredElementSizes The preferredSizes of the rows or columns.
0505:             *                              After invocation of this method, this array
0506:             *                              holds the sizes that should be used
0507:             * @param minimumElementSizes   The minimumSizes of the rows or columns
0508:             * @param maximumElementSizes   The maximumSizes of the rows or columns
0509:             */
0510:            private void redistributeSpace(int totalSize, int freeSize,
0511:                    int start, int stop, int[] preferredElementSizes,
0512:                    int[] minimumElementSizes, int[] maximumElementSizes) {
0513:                if (totalSize != freeSize) {
0514:                    boolean grow = totalSize < freeSize;
0515:                    // calculate the size that is available for redistribution
0516:                    freeSize = (freeSize - totalSize) * (grow ? 1 : -1);
0517:                    while (freeSize > 0) {
0518:                        // calculate the amount of elements that can be resized without violating
0519:                        // the minimum and maximum sizes and their current cumulated size
0520:                        int modifyableAmount = 0;
0521:                        long modifySize = 0;
0522:                        for (int i = start; i < stop; i++) {
0523:                            if ((grow && (preferredElementSizes[i] < maximumElementSizes[i]))
0524:                                    || (!grow && (preferredElementSizes[i] > minimumElementSizes[i]))) {
0525:                                modifyableAmount++;
0526:                                modifySize += preferredElementSizes[i];
0527:                            }
0528:                        }
0529:                        boolean checkBounds = true;
0530:                        // if all elements are at their minimum or maximum size, resize all elements
0531:                        if (0 == modifyableAmount) {
0532:                            for (int i = start; i < stop; i++) {
0533:                                modifySize += preferredElementSizes[i];
0534:                            }
0535:                            checkBounds = false;
0536:                            modifyableAmount = stop - start;
0537:                        }
0538:                        // to prevent an endless loop if the container gets resized to a very small amount
0539:                        if (modifySize == 0) {
0540:                            break;
0541:                        }
0542:                        // resize the elements
0543:                        if (freeSize < modifyableAmount) {
0544:                            for (int i = start; i < stop; i++) {
0545:                                if ((freeSize != 0)
0546:                                        && (!checkBounds || (checkBounds
0547:                                                && (grow && (preferredElementSizes[i] < maximumElementSizes[i])) || (!grow && (preferredElementSizes[i] > minimumElementSizes[i]))))) {
0548:                                    preferredElementSizes[i] += (grow ? 1 : -1);
0549:                                    if (0 > preferredElementSizes[i]) {
0550:                                        preferredElementSizes[i] = 0;
0551:                                    }
0552:                                    freeSize--;
0553:                                }
0554:                            }
0555:                        } else {
0556:                            long modifySizeAddition = 0;
0557:                            double factor = (double) (freeSize + modifySize)
0558:                                    / (double) modifySize;
0559:                            for (int i = start; i < stop; i++) {
0560:                                long modifyableSize = (checkBounds ? (grow ? maximumElementSizes[i]
0561:                                        - preferredElementSizes[i]
0562:                                        : preferredElementSizes[i]
0563:                                                - minimumElementSizes[i])
0564:                                        : Integer.MAX_VALUE
0565:                                                - preferredElementSizes[i]);
0566:                                long elementModifySize = Math
0567:                                        .abs(Math
0568:                                                .round((factor * preferredElementSizes[i])
0569:                                                        - preferredElementSizes[i]));
0570:                                if (elementModifySize <= modifyableSize) {
0571:                                    preferredElementSizes[i] += (grow ? elementModifySize
0572:                                            : -elementModifySize);
0573:                                    modifySizeAddition += (grow ? elementModifySize
0574:                                            : -elementModifySize);
0575:                                    freeSize -= elementModifySize;
0576:                                } else {
0577:                                    preferredElementSizes[i] += (grow ? modifyableSize
0578:                                            : -modifyableSize);
0579:                                    modifySizeAddition += (grow ? modifyableSize
0580:                                            : -modifyableSize);
0581:                                    freeSize -= modifyableSize;
0582:                                }
0583:                                if (0 > preferredElementSizes[i]) {
0584:                                    preferredElementSizes[i] = 0;
0585:                                }
0586:                            }
0587:                            modifySize += modifySizeAddition;
0588:                        }
0589:                    }
0590:                }
0591:            }
0592:
0593:            /**
0594:             * Calculates the minimum, preferred or maximum size dimensions
0595:             * for the specified container, given the components it contains.
0596:             * 
0597:             * @param parent       The container to be laid out
0598:             * @param layoutSize   if {@code LayoutSize.MINIMUM} compute minimum layout size,
0599:             *                     if {@code LayoutSize.PREFERRED} compute preferred layout size,
0600:             *                     if {@code LayoutSize.MAXIMUM} compute maximum layout size,
0601:             *                     if {@code fillRawSizes} is {@code true}, the layout size is computed
0602:             *                     without applying gaps between components or between
0603:             *                     the grid and the borders of the parent container
0604:             * @param fillRawSizes Whether to fill the resultArrays with the raw
0605:             *                     row heights and column widths and whether to apply
0606:             *                     gaps between components or between
0607:             *                     the grid and the borders of the parent container
0608:             *                     when computing the layout size
0609:             * @param gridSize     The amount of rows and columns in the grid
0610:             * @param gridRows     The grid holding the constraints for the components
0611:             * @param colspans     In this {@code Set} the constraints which are part
0612:             *                     of a colspan are stored
0613:             * @param rowspans     In this {@code Set} the constraints which are part
0614:             *                     of a rowspan are stored
0615:             * @param resultArrays If {@code fillRawSizes} is {@code true}, the first six arrays
0616:             *                     get filled with the raw row heights and column widths.
0617:             *                     resultArrays[0] = resultMinimumColWidths;
0618:             *                     resultArrays[1] = resultMinimumRowHeights;
0619:             *                     resultArrays[2] = resultPreferredColWidths;
0620:             *                     resultArrays[3] = resultPreferredRowHeights;
0621:             *                     resultArrays[4] = resultMaximumColWidths;
0622:             *                     resultArrays[5] = resultMaximumRowHeights;
0623:             * @return The minimum, preferred or maximum size dimensions for the specified container
0624:             * @throws IllegalArgumentException If {@code fillRawSizes == true} and {@code resultArrays.length < 6}
0625:             */
0626:            private Dimension getSize(Container parent, LayoutSize layoutSize,
0627:                    boolean fillRawSizes, Dimension gridSize,
0628:                    List<List<ExtendedGridLayoutConstraints>> gridRows,
0629:                    Set<ExtendedGridLayoutConstraints> colspans,
0630:                    Set<ExtendedGridLayoutConstraints> rowspans,
0631:                    int[][] resultArrays) {
0632:                if (fillRawSizes && (resultArrays.length < 6)) {
0633:                    throw new IllegalArgumentException(
0634:                            "If fillRawSizes is true, resultArrays.length must be >= 6 ("
0635:                                    + resultArrays.length + ')');
0636:                }
0637:                int[] minimumColWidths = new int[gridSize.width];
0638:                int[] minimumRowHeights = new int[gridSize.height];
0639:                int[] preferredColWidths = new int[gridSize.width];
0640:                int[] preferredRowHeights = new int[gridSize.height];
0641:                int[] maximumColWidths = new int[gridSize.width];
0642:                int[] maximumRowHeights = new int[gridSize.height];
0643:                Arrays.fill(minimumColWidths, 0);
0644:                Arrays.fill(minimumRowHeights, 0);
0645:                Arrays.fill(preferredColWidths, 0);
0646:                Arrays.fill(preferredRowHeights, 0);
0647:                Arrays.fill(maximumColWidths, 0);
0648:                Arrays.fill(maximumRowHeights, 0);
0649:
0650:                // get the maximum of the minimum sizes,
0651:                //     the maximum of the preferred sizes and
0652:                //     the minimum of the maximum sizes
0653:                // of all rows and columns, not taking
0654:                // rowspans and colspans into account
0655:                for (int row = 0; row < gridSize.height; row++) {
0656:                    List<ExtendedGridLayoutConstraints> gridRow = gridRows
0657:                            .get(row);
0658:                    for (int col = 0; col < gridSize.width; col++) {
0659:                        ExtendedGridLayoutConstraints cell = gridRow.get(col);
0660:                        if ((null != cell) && (null != cell.getComponent())) {
0661:                            Component component = cell.getComponent();
0662:                            Dimension minimumSize = component.getMinimumSize();
0663:                            Dimension preferredSize = component
0664:                                    .getPreferredSize();
0665:                            Dimension maximumSize = component.getMaximumSize();
0666:                            if (!colspans.contains(cell)) {
0667:                                minimumColWidths[col] = Math.max(
0668:                                        minimumColWidths[col],
0669:                                        minimumSize.width);
0670:                                preferredColWidths[col] = Math.max(
0671:                                        preferredColWidths[col],
0672:                                        preferredSize.width);
0673:                                maximumColWidths[col] = Math.max(
0674:                                        maximumColWidths[col],
0675:                                        maximumSize.width);
0676:                            }
0677:                            if (!rowspans.contains(cell)) {
0678:                                minimumRowHeights[row] = Math.max(
0679:                                        minimumRowHeights[row],
0680:                                        minimumSize.height);
0681:                                preferredRowHeights[row] = Math.max(
0682:                                        preferredRowHeights[row],
0683:                                        preferredSize.height);
0684:                                maximumRowHeights[row] = Math.max(
0685:                                        maximumRowHeights[row],
0686:                                        maximumSize.height);
0687:                            }
0688:                        }
0689:                    }
0690:                }
0691:
0692:                // correct cases where
0693:                // minimumColWidths[col] <= preferredColWidths[col] <= maximumColWidths[col]
0694:                // is not true by clipping to the minimumColWidths and maximumColWidths
0695:                for (int col = 0; col < gridSize.width; col++) {
0696:                    if (minimumColWidths[col] >= maximumColWidths[col]) {
0697:                        maximumColWidths[col] = minimumColWidths[col];
0698:                        preferredColWidths[col] = minimumColWidths[col];
0699:                    } else if (preferredColWidths[col] < minimumColWidths[col]) {
0700:                        preferredColWidths[col] = minimumColWidths[col];
0701:                    } else if (preferredColWidths[col] > maximumColWidths[col]) {
0702:                        preferredColWidths[col] = maximumColWidths[col];
0703:                    }
0704:                }
0705:
0706:                // plug in the colspans and correct the minimum, preferred and
0707:                // maximum column widths the colspans are part of
0708:                for (ExtendedGridLayoutConstraints cell : colspans) {
0709:                    int fromCol = cell.getCol();
0710:                    int colspan = cell.getEffectiveColspan();
0711:                    int toCol = fromCol + colspan;
0712:                    int currentMinimumColWidth = 0;
0713:                    int currentPreferredColWidth = 0;
0714:                    int currentMaximumColWidth = 0;
0715:                    for (int col = fromCol; col < toCol; col++) {
0716:                        int minimumColWidth = minimumColWidths[col];
0717:                        if ((Integer.MAX_VALUE - minimumColWidth) < currentMinimumColWidth) {
0718:                            currentMinimumColWidth = Integer.MAX_VALUE;
0719:                        } else {
0720:                            currentMinimumColWidth += minimumColWidth;
0721:                        }
0722:                        int preferredColWidth = preferredColWidths[col];
0723:                        if ((Integer.MAX_VALUE - preferredColWidth) < currentPreferredColWidth) {
0724:                            currentPreferredColWidth = Integer.MAX_VALUE;
0725:                        } else {
0726:                            currentPreferredColWidth += preferredColWidth;
0727:                        }
0728:                        int maximumColWidth = maximumColWidths[col];
0729:                        if ((Integer.MAX_VALUE - maximumColWidth) < currentMaximumColWidth) {
0730:                            currentMaximumColWidth = Integer.MAX_VALUE;
0731:                        } else {
0732:                            currentMaximumColWidth += maximumColWidth;
0733:                        }
0734:                    }
0735:                    Component component = cell.getComponent();
0736:                    int wantedMaximumColWidth = component.getMaximumSize().width
0737:                            - ((colspan - 1) * hgap);
0738:                    if (currentMaximumColWidth < wantedMaximumColWidth) {
0739:                        redistributeSpace(currentMaximumColWidth,
0740:                                wantedMaximumColWidth, fromCol, toCol,
0741:                                maximumColWidths, maximumColWidths,
0742:                                maximumColWidths);
0743:                    }
0744:                    int wantedMinimumColWidth = component.getMinimumSize().width
0745:                            - ((colspan - 1) * hgap);
0746:                    if (currentMinimumColWidth < wantedMinimumColWidth) {
0747:                        redistributeSpace(currentMinimumColWidth,
0748:                                wantedMinimumColWidth, fromCol, toCol,
0749:                                minimumColWidths, minimumColWidths,
0750:                                maximumColWidths);
0751:                    }
0752:                    int wantedPreferredColWidth = component.getPreferredSize().width
0753:                            - ((colspan - 1) * hgap);
0754:                    if (currentPreferredColWidth < wantedPreferredColWidth) {
0755:                        redistributeSpace(currentPreferredColWidth,
0756:                                wantedPreferredColWidth, fromCol, toCol,
0757:                                preferredColWidths, minimumColWidths,
0758:                                maximumColWidths);
0759:                    }
0760:                }
0761:
0762:                // correct cases where
0763:                // minimumColWidths[col] <= preferredColWidths[col] <= maximumColWidths[col]
0764:                // is not true by clipping to the minimumColWidths and maximumColWidths
0765:                for (int col = 0; col < gridSize.width; col++) {
0766:                    if (minimumColWidths[col] >= maximumColWidths[col]) {
0767:                        maximumColWidths[col] = minimumColWidths[col];
0768:                        preferredColWidths[col] = minimumColWidths[col];
0769:                    } else if (preferredColWidths[col] < minimumColWidths[col]) {
0770:                        preferredColWidths[col] = minimumColWidths[col];
0771:                    } else if (preferredColWidths[col] > maximumColWidths[col]) {
0772:                        preferredColWidths[col] = maximumColWidths[col];
0773:                    }
0774:                }
0775:
0776:                // correct cases where
0777:                // minimumRowHeights[row] <= preferredRowHeights[row] <= maximumRowHeights[row]
0778:                // is not true by clipping to the minimumRowHeights and maximumRowHeights
0779:                for (int row = 0; row < gridSize.height; row++) {
0780:                    if (minimumRowHeights[row] >= maximumRowHeights[row]) {
0781:                        maximumRowHeights[row] = minimumRowHeights[row];
0782:                        preferredRowHeights[row] = minimumRowHeights[row];
0783:                    } else if (preferredRowHeights[row] < minimumRowHeights[row]) {
0784:                        preferredRowHeights[row] = minimumRowHeights[row];
0785:                    } else if (preferredRowHeights[row] > maximumRowHeights[row]) {
0786:                        preferredRowHeights[row] = maximumRowHeights[row];
0787:                    }
0788:                }
0789:
0790:                // plug in the rowspans and correct the minimum, preferred and
0791:                // maximum row heights the rowspans are part of
0792:                for (ExtendedGridLayoutConstraints cell : rowspans) {
0793:                    int fromRow = cell.getRow();
0794:                    int rowspan = cell.getEffectiveRowspan();
0795:                    int toRow = fromRow + rowspan;
0796:                    int currentMinimumRowHeight = 0;
0797:                    int currentPreferredRowHeight = 0;
0798:                    int currentMaximumRowHeight = 0;
0799:                    for (int row = fromRow; row < toRow; row++) {
0800:                        int minimumRowHeight = minimumRowHeights[row];
0801:                        if ((Integer.MAX_VALUE - minimumRowHeight) < currentMinimumRowHeight) {
0802:                            currentMinimumRowHeight = Integer.MAX_VALUE;
0803:                        } else {
0804:                            currentMinimumRowHeight += minimumRowHeight;
0805:                        }
0806:                        int preferredRowHeight = preferredRowHeights[row];
0807:                        if ((Integer.MAX_VALUE - preferredRowHeight) < currentPreferredRowHeight) {
0808:                            currentPreferredRowHeight = Integer.MAX_VALUE;
0809:                        } else {
0810:                            currentPreferredRowHeight += preferredRowHeight;
0811:                        }
0812:                        int maximumRowHeight = maximumRowHeights[row];
0813:                        if ((Integer.MAX_VALUE - maximumRowHeight) < currentMaximumRowHeight) {
0814:                            currentMaximumRowHeight = Integer.MAX_VALUE;
0815:                        } else {
0816:                            currentMaximumRowHeight += maximumRowHeight;
0817:                        }
0818:                    }
0819:                    Component component = cell.getComponent();
0820:                    int wantedMaximumRowHeight = component.getMaximumSize().height
0821:                            - ((rowspan - 1) * vgap);
0822:                    if (currentMaximumRowHeight < wantedMaximumRowHeight) {
0823:                        redistributeSpace(currentMaximumRowHeight,
0824:                                wantedMaximumRowHeight, fromRow, toRow,
0825:                                maximumRowHeights, maximumRowHeights,
0826:                                maximumRowHeights);
0827:                    }
0828:                    int wantedMinimumRowHeight = component.getMinimumSize().height
0829:                            - ((rowspan - 1) * vgap);
0830:                    if (currentMinimumRowHeight < wantedMinimumRowHeight) {
0831:                        redistributeSpace(currentMinimumRowHeight,
0832:                                wantedMinimumRowHeight, fromRow, toRow,
0833:                                minimumRowHeights, minimumRowHeights,
0834:                                maximumRowHeights);
0835:                    }
0836:                    int wantedPreferredRowHeight = component.getPreferredSize().height
0837:                            - ((rowspan - 1) * vgap);
0838:                    if (currentPreferredRowHeight < wantedPreferredRowHeight) {
0839:                        redistributeSpace(currentPreferredRowHeight,
0840:                                wantedPreferredRowHeight, fromRow, toRow,
0841:                                preferredRowHeights, minimumRowHeights,
0842:                                maximumRowHeights);
0843:                    }
0844:                }
0845:
0846:                // correct cases where
0847:                // minimumRowHeights[row] <= preferredRowHeights[row] <= maximumRowHeights[row]
0848:                // is not true by clipping to the minimumRowHeights and maximumRowHeights
0849:                for (int row = 0; row < gridSize.height; row++) {
0850:                    if (minimumRowHeights[row] >= maximumRowHeights[row]) {
0851:                        maximumRowHeights[row] = minimumRowHeights[row];
0852:                        preferredRowHeights[row] = minimumRowHeights[row];
0853:                    } else if (preferredRowHeights[row] < minimumRowHeights[row]) {
0854:                        preferredRowHeights[row] = minimumRowHeights[row];
0855:                    } else if (preferredRowHeights[row] > maximumRowHeights[row]) {
0856:                        preferredRowHeights[row] = maximumRowHeights[row];
0857:                    }
0858:                }
0859:
0860:                // copies the computed sizes to the result arrays
0861:                if (fillRawSizes) {
0862:                    resultArrays[0] = minimumColWidths;
0863:                    resultArrays[1] = minimumRowHeights;
0864:                    resultArrays[2] = preferredColWidths;
0865:                    resultArrays[3] = preferredRowHeights;
0866:                    resultArrays[4] = maximumColWidths;
0867:                    resultArrays[5] = maximumRowHeights;
0868:                }
0869:
0870:                // sums up the sizes for return value
0871:                int[] colWidths;
0872:                int[] rowHeights;
0873:                switch (layoutSize) {
0874:                case MINIMUM:
0875:                    colWidths = minimumColWidths;
0876:                    rowHeights = minimumRowHeights;
0877:                    break;
0878:
0879:                case PREFERRED:
0880:                    colWidths = preferredColWidths;
0881:                    rowHeights = preferredRowHeights;
0882:                    break;
0883:
0884:                case MAXIMUM:
0885:                    colWidths = maximumColWidths;
0886:                    rowHeights = maximumRowHeights;
0887:                    break;
0888:
0889:                default:
0890:                    throw new InternalError(
0891:                            "Missing case branch for LayoutSize: " + layoutSize);
0892:                }
0893:                long totalWidth = 0;
0894:                long totalHeight = 0;
0895:                for (int width : colWidths) {
0896:                    totalWidth += width;
0897:                }
0898:                for (int height : rowHeights) {
0899:                    totalHeight += height;
0900:                }
0901:
0902:                // add space between components or between
0903:                // componetns and the borders of the parent container
0904:                if (!fillRawSizes) {
0905:                    Insets insets = parent.getInsets();
0906:                    totalWidth += insets.left + insets.right
0907:                            + ((gridSize.width - 1) * hgap)
0908:                            + distanceToBorders.left + distanceToBorders.right;
0909:                    totalHeight += insets.top + insets.bottom
0910:                            + ((gridSize.height - 1) * vgap)
0911:                            + distanceToBorders.top + distanceToBorders.bottom;
0912:                }
0913:
0914:                // clip the size to Integer.MAX_VALUE if too big
0915:                if (totalWidth > Integer.MAX_VALUE) {
0916:                    totalWidth = Integer.MAX_VALUE;
0917:                }
0918:                if (totalHeight > Integer.MAX_VALUE) {
0919:                    totalHeight = Integer.MAX_VALUE;
0920:                }
0921:
0922:                return new Dimension((int) totalWidth, (int) totalHeight);
0923:            }
0924:
0925:            /**
0926:             * Builds up the grid for the specified container,
0927:             * given the components it contains.
0928:             * 
0929:             * @param parent   The container to be laid out
0930:             * @param gridRows In this {@code List<List>} the grid gets stored
0931:             * @param colspans In this {@code Set} the constraints which are part
0932:             *                 of a colspan get stored
0933:             * @param rowspans In this {@code Set} the constraints which are part
0934:             *                 of a rowspan get stored
0935:             * @return The amount of rows and columns in the grid
0936:             */
0937:            private Dimension buildGrid(Container parent,
0938:                    List<List<ExtendedGridLayoutConstraints>> gridRows,
0939:                    Set<ExtendedGridLayoutConstraints> colspans,
0940:                    Set<ExtendedGridLayoutConstraints> rowspans) {
0941:                // put the parent's components in source rows
0942:                List<List<ExtendedGridLayoutConstraints>> rows = new ArrayList<List<ExtendedGridLayoutConstraints>>();
0943:                Component[] components = parent.getComponents();
0944:                for (Component component : components) {
0945:                    if (component.isVisible()) {
0946:                        ExtendedGridLayoutConstraints constraints = lookupConstraints(
0947:                                component).getWorkCopy();
0948:                        int rowNumber = constraints.getRow();
0949:                        for (int i = rowNumber, c = rows.size(); i >= c; i--) {
0950:                            rows
0951:                                    .add(new ArrayList<ExtendedGridLayoutConstraints>());
0952:                        }
0953:                        List<ExtendedGridLayoutConstraints> row = rows
0954:                                .get(rowNumber);
0955:                        row.add(constraints);
0956:                    }
0957:                }
0958:
0959:                // initialize the rowIterators, gridRowIterators and gridRows
0960:                List<Iterator<ExtendedGridLayoutConstraints>> rowIterators = new ArrayList<Iterator<ExtendedGridLayoutConstraints>>();
0961:                List<ListIterator<ExtendedGridLayoutConstraints>> gridRowIterators = new ArrayList<ListIterator<ExtendedGridLayoutConstraints>>();
0962:                boolean haveNext = false;
0963:                for (List<ExtendedGridLayoutConstraints> row : rows) {
0964:                    Iterator<ExtendedGridLayoutConstraints> rowIterator = row
0965:                            .iterator();
0966:                    rowIterators.add(rowIterator);
0967:                    if (rowIterator.hasNext()) {
0968:                        haveNext = true;
0969:                    }
0970:                    List<ExtendedGridLayoutConstraints> gridRow = new ArrayList<ExtendedGridLayoutConstraints>();
0971:                    gridRows.add(gridRow);
0972:                    gridRowIterators.add(gridRow.listIterator());
0973:                }
0974:
0975:                // build the grid
0976:                int col = -1;
0977:                while (haveNext) {
0978:                    col++;
0979:                    haveNext = false;
0980:                    for (int row = 0, c = gridRows.size(); row < c; row++) {
0981:                        Iterator<ExtendedGridLayoutConstraints> rowIterator = rowIterators
0982:                                .get(row);
0983:                        ListIterator<ExtendedGridLayoutConstraints> gridRowIterator = gridRowIterators
0984:                                .get(row);
0985:
0986:                        // look for a rowspan in the previous row
0987:                        if (row > 0) {
0988:                            ExtendedGridLayoutConstraints rowspanSource = gridRows
0989:                                    .get(row - 1).get(col);
0990:                            if (null != rowspanSource) {
0991:                                ExtendedGridLayoutConstraints rowspanPlaceholder = rowspanSource
0992:                                        .getRowspanPlaceholder(true);
0993:                                if (null != rowspanPlaceholder) {
0994:                                    rowspans.add(rowspanSource);
0995:                                    gridRowIterator.add(rowspanPlaceholder);
0996:                                    if (null != rowspanPlaceholder
0997:                                            .getColspanPlaceholder(false)) {
0998:                                        switch (rowspanPlaceholder.getColspan()) {
0999:                                        case REMAINDER:
1000:                                            break;
1001:
1002:                                        default:
1003:                                            haveNext = true;
1004:                                        }
1005:                                    } else if (rowIterator.hasNext()) {
1006:                                        haveNext = true;
1007:                                    }
1008:                                    continue;
1009:                                }
1010:                            }
1011:                        }
1012:
1013:                        // look for a colspan in the previous column
1014:                        if (gridRowIterator.hasPrevious()) {
1015:                            ExtendedGridLayoutConstraints colspanSource = gridRowIterator
1016:                                    .previous();
1017:                            gridRowIterator.next();
1018:                            if (null != colspanSource) {
1019:                                ExtendedGridLayoutConstraints colspanPlaceholder = colspanSource
1020:                                        .getColspanPlaceholder(true);
1021:                                if (null != colspanPlaceholder) {
1022:                                    colspans.add(colspanSource);
1023:                                    gridRowIterator.add(colspanPlaceholder);
1024:                                    if (null != colspanPlaceholder
1025:                                            .getColspanPlaceholder(false)) {
1026:                                        switch (colspanPlaceholder.getColspan()) {
1027:                                        case REMAINDER:
1028:                                            break;
1029:
1030:                                        default:
1031:                                            haveNext = true;
1032:                                        }
1033:                                    } else if (rowIterator.hasNext()) {
1034:                                        haveNext = true;
1035:                                    }
1036:                                    continue;
1037:                                }
1038:                            }
1039:                        }
1040:
1041:                        // add a new element or null
1042:                        if (rowIterator.hasNext()) {
1043:                            ExtendedGridLayoutConstraints newConstraints = rowIterator
1044:                                    .next();
1045:                            newConstraints.setCol(col);
1046:                            gridRowIterator.add(newConstraints);
1047:                            if (null != newConstraints
1048:                                    .getColspanPlaceholder(false)) {
1049:                                switch (newConstraints.getColspan()) {
1050:                                case REMAINDER:
1051:                                    break;
1052:
1053:                                default:
1054:                                    haveNext = true;
1055:                                }
1056:                            } else if (rowIterator.hasNext()) {
1057:                                haveNext = true;
1058:                            }
1059:                        } else {
1060:                            gridRowIterator.add(null);
1061:                        }
1062:                    }
1063:                }
1064:
1065:                // check the last gridRow for rowspans and probably add rows for these
1066:                haveNext = false;
1067:                int gridRowsSize = gridRows.size();
1068:                if (gridRowsSize > 0) {
1069:                    ListIterator<ExtendedGridLayoutConstraints> gridRowIterator = gridRows
1070:                            .get(gridRows.size() - 1).listIterator();
1071:                    while (gridRowIterator.hasNext()) {
1072:                        ExtendedGridLayoutConstraints cell = gridRowIterator
1073:                                .next();
1074:                        if ((null != cell)
1075:                                && ((REMAINDER != cell.getRowspan()) && (null != cell
1076:                                        .getRowspanPlaceholder(false)))) {
1077:                            haveNext = true;
1078:                            break;
1079:                        }
1080:                    }
1081:                    while (haveNext) {
1082:                        haveNext = false;
1083:                        gridRowIterator = gridRows.get(gridRows.size() - 1)
1084:                                .listIterator();
1085:                        List<ExtendedGridLayoutConstraints> gridRow = new ArrayList<ExtendedGridLayoutConstraints>();
1086:                        gridRows.add(gridRow);
1087:                        ListIterator<ExtendedGridLayoutConstraints> newGridRowIterator = gridRow
1088:                                .listIterator();
1089:                        while (gridRowIterator.hasNext()) {
1090:                            ExtendedGridLayoutConstraints cell = gridRowIterator
1091:                                    .next();
1092:                            if ((null != cell)
1093:                                    && (null != cell
1094:                                            .getRowspanPlaceholder(false))) {
1095:                                rowspans.add(cell);
1096:                                ExtendedGridLayoutConstraints rowspanPlaceholder = cell
1097:                                        .getRowspanPlaceholder(true);
1098:                                newGridRowIterator.add(rowspanPlaceholder);
1099:                            } else {
1100:                                newGridRowIterator.add(null);
1101:                            }
1102:                        }
1103:                        gridRowIterator = gridRow.listIterator();
1104:                        while (gridRowIterator.hasNext()) {
1105:                            ExtendedGridLayoutConstraints cell = gridRowIterator
1106:                                    .next();
1107:                            if ((null != cell)
1108:                                    && ((REMAINDER != cell.getRowspan()) && (null != cell
1109:                                            .getRowspanPlaceholder(false)))) {
1110:                                haveNext = true;
1111:                                break;
1112:                            }
1113:                        }
1114:                    }
1115:                }
1116:
1117:                return new Dimension(col + 1, gridRows.size());
1118:            }
1119:
1120:            /**
1121:             * Returns a string representation of the object. In general, the
1122:             * {@code toString} method returns a string that
1123:             * "textually represents" this object. The result should
1124:             * be a concise but informative representation that is easy for a
1125:             * person to read.
1126:             * 
1127:             * @return  a string representation of the object.
1128:             */
1129:            public String toString() {
1130:                return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap
1131:                        + ",distanceToBorders=" + distanceToBorders
1132:                        + ",comptable=" + comptable + "]";
1133:            }
1134:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.