1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 package hoplugins.commons.ui.info.clearthought.layout;
36
37 import java.awt.Component;
38 import java.awt.ComponentOrientation;
39 import java.awt.Container;
40 import java.awt.Dimension;
41 import java.awt.Insets;
42
43 import java.lang.reflect.Method;
44
45 import java.util.LinkedList;
46 import java.util.ListIterator;
47
48 /***
49 * TableLayout is a layout manager that arranges components in rows and columns like a spreadsheet.
50 * TableLayout allows each row or column to be a different size. A row or column can be given an
51 * absolute size in pixels, a percentage of the available space, or it can grow and shrink to fill
52 * the remaining space after other rows and columns have been resized.
53 *
54 * <p>
55 * Using spreadsheet terminology, a cell is the intersection of a row and column. Cells have
56 * finite, non-negative sizes measured in pixels. The dimensions of a cell depend solely upon the
57 * dimensions of its row and column.
58 * </p>
59 *
60 * <p>
61 * A component occupies a rectangular group of one or more cells. The component can be aligned in
62 * four ways within that cell.
63 * </p>
64 *
65 * <p>
66 * A component can be stretched horizontally to fit the cell set (full justification), or it can be
67 * placed in the center of the cell. The component could also be left justified or right
68 * justified. Similarly, the component can be full, center, top, or bottom justified along the
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 * </p>
122 *
123 * @author Daniel E. Barbalace
124 * @version 3.2 5/9/04
125 */
126 public class TableLayout implements java.awt.LayoutManager2,
127 java.io.Serializable,
128 hoplugins.commons.ui.info.clearthought.layout.TableLayoutConstants {
129
130
131
132
133
134
135
136
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 /*** Used to minimize reflection calls */
152 protected static boolean checkForComponentOrientationSupport = true;
153
154 /***
155 * Method used to get component orientation while preserving compatability with earlier
156 * versions of java.awt.Container. Necessary for supporting older JDKs and MicroEdition
157 * versions of Java.
158 */
159 protected static Method methodGetComponentOrientation;
160
161 /*** List of components and their sizes */
162 protected LinkedList list;
163
164 /***
165 * Offsets of crs in pixels. The left boarder of column n is at crOffset[C][n] and the right
166 * boarder is at cr[C][n + 1] for all columns including the last one. crOffset[C].length =
167 * crSize[C].length + 1
168 */
169 protected int[][] crOffset = { null, null };
170
171 /*** Sizes of crs in pixels */
172 protected int[][] crSize = { null, null };
173
174 /*** Sizes of crs expressed in absolute and relative terms */
175 protected double[][] crSpec = { null, null };
176
177 /***
178 * Indicates whether or not the size of the cells are known for the last known size of the
179 * container. If dirty is true or the container has been resized, the cell sizes must be
180 * recalculated using calculateSize.
181 */
182 protected boolean dirty;
183
184 /*** Horizontal gap between columns */
185 protected int hGap;
186
187 /*** Previous known height of the container */
188 protected int oldHeight;
189
190 /*** Previous known width of the container */
191 protected int oldWidth;
192
193 /*** Vertical gap between rows */
194 protected int vGap;
195
196 //*******************************************************************************
197 //** Constructors ***
198 //******************************************************************************
199
200 /**
201 * Constructs an instance of TableLayout. This TableLayout will have no columns or rows. This
202 * constructor is most useful for bean-oriented programming and dynamically adding columns and
203 * rows.
204 */
205 public TableLayout() {
206 init(defaultSize[C], defaultSize[R]);
207 }
208
209 /***
210 * Constructs an instance of TableLayout.
211 *
212 * @param size widths of columns and heights of rows in the format, {{col0, col1, col2, ...,
213 * colN}, {row0, row1, row2, ..., rowM}} If this parameter is invalid, the TableLayout
214 * will have exactly one row and one column.
215 *
216 * @throws IllegalArgumentException
217 */
218 public TableLayout(double[][] size) {
219
220 if ((size != null) && (size.length == 2)) {
221 init(size[C], size[R]);
222 }
223 else {
224 throw new IllegalArgumentException(
225 "Parameter size should be an array, a[2], where a[0] is the "
226 + "is an array of column widths and a[1] is an array or row "
227 + "heights.");
228 }
229 }
230
231 /***
232 * Constructs an instance of TableLayout.
233 *
234 * @param col widths of columns in the format, {{col0, col1, col2, ..., colN}
235 * @param row heights of rows in the format, {{row0, row1, row2, ..., rowN}
236 */
237 public TableLayout(double[] col, double[] row) {
238 init(col, row);
239 }
240
241 /***
242 * Adjusts the number and sizes of rows in this layout. After calling this method, the caller
243 * should request this layout manager to perform the layout. This can be done with the
244 * following code:
245 * <pre>
246 * layout.layoutContainer(container);
247 * container.repaint();
248 * </pre>
249 * or
250 * <pre>
251 * window.pack()
252 * </pre>
253 * If this is not done, the changes in the layout will not be seen until the container is
254 * resized.
255 *
256 * @param column widths of each of the columns
257 *
258 * @see #getColumn
259 */
260 public void setColumn(double[] column) {
261 setCr(C, column);
262 }
263
264 /***
265 * Adjusts the width of a single column in this layout. After calling this method, the caller
266 * should request this layout manager to perform the layout. This can be done with the
267 * following code: <code> layout.layoutContainer(container); container.repaint(); </code> or
268 * <pre>
269 * window.pack()
270 * </pre>
271 * If this is not done, the changes in the layout will not be seen until the container is
272 * resized.
273 *
274 * @param i zero-based index of column to set. If this parameter is not valid, an
275 * ArrayOutOfBoundsException will be thrown.
276 * @param size width of the column. This parameter cannot be null.
277 *
278 * @see #getColumn
279 */
280 public void setColumn(int i, double size) {
281 setCr(C, i, size);
282 }
283
284 /***
285 * Gets the sizes of columns in this layout.
286 *
287 * @return widths of each of the columns
288 *
289 * @see #setColumn
290 */
291 public double[] getColumn() {
292
293 double[] column = new double[crSpec[C].length];
294
295 System.arraycopy(crSpec[C], 0, column, 0, column.length);
296
297 return column;
298 }
299
300 /***
301 * Gets the width of a single column in this layout.
302 *
303 * @param i zero-based index of row to get. If this parameter is not valid, an
304 * ArrayOutOfBoundsException will be thrown.
305 *
306 * @return width of the requested column
307 *
308 * @see #setRow
309 */
310 public double getColumn(int i) {
311 return crSpec[C][i];
312 }
313
314 /***
315 * Sets the constraints of a given component.
316 *
317 * @param component desired component. This parameter cannot be null.
318 * @param constraint new set of constraints. This parameter cannot be null.
319 *
320 * @throws IllegalArgumentException
321 */
322 public void setConstraints(Component component,
323 TableLayoutConstraints constraint) {
324
325 if (component == null) {
326 throw new IllegalArgumentException(
327 "Parameter component cannot be null.");
328 }
329 else if (constraint == null) {
330 throw new IllegalArgumentException(
331 "Parameter constraint cannot be null.");
332 }
333
334
335 ListIterator iterator = list.listIterator(0);
336
337 while (iterator.hasNext()) {
338 Entry entry = (Entry) iterator.next();
339
340 if (entry.component == component) {
341 iterator.set(new Entry(component, constraint));
342 }
343 }
344 }
345
346 //*******************************************************************************
347 //** Get/Set methods ***
348 //******************************************************************************
349
350 /**
351 * Gets the constraints of a given component.
352 *
353 * @param component desired component
354 *
355 * @return If the given component is found, the constraints associated with that component. If
356 * the given component is null or is not found, null is returned.
357 */
358 public TableLayoutConstraints getConstraints(Component component) {
359 ListIterator iterator = list.listIterator(0);
360
361 while (iterator.hasNext()) {
362 Entry entry = (Entry) iterator.next();
363
364 if (entry.component == component) {
365 return new TableLayoutConstraints(entry.cr1[C], entry.cr1[R],
366 entry.cr2[C], entry.cr2[R], entry.alignment[C],
367 entry.alignment[R]);
368 }
369 }
370
371 return null;
372 }
373
374 /***
375 * Sets the horizontal gap between colunns.
376 *
377 * @param hGap the horizontal gap in pixels
378 *
379 * @throws IllegalArgumentException
380 */
381 public void setHGap(int hGap) {
382 if (hGap >= 0) {
383 this.hGap = hGap;
384 }
385 else {
386 throw new IllegalArgumentException(
387 "Parameter hGap must be non-negative.");
388 }
389 }
390
391 /***
392 * Gets the horizontal gap between colunns.
393 *
394 * @return the horizontal gap in pixels
395 */
396 public int getHGap() {
397 return hGap;
398 }
399
400 /***
401 * Determines whether or not there are any components with invalid constraints. An invalid
402 * constraint is one that references a non-existing row or column. For example, on a table
403 * with five rows, row -1 and row 5 are both invalid. Valid rows are 0 through 4, inclusively.
404 *
405 * @return a list of TableLayout.Entry instances refering to the invalid constraints and
406 * corresponding components
407 *
408 * @throws RuntimeException
409 *
410 * @see #getOverlappingEntry
411 */
412 public java.util.List getInvalidEntry() {
413 LinkedList listInvalid = new LinkedList();
414
415 try {
416 ListIterator iterator = list.listIterator(0);
417
418 while (iterator.hasNext()) {
419 Entry entry = (Entry) iterator.next();
420
421 if ((entry.cr1[R] < 0) || (entry.cr1[C] < 0)
422 || (entry.cr2[R] >= crSpec[R].length)
423 || (entry.cr2[C] >= crSpec[C].length)) {
424 listInvalid.add(entry.copy());
425 }
426 }
427 }
428 catch (CloneNotSupportedException error) {
429 throw new RuntimeException("Unexpected CloneNotSupportedException");
430 }
431
432 return listInvalid;
433 }
434
435 /***
436 * Returns the alignment along the x axis. This specifies how the component would like to be
437 * aligned relative to other components. The value should be a number between 0 and 1 where 0
438 * represents alignment along the origin, 1 is aligned the furthest away from the origin, 0.5
439 * is centered, etc.
440 *
441 * @param parent -
442 *
443 * @return unconditionally, 0.5
444 */
445 public float getLayoutAlignmentX(Container parent) {
446 return 0.5f;
447 }
448
449 /***
450 * Returns the alignment along the y axis. This specifies how the component would like to be
451 * aligned relative to other components. The value should be a number between 0 and 1 where 0
452 * represents alignment along the origin, 1 is aligned the furthest away from the origin, 0.5
453 * is centered, etc.
454 *
455 * @param parent
456 *
457 * @return unconditionally, 0.5
458 */
459 public float getLayoutAlignmentY(Container parent) {
460 return 0.5f;
461 }
462
463 /***
464 * Gets the number of columns in this layout.
465 *
466 * @return the number of columns
467 */
468 public int getNumColumn() {
469 return crSpec[C].length;
470 }
471
472 /***
473 * Gets the number of rows in this layout.
474 *
475 * @return the number of rows
476 */
477 public int getNumRow() {
478 return crSpec[R].length;
479 }
480
481 /***
482 * Gets a list of overlapping components and their constraints. Two components overlap if they
483 * cover at least one common cell.
484 *
485 * @return a list of zero or more TableLayout.Entry instances
486 *
487 * @throws RuntimeException -
488 *
489 * @see #getInvalidEntry
490 */
491 public java.util.List getOverlappingEntry() {
492 LinkedList listOverlapping = new LinkedList();
493
494 try {
495
496 int numEntry = list.size();
497
498
499 if (numEntry == 0) {
500 return listOverlapping;
501 }
502
503
504 Entry[] entry = (Entry[]) list.toArray(new Entry[numEntry]);
505
506
507 for (int knowUnique = 1; knowUnique < numEntry; knowUnique++) {
508 for (int checking = knowUnique - 1; checking >= 0;
509 checking--) {
510 if (((entry[checking].cr1[C] >= entry[knowUnique].cr1[C])
511 && (entry[checking].cr1[C] <= entry[knowUnique].cr2[C])
512 && (entry[checking].cr1[R] >= entry[knowUnique].cr1[R])
513 && (entry[checking].cr1[R] <= entry[knowUnique].cr2[R]))
514 || ((entry[checking].cr2[C] >= entry[knowUnique].cr1[C])
515 && (entry[checking].cr2[C] <= entry[knowUnique].cr2[C])
516 && (entry[checking].cr2[R] >= entry[knowUnique].cr1[R])
517 && (entry[checking].cr2[R] <= entry[knowUnique].cr2[R]))) {
518 listOverlapping.add(entry[checking].copy());
519 }
520 }
521 }
522 }
523 catch (CloneNotSupportedException error) {
524 throw new RuntimeException("Unexpected CloneNotSupportedException");
525 }
526
527 return listOverlapping;
528 }
529
530 /***
531 * Adjusts the number and sizes of rows in this layout. After calling this method, the caller
532 * should request this layout manager to perform the layout. This can be done with the
533 * following code: <code> layout.layoutContainer(container); container.repaint(); </code> or
534 * <pre>
535 * window.pack()
536 * </pre>
537 * If this is not done, the changes in the layout will not be seen until the container is
538 * resized.
539 *
540 * @param row heights of each of the rows. This parameter cannot be null.
541 *
542 * @see #getRow
543 */
544 public void setRow(double[] row) {
545 setCr(R, row);
546 }
547
548 /***
549 * Adjusts the height of a single row in this layout. After calling this method, the caller
550 * should request this layout manager to perform the layout. This can be done with the
551 * following code: <code> layout.layoutContainer(container); container.repaint(); </code> or
552 * <pre>
553 * window.pack()
554 * </pre>
555 * If this is not done, the changes in the layout will not be seen until the container is
556 * resized.
557 *
558 * @param i zero-based index of row to set. If this parameter is not valid, an
559 * ArrayOutOfBoundsException will be thrown.
560 * @param size height of the row. This parameter cannot be null.
561 *
562 * @see #getRow
563 */
564 public void setRow(int i, double size) {
565 setCr(R, i, size);
566 }
567
568 /***
569 * Gets the height of a single row in this layout.
570 *
571 * @return height of the requested row
572 *
573 * @see #setRow
574 */
575 public double[] getRow() {
576
577 double[] row = new double[crSpec[R].length];
578
579 System.arraycopy(crSpec[R], 0, row, 0, row.length);
580
581 return row;
582 }
583
584 /***
585 * Gets the sizes of a row in this layout.
586 *
587 * @param i zero-based index of row to get. If this parameter is not valid, an
588 * ArrayOutOfBoundsException will be thrown.
589 *
590 * @return height of each of the requested row
591 *
592 * @see #setRow
593 */
594 public double getRow(int i) {
595 return crSpec[R][i];
596 }
597
598 /***
599 * Sets the vertical gap between rows.
600 *
601 * @param vGap the horizontal gap in pixels
602 *
603 * @throws IllegalArgumentException -
604 */
605 public void setVGap(int vGap) {
606 if (vGap >= 0) {
607 this.vGap = vGap;
608 }
609 else {
610 throw new IllegalArgumentException(
611 "Parameter vGap must be non-negative.");
612 }
613 }
614
615 /***
616 * Gets the vertical gap between rows.
617 *
618 * @return the vertical gap in pixels
619 */
620 public int getVGap() {
621 return vGap;
622 }
623
624 /***
625 * Adds the specified component with the specified name to the layout.
626 *
627 * @param name indicates entry's position and anchor
628 * @param component component to add
629 */
630 public void addLayoutComponent(String name, Component component) {
631 addLayoutComponent(component, name);
632 }
633
634 //*******************************************************************************
635 //** java.awt.event.LayoutManager2 methods ***
636 //******************************************************************************
637
638 /**
639 * Adds the specified component with the specified name to the layout.
640 *
641 * @param component component to add
642 * @param constraint indicates entry's position and alignment
643 *
644 * @throws IllegalArgumentException -
645 */
646 public void addLayoutComponent(Component component, Object constraint) {
647 if (constraint instanceof String) {
648
649 constraint = new TableLayoutConstraints((String) constraint);
650
651
652 list.add(new Entry(component, (TableLayoutConstraints) constraint));
653
654
655 dirty = true;
656 }
657 else if (constraint instanceof TableLayoutConstraints) {
658
659 list.add(new Entry(component, (TableLayoutConstraints) constraint));
660
661
662 dirty = true;
663 }
664 else if (constraint == null) {
665 throw new IllegalArgumentException(
666 "No constraint for the component");
667 }
668 else {
669 throw new IllegalArgumentException(
670 "Cannot accept a constraint of class " + constraint.getClass());
671 }
672 }
673
674 /***
675 * Deletes a column in this layout. All components to the right of the deletion point are
676 * moved left one column. The container will need to be laid out after this method returns.
677 * See <code>setColumn</code>.
678 *
679 * @param i zero-based index of column to delete
680 *
681 * @see #setColumn
682 * @see #deleteColumn
683 */
684 public void deleteColumn(int i) {
685 deleteCr(C, i);
686 }
687
688 /***
689 * Deletes a row in this layout. All components below the deletion point are moved up one row.
690 * The container will need to be laid out after this method returns. See <code>setRow</code>.
691 * There must be at least two rows in order to delete a row.
692 *
693 * @param i zero-based index of row to delete
694 *
695 * @see #setRow
696 * @see #deleteRow
697 */
698 public void deleteRow(int i) {
699 deleteCr(R, i);
700 }
701
702 //*******************************************************************************
703 //** Insertion/Deletion methods ***
704 //******************************************************************************
705
706 /**
707 * Inserts a column in this layout. All components to the right of the insertion point are
708 * moved right one column. The container will need to be laid out after this method returns.
709 * See <code>setColumn</code>.
710 *
711 * @param i zero-based index at which to insert the column
712 * @param size size of the column to be inserted
713 *
714 * @see #setColumn
715 * @see #deleteColumn
716 */
717 public void insertColumn(int i, double size) {
718 insertCr(C, i, size);
719 }
720
721 /***
722 * Inserts a cr for the methods insertRow or insertColumn.
723 *
724 * @param z indicates row or column
725 * @param i zero-based index at which to insert the cr
726 * @param size size of cr being inserted
727 *
728 * @throws IllegalArgumentException -
729 */
730 public void insertCr(int z, int i, double size) {
731
732 if ((i < 0) || (i > crSpec[z].length)) {
733 throw new IllegalArgumentException("Parameter i is invalid. i = "
734 + i + ". Valid range is [0, "
735 + crSpec[z].length + "].");
736 }
737
738
739 if ((size < 0.0) && (size != FILL) && (size != PREFERRED)
740 && (size != MINIMUM)) {
741 size = 0.0;
742 }
743
744
745 double[] cr = new double[crSpec[z].length + 1];
746
747 System.arraycopy(crSpec[z], 0, cr, 0, i);
748 System.arraycopy(crSpec[z], i, cr, i + 1, crSpec[z].length - i);
749
750
751 cr[i] = size;
752 crSpec[z] = cr;
753
754
755 ListIterator iterator = list.listIterator(0);
756
757 while (iterator.hasNext()) {
758
759 Entry entry = (Entry) iterator.next();
760
761
762 if (entry.cr1[z] >= i) {
763
764 entry.cr1[z]++;
765 }
766
767
768 if (entry.cr2[z] >= i) {
769
770 entry.cr2[z]++;
771 }
772 }
773
774
775 dirty = true;
776 }
777
778 /***
779 * Inserts a row in this layout. All components below the insertion point are moved down one
780 * row. The container will need to be laid out after this method returns. See
781 * <code>setRow</code>.
782 *
783 * @param i zero-based index at which to insert the row
784 * @param size size of the row to be inserted
785 *
786 * @see #setRow
787 * @see #deleteRow
788 */
789 public void insertRow(int i, double size) {
790 insertCr(R, i, size);
791 }
792
793 /***
794 * Invalidates the layout, indicating that if the layout manager has cached information it
795 * should be discarded.
796 *
797 * @param target -
798 */
799 public void invalidateLayout(Container target) {
800 dirty = true;
801 }
802
803 //*******************************************************************************
804 //** java.awt.event.LayoutManager methods ***
805 //******************************************************************************
806
807 /**
808 * To lay out the specified container using this layout. This method reshapes the components
809 * in the specified target container in order to satisfy the constraints of all components.
810 *
811 * <p>
812 * User code should not have to call this method directly.
813 * </p>
814 *
815 * @param container container being served by this layout manager
816 */
817 public void layoutContainer(Container container) {
818
819 Dimension d = container.getSize();
820
821 if (dirty || (d.width != oldWidth) || (d.height != oldHeight)) {
822 calculateSize(container);
823 }
824
825
826 Component[] component = container.getComponents();
827
828
829 for (int counter = 0; counter < component.length; counter++) {
830 try {
831
832 ListIterator iterator = list.listIterator(0);
833 Entry entry = null;
834
835 while (iterator.hasNext()) {
836 entry = (Entry) iterator.next();
837
838 if (entry.component == component[counter]) {
839 break;
840 }
841 else {
842 entry = null;
843 }
844 }
845
846
847
848 if (entry == null) {
849 component[counter].setBounds(0, 0, 0, 0);
850
851 continue;
852 }
853
854
855
856
857
858
859
860 int preferredWidth = 0;
861 int preferredHeight = 0;
862
863 if ((entry.alignment[C] != FULL)
864 || (entry.alignment[R] != FULL)) {
865 Dimension preferredSize = component[counter]
866 .getPreferredSize();
867
868 preferredWidth = preferredSize.width;
869 preferredHeight = preferredSize.height;
870 }
871
872
873 int[] value = calculateSizeAndOffset(entry, preferredWidth, true);
874 int x = value[0];
875 int w = value[1];
876
877 value = calculateSizeAndOffset(entry, preferredHeight, false);
878
879 int y = value[0];
880 int h = value[1];
881
882
883 ComponentOrientation co = getComponentOrientation(container);
884
885 if (!co.isLeftToRight()) {
886 x = d.width - x - w;
887 }
888
889
890 component[counter].setBounds(x, y, w, h);
891 }
892 catch (Exception error) {
893
894
895 component[counter].setBounds(0, 0, 0, 0);
896
897 continue;
898 }
899 }
900 }
901
902 /***
903 * Returns the maximum dimensions for this layout given the components in the specified target
904 * container.
905 *
906 * @param target the component which needs to be laid out
907 *
908 * @return unconditionally, a Dimension of Integer.MAX_VALUE by Integer.MAX_VALUE since
909 * TableLayout does not limit the maximum size of a container
910 */
911 public Dimension maximumLayoutSize(Container target) {
912 return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
913 }
914
915 /***
916 * Determines the minimum size of the container argument using this layout. The minimum size is
917 * the smallest size that, if used for the container's size, will ensure that all components
918 * are at least as large as their minimum size. This method cannot guarantee that all
919 * components will be their minimum size. For example, if component A and component B are
920 * each allocate half of the container's width and component A wants to be 10 pixels wide
921 * while component B wants to be 100 pixels wide, they cannot both be accommodated. Since in
922 * general components rather be larger than their minimum size instead of smaller, component
923 * B's request will be fulfilled. The minimum size of the container would be 200 pixels.
924 *
925 * @param container container being served by this layout manager
926 *
927 * @return a dimension indicating the container's minimum size
928 */
929 public Dimension minimumLayoutSize(Container container) {
930 return calculateLayoutSize(container, MINIMUM);
931 }
932
933 /***
934 * Determines the preferred size of the container argument using this layout. The preferred
935 * size is the smallest size that, if used for the container's size, will ensure that all
936 * components are at least as large as their preferred size. This method cannot guarantee
937 * that all components will be their preferred size. For example, if component A and
938 * component B are each allocate half of the container's width and component A wants to be 10
939 * pixels wide while component B wants to be 100 pixels wide, they cannot both be
940 * accommodated. Since in general components rather be larger than their preferred size
941 * instead of smaller, component B's request will be fulfilled. The preferred size of the
942 * container would be 200 pixels.
943 *
944 * @param container container being served by this layout manager
945 *
946 * @return a dimension indicating the container's preferred size
947 */
948 public Dimension preferredLayoutSize(Container container) {
949 return calculateLayoutSize(container, PREFERRED);
950 }
951
952 /***
953 * Removes the specified component from the layout.
954 *
955 * @param component component being removed
956 */
957 public void removeLayoutComponent(Component component) {
958
959 ListIterator iterator = list.listIterator(0);
960
961 while (iterator.hasNext()) {
962 Entry entry = (Entry) iterator.next();
963
964 if (entry.component == component) {
965 iterator.remove();
966 }
967 }
968
969
970 dirty = true;
971 }
972
973 //*******************************************************************************
974 //** Misc methods ***
975 //******************************************************************************
976
977 /**
978 * Converts this TableLayout to a string.
979 *
980 * @return a string representing the columns and row sizes in the form "{{col0, col1, col2,
981 * ..., colN}, {row0, row1, row2, ..., rowM}}"
982 */
983 public String toString() {
984 int counter;
985
986 String value = "TableLayout {{";
987
988 if (crSpec[C].length > 0) {
989 for (counter = 0; counter < (crSpec[C].length - 1); counter++) {
990 value += (crSpec[C][counter] + ", ");
991 }
992
993 value += (crSpec[C][crSpec[C].length - 1] + "}, {");
994 }
995 else {
996 value += "}, {";
997 }
998
999 if (crSpec[R].length > 0) {
1000 for (counter = 0; counter < (crSpec[R].length - 1); counter++) {
1001 value += (crSpec[R][counter] + ", ");
1002 }
1003
1004 value += (crSpec[R][crSpec[R].length - 1] + "}}");
1005 }
1006 else {
1007 value += "}}";
1008 }
1009
1010 return value;
1011 }
1012
1013 /***
1014 * Gets the container's component orientation. If a JDK that does not support component
1015 * orientation is being used, then null is returned.
1016 *
1017 * @param container Container whose orientation is being queried
1018 *
1019 * @return the container's orientation or null if no orientation is supported
1020 */
1021 protected ComponentOrientation getComponentOrientation(Container container) {
1022
1023
1024
1025 ComponentOrientation co = null;
1026
1027 try {
1028 if (checkForComponentOrientationSupport) {
1029 methodGetComponentOrientation = Class.forName(
1030 "java.awt.Container").getMethod
1031 ("getComponentOrientation", new Class[0]);
1032
1033 checkForComponentOrientationSupport = false;
1034 }
1035
1036 if (methodGetComponentOrientation != null) {
1037 co = (ComponentOrientation) methodGetComponentOrientation
1038 .invoke(container, new Object[0]);
1039 }
1040 }
1041 catch (Exception e) {
1042 }
1043
1044 return co;
1045 }
1046
1047 /***
1048 * Sets the sizes of rows or columns for the methods setRow or setColumn.
1049 *
1050 * @param z indicates row or column
1051 * @param size new cr size
1052 */
1053 protected void setCr(int z, double[] size) {
1054
1055 crSpec[z] = new double[size.length];
1056 System.arraycopy(size, 0, crSpec[z], 0, crSpec[z].length);
1057
1058
1059 for (int counter = 0; counter < crSpec[z].length; counter++) {
1060 if ((crSpec[z][counter] < 0.0) && (crSpec[z][counter] != FILL)
1061 && (crSpec[z][counter] != PREFERRED)
1062 && (crSpec[z][counter] != MINIMUM)) {
1063 crSpec[z][counter] = 0.0;
1064 }
1065 }
1066
1067
1068 dirty = true;
1069 }
1070
1071 /***
1072 * Sets the sizes of rows or columns for the methods setRow or setColumn.
1073 *
1074 * @param z indicates row or column
1075 * @param i indicates which cr to resize
1076 * @param size new cr size
1077 */
1078 protected void setCr(int z, int i, double size) {
1079
1080 if ((size < 0.0) && (size != FILL) && (size != PREFERRED)
1081 && (size != MINIMUM)) {
1082 size = 0.0;
1083 }
1084
1085
1086 crSpec[z][i] = size;
1087
1088
1089 dirty = true;
1090 }
1091
1092 /***
1093 * Assigns absolute sizes.
1094 *
1095 * @param z indicates row or column
1096 * @param availableSize amount of space available in the container
1097 *
1098 * @return the amount of space available after absolute crs have been assigned sizes
1099 */
1100 protected int assignAbsoluteSize(int z, int availableSize) {
1101 int numCr = crSpec[z].length;
1102
1103 for (int counter = 0; counter < numCr; counter++) {
1104 if ((crSpec[z][counter] >= 1.0) || (crSpec[z][counter] == 0.0)) {
1105 crSize[z][counter] = (int) (crSpec[z][counter] + 0.5);
1106 availableSize -= crSize[z][counter];
1107 }
1108 }
1109
1110 return availableSize;
1111 }
1112
1113 /***
1114 * Assigns FILL sizes.
1115 *
1116 * @param z indicates row or column
1117 * @param availableSize amount of space available in the container
1118 */
1119 protected void assignFillSize(int z, int availableSize) {
1120
1121 if (availableSize <= 0) {
1122 return;
1123 }
1124
1125
1126 int numFillSize = 0;
1127 int numCr = crSpec[z].length;
1128
1129 for (int counter = 0; counter < numCr; counter++) {
1130 if (crSpec[z][counter] == FILL) {
1131 numFillSize++;
1132 }
1133 }
1134
1135
1136
1137
1138
1139 int slackSize = availableSize;
1140
1141
1142 for (int counter = 0; counter < numCr; counter++) {
1143 if (crSpec[z][counter] == FILL) {
1144 crSize[z][counter] = availableSize / numFillSize;
1145 slackSize -= crSize[z][counter];
1146 }
1147 }
1148
1149
1150
1151 for (int counter = numCr - 1; (counter >= 0) && (slackSize > 0);
1152 counter--) {
1153 if (crSpec[z][counter] == FILL) {
1154 crSize[z][counter]++;
1155 slackSize--;
1156 }
1157 }
1158 }
1159
1160 /***
1161 * Assigned widths to preferred and minimum size columns and rows. This reduces the available
1162 * width and height. Minimum widths/heights must be calculated first because they affect
1163 * preferred widths/heights, but not vice versa. The end result is that any component
1164 * contained wholly or partly in a column/row of minimum/preferred width will get at least its
1165 * minimum/preferred width, respectively.
1166 *
1167 * @param z indicates row or column
1168 * @param availableSize amount of space available in the container
1169 * @param typeOfSize indicates preferred or minimum
1170 *
1171 * @return the amount of space available after absolute crs have been assigned sizes
1172 */
1173 protected int assignPrefMinSize(int z, int availableSize, double typeOfSize) {
1174
1175 int numCr = crSpec[z].length;
1176
1177
1178 for (int counter = 0; counter < numCr; counter++) {
1179
1180 if (crSpec[z][counter] == typeOfSize) {
1181
1182 int maxSize = 0;
1183
1184
1185
1186 ListIterator iterator = list.listIterator(0);
1187
1188 nextComponent:
1189 while (iterator.hasNext()) {
1190 Entry entry = (Entry) iterator.next();
1191
1192
1193 if ((entry.cr1[z] < 0) || (entry.cr2[z] >= numCr)) {
1194 continue nextComponent;
1195 }
1196
1197
1198
1199 if ((entry.cr1[z] <= counter) && (entry.cr2[z] >= counter)) {
1200
1201 Dimension p = (typeOfSize == PREFERRED)
1202 ? entry.component.getPreferredSize()
1203 : entry.component.getMinimumSize();
1204
1205 int size = (p == null) ? 0 : ((z == C) ? p.width
1206 : p.height);
1207 int numAdjustable = 0;
1208
1209
1210 if (typeOfSize == PREFERRED) {
1211
1212 for (int entryCr = entry.cr1[z];
1213 entryCr <= entry.cr2[z]; entryCr++) {
1214
1215
1216 if ((crSpec[z][entryCr] >= 0.0)
1217 || (crSpec[z][entryCr] == MINIMUM)) {
1218 size -= crSize[z][entryCr];
1219 }
1220
1221
1222 else if (crSpec[z][entryCr] == PREFERRED) {
1223 numAdjustable++;
1224 }
1225
1226
1227
1228
1229 else if (crSpec[z][entryCr] == FILL) {
1230 continue nextComponent;
1231 }
1232 }
1233 }
1234
1235
1236 else {
1237
1238 for (int entryCr = entry.cr1[z];
1239 entryCr <= entry.cr2[z]; entryCr++) {
1240
1241
1242 if (crSpec[z][entryCr] >= 0.0) {
1243 size -= crSize[z][entryCr];
1244 }
1245
1246
1247 else if ((crSpec[z][entryCr] == PREFERRED)
1248 || (crSpec[z][entryCr] == MINIMUM)) {
1249 numAdjustable++;
1250 }
1251
1252
1253
1254
1255 else if (crSpec[z][entryCr] == FILL) {
1256 continue nextComponent;
1257 }
1258 }
1259 }
1260
1261
1262 size = (int) Math.ceil(size / (double) numAdjustable);
1263
1264
1265 if (maxSize < size) {
1266 maxSize = size;
1267 }
1268 }
1269 }
1270
1271
1272 crSize[z][counter] = maxSize;
1273
1274
1275 availableSize -= maxSize;
1276 }
1277 }
1278
1279 return availableSize;
1280 }
1281
1282 /***
1283 * Assigns relative sizes.
1284 *
1285 * @param z indicates row or column
1286 * @param availableSize amount of space available in the container
1287 *
1288 * @return the amount of space available after relative crs have been assigned sizes
1289 */
1290 protected int assignRelativeSize(int z, int availableSize) {
1291 int relativeSize = (availableSize < 0) ? 0 : availableSize;
1292 int numCr = crSpec[z].length;
1293
1294 for (int counter = 0; counter < numCr; counter++) {
1295 if ((crSpec[z][counter] > 0.0) && (crSpec[z][counter] < 1.0)) {
1296 crSize[z][counter] = (int) ((crSpec[z][counter] * relativeSize)
1297 + 0.5);
1298
1299 availableSize -= crSize[z][counter];
1300 }
1301 }
1302
1303 return availableSize;
1304 }
1305
1306 /***
1307 * Calculates the preferred or minimum size for the methods preferredLayoutSize and
1308 * minimumLayoutSize.
1309 *
1310 * @param container container whose size is being calculated
1311 * @param typeOfSize indicates preferred or minimum
1312 *
1313 * @return a dimension indicating the container's preferred or minimum size
1314 */
1315 protected Dimension calculateLayoutSize(Container container,
1316 double typeOfSize) {
1317
1318 Entry[] entryList = (Entry[]) list.toArray(new Entry[list.size()]);
1319 int numEntry = entryList.length;
1320 Dimension[] prefMinSize = new Dimension[numEntry];
1321
1322 for (int i = 0; i < numEntry; i++) {
1323 prefMinSize[i] = (typeOfSize == PREFERRED)
1324 ? entryList[i].component.getPreferredSize()
1325 : entryList[i].component.getMinimumSize();
1326 }
1327
1328
1329 int width = calculateLayoutSize(container, C, typeOfSize, entryList,
1330 prefMinSize);
1331
1332 int height = calculateLayoutSize(container, R, typeOfSize, entryList,
1333 prefMinSize);
1334
1335
1336 Insets inset = container.getInsets();
1337
1338 width += (inset.left + inset.right);
1339 height += (inset.top + inset.bottom);
1340
1341 return new Dimension(width, height);
1342 }
1343
1344 /***
1345 * Calculates the preferred or minimum size for the method calculateLayoutSize(Container
1346 * container, double typeOfSize). This method is passed the preferred/minimum sizes of the
1347 * components so that the potentially expensive methods getPreferredSize()/getMinimumSize()
1348 * are not called twice for the same component.
1349 *
1350 * @param container container whose size is being calculated
1351 * @param z -
1352 * @param typeOfSize indicates preferred or minimum
1353 * @param entryList list of Entry objects
1354 * @param prefMinSize list of preferred or minimum sizes
1355 *
1356 * @return a dimension indicating the container's preferred or minimum size
1357 */
1358 protected int calculateLayoutSize(Container container, int z,
1359 double typeOfSize, Entry[] entryList, Dimension[] prefMinSize) {
1360 Dimension size;
1361 int scaledSize = 0;
1362 int temp;
1363 int counter;
1364
1365
1366 int numCr = crSpec[z].length;
1367
1368
1369
1370 double fillSizeRatio = 1.0;
1371 int numFillSize = 0;
1372
1373 for (counter = 0; counter < numCr; counter++) {
1374 if ((crSpec[z][counter] > 0.0) && (crSpec[z][counter] < 1.0)) {
1375 fillSizeRatio -= crSpec[z][counter];
1376 }
1377 else if (crSpec[z][counter] == FILL) {
1378 numFillSize++;
1379 }
1380 }
1381
1382
1383 if (numFillSize > 1) {
1384 fillSizeRatio /= numFillSize;
1385 }
1386
1387
1388 if (fillSizeRatio < 0.0) {
1389 fillSizeRatio = 0.0;
1390 }
1391
1392
1393 crSize[z] = new int[numCr];
1394
1395
1396
1397 assignAbsoluteSize(z, 0);
1398
1399
1400
1401 assignPrefMinSize(z, 0, typeOfSize);
1402
1403 int[] crPrefMin = new int[numCr];
1404
1405 for (counter = 0; counter < numCr; counter++) {
1406 if ((crSpec[z][counter] == PREFERRED)
1407 || (crSpec[z][counter] == MINIMUM)) {
1408 crPrefMin[counter] = crSize[z][counter];
1409 }
1410 }
1411
1412
1413 int numColumn = crSpec[C].length;
1414 int numRow = crSpec[R].length;
1415 int numEntry = entryList.length;
1416
1417 for (int entryCounter = 0; entryCounter < numEntry; entryCounter++) {
1418
1419 Entry entry = entryList[entryCounter];
1420
1421
1422 if ((entry.cr1[C] < 0) || (entry.cr1[C] >= numColumn)
1423 || (entry.cr2[C] >= numColumn) || (entry.cr1[R] < 0)
1424 || (entry.cr1[R] >= numRow) || (entry.cr2[R] >= numRow)) {
1425
1426 continue;
1427 }
1428
1429
1430 size = prefMinSize[entryCounter];
1431
1432
1433
1434 int scalableSize = (z == C) ? size.width : size.height;
1435
1436 for (counter = entry.cr1[z]; counter <= entry.cr2[z]; counter++) {
1437 if (crSpec[z][counter] >= 1.0) {
1438 scalableSize -= crSpec[z][counter];
1439 }
1440 else if ((crSpec[z][counter] == PREFERRED)
1441 || (crSpec[z][counter] == MINIMUM)) {
1442 scalableSize -= crPrefMin[counter];
1443 }
1444 }
1445
1446
1447
1448
1449 double relativeSize = 0.0;
1450
1451 for (counter = entry.cr1[z]; counter <= entry.cr2[z]; counter++) {
1452
1453 if ((crSpec[z][counter] > 0.0) && (crSpec[z][counter] < 1.0)) {
1454
1455 relativeSize += crSpec[z][counter];
1456 }
1457
1458
1459 else if ((crSpec[z][counter] == FILL) && (fillSizeRatio != 0.0)) {
1460
1461 relativeSize += fillSizeRatio;
1462 }
1463 }
1464
1465
1466 if (relativeSize == 0) {
1467 temp = 0;
1468 }
1469 else {
1470 temp = (int) ((scalableSize / relativeSize) + 0.5);
1471 }
1472
1473
1474
1475 if (scaledSize < temp) {
1476 scaledSize = temp;
1477 }
1478 }
1479
1480
1481
1482 int totalSize = scaledSize;
1483
1484 for (counter = 0; counter < numCr; counter++) {
1485
1486 if (crSpec[z][counter] >= 1.0) {
1487 totalSize += (int) (crSpec[z][counter] + 0.5);
1488 }
1489
1490
1491 else if ((crSpec[z][counter] == PREFERRED)
1492 || (crSpec[z][counter] == MINIMUM)) {
1493
1494 totalSize += crPrefMin[counter];
1495 }
1496 }
1497
1498
1499 if (numCr > 0) {
1500 totalSize += (((z == C) ? hGap : vGap) * (numCr - 1));
1501 }
1502
1503 return totalSize;
1504 }
1505
1506 /***
1507 * Calculates the offset of each cr.
1508 *
1509 * @param z indicates row or column
1510 * @param inset -
1511 */
1512 protected void calculateOffset(int z, Insets inset) {
1513 int numCr = crSpec[z].length;
1514
1515 crOffset[z] = new int[numCr + 1];
1516 crOffset[z][0] = (z == C) ? inset.left : inset.top;
1517
1518 for (int counter = 0; counter < numCr; counter++) {
1519 crOffset[z][counter + 1] = crOffset[z][counter]
1520 + crSize[z][counter];
1521 }
1522 }
1523
1524 //*******************************************************************************
1525 //** Calculation methods ***
1526 //******************************************************************************
1527
1528 /**
1529 * Calculates the sizes of the rows and columns based on the absolute and relative sizes
1530 * specified in <code>crSpec[R]</code> and <code>crSpec[C]</code> and the size of the
1531 * container. The result is stored in <code>crSize[R]</code> and <code>crSize[C]</code>.
1532 *
1533 * @param container container using this TableLayout
1534 */
1535 protected void calculateSize(Container container) {
1536
1537 Insets inset = container.getInsets();
1538
1539
1540 Dimension d = container.getSize();
1541 int availableWidth = d.width - inset.left - inset.right;
1542 int availableHeight = d.height - inset.top - inset.bottom;
1543
1544
1545 if (crSpec[C].length > 0) {
1546 availableWidth -= (hGap * (crSpec[C].length - 1));
1547 }
1548
1549 if (crSpec[R].length > 0) {
1550 availableHeight -= (vGap * (crSpec[R].length - 1));
1551 }
1552
1553
1554 crSize[C] = new int[crSpec[C].length];
1555 crSize[R] = new int[crSpec[R].length];
1556
1557
1558 availableWidth = assignAbsoluteSize(C, availableWidth);
1559 availableHeight = assignAbsoluteSize(R, availableHeight);
1560
1561
1562 availableWidth = assignPrefMinSize(C, availableWidth, MINIMUM);
1563 availableWidth = assignPrefMinSize(C, availableWidth, PREFERRED);
1564 availableHeight = assignPrefMinSize(R, availableHeight, MINIMUM);
1565 availableHeight = assignPrefMinSize(R, availableHeight, PREFERRED);
1566
1567
1568 availableWidth = assignRelativeSize(C, availableWidth);
1569 availableHeight = assignRelativeSize(R, availableHeight);
1570
1571
1572 assignFillSize(C, availableWidth);
1573 assignFillSize(R, availableHeight);
1574
1575
1576 calculateOffset(C, inset);
1577 calculateOffset(R, inset);
1578
1579
1580
1581 dirty = false;
1582 oldWidth = d.width;
1583 oldHeight = d.height;
1584 }
1585
1586 /***
1587 * Calculates the vertical/horizontal offset and size of a component.
1588 *
1589 * @param entry entry containing component and contraints
1590 * @param preferredSize previously calculated preferred width/height of component
1591 * @param isColumn if true, this method is being called to calculate the offset/size of a
1592 * column. if false,... of a row.
1593 *
1594 * @return an array, a, of two integers such that a[0] is the offset and a[1] is the size
1595 */
1596 protected int[] calculateSizeAndOffset(Entry entry, int preferredSize,
1597 boolean isColumn) {
1598
1599 int[] crOffset = isColumn ? this.crOffset[C] : this.crOffset[R];
1600 int entryAlignment = isColumn ? entry.alignment[C] : entry.alignment[R];
1601
1602
1603 int cellSetSize = isColumn
1604 ? (crOffset[entry.cr2[C] + 1] - crOffset[entry.cr1[C]])
1605 : (crOffset[entry.cr2[R] + 1] - crOffset[entry.cr1[R]]);
1606
1607
1608 int size;
1609
1610 if ((entryAlignment == FULL) || (cellSetSize < preferredSize)) {
1611 size = cellSetSize;
1612 }
1613 else {
1614 size = preferredSize;
1615 }
1616
1617
1618
1619
1620 if (isColumn && (entryAlignment == LEADING)) {
1621 entryAlignment = LEFT;
1622 }
1623
1624 if (isColumn && (entryAlignment == TRAILING)) {
1625 entryAlignment = RIGHT;
1626 }
1627
1628
1629 int offset;
1630
1631 switch (entryAlignment) {
1632 case LEFT:
1633 offset = crOffset[isColumn ? entry.cr1[C] : entry.cr1[R]];
1634
1635 break;
1636
1637 case RIGHT:
1638 offset = crOffset[(isColumn ? entry.cr2[C] : entry.cr2[R]) + 1]
1639 - size;
1640
1641 break;
1642
1643 case CENTER:
1644 offset = crOffset[isColumn ? entry.cr1[C] : entry.cr1[R]]
1645 + ((cellSetSize - size) >> 1);
1646
1647 break;
1648
1649 case FULL:
1650 offset = crOffset[isColumn ? entry.cr1[C] : entry.cr1[R]];
1651
1652 break;
1653
1654 default:
1655 offset = 0;
1656 }
1657
1658
1659 if (isColumn) {
1660 offset += (hGap * entry.cr1[C]);
1661 size += (hGap * (entry.cr2[C] - entry.cr1[C]));
1662 }
1663 else {
1664 offset += (vGap * entry.cr1[R]);
1665 size += (vGap * (entry.cr2[R] - entry.cr1[R]));
1666 }
1667
1668
1669 int[] value = { offset, size };
1670
1671 return value;
1672 }
1673
1674 /***
1675 * Deletes a cr for the methods deleteRow or deleteColumn.
1676 *
1677 * @param z indicates row or column
1678 * @param i zero-based index of cr to delete
1679 *
1680 * @throws IllegalArgumentException -
1681 */
1682 protected void deleteCr(int z, int i) {
1683
1684 if ((i < 0) || (i >= crSpec[z].length)) {
1685 throw new IllegalArgumentException("Parameter i is invalid. i = "
1686 + i + ". Valid range is [0, "
1687 + (crSpec[z].length - 1) + "].");
1688 }
1689
1690
1691 double[] cr = new double[crSpec[z].length - 1];
1692
1693 System.arraycopy(crSpec[z], 0, cr, 0, i);
1694 System.arraycopy(crSpec[z], i + 1, cr, i, crSpec[z].length - i - 1);
1695
1696
1697 crSpec[z] = cr;
1698
1699
1700 ListIterator iterator = list.listIterator(0);
1701
1702 while (iterator.hasNext()) {
1703
1704 Entry entry = (Entry) iterator.next();
1705
1706
1707 if (entry.cr1[z] > i) {
1708
1709 entry.cr1[z]--;
1710 }
1711
1712
1713 if (entry.cr2[z] > i) {
1714
1715 entry.cr2[z]--;
1716 }
1717 }
1718
1719
1720 dirty = true;
1721 }
1722
1723 /***
1724 * Initializes the TableLayout for all constructors.
1725 *
1726 * @param col widths of columns in the format, {{col0, col1, col2, ..., colN}
1727 * @param row heights of rows in the format, {{row0, row1, row2, ..., rowN}
1728 *
1729 * @throws IllegalArgumentException -
1730 */
1731 protected void init(double[] col, double[] row) {
1732
1733 if (col == null) {
1734 throw new IllegalArgumentException("Parameter col cannot be null");
1735 }
1736
1737 if (row == null) {
1738 throw new IllegalArgumentException("Parameter row cannot be null");
1739 }
1740
1741
1742 crSpec[C] = new double[col.length];
1743 crSpec[R] = new double[row.length];
1744
1745
1746 System.arraycopy(col, 0, crSpec[C], 0, crSpec[C].length);
1747 System.arraycopy(row, 0, crSpec[R], 0, crSpec[R].length);
1748
1749
1750 for (int counter = 0; counter < crSpec[C].length; counter++) {
1751 if ((crSpec[C][counter] < 0.0) && (crSpec[C][counter] != FILL)
1752 && (crSpec[C][counter] != PREFERRED)
1753 && (crSpec[C][counter] != MINIMUM)) {
1754 crSpec[C][counter] = 0.0;
1755 }
1756 }
1757
1758 for (int counter = 0; counter < crSpec[R].length; counter++) {
1759 if ((crSpec[R][counter] < 0.0) && (crSpec[R][counter] != FILL)
1760 && (crSpec[R][counter] != PREFERRED)
1761 && (crSpec[R][counter] != MINIMUM)) {
1762 crSpec[R][counter] = 0.0;
1763 }
1764 }
1765
1766
1767 list = new LinkedList();
1768
1769
1770 dirty = true;
1771 }
1772
1773 //*******************************************************************************
1774 //*** Inner Class ***
1775 //******************************************************************************
1776 // The following inner class is used to bind components to their constraints
1777 public static class Entry implements Cloneable {
1778 /** Component bound by the constraints */
1779 public Component component;
1780
1781 /*** Horizontal and vertical alignment */
1782 public int[] alignment;
1783
1784 /*** Cell in which the upper-left corner of the component lies */
1785 public int[] cr1;
1786
1787 /*** Cell in which the lower-right corner of the component lies */
1788 public int[] cr2;
1789
1790 /***
1791 * Constructs an Entry that binds a component to a set of constraints.
1792 *
1793 * @param component component being bound
1794 * @param constraint constraints being applied
1795 */
1796 public Entry(Component component, TableLayoutConstraints constraint) {
1797 int[] cr1 = { constraint.col1, constraint.row1 };
1798 int[] cr2 = { constraint.col2, constraint.row2 };
1799 int[] alignment = { constraint.hAlign, constraint.vAlign };
1800
1801 this.cr1 = cr1;
1802 this.cr2 = cr2;
1803 this.alignment = alignment;
1804 this.component = component;
1805 }
1806
1807 /***
1808 * Copies this Entry.
1809 *
1810 * @return -
1811 *
1812 * @throws CloneNotSupportedException -
1813 */
1814 public Object copy() throws CloneNotSupportedException {
1815 return clone();
1816 }
1817
1818 /***
1819 * Gets the string representation of this Entry.
1820 *
1821 * @return a string in the form "(col1, row1, col2, row2, vAlign, hAlign) component"
1822 */
1823 public String toString() {
1824 TableLayoutConstraints c = new TableLayoutConstraints(cr1[C],
1825 cr1[R], cr2[C], cr2[R], alignment[C], alignment[R]);
1826
1827 return "(" + c + ") " + component;
1828 }
1829 }
1830 }