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
36
37
38 package com.gargoylesoftware.base.gui;
39
40 import com.gargoylesoftware.base.util.DetailedIllegalArgumentException;
41 import com.gargoylesoftware.base.util.DetailedNullPointerException;
42 import java.io.Serializable;
43
44 /***
45 * This object contains all the constraints that apply to a specific
46 * component inside a TableLayout.
47 * <p>
48 * We use the convention of specifying row before column to conform with the
49 * swing standards. This seems counterintuitive when specifying x,y
50 * (actually y,x) co-ordinates however we felt it was more important to
51 * conform to existing java layout standards.
52 *
53 * @version $Revision: 1.6 $
54 * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
55 */
56 public class TableLayoutConstraints implements Serializable {
57
58
59 private static final long serialVersionUID = 4323958798646824406L;
60
61 private boolean isImmutable_ = false;
62
63
64 private boolean obeyMaximumSize_ = false;
65
66 private boolean obeyMinimumSize_ = true;
67
68 private int row_;
69 private int column_;
70 private int rowSpan_;
71 private int columnSpan_;
72 private int verticalAlignment_;
73 private boolean verticalStretch_;
74 private int horizontalAlignment_;
75 private boolean horizontalStretch_;
76
77 /***
78 * Create a new instance.
79 * @param row The starting row.
80 * @param column The starting column.
81 */
82 public TableLayoutConstraints( final int row,
83 final int column ) {
84
85 setRow(row);
86 setColumn(column);
87
88 setRowSpan(1);
89 setColumnSpan(1);
90 setVerticalAlignment( TableLayout.CENTER );
91 setHorizontalAlignment( TableLayout.LEFT );
92 setVerticalStretch( false );
93 setHorizontalStretch( false );
94 }
95
96 /***
97 * Return a string representation of this object.
98 * @return Return a string representation of this object.
99 */
100 public final String toString() {
101 return getClass().getName()
102 + "] row_=[" + row_
103 + "] rowSpan_=[" + rowSpan_
104 + "] column_=[" + column_
105 + "] columnSpan_=[" + columnSpan_
106 + "] verticalAlignment_=[" + verticalAlignment_
107 + "] verticalStretch_=["+ verticalStretch_
108 + "] horizontalAlignment_=[" + horizontalAlignment_
109 + "] horizontalStretch_=["+ horizontalStretch_
110 + "] isImmutable_=["+ isImmutable_
111 + "] obeyMinimumSize_=["+ obeyMinimumSize_
112 + "] obeyMaximumSize_=["+ obeyMaximumSize_
113 + "]";
114
115 }
116
117 /***
118 * Make this object immutable.
119 */
120 public final void setImmutable() {
121 isImmutable_ = true;
122 }
123
124 /***
125 * Return true if this object is immutable.
126 * @return Return true if this object is immutable.
127 */
128 public final boolean isImmutable() {
129 return isImmutable_;
130 }
131
132 /***
133 * Check to make sure that we are allowed to modify this object. If not, throw an
134 * exception.
135 * @throws IllegalArgumentException If the object is immutable
136 */
137 private void ensureMutable() throws IllegalArgumentException {
138 if( isImmutable_ == true ) {
139 throw new IllegalArgumentException("This object is now immutable and cannot be modified");
140 }
141 }
142
143 /***
144 * Set the row.
145 * @param row The row.
146 */
147 public final void setRow( final int row ) {
148 ensureMutable();
149 if( row < 0 ) {
150 throw new DetailedIllegalArgumentException("row", new Integer(row), "Is less than zero");
151 }
152 row_ = row;
153 }
154
155 /***
156 * Return the row.
157 * @return The row.
158 */
159 public final int getRow() {
160 return row_;
161 }
162
163 /***
164 * Set the column.
165 * @param column The new column.
166 */
167 public final void setColumn( final int column ) {
168 ensureMutable();
169 if( column < 0 ) {
170 throw new DetailedIllegalArgumentException("column", new Integer(column), "Is less than zero");
171 }
172 column_ = column;
173 }
174
175 /***
176 * Return the column.
177 * @return The column.
178 */
179 public final int getColumn() {
180 return column_;
181 }
182
183 /***
184 * Set the number of rows that this component will span. The new span
185 * must be greater than or equal to one.
186 * @param span The new row span.
187 */
188 public final void setRowSpan( final int span ) {
189 ensureMutable();
190 if( span < 1 ) {
191 throw new DetailedIllegalArgumentException("span", span, "Is less than one");
192 }
193 rowSpan_ = span;
194 }
195
196 /***
197 * Return the number of rows this component will span.
198 * @return The row span.
199 */
200 public final int getRowSpan() {
201 return rowSpan_;
202 }
203
204 /***
205 * Set the number of columns that this component will span. The new span
206 * must be greater than or equal to one.
207 * @param span The new span.
208 */
209 public final void setColumnSpan( final int span ) {
210 ensureMutable();
211 if( span < 1 ) {
212 throw new DetailedIllegalArgumentException("span", new Integer(span), "Is less than one");
213 }
214 columnSpan_ = span;
215 }
216
217 /***
218 * Return the number of columns this component will span.
219 * @return the column span.
220 */
221 public final int getColumnSpan() {
222 return columnSpan_;
223 }
224
225 /***
226 * Set the vertical alignment of the component within the specified area.
227 * Possible values are
228 * <ul>
229 * <li>TableLayout.TOP
230 * <li>TableLayout.BOTTOM
231 * <li>TableLayout.CENTER
232 * </ul>
233 * @param alignment The new alignment.
234 */
235 public final void setVerticalAlignment( final int alignment ) {
236 ensureMutable();
237 switch( alignment ) {
238 case TableLayout.TOP:
239 case TableLayout.BOTTOM:
240 case TableLayout.CENTER:
241
242 break;
243
244 default:
245 throw new DetailedIllegalArgumentException("alignment", alignment);
246 }
247
248 verticalAlignment_ = alignment;
249 }
250
251 /***
252 * Return the vertical alignment.
253 * @return Return the vertical alignment.
254 */
255 public final int getVerticalAlignment() {
256 return verticalAlignment_;
257 }
258
259 /***
260 * Set the horizontal alignment of the component within the specified
261 * area. Possible values are
262 * <ul>
263 * <li>TableLayout.LEFT
264 * <li>TableLayout.RIGHT
265 * <li>TableLayout.CENTER
266 * </ul>
267 * @param alignment The new alignment.
268 */
269 public final void setHorizontalAlignment( final int alignment ) {
270 ensureMutable();
271
272 switch( alignment ) {
273 case TableLayout.LEFT:
274 case TableLayout.RIGHT:
275 case TableLayout.CENTER:
276
277 break;
278
279 default:
280 throw new DetailedIllegalArgumentException("alignment", alignment);
281 }
282
283 horizontalAlignment_ = alignment;
284 }
285
286 /***
287 * Return the horizontalAlignment.
288 * @return Return the horizontalAlignment.
289 */
290 public final int getHorizontalAlignment() {
291 return horizontalAlignment_;
292 }
293
294 /***
295 * Set whether or not this component can be stretched vertically.
296 * @param stretch true if the component will stretch vertically.
297 */
298 public final void setVerticalStretch( final boolean stretch ) {
299 ensureMutable();
300 verticalStretch_ = stretch;
301 }
302
303 /***
304 * Return true if this component can be stretched vertically.
305 * @return Return true if this component can be stretched vertically.
306 */
307 public final boolean getVerticalStretch() {
308 return verticalStretch_;
309 }
310
311 /***
312 * Set whether or not this component can be stretched horizontally.
313 * @param stretch true if the component will stretch horizontally.
314 */
315 public final void setHorizontalStretch( final boolean stretch ) {
316 ensureMutable();
317 horizontalStretch_ = stretch;
318 }
319
320 /***
321 * Return true if this component can be stretched horizontally.
322 * @return Return true if this component can be stretched horizontally.
323 */
324 public final boolean getHorizontalStretch() {
325 return horizontalStretch_;
326 }
327
328 /***
329 * Set whether or not the component should obey it's maximum size. Most components
330 * do not provide sensible maximum values so always obeying these values, ends up
331 * with very strange layouts. The default value is false.
332 * @param obey true if we are to obey the maximum size.
333 */
334 public final void setObeyMaximumSize( final boolean obey ) {
335 ensureMutable();
336 obeyMaximumSize_ = obey;
337 }
338
339 /***
340 * Return true if we are obeying the maximum size.
341 * @return Return true if we are obeying the maximum size.
342 */
343 public final boolean getObeyMaximumSize() {
344 return obeyMaximumSize_;
345 }
346
347 /***
348 * Set whether or not we should obey the minimum size of the component. Default is true.
349 * @param obey true if we are to obey the minimum size.
350 */
351 public final void setObeyMinimumSize( final boolean obey ) {
352 ensureMutable();
353 obeyMinimumSize_ = obey;
354 }
355
356 /***
357 * Return true if we are obeying the minimum size.
358 * @return Return true if we are obeying the minimum size.
359 */
360 public final boolean getObeyMinimumSize() {
361 return obeyMinimumSize_;
362 }
363
364 /***
365 * Create an instance of TableLayoutConstraints from the specified string.
366 * Format: "1,1"
367 * @param constraintString The constraints string.
368 * @return A new TableLayoutConstraints object.
369 */
370 public static TableLayoutConstraints makeConstraints( final String constraintString ) {
371 assertNotNull("constraintString", constraintString);
372 if( constraintString.length() == 0 ) {
373 throw new DetailedIllegalArgumentException("constraintString", constraintString, "May not be empty");
374 }
375
376 final int commaIndex = constraintString.indexOf(',');
377 if( commaIndex == -1 ) {
378 throw new DetailedIllegalArgumentException("constraintString", constraintString, "Missing a comma");
379 }
380
381 final TableLayoutConstraints constraints = new TableLayoutConstraints(0,0);
382 parseConstraintString( constraints, constraintString.substring(0, commaIndex), true );
383 parseConstraintString( constraints, constraintString.substring(commaIndex+1), false );
384
385 return constraints;
386 }
387
388 /***
389 * Parse the constraint string.
390 * @param constraints The new constraints object
391 * @param constraintString The constraints as an input string
392 * @param isRow true if these constraints are for a row
393 */
394 private static void parseConstraintString( final TableLayoutConstraints constraints,
395 final String constraintString,
396 final boolean isRow ) {
397
398 final int stringLength = constraintString.length();
399
400 if( stringLength == 0 ) {
401 throw new DetailedIllegalArgumentException("constraintString", constraintString, "May not be empty");
402 }
403
404 int index = 0;
405 while( index < stringLength && Character.isDigit( constraintString.charAt(index) ) ) {
406 index++;
407 }
408
409 final int number = Integer.parseInt( constraintString.substring(0,index) );
410 if( isRow ) {
411 constraints.setRow(number);
412 }
413 else {
414 constraints.setColumn(number);
415 }
416
417 char nextChar;
418
419 for( ;index < stringLength; index++ ) {
420 nextChar = constraintString.charAt(index);
421
422 switch(nextChar) {
423 case 's':
424 if( isRow ) {
425 constraints.setVerticalStretch(true);
426 }
427 else {
428 constraints.setHorizontalStretch(true);
429 }
430 break;
431
432 case '+':
433 index++;
434 final int startIndex = index;
435 while( index < stringLength && Character.isDigit( constraintString.charAt(index) ) ) {
436 index++;
437 }
438
439 final int span = Integer.parseInt( constraintString.substring(startIndex,index) );
440 if( isRow ) {
441 constraints.setRowSpan(span);
442 }
443 else {
444 constraints.setColumnSpan(span);
445 }
446 index--;
447 break;
448
449 default:
450 throw new IllegalArgumentException("Unexpected command ["+nextChar+"]");
451 }
452 }
453 }
454
455
456 /***
457 * Verify that the specified value is not null. If it is then throw an exception
458 *
459 * @param fieldName The name of the field to check
460 * @param fieldValue The value of the field to check
461 * @exception DetailedNullPointerException If fieldValue is null
462 */
463 protected static final void assertNotNull( final String fieldName, final Object fieldValue )
464 throws DetailedNullPointerException {
465
466 if( fieldValue == null ) {
467 throw new DetailedNullPointerException(fieldName);
468 }
469 }
470 }
471