001/* 002 * Copyright (c) 2002-2007 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 031package com.jgoodies.forms.factories; 032 033import com.jgoodies.forms.layout.ColumnSpec; 034import com.jgoodies.forms.layout.ConstantSize; 035import com.jgoodies.forms.layout.FormLayout; 036import com.jgoodies.forms.layout.FormSpec; 037import com.jgoodies.forms.layout.RowSpec; 038import com.jgoodies.forms.layout.Sizes; 039import com.jgoodies.forms.util.LayoutStyle; 040 041/** 042 * A factory that creates instances of FormLayout for frequently used 043 * form layouts. It makes form creation easier and more consistent. 044 * 045 * <p><strong>I consider removing the <code>FormLayout</code> factory methods. 046 * These seem to be less useful and may lead to poor layout readability. 047 * If you want to use these methods, you may consider copying them 048 * to your codebase.</strong></p> 049 * 050 * <p>The forms are described by major and minor columns. Major columns 051 * consist of a leading label and a set of related components, for example: a 052 * label plus textfield, or label plus textfield plus button. The component 053 * part of a major column is divided into minor columns as shown in this 054 * layout:</p> 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>Many forms use 1, 2, 3 or 4 major columns, which in turn are often split 063 * into 1, 2, 3 or 4 minor columns.</p> 064 * 065 * @author Karsten Lentzsch 066 * @version $Revision$ 067 * 068 * @see com.jgoodies.forms.layout.FormLayout 069 * @see ColumnSpec 070 */ 071public final class FormFactory { 072 073 private FormFactory() { 074 // Suppresses default constructor, ensuring non-instantiability. 075 } 076 077 // Frequently used Column Specifications ******************************** 078 079 /** 080 * An unmodifyable <code>ColumnSpec</code> that determines its width by 081 * computing the maximum of all column component minimum widths. 082 * 083 * @see #PREF_COLSPEC 084 * @see #DEFAULT_COLSPEC 085 */ 086 public static final ColumnSpec MIN_COLSPEC = new ColumnSpec(Sizes.MINIMUM); 087 088 /** 089 * An unmodifyable <code>ColumnSpec</code> that determines its width by 090 * computing the maximum of all column component preferred widths. 091 * 092 * @see #MIN_COLSPEC 093 * @see #DEFAULT_COLSPEC 094 */ 095 public static final ColumnSpec PREF_COLSPEC = new ColumnSpec( 096 Sizes.PREFERRED); 097 098 /** 099 * An unmodifyable <code>ColumnSpec</code> that determines its preferred 100 * width by computing the maximum of all column component preferred widths 101 * and its minimum width by computing all column component minimum widths.<p> 102 * 103 * Useful to let a column shrink from preferred width to minimum width 104 * if 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 114 * of 0 pixels and that grows. Useful to describe <em>glue</em> columns 115 * that 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, FormSpec.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.<p> 128 * 129 * <strong>Note:</strong> In a future version this constant will likely 130 * be moved to a class <code>LogicalSize</code> or <code>StyledSize</code>. 131 * 132 * @since 1.0.3 133 */ 134 public static final ColumnSpec LABEL_COMPONENT_GAP_COLSPEC = createGapColumnSpec( 135 LayoutStyle.getCurrent().getLabelComponentPadX()); 136 137 /** 138 * Describes a logical horizontal gap between two related components. 139 * For example the <em>OK</em> and <em>Cancel</em> buttons are considered 140 * related.<p> 141 * 142 * <strong>Note:</strong> In a future version this constant will likely 143 * be moved to a class <code>LogicalSize</code> or <code>StyledSize</code>. 144 * 145 * @see #UNRELATED_GAP_COLSPEC 146 */ 147 public static final ColumnSpec RELATED_GAP_COLSPEC = createGapColumnSpec( 148 LayoutStyle.getCurrent().getRelatedComponentsPadX()); 149 150 /** 151 * Describes a logical horizontal gap between two unrelated components.<p> 152 * 153 * <strong>Note:</strong> In a future version this constant will likely 154 * be moved to a class <code>LogicalSize</code> or <code>StyledSize</code>. 155 * 156 * @see #RELATED_GAP_COLSPEC 157 */ 158 public static final ColumnSpec UNRELATED_GAP_COLSPEC = createGapColumnSpec( 159 LayoutStyle.getCurrent().getUnrelatedComponentsPadX()); 160 161 /** 162 * Describes a logical horizontal column for a fixed size button. This spec 163 * honors the current layout style's default button minimum width.<p> 164 * 165 * <strong>Note:</strong> In a future version this constant will likely 166 * be moved to a class <code>LogicalSize</code> or <code>StyledSize</code>. 167 * 168 * @see #GROWING_BUTTON_COLSPEC 169 */ 170 public static final ColumnSpec BUTTON_COLSPEC = new ColumnSpec( 171 Sizes.bounded(Sizes.PREFERRED, 172 LayoutStyle.getCurrent().getDefaultButtonWidth(), null)); 173 174 /** 175 * Describes a logical horizontal column for a growing button. This spec 176 * does <em>not</em> use the layout style's default button minimum width.<p> 177 * 178 * <strong>Note:</strong> In a future version this constant will likely 179 * be moved to a class <code>LogicalSize</code> or <code>StyledSize</code>. 180 * 181 * @see #BUTTON_COLSPEC 182 */ 183 public static final ColumnSpec GROWING_BUTTON_COLSPEC = new ColumnSpec( 184 ColumnSpec.DEFAULT, BUTTON_COLSPEC.getSize(), 185 FormSpec.DEFAULT_GROW); 186 187 // Frequently used Row Specifications *********************************** 188 189 /** 190 * An unmodifyable <code>RowSpec</code> that determines its height by 191 * computing the maximum of all column component minimum heights. 192 * 193 * @see #PREF_ROWSPEC 194 * @see #DEFAULT_ROWSPEC 195 */ 196 public static final RowSpec MIN_ROWSPEC = new RowSpec(Sizes.MINIMUM); 197 198 /** 199 * An unmodifyable <code>RowSpec</code> that determines its height by 200 * computing the maximum of all column component preferred heights. 201 * 202 * @see #MIN_ROWSPEC 203 * @see #DEFAULT_ROWSPEC 204 */ 205 public static final RowSpec PREF_ROWSPEC = new RowSpec(Sizes.PREFERRED); 206 207 /** 208 * An unmodifyable <code>RowSpec</code> that determines its preferred 209 * height by computing the maximum of all column component preferred heights 210 * and its minimum height by computing all column component minimum heights.<p> 211 * 212 * Useful to let a column shrink from preferred height to minimum height 213 * if the container space gets scarce. 214 * 215 * @see #MIN_COLSPEC 216 * @see #PREF_COLSPEC 217 */ 218 public static final RowSpec DEFAULT_ROWSPEC = new RowSpec(Sizes.DEFAULT); 219 220 /** 221 * An unmodifyable <code>RowSpec</code> that has an initial height 222 * of 0 pixels and that grows. Useful to describe <em>glue</em> rows 223 * that fill the space between other rows. 224 * 225 * @see #GLUE_COLSPEC 226 */ 227 public static final RowSpec GLUE_ROWSPEC = new RowSpec(RowSpec.DEFAULT, 228 Sizes.ZERO, FormSpec.DEFAULT_GROW); 229 230 // Layout Style Dependent Row Specs ************************************* 231 232 /** 233 * Describes a logical vertical gap between two related components. 234 * For example the <em>OK</em> and <em>Cancel</em> buttons are considered 235 * related.<p> 236 * 237 * <strong>Note:</strong> In a future version this constant will likely 238 * be moved to a class <code>LogicalSize</code> or <code>StyledSize</code>. 239 * 240 * @see #UNRELATED_GAP_ROWSPEC 241 */ 242 public static final RowSpec RELATED_GAP_ROWSPEC = createGapRowSpec( 243 LayoutStyle.getCurrent().getRelatedComponentsPadY()); 244 245 /** 246 * Describes a logical vertical gap between two unrelated components.<p> 247 * 248 * <strong>Note:</strong> In a future version this constant will likely 249 * be moved to a class <code>LogicalSize</code> or <code>StyledSize</code>. 250 * 251 * @see #RELATED_GAP_ROWSPEC 252 */ 253 public static final RowSpec UNRELATED_GAP_ROWSPEC = createGapRowSpec( 254 LayoutStyle.getCurrent().getUnrelatedComponentsPadY()); 255 256 /** 257 * Describes a logical vertical narrow gap between two rows in the grid. 258 * Useful if the vertical space is scarce or if an individual vertical gap 259 * shall be small than the default line gap.<p> 260 * 261 * <strong>Note:</strong> In a future version this constant will likely 262 * be moved to a class <code>LogicalSize</code> or <code>StyledSize</code>. 263 * 264 * @see #LINE_GAP_ROWSPEC 265 * @see #PARAGRAPH_GAP_ROWSPEC 266 */ 267 public static final RowSpec NARROW_LINE_GAP_ROWSPEC = createGapRowSpec( 268 LayoutStyle.getCurrent().getNarrowLinePad()); 269 270 /** 271 * Describes the logical vertical default gap between two rows in the grid. 272 * A little bit larger than the narrow line gap.<p> 273 * 274 * <strong>Note:</strong> In a future version this constant will likely 275 * be moved to a class <code>LogicalSize</code> or <code>StyledSize</code>. 276 * 277 * @see #NARROW_LINE_GAP_ROWSPEC 278 * @see #PARAGRAPH_GAP_ROWSPEC 279 */ 280 public static final RowSpec LINE_GAP_ROWSPEC = createGapRowSpec( 281 LayoutStyle.getCurrent().getLinePad()); 282 283 /** 284 * Describes the logical vertical default gap between two paragraphs in 285 * the layout grid. This gap is larger than the default line gap.<p> 286 * 287 * <strong>Note:</strong> In a future version this constant will likely 288 * be moved to a class <code>LogicalSize</code> or <code>StyledSize</code>. 289 * 290 * @see #NARROW_LINE_GAP_ROWSPEC 291 * @see #LINE_GAP_ROWSPEC 292 */ 293 public static final RowSpec PARAGRAPH_GAP_ROWSPEC = createGapRowSpec( 294 LayoutStyle.getCurrent().getParagraphPad()); 295 296 // Factory Methods ****************************************************** 297 298 /** 299 * Creates and returns an instance of <code>FormLayout</code> 300 * to build forms with the specified number of major and minor columns.<p> 301 * 302 * The layout will use default values for all gaps.<p> 303 * 304 * <strong>This method may be removed from a future version.</strong> 305 * 306 * @param majorColumns the number of used major columns 307 * @param minorColumns the number of used minor columns 308 * @param labelColumnSpec specifies the label columns 309 * @return a prepared <code>FormLayout</code> 310 */ 311 public static FormLayout createColumnLayout(int majorColumns, 312 int minorColumns, ColumnSpec labelColumnSpec) { 313 return createColumnLayout(majorColumns, minorColumns, labelColumnSpec, 314 Sizes.DLUX14, Sizes.DLUX2); 315 } 316 317 /** 318 * Creates and returns an instance of <code>FormLayout</code> 319 * to build forms with the given number of major columns. 320 * Major columns consists of a label and a component section, where each 321 * component section is divided into the given number of minor columns.<p> 322 * 323 * The layout will use the specified gaps to separate major columns, 324 * and the label and component section.<p> 325 * 326 * <strong>This method may be removed from a future version.</strong> 327 * 328 * @param majorColumns the number of major columns 329 * @param minorColumns the number of minor columns 330 * @param labelColumnSpec specifies the label columns 331 * @param indent an optional <code>ConstantSize</code> 332 * that describes the width of the leading indent column 333 * @param minorColumnGap a <code>ConstantSize</code> that describes 334 * the gap between minor columns 335 * @return a prepared <code>FormLayout</code> 336 */ 337 public static FormLayout createColumnLayout(int majorColumns, 338 int minorColumns, ColumnSpec labelColumnSpec, ConstantSize indent, 339 ConstantSize minorColumnGap) { 340 return createColumnLayout(majorColumns, minorColumns, labelColumnSpec, 341 PREF_COLSPEC, indent, Sizes.DLUX14, minorColumnGap); 342 } 343 344 /** 345 * Creates and returns an instance of <code>FormLayout</code> 346 * to build forms with the given number of major columns. 347 * Major columns consists of a label and a component section, where each 348 * component section is divided into the given number of minor columns.<p> 349 * 350 * The layout will use the specified gaps to separate major columns, 351 * minor columns, and the label and component section.<p> 352 * 353 * <strong>This method may be removed from a future version.</strong> 354 * 355 * @param majorColumns the number of major columns 356 * @param minorColumns the number of minor columns 357 * @param labelColumnSpec specifies the label columns 358 * @param componentColumnSpec specifies the label columns 359 * @param indent an optional <code>ConstantSize</code> 360 * that describes the width of the leading indent column 361 * @param majorColumnGap a <code>ConstantSize</code> that describes 362 * the gap between major columns 363 * @param minorColumnGap a <code>ConstantSize</code> that describes 364 * the gap between minor columns 365 * @return a prepared <code>FormLayout</code> 366 */ 367 public static FormLayout createColumnLayout(int majorColumns, 368 int minorColumns, ColumnSpec labelColumnSpec, 369 ColumnSpec componentColumnSpec, ConstantSize indent, 370 ConstantSize majorColumnGap, ConstantSize minorColumnGap) { 371 372 ColumnSpec majorGapColSpec = createGapColumnSpec(majorColumnGap); 373 ColumnSpec minorGapColSpec = createGapColumnSpec(minorColumnGap); 374 FormLayout layout = new FormLayout(new ColumnSpec[] {}, 375 new RowSpec[] {}); 376 377 // Add the optional leading indent. 378 if (indent != null) { 379 layout.appendColumn(createGapColumnSpec(indent)); 380 } 381 for (int i = 0; i < majorColumns; i++) { 382 // Add the optional label column with gap. 383 if (labelColumnSpec != null) { 384 layout.appendColumn(labelColumnSpec); 385 layout.appendColumn(RELATED_GAP_COLSPEC); 386 } 387 // Add the minor columns with separating gaps. 388 for (int j = 0; j < minorColumns; j++) { 389 layout.appendColumn(componentColumnSpec); 390 layout.addGroupedColumn(layout.getColumnCount()); 391 if (j < minorColumns - 1) { 392 layout.appendColumn(minorGapColSpec); 393 } 394 } 395 // Add a gap between major columns. 396 if (i < majorColumns - 1) { 397 layout.appendColumn(majorGapColSpec); 398 } 399 } 400 return layout; 401 } 402 403 // Helper Code ********************************************************** 404 405 /** 406 * Creates and returns a {@link ColumnSpec} that represents a gap with the 407 * specified {@link ConstantSize}. 408 * 409 * @param gapSize a <code>ConstantSize</code> that specifies the gap 410 * @return a <code>ColumnSpec</code> that describes a horizontal gap 411 */ 412 public static ColumnSpec createGapColumnSpec(ConstantSize gapSize) { 413 return new ColumnSpec(ColumnSpec.LEFT, gapSize, FormSpec.NO_GROW); 414 } 415 416 /** 417 * Creates and returns a {@link RowSpec} that represents a gap with the 418 * specified {@link ConstantSize}. 419 * 420 * @param gapSize a <code>ConstantSize</code> that specifies the gap 421 * @return a <code>RowSpec</code> that describes a vertical gap 422 */ 423 public static RowSpec createGapRowSpec(ConstantSize gapSize) { 424 return new RowSpec(RowSpec.TOP, gapSize, FormSpec.NO_GROW); 425 } 426 427}