001: /*
002: * Copyright (c) 2002-2004 JGoodies Karsten Lentzsch. All Rights Reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * o Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * o Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * o Neither the name of JGoodies Karsten Lentzsch nor the names of
015: * its contributors may be used to endorse or promote products derived
016: * from this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
020: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
021: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
022: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
025: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
026: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
027: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030:
031: package com.jgoodies.forms.factories;
032:
033: import com.jgoodies.forms.layout.ColumnSpec;
034: import com.jgoodies.forms.layout.ConstantSize;
035: import com.jgoodies.forms.layout.FormLayout;
036: import com.jgoodies.forms.layout.RowSpec;
037: import com.jgoodies.forms.layout.Sizes;
038: import com.jgoodies.forms.util.LayoutStyle;
039:
040: /**
041: * A factory that creates instances of FormLayout for frequently used form
042: * layouts. It makes form creation easier and more consistent.
043: * <p>
044: *
045: * <strong>I consider removing the <code>FormLayout</code> factory methods.
046: * These seem to be less usefull and may lead to poor layout readability. If you
047: * want to use these methods, you may consider copying them to your codebase.</strong>
048: * <p>
049: *
050: * The forms are described by major and minor columns. Major columns consist of
051: * a leading label and a set of related components, for example: a label plus
052: * textfield, or label plus textfield plus button. The component part of a major
053: * column is divided into minor columns as shown in this layout:
054: *
055: * <pre>
056: * <- major column 1 -> <- major column 2 ->
057: * label1 textfield1a textfield1b label2 textfield2a textfield2b
058: * label3 textfield3a textfield3b label4 textfield4
059: * label5 textfield5 label6 textfield6
060: * </pre>
061: *
062: * <p>
063: *
064: * Many forms use 1, 2, 3 or 4 major columns, which in turn are often split into
065: * 1, 2, 3 or 4 minor columns.
066: *
067: * @author Karsten Lentzsch
068: * @version $Revision: 1.2 $
069: *
070: * @see com.jgoodies.forms.layout.FormLayout
071: * @see ColumnSpec
072: */
073: public final class FormFactory {
074:
075: // Frequently used Column Specifications ********************************
076:
077: /**
078: * An unmodifyable <code>ColumnSpec</code> that determines its width by
079: * computing the maximum of all column component minimum widths.
080: *
081: * @see #PREF_COLSPEC
082: * @see #DEFAULT_COLSPEC
083: */
084: public static final ColumnSpec MIN_COLSPEC = new ColumnSpec(
085: Sizes.MINIMUM);
086:
087: /**
088: * An unmodifyable <code>ColumnSpec</code> that determines its width by
089: * computing the maximum of all column component preferred widths.
090: *
091: * @see #MIN_COLSPEC
092: * @see #DEFAULT_COLSPEC
093: */
094: public static final ColumnSpec PREF_COLSPEC = new ColumnSpec(
095: Sizes.PREFERRED);
096:
097: /**
098: * An unmodifyable <code>ColumnSpec</code> that determines its preferred
099: * width by computing the maximum of all column component preferred widths
100: * and its minimum width by computing all column component minimum widths.
101: * <p>
102: *
103: * Useful to let a column shrink from preferred width to minimum width if
104: * the container space gets scarce.
105: *
106: * @see #MIN_COLSPEC
107: * @see #PREF_COLSPEC
108: */
109: public static final ColumnSpec DEFAULT_COLSPEC = new ColumnSpec(
110: Sizes.DEFAULT);
111:
112: /**
113: * An unmodifyable <code>ColumnSpec</code> that has an initial width of 0
114: * pixels and that grows. Useful to describe <em>glue</em> columns that
115: * fill the space between other columns.
116: *
117: * @see #GLUE_ROWSPEC
118: */
119: public static final ColumnSpec GLUE_COLSPEC = new ColumnSpec(
120: ColumnSpec.DEFAULT, Sizes.ZERO, ColumnSpec.DEFAULT_GROW);
121:
122: // Layout Style Dependent Column Specs ***********************************
123:
124: /**
125: * Describes a logical horizontal gap between a label and an associated
126: * component. Useful for builders that automatically fill a grid with labels
127: * and components.
128: * <p>
129: *
130: * <strong>Note:</strong> In a future version this constant will likely be
131: * moved to a class <code>LogicalSize</code> or <code>StyledSize</code>.
132: *
133: * @since 1.0.3
134: */
135: public static final ColumnSpec LABEL_COMPONENT_GAP_COLSPEC = createGapColumnSpec(LayoutStyle
136: .getCurrent().getLabelComponentPadX());
137:
138: /**
139: * Describes a logical horizontal gap between two related components. For
140: * example the <em>OK</em> and <em>Cancel</em> buttons are considered
141: * related.
142: * <p>
143: *
144: * <strong>Note:</strong> In a future version this constant will likely be
145: * moved to a class <code>LogicalSize</code> or <code>StyledSize</code>.
146: *
147: * @see #UNRELATED_GAP_COLSPEC
148: */
149: public static final ColumnSpec RELATED_GAP_COLSPEC = createGapColumnSpec(LayoutStyle
150: .getCurrent().getRelatedComponentsPadX());
151:
152: /**
153: * Describes a logical horizontal gap between two unrelated components.
154: * <p>
155: *
156: * <strong>Note:</strong> In a future version this constant will likely be
157: * moved to a class <code>LogicalSize</code> or <code>StyledSize</code>.
158: *
159: * @see #RELATED_GAP_COLSPEC
160: */
161: public static final ColumnSpec UNRELATED_GAP_COLSPEC = createGapColumnSpec(LayoutStyle
162: .getCurrent().getUnrelatedComponentsPadX());
163:
164: /**
165: * Describes a logical horizontal column for a fixed size button. This spec
166: * honors the current layout style's default button minimum width.
167: * <p>
168: *
169: * <strong>Note:</strong> In a future version this constant will likely be
170: * moved to a class <code>LogicalSize</code> or <code>StyledSize</code>.
171: *
172: * @see #GROWING_BUTTON_COLSPEC
173: */
174: public static final ColumnSpec BUTTON_COLSPEC = new ColumnSpec(
175: Sizes.bounded(Sizes.PREFERRED, LayoutStyle.getCurrent()
176: .getDefaultButtonWidth(), null));
177:
178: /**
179: * Describes a logical horizontal column for a growing button. This spec
180: * does <em>not</em> use the layout style's default button minimum width.
181: * <p>
182: *
183: * <strong>Note:</strong> In a future version this constant will likely be
184: * moved to a class <code>LogicalSize</code> or <code>StyledSize</code>.
185: *
186: * @see #BUTTON_COLSPEC
187: */
188: public static final ColumnSpec GROWING_BUTTON_COLSPEC = new ColumnSpec(
189: ColumnSpec.DEFAULT, BUTTON_COLSPEC.getSize(),
190: ColumnSpec.DEFAULT_GROW);
191:
192: // Frequently used Row Specifications ***********************************
193:
194: /**
195: * An unmodifyable <code>RowSpec</code> that determines its height by
196: * computing the maximum of all column component minimum heights.
197: *
198: * @see #PREF_ROWSPEC
199: * @see #DEFAULT_ROWSPEC
200: */
201: public static final RowSpec MIN_ROWSPEC = new RowSpec(Sizes.MINIMUM);
202:
203: /**
204: * An unmodifyable <code>RowSpec</code> that determines its height by
205: * computing the maximum of all column component preferred heights.
206: *
207: * @see #MIN_ROWSPEC
208: * @see #DEFAULT_ROWSPEC
209: */
210: public static final RowSpec PREF_ROWSPEC = new RowSpec(
211: Sizes.PREFERRED);
212:
213: /**
214: * An unmodifyable <code>RowSpec</code> that determines its preferred
215: * height by computing the maximum of all column component preferred heights
216: * and its minimum height by computing all column component minimum heights.
217: * <p>
218: *
219: * Useful to let a column shrink from preferred height to minimum height if
220: * the container space gets scarce.
221: *
222: * @see #MIN_COLSPEC
223: * @see #PREF_COLSPEC
224: */
225: public static final RowSpec DEFAULT_ROWSPEC = new RowSpec(
226: Sizes.DEFAULT);
227:
228: /**
229: * An unmodifyable <code>RowSpec</code> that has an initial height of 0
230: * pixels and that grows. Useful to describe <em>glue</em> rows that fill
231: * the space between other rows.
232: *
233: * @see #GLUE_COLSPEC
234: */
235: public static final RowSpec GLUE_ROWSPEC = new RowSpec(
236: RowSpec.DEFAULT, Sizes.ZERO, RowSpec.DEFAULT_GROW);
237:
238: // Layout Style Dependent Row Specs *************************************
239:
240: /**
241: * Describes a logical vertzical gap between two related components. For
242: * example the <em>OK</em> and <em>Cancel</em> buttons are considered
243: * related.
244: * <p>
245: *
246: * <strong>Note:</strong> In a future version this constant will likely be
247: * moved to a class <code>LogicalSize</code> or <code>StyledSize</code>.
248: *
249: * @see #UNRELATED_GAP_ROWSPEC
250: */
251: public static final RowSpec RELATED_GAP_ROWSPEC = createGapRowSpec(LayoutStyle
252: .getCurrent().getRelatedComponentsPadY());
253:
254: /**
255: * Describes a logical vertical gap between two unrelated components.
256: * <p>
257: *
258: * <strong>Note:</strong> In a future version this constant will likely be
259: * moved to a class <code>LogicalSize</code> or <code>StyledSize</code>.
260: *
261: * @see #RELATED_GAP_ROWSPEC
262: */
263: public static final RowSpec UNRELATED_GAP_ROWSPEC = createGapRowSpec(LayoutStyle
264: .getCurrent().getUnrelatedComponentsPadY());
265:
266: /**
267: * Describes a logical vertical narrow gap between two rows in the grid.
268: * Useful if the vertical space is scarce or if an individual vertical gap
269: * shall be small than the default line gap.
270: * <p>
271: *
272: * <strong>Note:</strong> In a future version this constant will likely be
273: * moved to a class <code>LogicalSize</code> or <code>StyledSize</code>.
274: *
275: * @see #LINE_GAP_ROWSPEC
276: * @see #PARAGRAPH_GAP_ROWSPEC
277: */
278: public static final RowSpec NARROW_LINE_GAP_ROWSPEC = createGapRowSpec(LayoutStyle
279: .getCurrent().getNarrowLinePad());
280:
281: /**
282: * Describes the logical vertical default gap between two rows in the grid.
283: * A little bit larger than the narrow line gap.
284: * <p>
285: *
286: * <strong>Note:</strong> In a future version this constant will likely be
287: * moved to a class <code>LogicalSize</code> or <code>StyledSize</code>.
288: *
289: * @see #NARROW_LINE_GAP_ROWSPEC
290: * @see #PARAGRAPH_GAP_ROWSPEC
291: */
292: public static final RowSpec LINE_GAP_ROWSPEC = createGapRowSpec(LayoutStyle
293: .getCurrent().getLinePad());
294:
295: /**
296: * Describes the logical vertical default gap between two paragraphs in the
297: * layout grid. This gap is larger than the default line gap.
298: * <p>
299: *
300: * <strong>Note:</strong> In a future version this constant will likely be
301: * moved to a class <code>LogicalSize</code> or <code>StyledSize</code>.
302: *
303: * @see #NARROW_LINE_GAP_ROWSPEC
304: * @see #LINE_GAP_ROWSPEC
305: */
306: public static final RowSpec PARAGRAPH_GAP_ROWSPEC = createGapRowSpec(LayoutStyle
307: .getCurrent().getParagraphPad());
308:
309: // Factory Methods ******************************************************
310:
311: /**
312: * Creates and returns an instance of <code>FormLayout</code> to build
313: * forms with the specified number of major and minor columns.
314: * <p>
315: *
316: * The layout will use default values for all gaps.
317: * <p>
318: *
319: * <strong>This method may be removed from a future version.</strong>
320: *
321: * @param majorColumns
322: * the number of used major columns
323: * @param minorColumns
324: * the number of used minor columns
325: * @param labelColumnSpec
326: * specifies the label columns
327: * @return a prepared <code>FormLayout</code>
328: */
329: public static FormLayout createColumnLayout(int majorColumns,
330: int minorColumns, ColumnSpec labelColumnSpec) {
331: return createColumnLayout(majorColumns, minorColumns,
332: labelColumnSpec, Sizes.DLUX14, Sizes.DLUX2);
333: }
334:
335: /**
336: * Creates and returns an instance of <code>FormLayout</code> to build
337: * forms with the given number of major columns. Major columns consists of a
338: * label and a component section, where each component section is divided
339: * into the given number of minor columns.
340: * <p>
341: *
342: * The layout will use the specified gaps to separate major columns, and the
343: * label and component section.
344: * <p>
345: *
346: * <strong>This method may be removed from a future version.</strong>
347: *
348: * @param majorColumns
349: * the number of major columns
350: * @param minorColumns
351: * the number of minor columns
352: * @param labelColumnSpec
353: * specifies the label columns
354: * @param indent
355: * an optional <code>ConstantSize</code> that describes the
356: * width of the leading indent column
357: * @param minorColumnGap
358: * a <code>ConstantSize</code> that describes the gap between
359: * minor columns
360: * @return a prepared <code>FormLayout</code>
361: */
362: public static FormLayout createColumnLayout(int majorColumns,
363: int minorColumns, ColumnSpec labelColumnSpec,
364: ConstantSize indent, ConstantSize minorColumnGap) {
365: return createColumnLayout(majorColumns, minorColumns,
366: labelColumnSpec, PREF_COLSPEC, indent, Sizes.DLUX14,
367: minorColumnGap);
368: }
369:
370: /**
371: * Creates and returns an instance of <code>FormLayout</code> to build
372: * forms with the given number of major columns. Major columns consists of a
373: * label and a component section, where each component section is divided
374: * into the given number of minor columns.
375: * <p>
376: *
377: * The layout will use the specified gaps to separate major columns, minor
378: * columns, and the label and component section.
379: * <p>
380: *
381: * <strong>This method may be removed from a future version.</strong>
382: *
383: * @param majorColumns
384: * the number of major columns
385: * @param minorColumns
386: * the number of minor columns
387: * @param labelColumnSpec
388: * specifies the label columns
389: * @param componentColumnSpec
390: * specifies the label columns
391: * @param indent
392: * an optional <code>ConstantSize</code> that describes the
393: * width of the leading indent column
394: * @param majorColumnGap
395: * a <code>ConstantSize</code> that describes the gap between
396: * major columns
397: * @param minorColumnGap
398: * a <code>ConstantSize</code> that describes the gap between
399: * minor columns
400: * @return a prepared <code>FormLayout</code>
401: */
402: public static FormLayout createColumnLayout(int majorColumns,
403: int minorColumns, ColumnSpec labelColumnSpec,
404: ColumnSpec componentColumnSpec, ConstantSize indent,
405: ConstantSize majorColumnGap, ConstantSize minorColumnGap) {
406:
407: ColumnSpec majorGapColSpec = createGapColumnSpec(majorColumnGap);
408: ColumnSpec minorGapColSpec = createGapColumnSpec(minorColumnGap);
409: FormLayout layout = new FormLayout(new ColumnSpec[] {},
410: new RowSpec[] {});
411:
412: // Add the optional leading indent.
413: if (indent != null) {
414: layout.appendColumn(createGapColumnSpec(indent));
415: }
416: for (int i = 0; i < majorColumns; i++) {
417: // Add the optional label column with gap.
418: if (labelColumnSpec != null) {
419: layout.appendColumn(labelColumnSpec);
420: layout.appendColumn(RELATED_GAP_COLSPEC);
421: }
422: // Add the minor columns with separating gaps.
423: for (int j = 0; j < minorColumns; j++) {
424: layout.appendColumn(componentColumnSpec);
425: layout.addGroupedColumn(layout.getColumnCount());
426: if (j < minorColumns - 1) {
427: layout.appendColumn(minorGapColSpec);
428: }
429: }
430: // Add a gap between major columns.
431: if (i < majorColumns - 1) {
432: layout.appendColumn(majorGapColSpec);
433: }
434: }
435: return layout;
436: }
437:
438: // Helper Code **********************************************************
439:
440: /**
441: * Creates and returns a {@link ColumnSpec} that represents a gap with the
442: * specified {@link ConstantSize}.
443: *
444: * @param gapSize
445: * a <code>ConstantSize</code> that specifies the gap
446: * @return a <code>ColumnSpec</code> that describes a horizontal gap
447: */
448: public static ColumnSpec createGapColumnSpec(ConstantSize gapSize) {
449: return new ColumnSpec(ColumnSpec.LEFT, gapSize,
450: ColumnSpec.NO_GROW);
451: }
452:
453: /**
454: * Creates and returns a {@link RowSpec} that represents a gap with the
455: * specified {@link ConstantSize}.
456: *
457: * @param gapSize
458: * a <code>ConstantSize</code> that specifies the gap
459: * @return a <code>RowSpec</code> that describes a vertical gap
460: */
461: public static RowSpec createGapRowSpec(ConstantSize gapSize) {
462: return new RowSpec(RowSpec.TOP, gapSize, RowSpec.NO_GROW);
463: }
464:
465: }
|