Source code: org/gui4j/core/swing/TableLayout.java
1 /*
2 * June 2006: This is the original file except of this paragraph and
3 * for consistency, the original package name info.clearthought
4 * was renamed.
5 */
6 /*
7 * ====================================================================
8 *
9 * The Clearthought Software License, Version 1.0
10 *
11 * Copyright (c) 2001 Daniel Barbalace. All rights reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 *
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 *
20 * 2. The original software may not be altered. However, the classes
21 * provided may be subclasses as long as the subclasses are not
22 * packaged in the info.clearthought package or any subpackage of
23 * info.clearthought.
24 *
25 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
26 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR, AFFILATED BUSINESSES,
29 * OR ANYONE ELSE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
32 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
33 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
34 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
35 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 * ====================================================================
38 */
39
40 package org.gui4j.core.swing;
41
42 import java.awt.Component;
43 import java.awt.Container;
44 import java.awt.Dimension;
45 import java.awt.Insets;
46 import java.util.LinkedList;
47 import java.util.ListIterator;
48
49 /**
50 * TableLayout is a layout manager that arranges components in rows and columns
51 * like a spreadsheet. TableLayout allows each row or column to be a different
52 * size. A row or column can be given an absolute size in pixels, a percentage
53 * of the available space, or it can grow and shrink to fill the remaining space
54 * after other rows and columns have been resized.
55 *
56 * <p>Using spreadsheet terminology, a cell is the intersection of a row and
57 * column. Cells have finite, non-negative sizes measured in pixels. The
58 * dimensions of a cell depend solely upon the dimensions of its row and column.
59 * </p>
60 *
61 * <p>A component occupies a rectangular group of one or more cells. The
62 * component can be aligned in four ways within that cell.</p>
63 *
64 * <p>A component can be stretched horizontally to fit the cell set (full
65 * justification), or it can be placed in the center of the cell. The
66 * component could also be left justified or right justified. Similarly, the
67 * component can be full, center, top, or bottom justified along the
68 *
69 * <pre>
70 * public static void main (String args[])
71 * {
72 * // Create a frame
73 * Frame frame = new Frame("Example of TableLayout");
74 * frame.setBounds (100, 100, 300, 300);
75 * <spc>
76 * // Create a TableLayout for the frame
77 * double border = 10;
78 * double size[][] =
79 * {{border, 0.10, 20, TableLayout.FILL, 20, 0.20, border}, // Columns
80 * {border, 0.20, 20, TableLayout.FILL, 20, 0.20, border}}; // Rows
81 * <spc>
82 * frame.setLayout (new TableLayout(size));
83 * <spc>
84 * // Create some buttons
85 * String label[] = {"Top", "Bottom", "Left", "Right", "Center", "Overlap"};
86 * Button button[] = new Button[label.length];
87 * <spc>
88 * for (int i = 0; i < label.length; i++)
89 * button[i] = new Button(label[i]);
90 * <spc>
91 * // Add buttons
92 * frame.add (button[0], "1, 1, 5, 1"); // Top
93 * frame.add (button[1], "1, 5, 5, 5"); // Bottom
94 * frame.add (button[2], "1, 3 "); // Left
95 * frame.add (button[3], "5, 3 "); // Right
96 * frame.add (button[4], "3, 3, c, c"); // Center
97 * frame.add (button[5], "3, 3, 3, 5"); // Overlap
98 * <spc>
99 * // Allow user to close the window to terminate the program
100 * frame.addWindowListener
101 * (new WindowListener()
102 * {
103 * public void windowClosing (WindowEvent e)
104 * {
105 * System.exit (0);
106 * }
107 * <spc>
108 * public void windowOpened (WindowEvent e) {}
109 * public void windowClosed (WindowEvent e) {}
110 * public void windowIconified (WindowEvent e) {}
111 * public void windowDeiconified (WindowEvent e) {}
112 * public void windowActivated (WindowEvent e) {}
113 * public void windowDeactivated (WindowEvent e) {}
114 * }
115 * );
116 * <spc>
117 * // Show frame
118 * frame.show();
119 * }
120 * </pre>
121 *
122 * @version 2.1 4/26/02
123 * @author Daniel E. Barbalace
124 */
125
126 public class TableLayout implements java.awt.LayoutManager2, java.io.Serializable, TableLayoutConstants
127 {
128
129 /*
130 Note: In this file, a cr refers to either a column or a row. cr[C] always
131 means column and cr[R] always means row. A cr size is either a column
132 width or a row Height. TableLayout views columns and rows as being
133 conceptually symmetric. Therefore, much of the code applies to both
134 columns and rows, and the use of the cr terminology eliminates redundancy.
135 Also, for ease of reading, z always indicates a parameter whose value is
136 either C or R.
137 */
138
139 /** Default row/column size */
140 protected static final double defaultSize[][] = { {
141 }, {
142 }
143 };
144
145 /** Indicates a column */
146 protected static final int C = 0;
147
148 /** Indicates a row */
149 protected static final int R = 1;
150
151 /** Sizes of crs expressed in absolute and relative terms */
152 protected double crSpec[][] = { null, null };
153
154 /** Sizes of crs in pixels */
155 protected int crSize[][] = { null, null };
156
157 /** Offsets of crs in pixels. The left boarder of column n is at
158 crOffset[C][n] and the right boarder is at cr[C][n + 1] for all
159 columns including the last one. crOffset[C].length = crSize[C].length + 1 */
160 protected int crOffset[][] = { null, null };
161
162 /** List of components and their sizes */
163 protected LinkedList list;
164
165 /** Indicates whether or not the size of the cells are known for the last known
166 size of the container. If dirty is true or the container has been resized,
167 the cell sizes must be recalculated using calculateSize. */
168 protected boolean dirty;
169
170 /** Previous known width of the container */
171 protected int oldWidth;
172
173 /** Previous known height of the container */
174 protected int oldHeight;
175
176 /** Horizontal gap between columns */
177 protected int hGap;
178
179 /** Vertical gap between rows */
180 protected int vGap;
181
182 //******************************************************************************
183 //** Constructors ***
184 //******************************************************************************
185
186 /**
187 * Constructs an instance of TableLayout. This TableLayout will have one row
188 * and one column.
189 */
190
191 public TableLayout()
192 {
193 this(defaultSize);
194 }
195
196 /**
197 * Constructs an instance of TableLayout.
198 *
199 * @param size widths of columns and heights of rows in the format,
200 * {{col0, col1, col2, ..., colN}, {row0, row1, row2, ..., rowM}}
201 * If this parameter is invalid, the TableLayout will have
202 * exactly one row and one column.
203 */
204
205 public TableLayout(double size[][])
206 {
207 // Make sure rows and columns and nothing else is specified
208 if ((size != null) && (size.length == 2))
209 {
210 // Get the rows and columns
211 double tempCol[] = size[0];
212 double tempRow[] = size[1];
213
214 // Create new rows and columns
215 crSpec[C] = new double[tempCol.length];
216 crSpec[R] = new double[tempRow.length];
217
218 // Copy rows and columns
219 System.arraycopy(tempCol, 0, crSpec[C], 0, crSpec[C].length);
220 System.arraycopy(tempRow, 0, crSpec[R], 0, crSpec[R].length);
221
222 // Make sure rows and columns are valid
223 for (int counter = 0; counter < crSpec[C].length; counter++)
224 if ((crSpec[C][counter] < 0.0)
225 && (crSpec[C][counter] != FILL)
226 && (crSpec[C][counter] != PREFERRED)
227 && (crSpec[C][counter] != MINIMUM))
228 {
229 crSpec[C][counter] = 0.0;
230 }
231
232 for (int counter = 0; counter < crSpec[R].length; counter++)
233 if ((crSpec[R][counter] < 0.0)
234 && (crSpec[R][counter] != FILL)
235 && (crSpec[R][counter] != PREFERRED)
236 && (crSpec[R][counter] != MINIMUM))
237 {
238 crSpec[R][counter] = 0.0;
239 }
240 }
241 else
242 {
243 throw new IllegalArgumentException(
244 "Parameter size should be an array, a[2], where a[0] is the "
245 + "is an array of column widths and a[1] is an array or row "
246 + "heights.");
247 }
248
249 // Create an empty list of components
250 list = new LinkedList();
251
252 // Indicate that the cell sizes are not known
253 dirty = true;
254 }
255
256 //******************************************************************************
257 //** Get/Set methods ***
258 //******************************************************************************
259
260 /**
261 * Gets the constraints of a given component.
262 *
263 * @param component desired component
264 *
265 * @return If the given component is found, the constraints associated with
266 * that component. If the given component is null or is not found,
267 * null is returned.
268 */
269
270 public TableLayoutConstraints getConstraints(Component component)
271 {
272 ListIterator iterator = list.listIterator(0);
273
274 while (iterator.hasNext())
275 {
276 Entry entry = (Entry) iterator.next();
277
278 if (entry.component == component)
279 return new TableLayoutConstraints(
280 entry.cr1[C],
281 entry.cr1[R],
282 entry.cr2[C],
283 entry.cr2[R],
284 entry.alignment[C],
285 entry.alignment[R]);
286 }
287
288 return null;
289 }
290
291 /**
292 * Sets the constraints of a given component.
293 *
294 * @param component desired component. This parameter cannot be null.
295 * @param constraint new set of constraints. This parameter cannot be null.
296 */
297
298 public void setConstraints(Component component, TableLayoutConstraints constraint)
299 {
300 // Check parameters
301 if (component == null)
302 throw new IllegalArgumentException("Parameter component cannot be null.");
303 else if (constraint == null)
304 throw new IllegalArgumentException("Parameter constraint cannot be null.");
305
306 // Find and update constraints for the given component
307 ListIterator iterator = list.listIterator(0);
308
309 while (iterator.hasNext())
310 {
311 Entry entry = (Entry) iterator.next();
312
313 if (entry.component == component)
314 iterator.set(new Entry(component, constraint));
315 }
316 }
317
318 /**
319 * Adjusts the number and sizes of rows in this layout. After calling this
320 * method, the caller should request this layout manager to perform the
321 * layout. This can be done with the following code:
322 *
323 * <pre>
324 * layout.layoutContainer(container);
325 * container.repaint();
326 * </pre>
327 *
328 * or
329 *
330 * <pre>
331 * window.pack()
332 * </pre>
333 *
334 * If this is not done, the changes in the layout will not be seen until the
335 * container is resized.
336 *
337 * @param column heights of each of the columns
338 */
339
340 public void setColumn(double column[])
341 {
342 setCr(C, column);
343 }
344
345 /**
346 * Adjusts the number and sizes of rows in this layout. After calling this
347 * method, the caller should request this layout manager to perform the
348 * layout. This can be done with the following code:
349 *
350 * <code>
351 * layout.layoutContainer(container);
352 * container.repaint();
353 * </code>
354 *
355 * or
356 *
357 * <pre>
358 * window.pack()
359 * </pre>
360 *
361 * If this is not done, the changes in the layout will not be seen until the
362 * container is resized.
363 *
364 * @param row widths of each of the rows. This parameter cannot be null.
365 */
366
367 public void setRow(double row[])
368 {
369 setCr(R, row);
370 }
371
372 /**
373 * Sets the sizes of rows or columns for the methods setRow or setColumn.
374 *
375 * @param z indicates row or column
376 * @param size new cr size
377 */
378
379 protected void setCr(int z, double size[])
380 {
381 // Copy crs
382 crSpec[z] = new double[size.length];
383 System.arraycopy(size, 0, crSpec[z], 0, crSpec[z].length);
384
385 // Make sure rows are valid
386 for (int counter = 0; counter < crSpec[z].length; counter++)
387 if ((crSpec[z][counter] < 0.0)
388 && (crSpec[z][counter] != FILL)
389 && (crSpec[z][counter] != PREFERRED)
390 && (crSpec[z][counter] != MINIMUM))
391 {
392 crSpec[z][counter] = 0.0;
393 }
394
395 // Indicate that the cell sizes are not known
396 dirty = true;
397 }
398
399 /**
400 * Adjusts the width of a single column in this layout. After calling this
401 * method, the caller should request this layout manager to perform the
402 * layout. This can be done with the following code:
403 *
404 * <code>
405 * layout.layoutContainer(container);
406 * container.repaint();
407 * </code>
408 *
409 * or
410 *
411 * <pre>
412 * window.pack()
413 * </pre>
414 *
415 * If this is not done, the changes in the layout will not be seen until the
416 * container is resized.
417 *
418 * @param i zero-based index of column to set. If this parameter is not
419 * valid, an ArrayOutOfBoundsException will be thrown.
420 * @param size width of the column. This parameter cannot be null.
421 */
422
423 public void setColumn(int i, double size)
424 {
425 setCr(C, i, size);
426 }
427
428 /**
429 * Adjusts the height of a single row in this layout. After calling this
430 * method, the caller should request this layout manager to perform the
431 * layout. This can be done with the following code:
432 *
433 * <code>
434 * layout.layoutContainer(container);
435 * container.repaint();
436 * </code>
437 *
438 * or
439 *
440 * <pre>
441 * window.pack()
442 * </pre>
443 *
444 * If this is not done, the changes in the layout will not be seen until the
445 * container is resized.
446 *
447 * @param i zero-based index of row to set. If this parameter is not
448 * valid, an ArrayOutOfBoundsException will be thrown.
449 * @param size height of the row. This parameter cannot be null.
450 */
451
452 public void setRow(int i, double size)
453 {
454 setCr(R, i, size);
455 }
456
457 /**
458 * Sets the sizes of rows or columns for the methods setRow or setColumn.
459 *
460 * @param z indicates row or column
461 * @param i indicates which cr to resize
462 * @param size new cr size
463 */
464
465 protected void setCr(int z, int i, double size)
466 {
467 // Make sure size is valid
468 if ((size < 0.0) && (size != FILL) && (size != PREFERRED) && (size != MINIMUM))
469 {
470 size = 0.0;
471 }
472
473 // Copy new size
474 crSpec[z][i] = size;
475
476 // Indicate that the cell sizes are not known
477 dirty = true;
478 }
479
480 /**
481 * Gets the sizes of columns in this layout.
482 *
483 * @return widths of each of the columns
484 */
485
486 public double[] getColumn()
487 {
488 // Copy columns
489 double column[] = new double[crSpec[C].length];
490 System.arraycopy(crSpec[C], 0, column, 0, column.length);
491
492 return column;
493 }
494
495 /**
496 * Gets the height of a single row in this layout.
497 *
498 * @return height of the requested row
499 */
500
501 public double[] getRow()
502 {
503 // Copy rows
504 double row[] = new double[crSpec[R].length];
505 System.arraycopy(crSpec[R], 0, row, 0, row.length);
506
507 return row;
508 }
509
510 /**
511 * Gets the width of a single column in this layout.
512 *
513 * @param i zero-based index of row to get. If this parameter is not valid,
514 * an ArrayOutOfBoundsException will be thrown.
515 *
516 * @return width of the requested column
517 */
518
519 public double getColumn(int i)
520 {
521 return crSpec[C][i];
522 }
523
524 /**
525 * Gets the sizes of a row in this layout.
526 *
527 * @param i zero-based index of row to get. If this parameter is not valid,
528 * an ArrayOutOfBoundsException will be thrown.
529 *
530 * @return height of each of the requested row
531 */
532
533 public double getRow(int i)
534 {
535 return crSpec[R][i];
536 }
537
538 /**
539 * Gets the number of columns in this layout.
540 *
541 * @return the number of columns
542 */
543
544 public int getNumColumn()
545 {
546 return crSpec[C].length;
547 }
548
549 /**
550 * Gets the number of rows in this layout.
551 *
552 * @return the number of rows
553 */
554
555 public int getNumRow()
556 {
557 return crSpec[R].length;
558 }
559
560 /**
561 * Gets the horizontal gap between colunns.
562 *
563 * @return the horizontal gap in pixels
564 */
565
566 public int getHGap()
567 {
568 return hGap;
569 }
570
571 /**
572 * Gets the vertical gap between rows.
573 *
574 * @return the vertical gap in pixels
575 */
576
577 public int getVGap()
578 {
579 return vGap;
580 }
581
582 /**
583 * Sets the horizontal gap between colunns.
584 *
585 * @param hGap the horizontal gap in pixels
586 */
587
588 public void setHGap(int hGap)
589 {
590 if (hGap >= 0)
591 this.hGap = hGap;
592 else
593 throw new IllegalArgumentException("Parameter hGap must be non-negative.");
594 }
595
596 /**
597 * Sets the vertical gap between rows.
598 *
599 * @param vGap the horizontal gap in pixels
600 */
601
602 public void setVGap(int vGap)
603 {
604 if (vGap >= 0)
605 this.vGap = vGap;
606 else
607 throw new IllegalArgumentException("Parameter vGap must be non-negative.");
608 }
609
610 //******************************************************************************
611 //** Insertion/Deletion methods ***
612 //******************************************************************************
613
614 /**
615 * Inserts a column in this layout. All components to the right of the
616 * insertion point are moved right one column. The container will need to
617 * be laid out after this method returns. See <code>setColumn</code>.
618 *
619 * @param i zero-based index at which to insert the column
620 * @param size size of the column to be inserted
621 */
622
623 public void insertColumn(int i, double size)
624 {
625 insertCr(C, i, size);
626 }
627
628 /**
629 * Inserts a row in this layout. All components below the insertion point
630 * are moved down one row. The container will need to be laid out after this
631 * method returns. See <code>setRow</code>.
632 *
633 * @param i zero-based index at which to insert the row
634 * @param size size of the row to be inserted
635 */
636
637 public void insertRow(int i, double size)
638 {
639 insertCr(R, i, size);
640 }
641
642 /**
643 * Inserts a cr for the methods insertRow or insertColumn.
644 *
645 * @param z indicates row or column
646 * @param i zero-based index at which to insert the cr
647 * @param size size of cr being inserted
648 */
649
650 public void insertCr(int z, int i, double size)
651 {
652 // Make sure position is valid
653 if ((i < 0) || (i > crSpec[z].length))
654 throw new IllegalArgumentException(
655 "Parameter i is invalid. i = " + i + ". Valid range is [0, " + crSpec[z].length + "].");
656
657 // Make sure row size is valid
658 if ((size < 0.0) && (size != FILL) && (size != PREFERRED) && (size != MINIMUM))
659 {
660 size = 0.0;
661 }
662
663 // Copy crs
664 double cr[] = new double[crSpec[z].length + 1];
665 System.arraycopy(crSpec[z], 0, cr, 0, i);
666 System.arraycopy(crSpec[z], i, cr, i + 1, crSpec[z].length - i);
667
668 // Insert cr
669 cr[i] = size;
670 crSpec[z] = cr;
671
672 // Move all components that are below the new cr
673 ListIterator iterator = list.listIterator(0);
674
675 while (iterator.hasNext())
676 {
677 // Get next entry
678 Entry entry = (Entry) iterator.next();
679
680 // Is the first cr below the new cr
681 if (entry.cr1[z] >= i)
682 // Move first cr
683 entry.cr1[z]++;
684
685 // Is the second cr below the new cr
686 if (entry.cr2[z] >= i)
687 // Move second cr
688 entry.cr2[z]++;
689 }
690
691 // Indicate that the cell sizes are not known
692 dirty = true;
693 }
694
695 /**
696 * Deletes a column in this layout. All components to the right of the
697 * deletion point are moved left one column. The container will need to
698 * be laid out after this method returns. See <code>setColumn</code>.
699 *
700 * @param i zero-based index of column to delete
701 */
702
703 public void deleteColumn(int i)
704 {
705 deleteCr(C, i);
706 }
707
708 /**
709 * Deletes a row in this layout. All components below the deletion point are
710 * moved up one row. The container will need to be laid out after this method
711 * returns. See <code>setRow</code>. There must be at least two rows in order
712 * to delete a row.
713 *
714 * @param i zero-based index of row to delete
715 */
716
717 public void deleteRow(int i)
718 {
719 deleteCr(R, i);
720 }
721
722 /**
723 * Deletes a cr for the methods deleteRow or deleteColumn.
724 *
725 * @param z indicates row or column
726 * @param i zero-based index of cr to delete
727 */
728
729 protected void deleteCr(int z, int i)
730 {
731 // Make sure position is valid
732 if ((i < 0) || (i >= crSpec[z].length))
733 throw new IllegalArgumentException(
734 "Parameter i is invalid. i = "
735 + i
736 + ". Valid range is [0, "
737 + (crSpec[z].length - 1)
738 + "].");
739
740 // Copy rows
741 double cr[] = new double[crSpec[z].length - 1];
742 System.arraycopy(crSpec[z], 0, cr, 0, i);
743 System.arraycopy(crSpec[z], i + 1, cr, i, crSpec[z].length - i - 1);
744
745 // Delete row
746 crSpec[z] = cr;
747
748 // Move all components that are to below the row deleted
749 ListIterator iterator = list.listIterator(0);
750
751 while (iterator.hasNext())
752 {
753 // Get next entry
754 Entry entry = (Entry) iterator.next();
755
756 // Is the first row below the new row
757 if (entry.cr1[z] > i)
758 // Move first row
759 entry.cr1[z]--;
760
761 // Is the second row below the new row
762 if (entry.cr2[z] > i)
763 // Move second row
764 entry.cr2[z]--;
765 }
766
767 // Indicate that the cell sizes are not known
768 dirty = true;
769 }
770
771 //******************************************************************************
772 //** Misc methods ***
773 //******************************************************************************
774
775 /**
776 * Converts this TableLayout to a string.
777 *
778 * @return a string representing the columns and row sizes in the form
779 * "{{col0, col1, col2, ..., colN}, {row0, row1, row2, ..., rowM}}"
780 */
781
782 public String toString()
783 {
784 int counter;
785
786 String value = "TableLayout {{";
787
788 if (crSpec[C].length > 0)
789 {
790 for (counter = 0; counter < crSpec[C].length - 1; counter++)
791 value += crSpec[C][counter] + ", ";
792
793 value += crSpec[C][crSpec[C].length - 1] + "}, {";
794 }
795 else
796 value += "}, {";
797
798 if (crSpec[R].length > 0)
799 {
800 for (counter = 0; counter < crSpec[R].length - 1; counter++)
801 value += crSpec[R][counter] + ", ";
802
803 value += crSpec[R][crSpec[R].length - 1] + "}}";
804 }
805 else
806 value += "}}";
807
808 return value;
809 }
810
811 /**
812 * Determines whether or not there are any components with invalid constraints.
813 * An invalid constraint is one that references a non-existing row or column.
814 * For example, on a table with five rows, row -1 and row 5 are both invalid.
815 * Valid rows are 0 through 4, inclusively.
816 *
817 * @return an array of zero or more Component instances
818 */
819
820 public Component[] getInvalidEntry()
821 {
822 LinkedList listInvalid = new LinkedList();
823 ListIterator iterator = list.listIterator(0);
824
825 while (iterator.hasNext())
826 {
827 Entry entry = (Entry) iterator.next();
828
829 if ((entry.cr1[R] < 0)
830 || (entry.cr1[C] < 0)
831 || (entry.cr2[R] >= crSpec[R].length)
832 || (entry.cr2[C] >= crSpec[C].length))
833 {
834 listInvalid.add(entry.component);
835 }
836 }
837
838 return (Component[]) listInvalid.toArray(new Component[listInvalid.size()]);
839 }
840
841 /**
842 * Gets a list of overlapping components. Two components overlap if they cover
843 * at least one common cell.
844 *
845 * @return a list of zero or more Component instances
846 */
847
848 public Component[] getOverlappingEntry()
849 {
850 LinkedList listOverlapping = new LinkedList();
851 int numEntry = list.size();
852 Entry entry[] = (Entry[]) list.toArray(new Entry[numEntry]);
853
854 for (int knowUnique = 1; knowUnique < numEntry; knowUnique++)
855 for (int checking = knowUnique - 1; checking >= 0; checking--)
856 if (((entry[checking].cr1[C] >= entry[knowUnique].cr1[C])
857 && (entry[checking].cr1[C] <= entry[knowUnique].cr2[C])
858 && (entry[checking].cr1[R] >= entry[knowUnique].cr1[R])
859 && (entry[checking].cr1[R] <= entry[knowUnique].cr2[R]))
860 || ((entry[checking].cr2[C] >= entry[knowUnique].cr1[C])
861 && (entry[checking].cr2[C] <= entry[knowUnique].cr2[C])
862 && (entry[checking].cr2[R] >= entry[knowUnique].cr1[R])
863 && (entry[checking].cr2[R] <= entry[knowUnique].cr2[R])))
864 {
865 listOverlapping.add(entry[checking].component);
866 }
867
868 return (Component[]) listOverlapping.toArray(new Component[listOverlapping.size()]);
869 }
870
871 //******************************************************************************
872 //** Calculation methods ***
873 //******************************************************************************
874
875 /**
876 * Calculates the sizes of the rows and columns based on the absolute and
877 * relative sizes specified in <code>crSpec[R]</code> and <code>crSpec[C]</code>
878 * and the size of the container. The result is stored in <code>crSize[R]</code>
879 * and <code>crSize[C]</code>.
880 *
881 * @param container container using this TableLayout
882 */
883
884 protected void calculateSize(Container container)
885 {
886 // Get the container's insets
887 Insets inset = container.getInsets();
888
889 // Get the size of the container's available space
890 Dimension d = container.getSize();
891 int availableWidth = d.width - inset.left - inset.right;
892 int availableHeight = d.height - inset.top - inset.bottom;
893
894 // Compensate for horiztonal and vertical gaps
895 if (crSpec[C].length > 0)
896 availableWidth -= hGap * (crSpec[C].length - 1);
897
898 if (crSpec[R].length > 0)
899 availableHeight -= vGap * (crSpec[R].length - 1);
900
901 // Create array to hold actual sizes in pixels
902 crSize[C] = new int[crSpec[C].length];
903 crSize[R] = new int[crSpec[R].length];
904
905 // Assign absolute sizes
906 availableWidth = assignAbsoluteSize(C, availableWidth);
907 availableHeight = assignAbsoluteSize(R, availableHeight);
908
909 // Assign preferred and minimum sizes
910 availableWidth = assignPrefMinSize(C, availableWidth, MINIMUM);
911 availableWidth = assignPrefMinSize(C, availableWidth, PREFERRED);
912 availableHeight = assignPrefMinSize(R, availableHeight, MINIMUM);
913 availableHeight = assignPrefMinSize(R, availableHeight, PREFERRED);
914
915 // Assign relative sizes
916 availableWidth = assignRelativeSize(C, availableWidth);
917 availableHeight = assignRelativeSize(R, availableHeight);
918
919 // Assign fill sizes
920 assignFillSize(C, availableWidth);
921 assignFillSize(R, availableHeight);
922
923 // Calculate cr offsets for effeciency
924 calculateOffset(C, inset);
925 calculateOffset(R, inset);
926
927 // Indicate that the size of the cells are known for the container's
928 // current size
929 dirty = false;
930 oldWidth = d.width;
931 oldHeight = d.height;
932 }
933
934 /**
935 * Assigns absolute sizes.
936 *
937 * @param z indicates row or column
938 * @param availableSize amount of space available in the container
939 *
940 * @return the amount of space available after absolute crs have been assigned
941 * sizes
942 */
943
944 protected int assignAbsoluteSize(int z, int availableSize)
945 {
946 int numCr = crSpec[z].length;
947
948 for (int counter = 0; counter < numCr; counter++)
949 if ((crSpec[z][counter] >= 1.0) || (crSpec[z][counter] == 0.0))
950 {
951 crSize[z][counter] = (int) (crSpec[z][counter] + 0.5);
952 availableSize -= crSize[z][counter];
953 }
954
955 return availableSize;
956 }
957
958 /**
959 * Assigns relative sizes.
960 *
961 * @param z indicates row or column
962 * @param availableSize amount of space available in the container
963 *
964 * @return the amount of space available after relative crs have been assigned
965 * sizes
966 */
967
968 protected int assignRelativeSize(int z, int availableSize)
969 {
970 int relativeSize = (availableSize < 0) ? 0 : availableSize;
971 int numCr = crSpec[z].length;
972
973 for (int counter = 0; counter < numCr; counter++)
974 if ((crSpec[z][counter] > 0.0) && (crSpec[z][counter] < 1.0))
975 {
976 crSize[z][counter] = (int) (crSpec[z][counter] * relativeSize + 0.5);
977
978 availableSize -= crSize[z][counter];
979 }
980
981 return availableSize;
982 }
983
984 /**
985 * Assigns FILL sizes.
986 *
987 * @param z indicates row or column
988 * @param availableSize amount of space available in the container
989 */
990
991 protected void assignFillSize(int z, int availableSize)
992 {
993 // Skip if there is no more space to allocate
994 if (availableSize <= 0)
995 return;
996
997 // Count the number of "fill" cells
998 int numFillSize = 0;
999 int numCr = crSpec[z].length;
1000
1001 for (int counter = 0; counter < numCr; counter++)
1002 if (crSpec[z][counter] == FILL)
1003 numFillSize++;
1004
1005 // If numFillSize is zero, the if statement below will always evaluate to
1006 // false and the division will not occur.
1007
1008 // If there are more than one "fill" cell, slack may occur due to rounding
1009 // errors
1010 int slackSize = availableSize;
1011
1012 // Assign "fill" cells equal amounts of the remaining space
1013 for (int counter = 0; counter < numCr; counter++)
1014 if (crSpec[z][counter] == FILL)
1015 {
1016 crSize[z][counter] = availableSize / numFillSize;
1017 slackSize -= crSize[z][counter];
1018 }
1019
1020 // Assign one pixel of slack to each FILL cr, starting at the last one,
1021 // until all slack has been consumed
1022 for (int counter = numCr - 1;(counter >= 0) && (slackSize > 0); counter--)
1023 {
1024 if (crSpec[z][counter] == FILL)
1025 {
1026 crSize[z][counter]++;
1027 slackSize--;
1028 }
1029 }
1030 }
1031
1032 /**
1033 * Calculates the offset of each cr.
1034 *
1035 * @param z indicates row or column
1036 * @param inset
1037 */
1038
1039 protected void calculateOffset(int z, Insets inset)
1040 {
1041 int numCr = crSpec[z].length;
1042
1043 crOffset[z] = new int[numCr + 1];
1044 crOffset[z][0] = (z == C) ? inset.left : inset.top;
1045
1046 for (int counter = 0; counter < numCr; counter++)
1047 crOffset[z][counter + 1] = crOffset[z][counter] + crSize[z][counter];
1048 }
1049
1050 /**
1051 * Assigned widths to preferred and minimum size columns and rows. This
1052 * reduces the available width and height. Minimum widths/heights must be
1053 * calculated first because they affect preferred widths/heights, but not vice
1054 * versa. The end result is that any component contained wholly or partly in
1055 * a column/row of minimum/preferred width will get at least its
1056 * minimum/preferred width, respectively.
1057 *
1058 * @param z indicates row or column
1059 * @param availableSize amount of space available in the container
1060 * @param typeOfSize indicates preferred or minimum
1061 *
1062 * @return the amount of space available after absolute crs have been assigned
1063 * sizes
1064 */
1065
1066 protected int assignPrefMinSize(int z, int availableSize, double typeOfSize)
1067 {
1068 // Get variables referring to columns or rows (crs)
1069 int numCr = crSpec[z].length;
1070
1071 // Address every cr
1072 for (int counter = 0; counter < numCr; counter++)
1073 // Is the current cr a preferred/minimum (based on typeOfSize) size
1074 if (crSpec[z][counter] == typeOfSize)
1075 {
1076 // Assume a maximum width of zero
1077 int maxSize = 0;
1078
1079 // Find maximum preferred/min width of all components completely
1080 // or partially contained within this cr
1081 ListIterator iterator = list.listIterator(0);
1082
1083 nextComponent : while (iterator.hasNext())
1084 {
1085 Entry entry = (Entry) iterator.next();
1086
1087 // Skip invalid entries
1088 if ((entry.cr1[z] < 0) || (entry.cr2[z] >= numCr))
1089 continue nextComponent;
1090
1091 // Find the maximum desired size of this cr based on all crs
1092 // the current component occupies
1093 if ((entry.cr1[z] <= counter) && (entry.cr2[z] >= counter))
1094 {
1095 // Setup size and number of adjustable crs
1096 Dimension p =
1097 (typeOfSize == PREFERRED)
1098 ? entry.component.getPreferredSize()
1099 : entry.component.getMinimumSize();
1100
1101 int size = (p == null) ? 0 : ((z == C) ? p.width : p.height);
1102 int numAdjustable = 0;
1103
1104 // Calculate for preferred size
1105 if (typeOfSize == PREFERRED)
1106 // Consider all crs this component occupies
1107 for (int entryCr = entry.cr1[z]; entryCr <= entry.cr2[z]; entryCr++)
1108 {
1109 // Subtract absolute, relative, and minumum cr
1110 // sizes, which have already been calculated
1111 if ((crSpec[z][entryCr] >= 0.0) || (crSpec[z][entryCr] == MINIMUM))
1112 {
1113 size -= crSize[z][entryCr];
1114 }
1115 // Count preferred/min width columns
1116 else if (crSpec[z][entryCr] == PREFERRED)
1117 numAdjustable++;
1118 // Skip any component that occupies a fill cr
1119 // because the fill should fulfill the size
1120 // requirements
1121 else if (crSpec[z][entryCr] == FILL)
1122 continue nextComponent;
1123 }
1124 // Calculate for minimum size
1125 else
1126 // Consider all crs this component occupies
1127 for (int entryCr = entry.cr1[z]; entryCr <= entry.cr2[z]; entryCr++)
1128 {
1129 // Subtract absolute and relative cr sizes, which
1130 // have already been calculated
1131 if (crSpec[z][entryCr] >= 0.0)
1132 size -= crSize[z][entryCr];
1133 // Count preferred/min width columns
1134 else if (
1135 (crSpec[z][entryCr] == PREFERRED) || (crSpec[z][entryCr] == MINIMUM))
1136 {
1137 numAdjustable++;
1138 }
1139 // Skip any component that occupies a fill cr
1140 // because the fill should fulfill the size
1141 // requirements
1142 else if (crSpec[z][entryCr] == FILL)
1143 continue nextComponent;
1144 }
1145
1146 // Divide the size evenly among the adjustable crs
1147 size = (int) Math.ceil(size / (double) numAdjustable);
1148
1149 // Take the maximumn size
1150 if (maxSize < size)
1151 maxSize = size;
1152 }
1153 }
1154
1155 // Assign preferred size
1156 crSize[z][counter] = maxSize;
1157
1158 // Reduce available size
1159 availableSize -= maxSize;
1160 }
1161
1162 return availableSize;
1163 }
1164
1165 //******************************************************************************
1166 //** java.awt.event.LayoutManager methods ***
1167 //******************************************************************************
1168
1169 /**
1170 * To lay out the specified container using this layout. This method reshapes
1171 * the components in the specified target container in order to satisfy the
1172 * constraints of all components.
1173 *
1174 * <p>User code should not have to call this method directly.</p>
1175 *
1176 * @param container container being served by this layout manager
1177 */
1178
1179 public void layoutContainer(Container container)
1180 {
1181 // Calculate sizes if container has changed size or components were added
1182 Dimension d = container.getSize();
1183
1184 if (dirty || (d.width != oldWidth) || (d.height != oldHeight))
1185 calculateSize(container);
1186
1187 // Get components
1188 Component component[] = container.getComponents();
1189
1190 // Layout components
1191 for (int counter = 0; counter < component.length; counter++)
1192 {
1193 try
1194 {
1195 // Get the entry for the next component
1196 ListIterator iterator = list.listIterator(0);
1197 Entry entry = null;
1198
1199 while (iterator.hasNext())
1200 {
1201 entry = (Entry) iterator.next();
1202
1203 if (entry.component == component[counter])
1204 break;
1205 else
1206 entry = null;
1207 }
1208
1209 // Skip any components that have not been place in a specific cell,
1210 // setting the skip component's bounds to zero
1211 if (entry == null)
1212 {
1213 component[counter].setBounds(0, 0, 0, 0);
1214 continue;
1215 }
1216
1217 // The following block of code has been optimized so that the
1218 // preferred size of the component is only obtained if it is
1219 // needed. There are components in which the getPreferredSize
1220 // method is extremely expensive, such as data driven controls
1221 // with a large amount of data.
1222
1223 // Get the preferred size of the component
1224 int preferredWidth = 0;
1225 int preferredHeight = 0;
1226
1227 if ((entry.alignment[C] != FULL) || (entry.alignment[R] != FULL))
1228 {
1229 Dimension preferredSize = component[counter].getPreferredSize();
1230
1231 preferredWidth = preferredSize.width;
1232 preferredHeight = preferredSize.height;
1233 }
1234
1235 // Calculate the coordinates and size of the component
1236 int value[] = calculateSizeAndOffset(entry, preferredWidth, true);
1237 int x = value[0];
1238 int w = value[1];
1239 value = calculateSizeAndOffset(entry, preferredHeight, false);
1240 int y = value[0];
1241 int h = value[1];
1242
1243 // Move and resize component
1244 component[counter].setBounds(x, y, w, h);
1245 }
1246 catch (Exception error)
1247 {
1248 // If any error occurs, set the bounds of this component to zero
1249 // and continue
1250 component[counter].setBounds(0, 0, 0, 0);
1251 continue;
1252 }
1253 }
1254 }
1255
1256 /**
1257 * Calculates the vertical/horizontal offset and size of a component.
1258 *
1259 * @param entry entry containing component and contraints
1260 * @param preferredSize previously calculated preferred width/height of
1261 * component
1262 * @param isColumn if true, this method is being called to calculate
1263 * the offset/size of a column. if false,... of a row.
1264 *
1265 * @return an array, a, of two integers such that a[0] is the offset and
1266 * a[1] is the size
1267 */
1268
1269 protected int[] calculateSizeAndOffset(Entry entry, int preferredSize, boolean isColumn)
1270 {
1271 // Get references to cr properties
1272 int lCrOffset[] = isColumn ? this.crOffset[C] : this.crOffset[R];
1273 int entryAlignment = isColumn ? entry.alignment[C] : entry.alignment[R];
1274
1275 // Determine cell set size
1276 int cellSetSize =
1277 isColumn
1278 ? lCrOffset[entry.cr2[C] + 1] - lCrOffset[entry.cr1[C]]
1279 : lCrOffset[entry.cr2[R] + 1] - lCrOffset[entry.cr1[R]];
1280
1281 // Determine the size of the component
1282 int size;
1283
1284 if ((entryAlignment == FULL) || (cellSetSize < preferredSize))
1285 size = cellSetSize;
1286 else
1287 size = preferredSize;
1288
1289 // Determine offset
1290 int offset;
1291
1292 switch (entryAlignment)
1293 {
1294 case LEFT : // Align left/top side along left edge of cell
1295 offset = lCrOffset[isColumn ? entry.cr1[C] : entry.cr1[R]];
1296 break;
1297
1298 case RIGHT : // Align right/bottom side along right edge of cell
1299 offset = lCrOffset[(isColumn ? entry.cr2[C] : entry.cr2[R]) + 1] - size;
1300 break;
1301
1302 case CENTER : // Center justify component
1303 offset = lCrOffset[isColumn ? entry.cr1[C] : entry.cr1[R]] + ((cellSetSize - size) >> 1);
1304 break;
1305
1306 case FULL : // Align left/top side along left/top edge of cell
1307 offset = lCrOffset[isColumn ? entry.cr1[C] : entry.cr1[R]];
1308 break;
1309
1310 default : // This is a never should happen case, but just in case
1311 offset = 0;
1312 }
1313
1314 // Compensate for gaps
1315 if (isColumn)
1316 {
1317 offset += hGap * entry.cr1[C];
1318 size += hGap * (entry.cr2[C] - entry.cr1[C]);
1319 }
1320 else
1321 {
1322 offset += vGap * entry.cr1[R];
1323 size += hGap * (entry.cr2[R] - entry.cr1[R]);
1324 }
1325
1326 // Package return values
1327 int value[] = { offset, size };
1328 return value;
1329 }
1330
1331 /**
1332 * Determines the preferred size of the container argument using this layout.
1333 * The preferred size is the smallest size that, if used for the container's
1334 * size, will ensure that all components are at least as large as their
1335 * preferred size. This method cannot guarantee that all components will be
1336 * their preferred size. For example, if component A and component B are each
1337 * allocate half of the container's width and component A wants to be 10 pixels
1338 * wide while component B wants to be 100 pixels wide, they cannot both be
1339 * accommodated. Since in general components rather be larger than their
1340 * preferred size instead of smaller, component B's request will be fulfilled.
1341 * The preferred size of the container would be 200 pixels.
1342 *
1343 * @param container container being served by this layout manager
1344 *
1345 * @return a dimension indicating the container's preferred size
1346 */
1347
1348 public Dimension preferredLayoutSize(Container container)
1349 {
1350 return calculateLayoutSize(container, PREFERRED);
1351 }
1352
1353 /**
1354 * Determines the minimum size of the container argument using this layout.
1355 * The minimum size is the smallest size that, if used for the container's
1356 * size, will ensure that all components are at least as large as their
1357 * minimum size. This method cannot guarantee that all components will be
1358 * their minimum size. For example, if component A and component B are each
1359 * allocate half of the container's width and component A wants to be 10 pixels
1360 * wide while component B wants to be 100 pixels wide, they cannot both be
1361 * accommodated. Since in general components rather be larger than their
1362 * minimum size instead of smaller, component B's request will be fulfilled.
1363 * The minimum size of the container would be 200 pixels.
1364 *
1365 * @param container container being served by this layout manager
1366 *
1367 * @return a dimension indicating the container's minimum size
1368 */
1369
1370 public Dimension minimumLayoutSize(Container container)
1371 {
1372 return calculateLayoutSize(container, MINIMUM);
1373 }
1374
1375 /**
1376 * Calculates the preferred or minimum size for the methods preferredLayoutSize
1377 * and minimumLayoutSize.
1378 *
1379 * @param container container whose size is being calculated
1380 * @param typeOfSize indicates preferred or minimum
1381 *
1382 * @return a dimension indicating the container's preferred or minimum size
1383 */
1384
1385 protected Dimension calculateLayoutSize(Container container, double typeOfSize)
1386 {
1387 // Get preferred/minimum sizes
1388 Entry entryList[] = (Entry[]) list.toArray(new Entry[list.size()]);
1389 int numEntry = entryList.length;
1390 Dimension prefMinSize[] = new Dimension[numEntry];
1391
1392 for (int i = 0; i < numEntry; i++)
1393 prefMinSize[i] =
1394 (typeOfSize == PREFERRED)
1395 ? entryList[i].component.getPreferredSize()
1396 : entryList[i].component.getMinimumSize();
1397
1398 // Calculate sizes
1399 int width = calculateLayoutSize(container, C, typeOfSize, entryList, prefMinSize);
1400
1401 int height = calculateLayoutSize(container, R, typeOfSize, entryList, prefMinSize);
1402
1403 // Compensate for container's insets
1404 Insets inset = container.getInsets();
1405 width += inset.left + inset.right;
1406 height += inset.top + inset.bottom;
1407
1408 return new Dimension(width, height);
1409 }
1410
1411 /**
1412 * Calculates the preferred or minimum size for the method
1413 * calculateLayoutSize(Container container, double typeOfSize). This method
1414 * is passed the preferred/minimum sizes of the components so that the
1415 * potentially expensive methods getPreferredSize()/getMinimumSize() are not
1416 * called twice for the same component.
1417 *
1418 * @param container container whose size is being calculated
1419 * @param z
1420 * @param typeOfSize indicates preferred or minimum
1421 * @param entryList list of Entry objects
1422 * @param prefMinSize list of preferred or minimum sizes
1423 *
1424 * @return a dimension indicating the container's preferred or minimum size
1425 */
1426
1427 protected int calculateLayoutSize(
1428 Container container,
1429 int z,
1430 double typeOfSize,
1431 Entry entryList[],
1432 Dimension prefMinSize[])
1433 {
1434 Dimension size; // Preferred/minimum size of current component
1435 int scaledSize = 0; // Preferred/minimum size of scaled components
1436 int temp; // Temporary variable used to compare sizes
1437 int counter; // Counting variable
1438
1439 // Get number of crs
1440 int numCr = crSpec[z].length;
1441
1442 // Determine percentage of space allocated to fill components. This is
1443 // one minus the sum of all scalable components.
1444 double fillSizeRatio = 1.0;
1445 int numFillSize = 0;
1446
1447 for (counter = 0; counter < numCr; counter++)
1448 if ((crSpec[z][counter] > 0.0) && (crSpec[z][counter] < 1.0))
1449 fillSizeRatio -= crSpec[z][counter];
1450 else if (crSpec[z][counter] == FILL)
1451 numFillSize++;
1452
1453 // Adjust fill ratios to reflect number of fill rows/columns
1454 if (numFillSize > 1)
1455 fillSizeRatio /= numFillSize;
1456
1457 // Cap fill ratio bottoms to 0.0
1458 if (fillSizeRatio < 0.0)
1459 fillSizeRatio = 0.0;
1460
1461 // Create array to hold actual sizes in pixels
1462 crSize[z] = new int[numCr];
1463
1464 // Calculate preferred/minimum cr sizes
1465 assignPrefMinSize(z, 0, typeOfSize);
1466
1467 int crPrefMin[] = new int[numCr];
1468
1469 for (counter = 0; counter < numCr; counter++)
1470 if ((crSpec[z][counter] == PREFERRED) || (crSpec[z][counter] == MINIMUM))
1471 {
1472 crPrefMin[counter] = crSize[z][counter];
1473 }
1474
1475 // Find maximum preferred/minimum size of all scaled components
1476 int numColumn = crSpec[C].length;
1477 int numRow = crSpec[R].length;
1478 int numEntry = entryList.length;
1479
1480 for (int entryCounter = 0; entryCounter < numEntry; entryCounter++)
1481 {
1482 // Get next entry
1483 Entry entry = entryList[entryCounter];
1484
1485 // Make sure entry is in valid rows and columns
1486 if ((entry.cr1[C] < 0)
1487 || (entry.cr1[C] >= numColumn)
1488 || (entry.cr2[C] >= numColumn)
1489 || (entry.cr1[R] < 0)
1490 || (entry.cr1[R] >= numRow)
1491 || (entry.cr2[R] >= numRow))
1492 {
1493 // Skip the bad component
1494 continue;
1495 }
1496
1497 // Get preferred/minimum size of current component
1498 size = prefMinSize[entryCounter];
1499
1500 //----------------------------------------------------------------------
1501
1502 // Calculate portion of component that is not absolutely sized
1503 int scalableSize = (z == C) ? size.width : size.height;
1504
1505 for (counter = entry.cr1[z]; counter <= entry.cr2[z]; counter++)
1506 if (crSpec[z][counter] >= 1.0)
1507 scalableSize -= crSpec[z][counter];
1508 else if ((crSpec[z][counter] == PREFERRED) || (crSpec[z][counter] == MINIMUM))
1509 {
1510 scalableSize -= crPrefMin[counter];
1511 }
1512
1513 //----------------------------------------------------------------------
1514
1515 // Determine total percentage of scalable space that the component
1516 // occupies by adding the relative columns and the fill columns
1517 double relativeSize = 0.0;
1518
1519 for (counter = entry.cr1[z]; counter <= entry.cr2[z]; counter++)
1520 {
1521 // Cr is scaled
1522 if ((crSpec[z][counter] > 0.0) && (crSpec[z][counter] < 1.0))
1523 // Add scaled size to relativeWidth
1524 relativeSize += crSpec[z][counter];
1525 // Cr is fill
1526 else if ((crSpec[z][counter] == FILL) && (fillSizeRatio != 0.0))
1527 // Add fill size to relativeWidth
1528 relativeSize += fillSizeRatio;
1529 }
1530
1531 // Determine the total scaled size as estimated by this component
1532 if (relativeSize == 0)
1533 temp = 0;
1534 else
1535 temp = (int) (scalableSize / relativeSize + 0.5);
1536
1537 //----------------------------------------------------------------------
1538
1539 // If the container needs to be bigger, make it so
1540 if (scaledSize < temp)
1541 scaledSize = temp;
1542 }
1543
1544 // totalSize is the scaledSize plus the sum of all absolute sizes and all
1545 // preferred sizes
1546 int totalSize = scaledSize;
1547
1548 for (counter = 0; counter < numCr; counter++)
1549 // Is the current cr an absolute size
1550 if (crSpec[z][counter] >= 1.0)
1551 totalSize += (int) (crSpec[z][counter] + 0.5);
1552 // Is the current cr a preferred/minimum size
1553 else if ((crSpec[z][counter] == PREFERRED) || (crSpec[z][counter] == MINIMUM))
1554 {
1555 // Add preferred/minimum width
1556 totalSize += crPrefMin[counter];
1557 }
1558
1559 // Compensate for horizontal and vertical gap
1560 if (numCr > 0)
1561 totalSize += ((z == C) ? hGap : vGap) * (numCr - 1);
1562
1563 return totalSize;
1564 }
1565
1566 /**
1567 * Adds the specified component with the specified name to the layout.
1568 *
1569 * @param name indicates entry's position and anchor
1570 * @param component component to add
1571 */
1572
1573 public void addLayoutComponent(String name, Component component)
1574 {
1575 addLayoutComponen