Source Code Cross Referenced for TableLayout.java in  » XML-UI » gui4j » org » gui4j » core » swing » 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 » XML UI » gui4j » org.gui4j.core.swing 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * June 2006: This is the original file except of this paragraph and 
0003:         * for consistency, the original package name info.clearthought
0004:         * was renamed.  
0005:         */
0006:        /*
0007:         * ====================================================================
0008:         *
0009:         * The Clearthought Software License, Version 1.0
0010:         *
0011:         * Copyright (c) 2001 Daniel Barbalace.  All rights reserved.
0012:         *
0013:         * Redistribution and use in source and binary forms, with or without
0014:         * modification, are permitted provided that the following conditions
0015:         * are met:
0016:         *
0017:         * 1. Redistributions of source code must retain the above copyright
0018:         *    notice, this list of conditions and the following disclaimer.
0019:         *
0020:         * 2. The original software may not be altered.  However, the classes
0021:         *    provided may be subclasses as long as the subclasses are not
0022:         *    packaged in the info.clearthought package or any subpackage of
0023:         *    info.clearthought.
0024:         *
0025:         * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0026:         * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0027:         * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0028:         * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR, AFFILATED BUSINESSES,
0029:         * OR ANYONE ELSE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0030:         * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0031:         * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0032:         * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0033:         * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0034:         * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0035:         * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0036:         * SUCH DAMAGE.
0037:         * ====================================================================
0038:         */
0039:
0040:        package org.gui4j.core.swing;
0041:
0042:        import java.awt.Component;
0043:        import java.awt.Container;
0044:        import java.awt.Dimension;
0045:        import java.awt.Insets;
0046:        import java.util.LinkedList;
0047:        import java.util.ListIterator;
0048:
0049:        /**
0050:         * TableLayout is a layout manager that arranges components in rows and columns
0051:         * like a spreadsheet.  TableLayout allows each row or column to be a different
0052:         * size.  A row or column can be given an absolute size in pixels, a percentage
0053:         * of the available space, or it can grow and shrink to fill the remaining space
0054:         * after other rows and columns have been resized.
0055:         *
0056:         * <p>Using spreadsheet terminology, a cell is the intersection of a row and
0057:         * column.  Cells have finite, non-negative sizes measured in pixels.  The
0058:         * dimensions of a cell depend solely upon the dimensions of its row and column.
0059:         * </p>
0060:         *
0061:         * <p>A component occupies a rectangular group of one or more cells.  The
0062:         * component can be aligned in four ways within that cell.</p>
0063:         *
0064:         * <p>A component can be stretched horizontally to fit the cell set (full
0065:         * justification), or it can be placed in the center of the cell.  The
0066:         * component could also be left justified or right justified.  Similarly, the
0067:         * component can be full, center, top, or bottom justified along the
0068:         *
0069:         * <pre>
0070:         * public static void main (String args[])
0071:         * {
0072:         *     // Create a frame
0073:         *     Frame frame = new Frame("Example of TableLayout");
0074:         *     frame.setBounds (100, 100, 300, 300);
0075:         * <spc>
0076:         *     // Create a TableLayout for the frame
0077:         *     double border = 10;
0078:         *     double size[][] =
0079:         *         {{border, 0.10, 20, TableLayout.FILL, 20, 0.20, border},  // Columns
0080:         *          {border, 0.20, 20, TableLayout.FILL, 20, 0.20, border}}; // Rows
0081:         * <spc>
0082:         *     frame.setLayout (new TableLayout(size));
0083:         * <spc>
0084:         *     // Create some buttons
0085:         *     String label[] = {"Top", "Bottom", "Left", "Right", "Center", "Overlap"};
0086:         *     Button button[] = new Button[label.length];
0087:         * <spc>
0088:         *     for (int i = 0; i < label.length; i++)
0089:         *         button[i] = new Button(label[i]);
0090:         * <spc>
0091:         *     // Add buttons
0092:         *     frame.add (button[0], "1, 1, 5, 1"); // Top
0093:         *     frame.add (button[1], "1, 5, 5, 5"); // Bottom
0094:         *     frame.add (button[2], "1, 3      "); // Left
0095:         *     frame.add (button[3], "5, 3      "); // Right
0096:         *     frame.add (button[4], "3, 3, c, c"); // Center
0097:         *     frame.add (button[5], "3, 3, 3, 5"); // Overlap
0098:         * <spc>
0099:         *     // Allow user to close the window to terminate the program
0100:         *     frame.addWindowListener
0101:         *         (new WindowListener()
0102:         *             {
0103:         *                 public void windowClosing (WindowEvent e)
0104:         *                 {
0105:         *                     System.exit (0);
0106:         *                 }
0107:         * <spc>
0108:         *                 public void windowOpened (WindowEvent e) {}
0109:         *                 public void windowClosed (WindowEvent e) {}
0110:         *                 public void windowIconified (WindowEvent e) {}
0111:         *                 public void windowDeiconified (WindowEvent e) {}
0112:         *                 public void windowActivated (WindowEvent e) {}
0113:         *                 public void windowDeactivated (WindowEvent e) {}
0114:         *             }
0115:         *         );
0116:         * <spc>
0117:         *     // Show frame
0118:         *     frame.show();
0119:         * }
0120:         * </pre>
0121:         *
0122:         * @version 2.1 4/26/02
0123:         * @author  Daniel E. Barbalace
0124:         */
0125:
0126:        public class TableLayout implements  java.awt.LayoutManager2,
0127:                java.io.Serializable, TableLayoutConstants {
0128:
0129:            /*
0130:                Note: In this file, a cr refers to either a column or a row.  cr[C] always
0131:                means column and cr[R] always means row.  A cr size is either a column
0132:                width or a row Height.  TableLayout views columns and rows as being
0133:                conceptually symmetric.  Therefore, much of the code applies to both
0134:                columns and rows, and the use of the cr terminology eliminates redundancy.
0135:                Also, for ease of reading, z always indicates a parameter whose value is
0136:                either C or R.
0137:             */
0138:
0139:            /** Default row/column size */
0140:            protected static final double defaultSize[][] = { {}, {} };
0141:
0142:            /** Indicates a column */
0143:            protected static final int C = 0;
0144:
0145:            /** Indicates a row */
0146:            protected static final int R = 1;
0147:
0148:            /** Sizes of crs expressed in absolute and relative terms */
0149:            protected double crSpec[][] = { null, null };
0150:
0151:            /** Sizes of crs in pixels */
0152:            protected int crSize[][] = { null, null };
0153:
0154:            /** Offsets of crs in pixels.  The left boarder of column n is at
0155:             crOffset[C][n] and the right boarder is at cr[C][n + 1] for all
0156:             columns including the last one.  crOffset[C].length = crSize[C].length + 1 */
0157:            protected int crOffset[][] = { null, null };
0158:
0159:            /** List of components and their sizes */
0160:            protected LinkedList list;
0161:
0162:            /** Indicates whether or not the size of the cells are known for the last known
0163:             size of the container.  If dirty is true or the container has been resized,
0164:             the cell sizes must be recalculated using calculateSize. */
0165:            protected boolean dirty;
0166:
0167:            /** Previous known width of the container */
0168:            protected int oldWidth;
0169:
0170:            /** Previous known height of the container */
0171:            protected int oldHeight;
0172:
0173:            /** Horizontal gap between columns */
0174:            protected int hGap;
0175:
0176:            /** Vertical gap between rows */
0177:            protected int vGap;
0178:
0179:            //******************************************************************************
0180:            //** Constructors                                                            ***
0181:            //******************************************************************************
0182:
0183:            /**
0184:             * Constructs an instance of TableLayout.  This TableLayout will have one row
0185:             * and one column.
0186:             */
0187:
0188:            public TableLayout() {
0189:                this (defaultSize);
0190:            }
0191:
0192:            /**
0193:             * Constructs an instance of TableLayout.
0194:             *
0195:             * @param size    widths of columns and heights of rows in the format,
0196:             *                {{col0, col1, col2, ..., colN}, {row0, row1, row2, ..., rowM}}
0197:             *                If this parameter is invalid, the TableLayout will have
0198:             *                exactly one row and one column.
0199:             */
0200:
0201:            public TableLayout(double size[][]) {
0202:                // Make sure rows and columns and nothing else is specified
0203:                if ((size != null) && (size.length == 2)) {
0204:                    // Get the rows and columns
0205:                    double tempCol[] = size[0];
0206:                    double tempRow[] = size[1];
0207:
0208:                    // Create new rows and columns
0209:                    crSpec[C] = new double[tempCol.length];
0210:                    crSpec[R] = new double[tempRow.length];
0211:
0212:                    // Copy rows and columns
0213:                    System
0214:                            .arraycopy(tempCol, 0, crSpec[C], 0,
0215:                                    crSpec[C].length);
0216:                    System
0217:                            .arraycopy(tempRow, 0, crSpec[R], 0,
0218:                                    crSpec[R].length);
0219:
0220:                    // Make sure rows and columns are valid
0221:                    for (int counter = 0; counter < crSpec[C].length; counter++)
0222:                        if ((crSpec[C][counter] < 0.0)
0223:                                && (crSpec[C][counter] != FILL)
0224:                                && (crSpec[C][counter] != PREFERRED)
0225:                                && (crSpec[C][counter] != MINIMUM)) {
0226:                            crSpec[C][counter] = 0.0;
0227:                        }
0228:
0229:                    for (int counter = 0; counter < crSpec[R].length; counter++)
0230:                        if ((crSpec[R][counter] < 0.0)
0231:                                && (crSpec[R][counter] != FILL)
0232:                                && (crSpec[R][counter] != PREFERRED)
0233:                                && (crSpec[R][counter] != MINIMUM)) {
0234:                            crSpec[R][counter] = 0.0;
0235:                        }
0236:                } else {
0237:                    throw new IllegalArgumentException(
0238:                            "Parameter size should be an array, a[2], where a[0] is the "
0239:                                    + "is an array of column widths and a[1] is an array or row "
0240:                                    + "heights.");
0241:                }
0242:
0243:                // Create an empty list of components
0244:                list = new LinkedList();
0245:
0246:                // Indicate that the cell sizes are not known
0247:                dirty = true;
0248:            }
0249:
0250:            //******************************************************************************
0251:            //** Get/Set methods                                                         ***
0252:            //******************************************************************************
0253:
0254:            /**
0255:             * Gets the constraints of a given component.
0256:             *
0257:             * @param component    desired component
0258:             *
0259:             * @return If the given component is found, the constraints associated with
0260:             *         that component.  If the given component is null or is not found,
0261:             *         null is returned.
0262:             */
0263:
0264:            public TableLayoutConstraints getConstraints(Component component) {
0265:                ListIterator iterator = list.listIterator(0);
0266:
0267:                while (iterator.hasNext()) {
0268:                    Entry entry = (Entry) iterator.next();
0269:
0270:                    if (entry.component == component)
0271:                        return new TableLayoutConstraints(entry.cr1[C],
0272:                                entry.cr1[R], entry.cr2[C], entry.cr2[R],
0273:                                entry.alignment[C], entry.alignment[R]);
0274:                }
0275:
0276:                return null;
0277:            }
0278:
0279:            /**
0280:             * Sets the constraints of a given component.
0281:             *
0282:             * @param component     desired component.  This parameter cannot be null.
0283:             * @param constraint    new set of constraints.  This parameter cannot be null.
0284:             */
0285:
0286:            public void setConstraints(Component component,
0287:                    TableLayoutConstraints constraint) {
0288:                // Check parameters
0289:                if (component == null)
0290:                    throw new IllegalArgumentException(
0291:                            "Parameter component cannot be null.");
0292:                else if (constraint == null)
0293:                    throw new IllegalArgumentException(
0294:                            "Parameter constraint cannot be null.");
0295:
0296:                // Find and update constraints for the given component
0297:                ListIterator iterator = list.listIterator(0);
0298:
0299:                while (iterator.hasNext()) {
0300:                    Entry entry = (Entry) iterator.next();
0301:
0302:                    if (entry.component == component)
0303:                        iterator.set(new Entry(component, constraint));
0304:                }
0305:            }
0306:
0307:            /**
0308:             * Adjusts the number and sizes of rows in this layout.  After calling this
0309:             * method, the caller should request this layout manager to perform the
0310:             * layout.  This can be done with the following code:
0311:             *
0312:             * <pre>
0313:             *     layout.layoutContainer(container);
0314:             *     container.repaint();
0315:             * </pre>
0316:             *
0317:             * or
0318:             *
0319:             * <pre>
0320:             *     window.pack()
0321:             * </pre>
0322:             *
0323:             * If this is not done, the changes in the layout will not be seen until the
0324:             * container is resized.
0325:             *
0326:             * @param column    heights of each of the columns
0327:             */
0328:
0329:            public void setColumn(double column[]) {
0330:                setCr(C, column);
0331:            }
0332:
0333:            /**
0334:             * Adjusts the number and sizes of rows in this layout.  After calling this
0335:             * method, the caller should request this layout manager to perform the
0336:             * layout.  This can be done with the following code:
0337:             *
0338:             * <code>
0339:             *     layout.layoutContainer(container);
0340:             *     container.repaint();
0341:             * </code>
0342:             *
0343:             * or
0344:             *
0345:             * <pre>
0346:             *     window.pack()
0347:             * </pre>
0348:             *
0349:             * If this is not done, the changes in the layout will not be seen until the
0350:             * container is resized.
0351:             *
0352:             * @param row    widths of each of the rows.  This parameter cannot be null.
0353:             */
0354:
0355:            public void setRow(double row[]) {
0356:                setCr(R, row);
0357:            }
0358:
0359:            /**
0360:             * Sets the sizes of rows or columns for the methods setRow or setColumn.
0361:             * 
0362:             * @param z       indicates row or column
0363:             * @param size    new cr size
0364:             */
0365:
0366:            protected void setCr(int z, double size[]) {
0367:                // Copy crs
0368:                crSpec[z] = new double[size.length];
0369:                System.arraycopy(size, 0, crSpec[z], 0, crSpec[z].length);
0370:
0371:                // Make sure rows are valid
0372:                for (int counter = 0; counter < crSpec[z].length; counter++)
0373:                    if ((crSpec[z][counter] < 0.0)
0374:                            && (crSpec[z][counter] != FILL)
0375:                            && (crSpec[z][counter] != PREFERRED)
0376:                            && (crSpec[z][counter] != MINIMUM)) {
0377:                        crSpec[z][counter] = 0.0;
0378:                    }
0379:
0380:                // Indicate that the cell sizes are not known
0381:                dirty = true;
0382:            }
0383:
0384:            /**
0385:             * Adjusts the width of a single column in this layout.  After calling this
0386:             * method, the caller should request this layout manager to perform the
0387:             * layout.  This can be done with the following code:
0388:             *
0389:             * <code>
0390:             *     layout.layoutContainer(container);
0391:             *     container.repaint();
0392:             * </code>
0393:             *
0394:             * or
0395:             *
0396:             * <pre>
0397:             *     window.pack()
0398:             * </pre>
0399:             *
0400:             * If this is not done, the changes in the layout will not be seen until the
0401:             * container is resized.
0402:             *
0403:             * @param i       zero-based index of column to set.  If this parameter is not
0404:             *                valid, an ArrayOutOfBoundsException will be thrown.
0405:             * @param size    width of the column.  This parameter cannot be null.
0406:             */
0407:
0408:            public void setColumn(int i, double size) {
0409:                setCr(C, i, size);
0410:            }
0411:
0412:            /**
0413:             * Adjusts the height of a single row in this layout.  After calling this
0414:             * method, the caller should request this layout manager to perform the
0415:             * layout.  This can be done with the following code:
0416:             *
0417:             * <code>
0418:             *     layout.layoutContainer(container);
0419:             *     container.repaint();
0420:             * </code>
0421:             *
0422:             * or
0423:             *
0424:             * <pre>
0425:             *     window.pack()
0426:             * </pre>
0427:             *
0428:             * If this is not done, the changes in the layout will not be seen until the
0429:             * container is resized.
0430:             *
0431:             * @param i       zero-based index of row to set.  If this parameter is not
0432:             *                valid, an ArrayOutOfBoundsException will be thrown.
0433:             * @param size    height of the row.  This parameter cannot be null.
0434:             */
0435:
0436:            public void setRow(int i, double size) {
0437:                setCr(R, i, size);
0438:            }
0439:
0440:            /**
0441:             * Sets the sizes of rows or columns for the methods setRow or setColumn.
0442:             * 
0443:             * @param z       indicates row or column
0444:             * @param i       indicates which cr to resize
0445:             * @param size    new cr size
0446:             */
0447:
0448:            protected void setCr(int z, int i, double size) {
0449:                // Make sure size is valid
0450:                if ((size < 0.0) && (size != FILL) && (size != PREFERRED)
0451:                        && (size != MINIMUM)) {
0452:                    size = 0.0;
0453:                }
0454:
0455:                // Copy new size
0456:                crSpec[z][i] = size;
0457:
0458:                // Indicate that the cell sizes are not known
0459:                dirty = true;
0460:            }
0461:
0462:            /**
0463:             * Gets the sizes of columns in this layout.
0464:             *
0465:             * @return widths of each of the columns
0466:             */
0467:
0468:            public double[] getColumn() {
0469:                // Copy columns
0470:                double column[] = new double[crSpec[C].length];
0471:                System.arraycopy(crSpec[C], 0, column, 0, column.length);
0472:
0473:                return column;
0474:            }
0475:
0476:            /**
0477:             * Gets the height of a single row in this layout.
0478:             *
0479:             * @return height of the requested row
0480:             */
0481:
0482:            public double[] getRow() {
0483:                // Copy rows
0484:                double row[] = new double[crSpec[R].length];
0485:                System.arraycopy(crSpec[R], 0, row, 0, row.length);
0486:
0487:                return row;
0488:            }
0489:
0490:            /**
0491:             * Gets the width of a single column in this layout.
0492:             *
0493:             * @param i    zero-based index of row to get.  If this parameter is not valid,
0494:             *             an ArrayOutOfBoundsException will be thrown.
0495:             *
0496:             * @return width of the requested column
0497:             */
0498:
0499:            public double getColumn(int i) {
0500:                return crSpec[C][i];
0501:            }
0502:
0503:            /**
0504:             * Gets the sizes of a row in this layout.
0505:             *
0506:             * @param i    zero-based index of row to get.  If this parameter is not valid,
0507:             *             an ArrayOutOfBoundsException will be thrown.
0508:             *
0509:             * @return height of each of the requested row
0510:             */
0511:
0512:            public double getRow(int i) {
0513:                return crSpec[R][i];
0514:            }
0515:
0516:            /**
0517:             * Gets the number of columns in this layout.
0518:             *
0519:             * @return the number of columns
0520:             */
0521:
0522:            public int getNumColumn() {
0523:                return crSpec[C].length;
0524:            }
0525:
0526:            /**
0527:             * Gets the number of rows in this layout.
0528:             *
0529:             * @return the number of rows
0530:             */
0531:
0532:            public int getNumRow() {
0533:                return crSpec[R].length;
0534:            }
0535:
0536:            /**
0537:             * Gets the horizontal gap between colunns.
0538:             *
0539:             * @return the horizontal gap in pixels
0540:             */
0541:
0542:            public int getHGap() {
0543:                return hGap;
0544:            }
0545:
0546:            /**
0547:             * Gets the vertical gap between rows.
0548:             *
0549:             * @return the vertical gap in pixels
0550:             */
0551:
0552:            public int getVGap() {
0553:                return vGap;
0554:            }
0555:
0556:            /**
0557:             * Sets the horizontal gap between colunns.
0558:             *
0559:             * @param hGap    the horizontal gap in pixels
0560:             */
0561:
0562:            public void setHGap(int hGap) {
0563:                if (hGap >= 0)
0564:                    this .hGap = hGap;
0565:                else
0566:                    throw new IllegalArgumentException(
0567:                            "Parameter hGap must be non-negative.");
0568:            }
0569:
0570:            /**
0571:             * Sets the vertical gap between rows.
0572:             *
0573:             * @param vGap    the horizontal gap in pixels
0574:             */
0575:
0576:            public void setVGap(int vGap) {
0577:                if (vGap >= 0)
0578:                    this .vGap = vGap;
0579:                else
0580:                    throw new IllegalArgumentException(
0581:                            "Parameter vGap must be non-negative.");
0582:            }
0583:
0584:            //******************************************************************************
0585:            //** Insertion/Deletion methods                                              ***
0586:            //******************************************************************************
0587:
0588:            /**
0589:             * Inserts a column in this layout.  All components to the right of the
0590:             * insertion point are moved right one column.  The container will need to
0591:             * be laid out after this method returns.  See <code>setColumn</code>.
0592:             *
0593:             * @param i       zero-based index at which to insert the column
0594:             * @param size    size of the column to be inserted
0595:             */
0596:
0597:            public void insertColumn(int i, double size) {
0598:                insertCr(C, i, size);
0599:            }
0600:
0601:            /**
0602:             * Inserts a row in this layout.  All components below the insertion point
0603:             * are moved down one row.  The container will need to be laid out after this
0604:             * method returns.  See <code>setRow</code>.
0605:             *
0606:             * @param i       zero-based index at which to insert the row
0607:             * @param size    size of the row to be inserted
0608:             */
0609:
0610:            public void insertRow(int i, double size) {
0611:                insertCr(R, i, size);
0612:            }
0613:
0614:            /**
0615:             * Inserts a cr for the methods insertRow or insertColumn.
0616:             * 
0617:             * @param z       indicates row or column
0618:             * @param i       zero-based index at which to insert the cr
0619:             * @param size    size of cr being inserted
0620:             */
0621:
0622:            public void insertCr(int z, int i, double size) {
0623:                // Make sure position is valid
0624:                if ((i < 0) || (i > crSpec[z].length))
0625:                    throw new IllegalArgumentException(
0626:                            "Parameter i is invalid.  i = " + i
0627:                                    + ".  Valid range is [0, "
0628:                                    + crSpec[z].length + "].");
0629:
0630:                // Make sure row size is valid
0631:                if ((size < 0.0) && (size != FILL) && (size != PREFERRED)
0632:                        && (size != MINIMUM)) {
0633:                    size = 0.0;
0634:                }
0635:
0636:                // Copy crs
0637:                double cr[] = new double[crSpec[z].length + 1];
0638:                System.arraycopy(crSpec[z], 0, cr, 0, i);
0639:                System.arraycopy(crSpec[z], i, cr, i + 1, crSpec[z].length - i);
0640:
0641:                // Insert cr
0642:                cr[i] = size;
0643:                crSpec[z] = cr;
0644:
0645:                // Move all components that are below the new cr
0646:                ListIterator iterator = list.listIterator(0);
0647:
0648:                while (iterator.hasNext()) {
0649:                    // Get next entry
0650:                    Entry entry = (Entry) iterator.next();
0651:
0652:                    // Is the first cr below the new cr
0653:                    if (entry.cr1[z] >= i)
0654:                        // Move first cr
0655:                        entry.cr1[z]++;
0656:
0657:                    // Is the second cr below the new cr
0658:                    if (entry.cr2[z] >= i)
0659:                        // Move second cr
0660:                        entry.cr2[z]++;
0661:                }
0662:
0663:                // Indicate that the cell sizes are not known
0664:                dirty = true;
0665:            }
0666:
0667:            /**
0668:             * Deletes a column in this layout.  All components to the right of the
0669:             * deletion point are moved left one column.  The container will need to
0670:             * be laid out after this method returns.  See <code>setColumn</code>.
0671:             *
0672:             * @param i    zero-based index of column to delete
0673:             */
0674:
0675:            public void deleteColumn(int i) {
0676:                deleteCr(C, i);
0677:            }
0678:
0679:            /**
0680:             * Deletes a row in this layout.  All components below the deletion point are
0681:             * moved up one row.  The container will need to be laid out after this method
0682:             * returns.  See <code>setRow</code>.  There must be at least two rows in order
0683:             * to delete a row.
0684:             *
0685:             * @param i    zero-based index of row to delete
0686:             */
0687:
0688:            public void deleteRow(int i) {
0689:                deleteCr(R, i);
0690:            }
0691:
0692:            /**
0693:             * Deletes a cr for the methods deleteRow or deleteColumn.
0694:             * 
0695:             * @param z       indicates row or column
0696:             * @param i       zero-based index of cr to delete
0697:             */
0698:
0699:            protected void deleteCr(int z, int i) {
0700:                // Make sure position is valid
0701:                if ((i < 0) || (i >= crSpec[z].length))
0702:                    throw new IllegalArgumentException(
0703:                            "Parameter i is invalid.  i = " + i
0704:                                    + ".  Valid range is [0, "
0705:                                    + (crSpec[z].length - 1) + "].");
0706:
0707:                // Copy rows
0708:                double cr[] = new double[crSpec[z].length - 1];
0709:                System.arraycopy(crSpec[z], 0, cr, 0, i);
0710:                System.arraycopy(crSpec[z], i + 1, cr, i, crSpec[z].length - i
0711:                        - 1);
0712:
0713:                // Delete row
0714:                crSpec[z] = cr;
0715:
0716:                // Move all components that are to below the row deleted
0717:                ListIterator iterator = list.listIterator(0);
0718:
0719:                while (iterator.hasNext()) {
0720:                    // Get next entry
0721:                    Entry entry = (Entry) iterator.next();
0722:
0723:                    // Is the first row below the new row
0724:                    if (entry.cr1[z] > i)
0725:                        // Move first row
0726:                        entry.cr1[z]--;
0727:
0728:                    // Is the second row below the new row
0729:                    if (entry.cr2[z] > i)
0730:                        // Move second row
0731:                        entry.cr2[z]--;
0732:                }
0733:
0734:                // Indicate that the cell sizes are not known
0735:                dirty = true;
0736:            }
0737:
0738:            //******************************************************************************
0739:            //** Misc methods                                                            ***
0740:            //******************************************************************************
0741:
0742:            /**
0743:             * Converts this TableLayout to a string.
0744:             *
0745:             * @return a string representing the columns and row sizes in the form
0746:             *         "{{col0, col1, col2, ..., colN}, {row0, row1, row2, ..., rowM}}"
0747:             */
0748:
0749:            public String toString() {
0750:                int counter;
0751:
0752:                String value = "TableLayout {{";
0753:
0754:                if (crSpec[C].length > 0) {
0755:                    for (counter = 0; counter < crSpec[C].length - 1; counter++)
0756:                        value += crSpec[C][counter] + ", ";
0757:
0758:                    value += crSpec[C][crSpec[C].length - 1] + "}, {";
0759:                } else
0760:                    value += "}, {";
0761:
0762:                if (crSpec[R].length > 0) {
0763:                    for (counter = 0; counter < crSpec[R].length - 1; counter++)
0764:                        value += crSpec[R][counter] + ", ";
0765:
0766:                    value += crSpec[R][crSpec[R].length - 1] + "}}";
0767:                } else
0768:                    value += "}}";
0769:
0770:                return value;
0771:            }
0772:
0773:            /**
0774:             * Determines whether or not there are any components with invalid constraints.
0775:             * An invalid constraint is one that references a non-existing row or column.
0776:             * For example, on a table with five rows, row -1 and row 5 are both invalid.
0777:             * Valid rows are 0 through 4, inclusively.
0778:             *
0779:             * @return an array of zero or more Component instances
0780:             */
0781:
0782:            public Component[] getInvalidEntry() {
0783:                LinkedList listInvalid = new LinkedList();
0784:                ListIterator iterator = list.listIterator(0);
0785:
0786:                while (iterator.hasNext()) {
0787:                    Entry entry = (Entry) iterator.next();
0788:
0789:                    if ((entry.cr1[R] < 0) || (entry.cr1[C] < 0)
0790:                            || (entry.cr2[R] >= crSpec[R].length)
0791:                            || (entry.cr2[C] >= crSpec[C].length)) {
0792:                        listInvalid.add(entry.component);
0793:                    }
0794:                }
0795:
0796:                return (Component[]) listInvalid
0797:                        .toArray(new Component[listInvalid.size()]);
0798:            }
0799:
0800:            /**
0801:             * Gets a list of overlapping components.  Two components overlap if they cover
0802:             * at least one common cell.
0803:             *
0804:             * @return a list of zero or more Component instances
0805:             */
0806:
0807:            public Component[] getOverlappingEntry() {
0808:                LinkedList listOverlapping = new LinkedList();
0809:                int numEntry = list.size();
0810:                Entry entry[] = (Entry[]) list.toArray(new Entry[numEntry]);
0811:
0812:                for (int knowUnique = 1; knowUnique < numEntry; knowUnique++)
0813:                    for (int checking = knowUnique - 1; checking >= 0; checking--)
0814:                        if (((entry[checking].cr1[C] >= entry[knowUnique].cr1[C])
0815:                                && (entry[checking].cr1[C] <= entry[knowUnique].cr2[C])
0816:                                && (entry[checking].cr1[R] >= entry[knowUnique].cr1[R]) && (entry[checking].cr1[R] <= entry[knowUnique].cr2[R]))
0817:                                || ((entry[checking].cr2[C] >= entry[knowUnique].cr1[C])
0818:                                        && (entry[checking].cr2[C] <= entry[knowUnique].cr2[C])
0819:                                        && (entry[checking].cr2[R] >= entry[knowUnique].cr1[R]) && (entry[checking].cr2[R] <= entry[knowUnique].cr2[R]))) {
0820:                            listOverlapping.add(entry[checking].component);
0821:                        }
0822:
0823:                return (Component[]) listOverlapping
0824:                        .toArray(new Component[listOverlapping.size()]);
0825:            }
0826:
0827:            //******************************************************************************
0828:            //** Calculation methods                                                     ***
0829:            //******************************************************************************
0830:
0831:            /**
0832:             * Calculates the sizes of the rows and columns based on the absolute and
0833:             * relative sizes specified in <code>crSpec[R]</code> and <code>crSpec[C]</code>
0834:             * and the size of the container.  The result is stored in <code>crSize[R]</code>
0835:             * and <code>crSize[C]</code>.
0836:             *
0837:             * @param container    container using this TableLayout
0838:             */
0839:
0840:            protected void calculateSize(Container container) {
0841:                // Get the container's insets
0842:                Insets inset = container.getInsets();
0843:
0844:                // Get the size of the container's available space
0845:                Dimension d = container.getSize();
0846:                int availableWidth = d.width - inset.left - inset.right;
0847:                int availableHeight = d.height - inset.top - inset.bottom;
0848:
0849:                // Compensate for horiztonal and vertical gaps
0850:                if (crSpec[C].length > 0)
0851:                    availableWidth -= hGap * (crSpec[C].length - 1);
0852:
0853:                if (crSpec[R].length > 0)
0854:                    availableHeight -= vGap * (crSpec[R].length - 1);
0855:
0856:                // Create array to hold actual sizes in pixels
0857:                crSize[C] = new int[crSpec[C].length];
0858:                crSize[R] = new int[crSpec[R].length];
0859:
0860:                // Assign absolute sizes
0861:                availableWidth = assignAbsoluteSize(C, availableWidth);
0862:                availableHeight = assignAbsoluteSize(R, availableHeight);
0863:
0864:                // Assign preferred and minimum sizes
0865:                availableWidth = assignPrefMinSize(C, availableWidth, MINIMUM);
0866:                availableWidth = assignPrefMinSize(C, availableWidth, PREFERRED);
0867:                availableHeight = assignPrefMinSize(R, availableHeight, MINIMUM);
0868:                availableHeight = assignPrefMinSize(R, availableHeight,
0869:                        PREFERRED);
0870:
0871:                // Assign relative sizes
0872:                availableWidth = assignRelativeSize(C, availableWidth);
0873:                availableHeight = assignRelativeSize(R, availableHeight);
0874:
0875:                // Assign fill sizes
0876:                assignFillSize(C, availableWidth);
0877:                assignFillSize(R, availableHeight);
0878:
0879:                // Calculate cr offsets for effeciency
0880:                calculateOffset(C, inset);
0881:                calculateOffset(R, inset);
0882:
0883:                // Indicate that the size of the cells are known for the container's
0884:                // current size
0885:                dirty = false;
0886:                oldWidth = d.width;
0887:                oldHeight = d.height;
0888:            }
0889:
0890:            /**
0891:             * Assigns absolute sizes.
0892:             *
0893:             * @param z                indicates row or column
0894:             * @param availableSize    amount of space available in the container
0895:             *
0896:             * @return the amount of space available after absolute crs have been assigned
0897:             *         sizes
0898:             */
0899:
0900:            protected int assignAbsoluteSize(int z, int availableSize) {
0901:                int numCr = crSpec[z].length;
0902:
0903:                for (int counter = 0; counter < numCr; counter++)
0904:                    if ((crSpec[z][counter] >= 1.0)
0905:                            || (crSpec[z][counter] == 0.0)) {
0906:                        crSize[z][counter] = (int) (crSpec[z][counter] + 0.5);
0907:                        availableSize -= crSize[z][counter];
0908:                    }
0909:
0910:                return availableSize;
0911:            }
0912:
0913:            /**
0914:             * Assigns relative sizes.
0915:             *
0916:             * @param z                indicates row or column
0917:             * @param availableSize    amount of space available in the container
0918:             *
0919:             * @return the amount of space available after relative crs have been assigned
0920:             *         sizes
0921:             */
0922:
0923:            protected int assignRelativeSize(int z, int availableSize) {
0924:                int relativeSize = (availableSize < 0) ? 0 : availableSize;
0925:                int numCr = crSpec[z].length;
0926:
0927:                for (int counter = 0; counter < numCr; counter++)
0928:                    if ((crSpec[z][counter] > 0.0)
0929:                            && (crSpec[z][counter] < 1.0)) {
0930:                        crSize[z][counter] = (int) (crSpec[z][counter]
0931:                                * relativeSize + 0.5);
0932:
0933:                        availableSize -= crSize[z][counter];
0934:                    }
0935:
0936:                return availableSize;
0937:            }
0938:
0939:            /**
0940:             * Assigns FILL sizes.
0941:             *
0942:             * @param z                indicates row or column
0943:             * @param availableSize    amount of space available in the container
0944:             */
0945:
0946:            protected void assignFillSize(int z, int availableSize) {
0947:                // Skip if there is no more space to allocate
0948:                if (availableSize <= 0)
0949:                    return;
0950:
0951:                // Count the number of "fill" cells
0952:                int numFillSize = 0;
0953:                int numCr = crSpec[z].length;
0954:
0955:                for (int counter = 0; counter < numCr; counter++)
0956:                    if (crSpec[z][counter] == FILL)
0957:                        numFillSize++;
0958:
0959:                // If numFillSize is zero, the if statement below will always evaluate to
0960:                // false and the division will not occur.
0961:
0962:                // If there are more than one "fill" cell, slack may occur due to rounding
0963:                // errors
0964:                int slackSize = availableSize;
0965:
0966:                // Assign "fill" cells equal amounts of the remaining space
0967:                for (int counter = 0; counter < numCr; counter++)
0968:                    if (crSpec[z][counter] == FILL) {
0969:                        crSize[z][counter] = availableSize / numFillSize;
0970:                        slackSize -= crSize[z][counter];
0971:                    }
0972:
0973:                // Assign one pixel of slack to each FILL cr, starting at the last one,
0974:                // until all slack has been consumed
0975:                for (int counter = numCr - 1; (counter >= 0) && (slackSize > 0); counter--) {
0976:                    if (crSpec[z][counter] == FILL) {
0977:                        crSize[z][counter]++;
0978:                        slackSize--;
0979:                    }
0980:                }
0981:            }
0982:
0983:            /**
0984:             * Calculates the offset of each cr.
0985:             *
0986:             * @param z    indicates row or column
0987:             * @param inset
0988:             */
0989:
0990:            protected void calculateOffset(int z, Insets inset) {
0991:                int numCr = crSpec[z].length;
0992:
0993:                crOffset[z] = new int[numCr + 1];
0994:                crOffset[z][0] = (z == C) ? inset.left : inset.top;
0995:
0996:                for (int counter = 0; counter < numCr; counter++)
0997:                    crOffset[z][counter + 1] = crOffset[z][counter]
0998:                            + crSize[z][counter];
0999:            }
1000:
1001:            /**
1002:             * Assigned widths to preferred and minimum size columns and rows.  This
1003:             * reduces the available width and height.  Minimum widths/heights must be
1004:             * calculated first because they affect preferred widths/heights, but not vice
1005:             * versa.  The end result is that any component contained wholly or partly in
1006:             * a column/row of minimum/preferred width will get at least its
1007:             * minimum/preferred width, respectively.
1008:             *
1009:             * @param z                indicates row or column
1010:             * @param availableSize    amount of space available in the container
1011:             * @param typeOfSize       indicates preferred or minimum
1012:             *
1013:             * @return the amount of space available after absolute crs have been assigned
1014:             *         sizes
1015:             */
1016:
1017:            protected int assignPrefMinSize(int z, int availableSize,
1018:                    double typeOfSize) {
1019:                // Get variables referring to columns or rows (crs)
1020:                int numCr = crSpec[z].length;
1021:
1022:                // Address every cr
1023:                for (int counter = 0; counter < numCr; counter++)
1024:                    // Is the current cr a preferred/minimum (based on typeOfSize) size
1025:                    if (crSpec[z][counter] == typeOfSize) {
1026:                        // Assume a maximum width of zero
1027:                        int maxSize = 0;
1028:
1029:                        // Find maximum preferred/min width of all components completely
1030:                        // or partially contained within this cr
1031:                        ListIterator iterator = list.listIterator(0);
1032:
1033:                        nextComponent: while (iterator.hasNext()) {
1034:                            Entry entry = (Entry) iterator.next();
1035:
1036:                            // Skip invalid entries
1037:                            if ((entry.cr1[z] < 0) || (entry.cr2[z] >= numCr))
1038:                                continue nextComponent;
1039:
1040:                            // Find the maximum desired size of this cr based on all crs
1041:                            // the current component occupies
1042:                            if ((entry.cr1[z] <= counter)
1043:                                    && (entry.cr2[z] >= counter)) {
1044:                                // Setup size and number of adjustable crs
1045:                                Dimension p = (typeOfSize == PREFERRED) ? entry.component
1046:                                        .getPreferredSize()
1047:                                        : entry.component.getMinimumSize();
1048:
1049:                                int size = (p == null) ? 0
1050:                                        : ((z == C) ? p.width : p.height);
1051:                                int numAdjustable = 0;
1052:
1053:                                // Calculate for preferred size
1054:                                if (typeOfSize == PREFERRED)
1055:                                    // Consider all crs this component occupies
1056:                                    for (int entryCr = entry.cr1[z]; entryCr <= entry.cr2[z]; entryCr++) {
1057:                                        // Subtract absolute, relative, and minumum cr
1058:                                        // sizes, which have already been calculated
1059:                                        if ((crSpec[z][entryCr] >= 0.0)
1060:                                                || (crSpec[z][entryCr] == MINIMUM)) {
1061:                                            size -= crSize[z][entryCr];
1062:                                        }
1063:                                        // Count preferred/min width columns
1064:                                        else if (crSpec[z][entryCr] == PREFERRED)
1065:                                            numAdjustable++;
1066:                                        // Skip any component that occupies a fill cr
1067:                                        // because the fill should fulfill the size
1068:                                        // requirements
1069:                                        else if (crSpec[z][entryCr] == FILL)
1070:                                            continue nextComponent;
1071:                                    }
1072:                                // Calculate for minimum size
1073:                                else
1074:                                    // Consider all crs this component occupies
1075:                                    for (int entryCr = entry.cr1[z]; entryCr <= entry.cr2[z]; entryCr++) {
1076:                                        // Subtract absolute and relative cr sizes, which
1077:                                        // have already been calculated
1078:                                        if (crSpec[z][entryCr] >= 0.0)
1079:                                            size -= crSize[z][entryCr];
1080:                                        // Count preferred/min width columns
1081:                                        else if ((crSpec[z][entryCr] == PREFERRED)
1082:                                                || (crSpec[z][entryCr] == MINIMUM)) {
1083:                                            numAdjustable++;
1084:                                        }
1085:                                        // Skip any component that occupies a fill cr
1086:                                        // because the fill should fulfill the size
1087:                                        // requirements
1088:                                        else if (crSpec[z][entryCr] == FILL)
1089:                                            continue nextComponent;
1090:                                    }
1091:
1092:                                // Divide the size evenly among the adjustable crs
1093:                                size = (int) Math.ceil(size
1094:                                        / (double) numAdjustable);
1095:
1096:                                // Take the maximumn size
1097:                                if (maxSize < size)
1098:                                    maxSize = size;
1099:                            }
1100:                        }
1101:
1102:                        // Assign preferred size
1103:                        crSize[z][counter] = maxSize;
1104:
1105:                        // Reduce available size
1106:                        availableSize -= maxSize;
1107:                    }
1108:
1109:                return availableSize;
1110:            }
1111:
1112:            //******************************************************************************
1113:            //** java.awt.event.LayoutManager methods                                    ***
1114:            //******************************************************************************
1115:
1116:            /**
1117:             * To lay out the specified container using this layout.  This method reshapes
1118:             * the components in the specified target container in order to satisfy the
1119:             * constraints of all components.
1120:             *
1121:             * <p>User code should not have to call this method directly.</p>
1122:             *
1123:             * @param container    container being served by this layout manager
1124:             */
1125:
1126:            public void layoutContainer(Container container) {
1127:                // Calculate sizes if container has changed size or components were added
1128:                Dimension d = container.getSize();
1129:
1130:                if (dirty || (d.width != oldWidth) || (d.height != oldHeight))
1131:                    calculateSize(container);
1132:
1133:                // Get components
1134:                Component component[] = container.getComponents();
1135:
1136:                // Layout components
1137:                for (int counter = 0; counter < component.length; counter++) {
1138:                    try {
1139:                        // Get the entry for the next component
1140:                        ListIterator iterator = list.listIterator(0);
1141:                        Entry entry = null;
1142:
1143:                        while (iterator.hasNext()) {
1144:                            entry = (Entry) iterator.next();
1145:
1146:                            if (entry.component == component[counter])
1147:                                break;
1148:                            else
1149:                                entry = null;
1150:                        }
1151:
1152:                        // Skip any components that have not been place in a specific cell,
1153:                        // setting the skip component's bounds to zero
1154:                        if (entry == null) {
1155:                            component[counter].setBounds(0, 0, 0, 0);
1156:                            continue;
1157:                        }
1158:
1159:                        // The following block of code has been optimized so that the
1160:                        // preferred size of the component is only obtained if it is
1161:                        // needed.  There are components in which the getPreferredSize
1162:                        // method is extremely expensive, such as data driven controls
1163:                        // with a large amount of data.
1164:
1165:                        // Get the preferred size of the component
1166:                        int preferredWidth = 0;
1167:                        int preferredHeight = 0;
1168:
1169:                        if ((entry.alignment[C] != FULL)
1170:                                || (entry.alignment[R] != FULL)) {
1171:                            Dimension preferredSize = component[counter]
1172:                                    .getPreferredSize();
1173:
1174:                            preferredWidth = preferredSize.width;
1175:                            preferredHeight = preferredSize.height;
1176:                        }
1177:
1178:                        // Calculate the coordinates and size of the component
1179:                        int value[] = calculateSizeAndOffset(entry,
1180:                                preferredWidth, true);
1181:                        int x = value[0];
1182:                        int w = value[1];
1183:                        value = calculateSizeAndOffset(entry, preferredHeight,
1184:                                false);
1185:                        int y = value[0];
1186:                        int h = value[1];
1187:
1188:                        // Move and resize component
1189:                        component[counter].setBounds(x, y, w, h);
1190:                    } catch (Exception error) {
1191:                        // If any error occurs, set the bounds of this component to zero
1192:                        // and continue
1193:                        component[counter].setBounds(0, 0, 0, 0);
1194:                        continue;
1195:                    }
1196:                }
1197:            }
1198:
1199:            /**
1200:             * Calculates the vertical/horizontal offset and size of a component.
1201:             *
1202:             * @param entry    entry containing component and contraints
1203:             * @param preferredSize    previously calculated preferred width/height of
1204:             *                         component
1205:             * @param isColumn         if true, this method is being called to calculate
1206:             *                         the offset/size of a column.  if false,... of a row.
1207:             *
1208:             * @return an array, a, of two integers such that a[0] is the offset and
1209:             *         a[1] is the size
1210:             */
1211:
1212:            protected int[] calculateSizeAndOffset(Entry entry,
1213:                    int preferredSize, boolean isColumn) {
1214:                // Get references to cr properties
1215:                int lCrOffset[] = isColumn ? this .crOffset[C]
1216:                        : this .crOffset[R];
1217:                int entryAlignment = isColumn ? entry.alignment[C]
1218:                        : entry.alignment[R];
1219:
1220:                // Determine cell set size
1221:                int cellSetSize = isColumn ? lCrOffset[entry.cr2[C] + 1]
1222:                        - lCrOffset[entry.cr1[C]] : lCrOffset[entry.cr2[R] + 1]
1223:                        - lCrOffset[entry.cr1[R]];
1224:
1225:                // Determine the size of the component
1226:                int size;
1227:
1228:                if ((entryAlignment == FULL) || (cellSetSize < preferredSize))
1229:                    size = cellSetSize;
1230:                else
1231:                    size = preferredSize;
1232:
1233:                // Determine offset
1234:                int offset;
1235:
1236:                switch (entryAlignment) {
1237:                case LEFT: // Align left/top side along left edge of cell
1238:                    offset = lCrOffset[isColumn ? entry.cr1[C] : entry.cr1[R]];
1239:                    break;
1240:
1241:                case RIGHT: // Align right/bottom side along right edge of cell
1242:                    offset = lCrOffset[(isColumn ? entry.cr2[C] : entry.cr2[R]) + 1]
1243:                            - size;
1244:                    break;
1245:
1246:                case CENTER: // Center justify component
1247:                    offset = lCrOffset[isColumn ? entry.cr1[C] : entry.cr1[R]]
1248:                            + ((cellSetSize - size) >> 1);
1249:                    break;
1250:
1251:                case FULL: // Align left/top side along left/top edge of cell
1252:                    offset = lCrOffset[isColumn ? entry.cr1[C] : entry.cr1[R]];
1253:                    break;
1254:
1255:                default: // This is a never should happen case, but just in case
1256:                    offset = 0;
1257:                }
1258:
1259:                // Compensate for gaps
1260:                if (isColumn) {
1261:                    offset += hGap * entry.cr1[C];
1262:                    size += hGap * (entry.cr2[C] - entry.cr1[C]);
1263:                } else {
1264:                    offset += vGap * entry.cr1[R];
1265:                    size += hGap * (entry.cr2[R] - entry.cr1[R]);
1266:                }
1267:
1268:                // Package return values
1269:                int value[] = { offset, size };
1270:                return value;
1271:            }
1272:
1273:            /**
1274:             * Determines the preferred size of the container argument using this layout.
1275:             * The preferred size is the smallest size that, if used for the container's
1276:             * size, will ensure that all components are at least as large as their
1277:             * preferred size.  This method cannot guarantee that all components will be
1278:             * their preferred size.  For example, if component A and component B are each
1279:             * allocate half of the container's width and component A wants to be 10 pixels
1280:             * wide while component B wants to be 100 pixels wide, they cannot both be
1281:             * accommodated.  Since in general components rather be larger than their
1282:             * preferred size instead of smaller, component B's request will be fulfilled.
1283:             * The preferred size of the container would be 200 pixels.
1284:             *
1285:             * @param container    container being served by this layout manager
1286:             *
1287:             * @return a dimension indicating the container's preferred size
1288:             */
1289:
1290:            public Dimension preferredLayoutSize(Container container) {
1291:                return calculateLayoutSize(container, PREFERRED);
1292:            }
1293:
1294:            /**
1295:             * Determines the minimum size of the container argument using this layout.
1296:             * The minimum size is the smallest size that, if used for the container's
1297:             * size, will ensure that all components are at least as large as their
1298:             * minimum size.  This method cannot guarantee that all components will be
1299:             * their minimum size.  For example, if component A and component B are each
1300:             * allocate half of the container's width and component A wants to be 10 pixels
1301:             * wide while component B wants to be 100 pixels wide, they cannot both be
1302:             * accommodated.  Since in general components rather be larger than their
1303:             * minimum size instead of smaller, component B's request will be fulfilled.
1304:             * The minimum size of the container would be 200 pixels.
1305:             *
1306:             * @param container    container being served by this layout manager
1307:             *
1308:             * @return a dimension indicating the container's minimum size
1309:             */
1310:
1311:            public Dimension minimumLayoutSize(Container container) {
1312:                return calculateLayoutSize(container, MINIMUM);
1313:            }
1314:
1315:            /**
1316:             * Calculates the preferred or minimum size for the methods preferredLayoutSize
1317:             * and minimumLayoutSize.
1318:             * 
1319:             * @param container     container whose size is being calculated
1320:             * @param typeOfSize    indicates preferred or minimum
1321:             * 
1322:             * @return a dimension indicating the container's preferred or minimum size
1323:             */
1324:
1325:            protected Dimension calculateLayoutSize(Container container,
1326:                    double typeOfSize) {
1327:                //  Get preferred/minimum sizes
1328:                Entry entryList[] = (Entry[]) list.toArray(new Entry[list
1329:                        .size()]);
1330:                int numEntry = entryList.length;
1331:                Dimension prefMinSize[] = new Dimension[numEntry];
1332:
1333:                for (int i = 0; i < numEntry; i++)
1334:                    prefMinSize[i] = (typeOfSize == PREFERRED) ? entryList[i].component
1335:                            .getPreferredSize()
1336:                            : entryList[i].component.getMinimumSize();
1337:
1338:                // Calculate sizes
1339:                int width = calculateLayoutSize(container, C, typeOfSize,
1340:                        entryList, prefMinSize);
1341:
1342:                int height = calculateLayoutSize(container, R, typeOfSize,
1343:                        entryList, prefMinSize);
1344:
1345:                // Compensate for container's insets
1346:                Insets inset = container.getInsets();
1347:                width += inset.left + inset.right;
1348:                height += inset.top + inset.bottom;
1349:
1350:                return new Dimension(width, height);
1351:            }
1352:
1353:            /**
1354:             * Calculates the preferred or minimum size for the method
1355:             * calculateLayoutSize(Container container, double typeOfSize).  This method
1356:             * is passed the preferred/minimum sizes of the components so that the
1357:             * potentially expensive methods getPreferredSize()/getMinimumSize() are not
1358:             * called twice for the same component.
1359:             * 
1360:             * @param container      container whose size is being calculated
1361:             * @param z
1362:             * @param typeOfSize     indicates preferred or minimum
1363:             * @param entryList      list of Entry objects
1364:             * @param prefMinSize    list of preferred or minimum sizes
1365:             * 
1366:             * @return a dimension indicating the container's preferred or minimum size
1367:             */
1368:
1369:            protected int calculateLayoutSize(Container container, int z,
1370:                    double typeOfSize, Entry entryList[],
1371:                    Dimension prefMinSize[]) {
1372:                Dimension size; // Preferred/minimum size of current component
1373:                int scaledSize = 0; // Preferred/minimum size of scaled components
1374:                int temp; // Temporary variable used to compare sizes
1375:                int counter; // Counting variable
1376:
1377:                // Get number of crs
1378:                int numCr = crSpec[z].length;
1379:
1380:                // Determine percentage of space allocated to fill components.  This is
1381:                // one minus the sum of all scalable components.
1382:                double fillSizeRatio = 1.0;
1383:                int numFillSize = 0;
1384:
1385:                for (counter = 0; counter < numCr; counter++)
1386:                    if ((crSpec[z][counter] > 0.0)
1387:                            && (crSpec[z][counter] < 1.0))
1388:                        fillSizeRatio -= crSpec[z][counter];
1389:                    else if (crSpec[z][counter] == FILL)
1390:                        numFillSize++;
1391:
1392:                // Adjust fill ratios to reflect number of fill rows/columns
1393:                if (numFillSize > 1)
1394:                    fillSizeRatio /= numFillSize;
1395:
1396:                // Cap fill ratio bottoms to 0.0
1397:                if (fillSizeRatio < 0.0)
1398:                    fillSizeRatio = 0.0;
1399:
1400:                // Create array to hold actual sizes in pixels
1401:                crSize[z] = new int[numCr];
1402:
1403:                // Calculate preferred/minimum cr sizes
1404:                assignPrefMinSize(z, 0, typeOfSize);
1405:
1406:                int crPrefMin[] = new int[numCr];
1407:
1408:                for (counter = 0; counter < numCr; counter++)
1409:                    if ((crSpec[z][counter] == PREFERRED)
1410:                            || (crSpec[z][counter] == MINIMUM)) {
1411:                        crPrefMin[counter] = crSize[z][counter];
1412:                    }
1413:
1414:                // Find maximum preferred/minimum size of all scaled components
1415:                int numColumn = crSpec[C].length;
1416:                int numRow = crSpec[R].length;
1417:                int numEntry = entryList.length;
1418:
1419:                for (int entryCounter = 0; entryCounter < numEntry; entryCounter++) {
1420:                    // Get next entry
1421:                    Entry entry = entryList[entryCounter];
1422:
1423:                    // Make sure entry is in valid rows and columns
1424:                    if ((entry.cr1[C] < 0) || (entry.cr1[C] >= numColumn)
1425:                            || (entry.cr2[C] >= numColumn)
1426:                            || (entry.cr1[R] < 0) || (entry.cr1[R] >= numRow)
1427:                            || (entry.cr2[R] >= numRow)) {
1428:                        // Skip the bad component
1429:                        continue;
1430:                    }
1431:
1432:                    // Get preferred/minimum size of current component
1433:                    size = prefMinSize[entryCounter];
1434:
1435:                    //----------------------------------------------------------------------
1436:
1437:                    // Calculate portion of component that is not absolutely sized
1438:                    int scalableSize = (z == C) ? size.width : size.height;
1439:
1440:                    for (counter = entry.cr1[z]; counter <= entry.cr2[z]; counter++)
1441:                        if (crSpec[z][counter] >= 1.0)
1442:                            scalableSize -= crSpec[z][counter];
1443:                        else if ((crSpec[z][counter] == PREFERRED)
1444:                                || (crSpec[z][counter] == MINIMUM)) {
1445:                            scalableSize -= crPrefMin[counter];
1446:                        }
1447:
1448:                    //----------------------------------------------------------------------
1449:
1450:                    // Determine total percentage of scalable space that the component
1451:                    // occupies by adding the relative columns and the fill columns
1452:                    double relativeSize = 0.0;
1453:
1454:                    for (counter = entry.cr1[z]; counter <= entry.cr2[z]; counter++) {
1455:                        // Cr is scaled
1456:                        if ((crSpec[z][counter] > 0.0)
1457:                                && (crSpec[z][counter] < 1.0))
1458:                            // Add scaled size to relativeWidth
1459:                            relativeSize += crSpec[z][counter];
1460:                        // Cr is fill
1461:                        else if ((crSpec[z][counter] == FILL)
1462:                                && (fillSizeRatio != 0.0))
1463:                            // Add fill size to relativeWidth
1464:                            relativeSize += fillSizeRatio;
1465:                    }
1466:
1467:                    // Determine the total scaled size as estimated by this component
1468:                    if (relativeSize == 0)
1469:                        temp = 0;
1470:                    else
1471:                        temp = (int) (scalableSize / relativeSize + 0.5);
1472:
1473:                    //----------------------------------------------------------------------
1474:
1475:                    // If the container needs to be bigger, make it so
1476:                    if (scaledSize < temp)
1477:                        scaledSize = temp;
1478:                }
1479:
1480:                // totalSize is the scaledSize plus the sum of all absolute sizes and all
1481:                // preferred sizes
1482:                int totalSize = scaledSize;
1483:
1484:                for (counter = 0; counter < numCr; counter++)
1485:                    // Is the current cr an absolute size
1486:                    if (crSpec[z][counter] >= 1.0)
1487:                        totalSize += (int) (crSpec[z][counter] + 0.5);
1488:                    // Is the current cr a preferred/minimum size
1489:                    else if ((crSpec[z][counter] == PREFERRED)
1490:                            || (crSpec[z][counter] == MINIMUM)) {
1491:                        // Add preferred/minimum width
1492:                        totalSize += crPrefMin[counter];
1493:                    }
1494:
1495:                // Compensate for horizontal and vertical gap
1496:                if (numCr > 0)
1497:                    totalSize += ((z == C) ? hGap : vGap) * (numCr - 1);
1498:
1499:                return totalSize;
1500:            }
1501:
1502:            /**
1503:             * Adds the specified component with the specified name to the layout.
1504:             *
1505:             * @param name         indicates entry's position and anchor
1506:             * @param component    component to add
1507:             */
1508:
1509:            public void addLayoutComponent(String name, Component component) {
1510:                addLayoutComponent(component, name);
1511:            }
1512:
1513:            //******************************************************************************
1514:            //** java.awt.event.LayoutManager2 methods                                   ***
1515:            //******************************************************************************
1516:
1517:            /**
1518:             * Adds the specified component with the specified name to the layout.
1519:             *
1520:             * @param component    component to add
1521:             * @param constraint   indicates entry's position and alignment
1522:             */
1523:
1524:            public void addLayoutComponent(Component component,
1525:                    Object constraint) {
1526:                if (constraint instanceof  String) {
1527:                    // Create an entry to associate component with its constraints
1528:                    constraint = new TableLayoutConstraints((String) constraint);
1529:
1530:                    // Add component and constraints to the list
1531:                    list.add(new Entry(component,
1532:                            (TableLayoutConstraints) constraint));
1533:
1534:                    // Indicate that the cell sizes are not known
1535:                    dirty = true;
1536:                } else if (constraint instanceof  TableLayoutConstraints) {
1537:                    // Add component and constraints to the list
1538:                    list.add(new Entry(component,
1539:                            (TableLayoutConstraints) constraint));
1540:
1541:                    // Indicate that the cell sizes are not known
1542:                    dirty = true;
1543:                } else if (constraint == null)
1544:                    throw new IllegalArgumentException(
1545:                            "No constraint for the component");
1546:                else
1547:                    throw new IllegalArgumentException(
1548:                            "Cannot accept a constraint of class "
1549:                                    + constraint.getClass());
1550:            }
1551:
1552:            /**
1553:             * Removes the specified component from the layout.
1554:             *
1555:             * @param component    component being removed
1556:             */
1557:
1558:            public void removeLayoutComponent(Component component) {
1559:                // Remove the component
1560:                ListIterator iterator = list.listIterator(0);
1561:
1562:                while (iterator.hasNext()) {
1563:                    Entry entry = (Entry) iterator.next();
1564:
1565:                    if (entry.component == component)
1566:                        iterator.remove();
1567:                }
1568:
1569:                // Indicate that the cell sizes are not known since
1570:                dirty = true;
1571:            }
1572:
1573:            /**
1574:             * Returns the maximum dimensions for this layout given the components in the
1575:             * specified target container.
1576:             *
1577:             * @param target the component which needs to be laid out
1578:             *
1579:             * @return unconditionally, a Dimension of Integer.MAX_VALUE by
1580:             *         Integer.MAX_VALUE since TableLayout does not limit the
1581:             *         maximum size of a container
1582:             */
1583:
1584:            public Dimension maximumLayoutSize(Container target) {
1585:                return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
1586:            }
1587:
1588:            /**
1589:             * Returns the alignment along the x axis.  This specifies how the component
1590:             * would like to be aligned relative to other components.  The value should be
1591:             * a number between 0 and 1 where 0 represents alignment along the origin, 1 is
1592:             * aligned the furthest away from the origin, 0.5 is centered, etc.
1593:             * @param parent
1594:             * @return unconditionally, 0.5
1595:             */
1596:
1597:            public float getLayoutAlignmentX(Container parent) {
1598:                return 0.5f;
1599:            }
1600:
1601:            /**
1602:             * Returns the alignment along the y axis.  This specifies how the component
1603:             * would like to be aligned relative to other components.  The value should be
1604:             * a number between 0 and 1 where 0 represents alignment along the origin, 1 is
1605:             * aligned the furthest away from the origin, 0.5 is centered, etc.
1606:             * @param parent
1607:             * @return unconditionally, 0.5
1608:             */
1609:
1610:            public float getLayoutAlignmentY(Container parent) {
1611:                return 0.5f;
1612:            }
1613:
1614:            /**
1615:             * Invalidates the layout, indicating that if the layout manager has cached
1616:             * information it should be discarded.
1617:             * @param target
1618:             */
1619:
1620:            public void invalidateLayout(Container target) {
1621:                dirty = true;
1622:            }
1623:
1624:            //******************************************************************************
1625:            //*** Inner Class                                                            ***
1626:            //******************************************************************************
1627:
1628:            // The following inner class is used to bind components to their constraints
1629:            protected static class Entry implements  Cloneable {
1630:                /** Component bound by the constraints */
1631:                protected Component component;
1632:
1633:                /** Cell in which the upper-left corner of the component lies */
1634:                protected int cr1[];
1635:
1636:                /** Cell in which the lower-right corner of the component lies */
1637:                protected int cr2[];
1638:
1639:                /** Horizontal and vertical alignment */
1640:                protected int alignment[];
1641:
1642:                /**
1643:                 * Constructs an Entry that binds a component to a set of constraints.
1644:                 *
1645:                 * @param component     component being bound
1646:                 * @param constraint    constraints being applied
1647:                 */
1648:
1649:                protected Entry(Component component,
1650:                        TableLayoutConstraints constraint) {
1651:                    int lCr1[] = { constraint.col1, constraint.row1 };
1652:                    int lCr2[] = { constraint.col2, constraint.row2 };
1653:                    int lAlignment[] = { constraint.hAlign, constraint.vAlign };
1654:
1655:                    this .cr1 = lCr1;
1656:                    this .cr2 = lCr2;
1657:                    this .alignment = lAlignment;
1658:                    this .component = component;
1659:                }
1660:
1661:                /**
1662:                 * Gets the string representation of this Entry.
1663:                 * 
1664:                 * @return a string in the form
1665:                 *         "(col1, row1, col2, row2, vAlign, hAlign) component"
1666:                 */
1667:
1668:                public String toString() {
1669:                    TableLayoutConstraints c = new TableLayoutConstraints(
1670:                            cr1[C], cr1[R], cr2[C], cr2[R], alignment[C],
1671:                            alignment[R]);
1672:
1673:                    return "(" + c + ") " + component;
1674:                }
1675:            }
1676:
1677:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.