KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > jgoodies > forms > layout > CellConstraints


1 /*
2  * Copyright (c) 2003 JGoodies Karsten Lentzsch. All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * o Redistributions of source code must retain the above copyright notice,
8  * this list of conditions and the following disclaimer.
9  *
10  * o Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * o Neither the name of JGoodies Karsten Lentzsch nor the names of
15  * its contributors may be used to endorse or promote products derived
16  * from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */

30
31 package com.jgoodies.forms.layout;
32
33 import java.awt.Component JavaDoc;
34 import java.awt.Insets JavaDoc;
35 import java.awt.Rectangle JavaDoc;
36 import java.util.StringTokenizer JavaDoc;
37
38 /**
39  * Defines constraints for components that are layed out with the
40  * {@link FormLayout}. Defines the components display area:
41  * grid x, grid y, grid width (column span),
42  * grid height (row span), horizontal alignment and vertical alignment.
43  * <p>
44  * Most methods return <em>this</em> object to enable method chaining.
45  * <p>
46  * <b>Examples</b>:<br>
47  * The following cell constraints locate a component in the third
48  * column of the fifth row; column and row span are 1; the component
49  * will be aligned with the column's right-hand side and the row's
50  * bottom.
51  * <pre>
52  * CellConstraints cc = new CellConstraints();
53  * cc.xy (3, 5);
54  * cc.xy (3, 5, CellConstraints.RIGHT, CellConstraints.BOTTOM);
55  * cc.xy (3, 5, "right, bottom");
56  * cc.xywh(3, 5, 1, 1);
57  * cc.xywh(3, 5, 1, 1, CellConstraints.RIGHT, CellConstraints.BOTTOM);
58  * cc.xywh(3, 5, 1, 1, "right, bottom");
59  * </pre>
60  * See also the examples in the {@link FormLayout} class comment.
61  *
62  * @author Karsten Lentzsch
63  * @version $Revision: 1.3 $
64  */

65 public final class CellConstraints implements Cloneable JavaDoc {
66     
67     // Alignment Constants *************************************************
68

69     /**
70      * Use the column's or row's default alignment.
71      */

72     public static final Alignment DEFAULT =
73         new Alignment("default", Alignment.BOTH);
74
75     /**
76      * Fill the cell either horizontally or vertically.
77      */

78     public static final Alignment FILL =
79         new Alignment("fill", Alignment.BOTH);
80
81     /**
82      * Put the component in the left.
83      */

84     public static final Alignment LEFT =
85         new Alignment("left", Alignment.HORIZONTAL);
86
87     /**
88      * Put the component in the right.
89      */

90     public static final Alignment RIGHT =
91         new Alignment("right", Alignment.HORIZONTAL);
92     /**
93      * Put the component in the center.
94      */

95     public static final Alignment CENTER =
96         new Alignment("center", Alignment.BOTH);
97
98     /**
99      * Put the component in the top.
100      */

101     public static final Alignment TOP =
102         new Alignment("top", Alignment.VERTICAL);
103
104     /**
105      * Put the component in the bottom.
106      */

107     public static final Alignment BOTTOM =
108         new Alignment("bottom", Alignment.VERTICAL);
109
110     private static final Insets JavaDoc EMPTY_INSETS =
111         new Insets JavaDoc(0, 0, 0, 0);
112     
113     // Fields ***************************************************************
114

115     /**
116      * Describes the component's horizontal grid origin (starts at 1).
117      */

118     public int gridX;
119
120     /**
121      * Describes the component's vertical grid origin (starts at 1).
122      */

123     public int gridY;
124
125     /**
126      * Describes the component's horizontal grid extend (number of cells).
127      */

128     public int gridWidth;
129
130     /**
131      * Describes the component's vertical grid extent (number of cells).
132      */

133     public int gridHeight;
134     
135     /**
136      * Describes the component's horizontal alignment.
137      */

138     public Alignment hAlign;
139     
140     /**
141      * Describes the component's vertical alignment.
142      */

143     public Alignment vAlign;
144     
145     /**
146      * Describes the component's <code>Insets</code> in it's display area.
147      */

148     public Insets JavaDoc insets;
149     
150     
151     // Instance Creation ****************************************************
152

153     /**
154      * Constructs a default instance of <code>CellConstraints</code>.
155      */

156     public CellConstraints() {
157         this(1, 1);
158     }
159
160     /**
161      * Constructs an instance of <code>CellConstraints</code> for the given
162      * cell position.
163      *
164      * @param gridX the component's horizontal grid origin
165      * @param gridY the component's vertical grid origin
166      */

167     public CellConstraints(int gridX, int gridY) {
168         this(gridX, gridY, 1, 1);
169     }
170
171     /**
172      * Constructs an instance of <code>CellConstraints</code> for the given
173      * cell position, anchor, and fill.
174      *
175      * @param gridX the component's horizontal grid origin
176      * @param gridY the component's vertical grid origin
177      * @param hAlign the component's horizontal alignment
178      * @param vAlign the component's vertical alignment
179      */

180     public CellConstraints(int gridX, int gridY,
181                             Alignment hAlign, Alignment vAlign) {
182         this(gridX, gridY, 1, 1, hAlign, vAlign, EMPTY_INSETS);
183     }
184
185     /**
186      * Constructs an instance of <code>CellConstraints</code> for the given
187      * cell position and size.
188      *
189      * @param gridX the component's horizontal grid origin
190      * @param gridY the component's vertical grid origin
191      * @param gridWidth the component's horizontal extent
192      * @param gridHeight the component's vertical extent
193      */

194     public CellConstraints(int gridX, int gridY, int gridWidth, int gridHeight) {
195         this(gridX, gridY, gridWidth, gridHeight, DEFAULT, DEFAULT);
196     }
197
198     /**
199      * Constructs an instance of <code>CellConstraints</code> for the given
200      * cell position and size, anchor, and fill.
201      *
202      * @param gridX the component's horizontal grid origin
203      * @param gridY the component's vertical grid origin
204      * @param gridWidth the component's horizontal extent
205      * @param gridHeight the component's vertical extent
206      * @param hAlign the component's horizontal alignment
207      * @param vAlign the component's vertical alignment
208      */

209     public CellConstraints(int gridX, int gridY, int gridWidth, int gridHeight,
210                             Alignment hAlign, Alignment vAlign) {
211         this(gridX, gridY, gridWidth, gridHeight, hAlign, vAlign, EMPTY_INSETS);
212     }
213
214     /**
215      * Constructs an instance of <code>CellConstraints</code> for
216      * the complete set of available properties.
217      *
218      * @param gridX the component's horizontal grid origin
219      * @param gridY the component's vertical grid origin
220      * @param gridWidth the component's horizontal extent
221      * @param gridHeight the component's vertical extent
222      * @param hAlign the component's horizontal alignment
223      * @param vAlign the component's vertical alignment
224      * @param insets the component's display area <code>Insets</code>
225      * @throws IndexOutOfBoundsException if the grid origin or extent is negative
226      * @throws NullPointerException if the horizontal or vertical alignment is null
227      * @throws IllegalArgumentException if an alignment orientation is invalid
228      */

229     public CellConstraints(int gridX, int gridY, int gridWidth, int gridHeight,
230                             Alignment hAlign, Alignment vAlign, Insets JavaDoc insets) {
231         this.gridX = gridX;
232         this.gridY = gridY;
233         this.gridWidth = gridWidth;
234         this.gridHeight = gridHeight;
235         this.hAlign = hAlign;
236         this.vAlign = vAlign;
237         this.insets = insets;
238         if (gridX <= 0)
239             throw new IndexOutOfBoundsException JavaDoc("The grid x must be a positive number.");
240         if (gridY <= 0)
241             throw new IndexOutOfBoundsException JavaDoc("The grid y must be a positive number.");
242         if (gridWidth <= 0)
243             throw new IndexOutOfBoundsException JavaDoc("The grid width must be a positive number.");
244         if (gridHeight <= 0)
245             throw new IndexOutOfBoundsException JavaDoc("The grid height must be a positive number.");
246         if (hAlign == null)
247             throw new NullPointerException JavaDoc("The horizontal alignment must not be null.");
248         if (vAlign == null)
249             throw new NullPointerException JavaDoc("The vertical alignment must not be null.");
250         ensureValidOrientations(hAlign, vAlign);
251     }
252     
253     /**
254      * Constructs an instance of <code>CellConstraints</code> from
255      * the given encoded string properties.
256      *
257      * @param encodedConstraints the constraints encoded as string
258      */

259     public CellConstraints(String JavaDoc encodedConstraints) {
260         this();
261         initFromConstraints(encodedConstraints);
262     }
263     
264
265     // Setters **************************************************************
266

267     /**
268      * Sets row and column origins; sets width and height to 1;
269      * uses the default alignments.
270      *
271      * @param col the new column index
272      * @param row the new row index
273      * @return this
274      */

275     public CellConstraints xy(int col, int row) {
276         return xywh(col, row, 1, 1);
277     }
278     
279     /**
280      * Sets row and column origins; sets width and height to 1;
281      * decodes alignments from the given string description.
282      *
283      * @param col the new column index
284      * @param row the new row index
285      * @param encodedAlignments string describing the alignments
286      * @return this
287      */

288     public CellConstraints xy(int col, int row, String JavaDoc encodedAlignments) {
289         return xywh(col, row, 1, 1, encodedAlignments);
290     }
291
292     /**
293      * Sets the row and column origins; sets width and height to 1;
294      * set horizontal and vertical alignment using the specified objects.
295      *
296      * @param col the new column index
297      * @param row the new row index
298      * @param colAlign horizontal component alignment
299      * @param rowAlign vertical component alignment
300      * @return this
301      */

302     public CellConstraints xy(int col, int row,
303                               Alignment colAlign, Alignment rowAlign) {
304         return xywh(col, row, 1, 1, colAlign, rowAlign);
305     }
306     
307
308     /**
309      * Sets the row, column, width, and height;
310      * uses default alignments.
311      *
312      * @param col the new column index
313      * @param row the new row index
314      * @param colSpan the column span or grid width
315      * @param rowSpan the row span or grid height
316      * @return this
317      */

318     public CellConstraints xywh(int col, int row, int colSpan, int rowSpan) {
319         return xywh(col, row, colSpan, rowSpan, DEFAULT, DEFAULT);
320     }
321     
322     /**
323      * Sets the row, column, width, and height;
324      * decodes the horizontal and vertical alignments from the given string.
325      *
326      * @param col the new column index
327      * @param row the new row index
328      * @param colSpan the column span or grid width
329      * @param rowSpan the row span or grid height
330      * @param encodedAlignments string describing the alignments
331      * @return this
332      * @throws IllegalArgumentException if an alignment orientation is invalid
333      */

334     public CellConstraints xywh(int col, int row, int colSpan, int rowSpan,
335                                  String JavaDoc encodedAlignments) {
336         CellConstraints result = xywh(col, row, colSpan, rowSpan);
337         result.setAlignments(encodedAlignments);
338         return result;
339     }
340
341     /**
342      * Sets the row, column, width, and height; sets the horizontal
343      * and vertical aligment using the specified alignment objects.
344      *
345      * @param col the new column index
346      * @param row the new row index
347      * @param colSpan the column span or grid width
348      * @param rowSpan the row span or grid height
349      * @param colAlign horizontal component alignment
350      * @param rowAlign vertical component alignment
351      * @return this
352      * @throws IllegalArgumentException if an alignment orientation is invalid
353      */

354     public CellConstraints xywh(int col, int row, int colSpan, int rowSpan,
355                                  Alignment colAlign, Alignment rowAlign) {
356         this.gridX = col;
357         this.gridY = row;
358         this.gridWidth = colSpan;
359         this.gridHeight = rowSpan;
360         this.hAlign = colAlign;
361         this.vAlign = rowAlign;
362         ensureValidOrientations(hAlign, vAlign);
363         return this;
364     }
365     
366
367     // Parsing and Decoding String Descriptions *****************************
368

369     /**
370      * Decodes and answers the grid bounds and alignments for this
371      * constraints as an array of six integers. The string representation
372      * is a comma separated sequence, one of
373      * <pre>
374      * "x, y"
375      * "x, y, w, h"
376      * "x, y, hAlign, vAlign"
377      * "x, y, w, h, hAlign, vAlign"
378      * </pre>
379      *
380      * @param encodedAlignments represents horizontal and vertical alignment
381      * @throws IllegalArgumentException if the encoded constraints do not
382      * follow the constraint syntax
383      */

384     private void initFromConstraints(String JavaDoc encodedConstraints) {
385         StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(encodedConstraints, " ,");
386         int argCount = tokenizer.countTokens();
387         if (!(argCount == 2 || argCount == 4 || argCount == 6))
388            throw new IllegalArgumentException JavaDoc(
389                     "You must provide 2, 4 or 6 arguments.");
390         
391         Integer JavaDoc nextInt = decodeInt(tokenizer.nextToken());
392         if (nextInt == null) {
393             throw new IllegalArgumentException JavaDoc(
394                     "First cell constraint element must be a number.");
395         }
396         gridX = nextInt.intValue();
397         if (gridX <= 0)
398             throw new IndexOutOfBoundsException JavaDoc("The grid x must be a positive number.");
399             
400         nextInt = decodeInt(tokenizer.nextToken());
401         if (nextInt == null) {
402             throw new IllegalArgumentException JavaDoc(
403                     "Second cell constraint element must be a number.");
404         }
405         gridY = nextInt.intValue();
406         if (gridY <= 0)
407             throw new IndexOutOfBoundsException JavaDoc(
408                     "The grid y must be a positive number.");
409
410         if (!tokenizer.hasMoreTokens())
411             return;
412             
413         String JavaDoc token = tokenizer.nextToken();
414         nextInt = decodeInt(token);
415         if (nextInt != null) {
416             // Case: "x, y, w, h" or
417
// "x, y, w, h, hAlign, vAlign"
418
gridWidth = nextInt.intValue();
419             if (gridWidth <= 0)
420                 throw new IndexOutOfBoundsException JavaDoc(
421                     "The grid width must be a positive number.");
422             nextInt = decodeInt(tokenizer.nextToken());
423             if (nextInt == null)
424                 throw new IllegalArgumentException JavaDoc(
425                     "Fourth cell constraint element must be like third.");
426             gridHeight = nextInt.intValue();
427             if (gridHeight <= 0)
428                 throw new IndexOutOfBoundsException JavaDoc(
429                     "The grid height must be a positive number.");
430
431             if (!tokenizer.hasMoreTokens())
432                 return;
433             token = tokenizer.nextToken();
434         }
435             
436         hAlign = decodeAlignment(token);
437         vAlign = decodeAlignment(tokenizer.nextToken());
438         ensureValidOrientations(hAlign, vAlign);
439     }
440     
441     
442     /**
443      * Decodes a string description for the horizontal and vertical
444      * alignment and set the alignment values.
445      * <p>
446      * Valid horizontal aligmnents are: left, middle, right, default, and fill.
447      * Valid vertical alignments are: top, center, bottom, default, and fill.
448      * The anchor's string representation abbreviates the alignment:
449      * l, m, r, d, f, t, c, and b.
450      * <p>
451      * Anchor examples:
452      * "mc" is centered, "lt" is northwest, "mt" is north, "rc" east.
453      * "md" is horizontally centered and uses the row's default alignment.
454      * "dt" is on top of the cell and uses the column's default alignment.
455      * <p>
456      *
457      * @param encodedAlignments represents horizontal and vertical alignment
458      * @throws IllegalArgumentException if an alignment orientation is invalid
459      */

460     private void setAlignments(String JavaDoc encodedAlignments) {
461         StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(encodedAlignments, " ,");
462         hAlign = decodeAlignment(tokenizer.nextToken());
463         vAlign = decodeAlignment(tokenizer.nextToken());
464         ensureValidOrientations(hAlign, vAlign);
465     }
466
467     /**
468      * Decodes an integer string representation and answers the
469      * associated Integer or null in case of an invalid number format.
470      *
471      * @param token the encoded integer
472      * @return the decoded Integer or null
473      */

474     private Integer JavaDoc decodeInt(String JavaDoc token) {
475         try {
476             return Integer.decode(token);
477         } catch (NumberFormatException JavaDoc e) {
478             return null;
479         }
480     }
481     
482     /**
483      * Parses an alignment string description and
484      * answers the corresponding alignment value.
485      *
486      * @param encodedAlignment the encoded alignment
487      * @return the associated <code>Alignment</code> instance
488      */

489     private Alignment decodeAlignment(String JavaDoc encodedAlignment) {
490         return Alignment.valueOf(encodedAlignment);
491     }
492
493     /**
494      * Checks and verifies that this constraints object has valid grid
495      * index values, i. e. the display area cells are inside the form's grid.
496      *
497      * @param colCount number of columns in the grid
498      * @param rowCount number of rows in the grid
499      * @throws IndexOutOfBoundsException if the display area described
500      * by this constraints object is not inside the grid
501      */

502     void ensureValidGridBounds(int colCount, int rowCount) {
503         if (gridX <= 0) {
504             throw new IndexOutOfBoundsException JavaDoc(
505                 "The column index " + gridX + " must be positive.");
506         }
507         if (gridX > colCount) {
508             throw new IndexOutOfBoundsException JavaDoc(
509                 "The column index " + gridX + " must be less than or equal to "
510                     + colCount + ".");
511         }
512         if (gridX + gridWidth - 1 > colCount) {
513             throw new IndexOutOfBoundsException JavaDoc(
514                 "The grid width " + gridWidth + " must be less than or equal to "
515                     + (colCount - gridX + 1) + ".");
516         }
517         if (gridY <= 0) {
518             throw new IndexOutOfBoundsException JavaDoc(
519                 "The row index " + gridY + " must be positive.");
520         }
521         if (gridY > rowCount) {
522             throw new IndexOutOfBoundsException JavaDoc(
523                 "The row index " + gridY + " must be less than or equal to "
524                     + rowCount + ".");
525         }
526         if (gridY + gridHeight - 1 > rowCount) {
527             throw new IndexOutOfBoundsException JavaDoc(
528                 "The grid height " + gridHeight + " must be less than or equal to "
529                     + (rowCount - gridY + 1) + ".");
530         }
531     }
532     
533     
534     /**
535      * Checks and verifies that the horizontal alignment is a horizontal
536      * and the vertical alignment is vertical.
537      *
538      * @param horizontalAlignment the horizontal alignment
539      * @param verticalAlignment the vertical alignment
540      * @throws IllegalArgumentException if an alignment is invalid
541      */

542     private void ensureValidOrientations(Alignment horizontalAlignment, Alignment verticalAlignment) {
543         if (!horizontalAlignment.isHorizontal())
544             throw new IllegalArgumentException JavaDoc("The horizontal alignment must be one of: left, center, right, fill, default.");
545         if (!verticalAlignment.isVertical())
546             throw new IllegalArgumentException JavaDoc("The vertical alignment must be one of: top, center, botto, fill, default.");
547     }
548     
549     
550     // Settings Component Bounds ********************************************
551

552     /**
553      * Sets the component's bounds using the given component and cell bounds.
554      *
555      * @param c the component to set bounds
556      * @param colSpec the specification for the component's column
557      * @param rowSpec the specification for the component's row
558      * @param cellBounds the cell's bounds
559      * @param minWidthMeasure measures the minimum width
560      * @param minHeightMeasure measures the minimum height
561      * @param prefWidthMeasure measures the preferred width
562      * @param prefHeightMeasure measures the preferred height
563      */

564     void setBounds(Component JavaDoc c, FormLayout layout,
565                    Rectangle JavaDoc cellBounds,
566                    FormLayout.Measure minWidthMeasure,
567                    FormLayout.Measure minHeightMeasure,
568                    FormLayout.Measure prefWidthMeasure,
569                    FormLayout.Measure prefHeightMeasure) {
570         ColumnSpec colSpec = gridWidth == 1 ? layout.getColumnSpec(gridX) : null;
571         RowSpec rowSpec = gridHeight == 1 ? layout.getRowSpec(gridY) : null;
572         Alignment concreteHAlign = concreteAlignment(this.hAlign, colSpec);
573         Alignment concreteVAlign = concreteAlignment(this.vAlign, rowSpec);
574         Insets JavaDoc concreteInsets = this.insets != null ? this.insets : EMPTY_INSETS;
575         int cellX = cellBounds.x + concreteInsets.left;
576         int cellY = cellBounds.y + concreteInsets.top;
577         int cellW = cellBounds.width - concreteInsets.left - concreteInsets.right;
578         int cellH = cellBounds.height - concreteInsets.top - concreteInsets.bottom;
579         int compW = componentSize(c, colSpec, cellW, minWidthMeasure,
580                                                      prefWidthMeasure);
581         int compH = componentSize(c, rowSpec, cellH, minHeightMeasure,
582                                                      prefHeightMeasure);
583         int x = origin(concreteHAlign, cellX, cellW, compW);
584         int y = origin(concreteVAlign, cellY, cellH, compH);
585         int w = extent(concreteHAlign, cellW, compW);
586         int h = extent(concreteVAlign, cellH, compH);
587         c.setBounds(x, y, w, h);
588     }
589     
590     
591     /**
592      * Computes and answers the concrete alignment. Takes into account
593      * the cell alignment and <i>the</i> <code>FormSpec</code> if applicable.
594      * <p>
595      * If this constraints object doesn't belong to a single column or row,
596      * the <code>formSpec</code> parameter is <code>null</code>.
597      * In this case the cell alignment is answered, but <code>DEFAULT</code>
598      * is mapped to <code>FILL</code>.
599      * <p>
600      * If the cell belongs to a single column or row, we use the cell
601      * alignment, unless it is <code>DEFAULT</code>, where the alignment
602      * is inherited from the column or row resp.
603      *
604      * @param alignment this cell's aligment
605      * @param formSpec the associated column or row specification
606      * @return the concrete alignment
607      */

608     private Alignment concreteAlignment(Alignment cellAlignment, FormSpec formSpec) {
609         return formSpec == null
610             ? (cellAlignment == DEFAULT ? FILL : cellAlignment)
611             : usedAlignment(cellAlignment, formSpec);
612     }
613
614     /**
615      * Answers the alignment used for a given form constraints object.
616      * The cell alignment overrides the column or row default, unless
617      * it is <code>DEFAULT</code>. In the latter case, we use the
618      * column or row alignment.
619      *
620      * @param cellAlignment this cell constraint's alignment
621      * @param formSpec the associated column or row specification
622      * @return the alignment used
623      */

624     private Alignment usedAlignment(Alignment cellAlignment, FormSpec formSpec) {
625         if (cellAlignment != CellConstraints.DEFAULT) {
626             // Cell alignments other than DEFAULT override col/row alignments
627
return cellAlignment;
628         }
629         FormSpec.DefaultAlignment defaultAlignment = formSpec.getDefaultAlignment();
630         if (defaultAlignment == FormSpec.FILL_ALIGN)
631             return FILL;
632         if (defaultAlignment == ColumnSpec.LEFT)
633             return LEFT;
634         else if (defaultAlignment == FormSpec.CENTER_ALIGN)
635             return CENTER;
636         else if (defaultAlignment == ColumnSpec.RIGHT)
637             return RIGHT;
638         else if (defaultAlignment == RowSpec.TOP)
639             return TOP;
640         else
641             return BOTTOM;
642     }
643     
644     /**
645      * Computes and answers the pixel size of the given component using the
646      * given form specification, measures, and cell size.
647      *
648      * @param component the component to measure
649      * @param formSpec the specification of the component's column/row
650      * @param minMeasure the measure for the minimum size
651      * @param prefMeasure the measure for the preferred size
652      * @param cellSize the cell size
653      * @return the component size as measured or a constant
654      */

655     private int componentSize(Component JavaDoc component,
656                                FormSpec formSpec,
657                                int cellSize,
658                                FormLayout.Measure minMeasure,
659                                FormLayout.Measure prefMeasure) {
660         if (formSpec == null) {
661             return prefMeasure.sizeOf(component);
662         } else if (formSpec.getSize() == Sizes.MINIMUM) {
663             return minMeasure.sizeOf(component);
664         } else if (formSpec.getSize() == Sizes.PREFERRED) {
665             return prefMeasure.sizeOf(component);
666         } else { // default mode
667
return Math.min(cellSize, prefMeasure.sizeOf(component));
668         }
669     }
670     
671     /**
672      * Computes and answers the component's pixel origin.
673      *
674      * @param alignment the component's alignment
675      * @param cellOrigin the origin of the display area
676      * @param cellSize the extent of the display area
677      * @param componentSize
678      * @return the component's pixel origin
679      */

680     private int origin(Alignment alignment,
681                         int cellOrigin,
682                         int cellSize,
683                         int componentSize) {
684         if (alignment == RIGHT || alignment == BOTTOM) {
685             return cellOrigin + cellSize - componentSize;
686         } else if (alignment == CENTER) {
687             return cellOrigin + (cellSize - componentSize) / 2;
688         } else { // left, top, fill
689
return cellOrigin;
690         }
691     }
692     
693     /**
694      * Answers the component's pixel extent.
695      *
696      * @param alignment the component's alignment
697      * @param cellSize the size of the display area
698      * @param componentSize the component's size
699      * @return the component's pixel extent
700      */

701     private int extent(Alignment alignment, int cellSize, int componentSize) {
702         return alignment == FILL
703                     ? cellSize
704                     : componentSize;
705     }
706     
707     
708     
709     // Misc *****************************************************************
710

711     /**
712      * Creates a copy of this cell constraints object.
713      *
714      * @return a copy of this cell constraints object
715      */

716     public Object JavaDoc clone() {
717         try {
718             CellConstraints c = (CellConstraints) super.clone();
719             c.insets = (Insets JavaDoc) insets.clone();
720             return c;
721         } catch (CloneNotSupportedException JavaDoc e) {
722             // This shouldn't happen, since we are Cloneable.
723
throw new InternalError JavaDoc();
724         }
725     }
726     
727     
728     /**
729      * Constructs and answers a string representation of this constraints object.
730      *
731      * @return string representation of this constraints object
732      */

733     public String JavaDoc toString() {
734         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc("CellConstraints");
735         buffer.append("[x=");
736         buffer.append(gridX);
737         buffer.append("; y=");
738         buffer.append(gridY);
739         buffer.append("; w=");
740         buffer.append(gridWidth);
741         buffer.append("; h=");
742         buffer.append(gridHeight);
743         buffer.append("; hAlign=");
744         buffer.append(hAlign);
745         buffer.append("; vAlign=");
746         buffer.append(vAlign);
747         if (!(EMPTY_INSETS.equals(insets))) {
748           buffer.append("; insets=");
749           buffer.append(insets);
750         }
751         
752         buffer.append(']');
753         return buffer.toString();
754     }
755     
756     /**
757      * Answers a short string representation of this constraints object.
758      *
759      * @return a short string representation of this constraints object
760      */

761     public String JavaDoc toShortString() {
762         return toShortString(null);
763     }
764     
765     
766     /**
767      * Answers a short string representation of this constraints object.
768      * This method can use the given <code>FormLayout</code>
769      * to display extra information how default alignments
770      * are mapped to concrete alignments. Therefore it asks the
771      * related column and row as specified by this constraints object.
772      *
773      * @return a short string representation of this constraints object
774      */

775     public String JavaDoc toShortString(FormLayout layout) {
776         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc("(");
777         buffer.append(formatInt(gridX));
778         buffer.append(", ");
779         buffer.append(formatInt(gridY));
780         buffer.append(", ");
781         buffer.append(formatInt(gridWidth));
782         buffer.append(", ");
783         buffer.append(formatInt(gridHeight));
784         buffer.append(", \"");
785         buffer.append(hAlign.abbreviation());
786         if (hAlign == DEFAULT && layout != null) {
787             buffer.append('=');
788             ColumnSpec colSpec = gridWidth == 1
789                 ? layout.getColumnSpec(gridX)
790                 : null;
791             buffer.append(concreteAlignment(hAlign, colSpec).abbreviation());
792         }
793         buffer.append(", ");
794         buffer.append(vAlign.abbreviation());
795         if (vAlign == DEFAULT && layout != null) {
796             buffer.append('=');
797             RowSpec rowSpec = gridHeight == 1
798                 ? layout.getRowSpec(gridY)
799                 : null;
800             buffer.append(concreteAlignment(vAlign, rowSpec).abbreviation());
801         }
802         buffer.append("\"");
803         if (!(EMPTY_INSETS.equals(insets))) {
804           buffer.append(", ");
805           buffer.append(insets);
806         }
807         
808         buffer.append(')');
809         return buffer.toString();
810     }
811     
812     
813     
814     // Helper Class *********************************************************
815

816     /**
817      * A typesafe enumeration for component alignment types as used by
818      * the {@link FormLayout}.
819      */

820     public static final class Alignment {
821         
822         private static final int HORIZONTAL = 0;
823         private static final int VERTICAL = 1;
824         private static final int BOTH = 2;
825         
826         private final String JavaDoc name;
827         private final int orientation;
828         
829         private Alignment(String JavaDoc name, int orientation) {
830             this.name = name;
831             this.orientation = orientation;
832         }
833         
834         static Alignment valueOf(String JavaDoc nameOrAbbreviation) {
835             String JavaDoc str = nameOrAbbreviation.toLowerCase();
836             if (str.equals("d") || str.equals("default"))
837                 return DEFAULT;
838             else if (str.equals("f") || str.equals("fill"))
839                 return FILL;
840             else if (str.equals("c") || str.equals("center"))
841                 return CENTER;
842             else if (str.equals("l") || str.equals("left"))
843                 return LEFT;
844             else if (str.equals("r") || str.equals("right"))
845                 return RIGHT;
846             else if (str.equals("t") || str.equals("top"))
847                 return TOP;
848             else if (str.equals("b") || str.equals("bottom"))
849                 return BOTTOM;
850             else
851                 throw new IllegalArgumentException JavaDoc(
852                     "Invalid alignment " + nameOrAbbreviation
853                     + ". Must be one of: left, center, right, top, bottom, "
854                     + "fill, default, l, c, r, t, b, f, d.");
855         }
856
857         public String JavaDoc toString() {
858             return name;
859         }
860
861         public char abbreviation() {
862             return name.charAt(0);
863         }
864         
865         private boolean isHorizontal() {
866             return orientation != VERTICAL;
867         }
868
869         private boolean isVertical() {
870             return orientation != HORIZONTAL;
871         }
872
873     }
874
875
876     /**
877      * Answers an integer that has a minimum of two characters.
878      * @param number the number to format
879      * @return a string representation for a number with a minum of two chars
880      */

881     private String JavaDoc formatInt(int number) {
882         String JavaDoc str = Integer.toString(number);
883         return number < 10 ? " " + str : str;
884     }
885 }
886
887
Popular Tags