Coverage Report - org.dishevelled.layout.LabelFieldLayout
 
Classes in this File Line Coverage Branch Coverage Complexity
LabelFieldLayout
100%
145/145
100%
22/22
1.857
LabelFieldLayout$Constraints
100%
1/1
N/A
1.857
 
 1  
 /*
 2  
 
 3  
     dsh-layout  Layout managers for lightweight components.
 4  
     Copyright (c) 2003-2012 held jointly by the individual authors.
 5  
 
 6  
     This library is free software; you can redistribute it and/or modify it
 7  
     under the terms of the GNU Lesser General Public License as published
 8  
     by the Free Software Foundation; either version 3 of the License, or (at
 9  
     your option) any later version.
 10  
 
 11  
     This library is distributed in the hope that it will be useful, but WITHOUT
 12  
     ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
 13  
     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 14  
     License for more details.
 15  
 
 16  
     You should have received a copy of the GNU Lesser General Public License
 17  
     along with this library;  if not, write to the Free Software Foundation,
 18  
     Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA.
 19  
 
 20  
     > http://www.fsf.org/licensing/licenses/lgpl.html
 21  
     > http://www.opensource.org/licenses/lgpl-license.php
 22  
 
 23  
 */
 24  
 package org.dishevelled.layout;
 25  
 
 26  
 import java.awt.Insets;
 27  
 import java.awt.GridBagLayout;
 28  
 import java.awt.GridBagConstraints;
 29  
 
 30  
 /**
 31  
  * A wrapper around GridBagLayout that simplifies things
 32  
  * for the common case of two columns, one of labels and
 33  
  * one of fields.
 34  
  *
 35  
  * <p>A simple example:
 36  
  * <pre>
 37  
  * JPanel panel = new JPanel();
 38  
  * LabelFieldLayout l = new LabelFieldLayout();
 39  
  * panel.setLayout(l);
 40  
  *
 41  
  * panel.add(new JLabel("Label label:"), l.labelLabel());
 42  
  * panel.add(new JLabel("Label field"), l.labelField());
 43  
  *
 44  
  * l.nextLine();
 45  
  * panel.add(new JLabel("Normal label:"), l.normalLabel());
 46  
  * panel.add(new JTextField("Normal field"), l.normalField());
 47  
  *
 48  
  * l.nextLine();
 49  
  * panel.add(Box.createVerticalStrut(12), l.spacing());
 50  
  *
 51  
  * l.nextLine();
 52  
  * panel.add(new JLabel("Wide label:"), l.wideLabel());
 53  
  *
 54  
  * l.nextLine();
 55  
  * JList list = new JList(new Object[] { "Final wide field A",
 56  
  *                                       "Final wide field B",
 57  
  *                                       "Final wide field C" });
 58  
  * panel.add(new JScrollPane(list), l.finalWideField());
 59  
  * </pre></p>
 60  
  *
 61  
  * <p>The labels are aligned in the left column and the fields are
 62  
  * aligned in the right column, except for a wide label or field
 63  
  * which stretches vertically across both columns (<code>wideLabel()</code>
 64  
  * or <code>wideField()</code>).  Rows containing fields that
 65  
  * are JLabels (<code>labelLabel()</code> and <code>labelField()</code>)
 66  
  * have less of a vertical gap than those containing other components
 67  
  * (<code>normalLabel()</code> and <code>normalField()</code>).</p>
 68  
  *
 69  
  * <p>The final line in a LabelFieldLayout is the one which stretches
 70  
  * vertically to cover space left at the bottom of a container.  Use a
 71  
  * final wide label
 72  
  * <pre>
 73  
  * panel.add(new JLabel("Final wide label", l.finalWideLabel()));
 74  
  * </pre>
 75  
  *
 76  
  * a final wide field
 77  
  * <pre>
 78  
  * JList list = new JList(new Object[] {"Final wide field A",
 79  
  *                                      "Final wide field B",
 80  
  *                                      "Final wide field C" });
 81  
  * panel.add(new JScrollPane(list), l.finalWideField());
 82  
  * </pre>
 83  
  *
 84  
  * or final spacing
 85  
  * <pre>
 86  
  * panel.add(Box.createGlue(), l.finalSpacing());
 87  
  * </pre>
 88  
  *
 89  
  * to allow the layout to adapt gracefully to container resize events.</p>
 90  
  *
 91  
  * <p>The width of the label and field columns can be specified using
 92  
  * the constructor <code>LabelFieldLayout(float, float)</code> or the
 93  
  * property setters <code>setLabelPercent(float)</code> and
 94  
  * <code>setFieldPercent(float)</code>.  The default configuration is
 95  
  * to split on thirds, with 33% of the container width for labels and 66%
 96  
  * for fields.</p>
 97  
  *
 98  
  * @author  Michael Heuer
 99  
  * @version $Revision: 1059 $ $Date: 2012-01-03 14:03:02 -0600 (Tue, 03 Jan 2012) $
 100  
  */
 101  
 public final class LabelFieldLayout
 102  
     extends GridBagLayout
 103  
 {
 104  
     /** Default inset size. */
 105  
     private static final int DEFAULT_INSET_SIZE = 6;
 106  
 
 107  
     /** Mac inset size. */
 108  
     private static final int MAC_INSET_SIZE = 8;
 109  
 
 110  
     /** Default label width, <code>33%</code>. */
 111  
     static final float DEFAULT_LABEL_WIDTH = 0.33f;
 112  
 
 113  
     /** Default field width, <code>66%</code>. */
 114  
     static final float DEFAULT_FIELD_WIDTH = 0.66f;
 115  
 
 116  
     /** Empty insets. */
 117  1
     private static final Insets EMPTY_INSETS = new Insets(0, 0, 0, 0);
 118  
 
 119  
     /** Mac empty insets. */
 120  1
     private static final Insets MAC_EMPTY_INSETS = new Insets(0, 0, 0, MAC_INSET_SIZE);
 121  
 
 122  
     /** Label insets. */
 123  1
     private static final Insets LABEL_INSETS = new Insets(0, 0, DEFAULT_INSET_SIZE, 0);
 124  
 
 125  
     /** Mac label insets. */
 126  1
     private static final Insets MAC_LABEL_INSETS = new Insets(0, 0, DEFAULT_INSET_SIZE, MAC_INSET_SIZE);
 127  
 
 128  
     /** Field insets. */
 129  1
     private static final Insets FIELD_INSETS = new Insets(0, 0, DEFAULT_INSET_SIZE, 0);
 130  
 
 131  
     /** Private constraints. */
 132  19
     private Constraints c = new Constraints();
 133  
 
 134  
     /** Percent of container width to use for labels. */
 135  
     private float labelPercent;
 136  
 
 137  
     /** Percent of container width to use for fields. */
 138  
     private float fieldPercent;
 139  
 
 140  
 
 141  
     /**
 142  
      * Create a new LabelFieldLayout in the default configuration,
 143  
      * split on thirds, with 33% of the container width for labels and 66%
 144  
      * for fields.
 145  
      */
 146  
     public LabelFieldLayout()
 147  
     {
 148  8
         this(DEFAULT_LABEL_WIDTH, DEFAULT_FIELD_WIDTH);
 149  8
     }
 150  
 
 151  
     /**
 152  
      * Create a new LabelFieldLayout with the specified percentages
 153  
      * of the container width to use for labels and fields respectively.
 154  
      * The sum of the label and field percentages must be less than or
 155  
      * equal to <code>1.0f</code>.
 156  
      *
 157  
      * @param labelPercent the percentage of the container width
 158  
      *    to use for labels, must be <code>&gt;= 0.0f</code>
 159  
      *   and <code>&lt;= 1.0f</code>
 160  
      * @param fieldPercent the percentage of the container width
 161  
      *    to use for fields, must be <code>&gt;= 0.0f</code>
 162  
      *   and <code>&lt;= 1.0f</code>
 163  
      */
 164  
     public LabelFieldLayout(final float labelPercent,
 165  
                             final float fieldPercent)
 166  
     {
 167  19
         super();
 168  
 
 169  19
         if ((labelPercent < 0.0f) || (labelPercent > 1.0f))
 170  
         {
 171  3
             throw new IllegalArgumentException("labelPercent must be >= 0.0f and <= 1.0f");
 172  
         }
 173  16
         if ((fieldPercent < 0.0f) || (fieldPercent > 1.0f))
 174  
         {
 175  2
             throw new IllegalArgumentException("fieldPercent must be >= 0.0f and <= 1.0f");
 176  
         }
 177  14
         if ((labelPercent + fieldPercent) > 1.0f)
 178  
         {
 179  1
             throw new IllegalArgumentException("the sum of labelPercent and fieldPercent must be <= 1.0f");
 180  
         }
 181  
 
 182  13
         c.gridy = 0;
 183  13
         this.labelPercent = labelPercent;
 184  13
         this.fieldPercent = fieldPercent;
 185  13
     }
 186  
 
 187  
 
 188  
     /**
 189  
      * Increment the layout cursor to the next line.  Returns
 190  
      * this instance of LabelFieldLayout, for use in chaining
 191  
      * calls.
 192  
      *
 193  
      * @return this instance of LabelFieldLayout, for use
 194  
      *    in chaining method calls
 195  
      */
 196  
     public LabelFieldLayout nextLine()
 197  
     {
 198  14
         c.gridy++;
 199  14
         return this;
 200  
     }
 201  
 
 202  
     /**
 203  
      * Set the percentage of the container width to
 204  
      * use for labels to <code>labelPercent</code>. The
 205  
      * sum of the label and field percentages must be less
 206  
      * than <code>1.0f</code>.
 207  
      *
 208  
      * @param labelPercent the percentage of the container
 209  
      *    width to use for labels, must be <code>&gt;= 0.0f</code>
 210  
      *   and <code>&lt;= 1.0f</code>
 211  
      */
 212  
     public void setLabelPercent(final float labelPercent)
 213  
     {
 214  7
         if ((labelPercent < 0.0f) || (labelPercent > 1.0f))
 215  
         {
 216  4
             throw new IllegalArgumentException("labelPercent must be >= 0.0f and <= 1.0f");
 217  
         }
 218  3
         if ((labelPercent + fieldPercent) > 1.0f)
 219  
         {
 220  1
             throw new IllegalArgumentException("the sum of labelPercent and fieldPercent must be <= 1.0f");
 221  
         }
 222  
 
 223  2
         this.labelPercent = labelPercent;
 224  2
     }
 225  
 
 226  
     /**
 227  
      * Return the percentage of the container width to
 228  
      * use for labels.
 229  
      *
 230  
      * @return the percentage of the container width
 231  
      *    to use for labels
 232  
      */
 233  
     public float getLabelPercent()
 234  
     {
 235  3
         return labelPercent;
 236  
     }
 237  
 
 238  
     /**
 239  
      * Set the percentage of the container width to use
 240  
      * for fields to <code>fieldPercent</code>.  The sum of
 241  
      * the label and field percentages must be less than or
 242  
      * equal to <code>1.0f</code>.
 243  
      *
 244  
      * @param fieldPercent the percentage of the container
 245  
      *    width to use for fields, must be <code>&gt;= 0.0f</code>
 246  
      *   and <code>&lt;= 1.0f</code>
 247  
      */
 248  
     public void setFieldPercent(final float fieldPercent)
 249  
     {
 250  6
         if ((fieldPercent < 0.0f) || (fieldPercent > 1.0f))
 251  
         {
 252  4
             throw new IllegalArgumentException("fieldPercent must be >= 0.0f and <= 1.0f");
 253  
         }
 254  2
         if ((labelPercent + fieldPercent) > 1.0f)
 255  
         {
 256  1
             throw new IllegalArgumentException("the sum of labelPercent and fieldPercent must be <= 1.0f");
 257  
         }
 258  
 
 259  1
         this.fieldPercent = fieldPercent;
 260  1
     }
 261  
 
 262  
     /**
 263  
      * Return the percentage of the container width to
 264  
      * use for fields.
 265  
      *
 266  
      * @return the percentage of the container width
 267  
      *    to use for fields
 268  
      */
 269  
     public float getFieldPercent()
 270  
     {
 271  3
         return fieldPercent;
 272  
     }
 273  
 
 274  
     /**
 275  
      * Return constraints suitable for a label.
 276  
      *
 277  
      * @see #normalLabel
 278  
      * @return constraints suitable for a label.
 279  
      */
 280  
     public Constraints label()
 281  
     {
 282  1
         return normalLabel();
 283  
     }
 284  
 
 285  
     /**
 286  
      * Return constraints suitable for a normal label, a label
 287  
      * for a field that is not a JLabel.
 288  
      *
 289  
      * @return constraints suitable for a normal label
 290  
      */
 291  
     public Constraints normalLabel()
 292  
     {
 293  2
         c.anchor = GridBagConstraints.WEST;
 294  2
         c.fill = GridBagConstraints.HORIZONTAL;
 295  2
         c.gridheight = 1;
 296  2
         c.gridwidth = GridBagConstraints.RELATIVE;
 297  2
         c.insets = LABEL_INSETS;
 298  
 
 299  2
         c.gridx = 0;
 300  2
         c.weighty = 0;
 301  2
         c.weightx = labelPercent;
 302  
 
 303  2
         return c;
 304  
     }
 305  
 
 306  
     /**
 307  
      * Return constraints suitable for a mac label, a label
 308  
      * for a field that is not a JLabel.
 309  
      *
 310  
      * @return constraints suitable for a mac label
 311  
      */
 312  
     Constraints macLabel()
 313  
     {
 314  3
         c.anchor = GridBagConstraints.WEST;
 315  3
         c.fill = GridBagConstraints.HORIZONTAL;
 316  3
         c.gridheight = 1;
 317  3
         c.gridwidth = GridBagConstraints.RELATIVE;
 318  3
         c.insets = MAC_LABEL_INSETS;
 319  
 
 320  3
         c.gridx = 0;
 321  3
         c.weighty = 0;
 322  3
         c.weightx = labelPercent;
 323  
 
 324  3
         return c;
 325  
     }
 326  
 
 327  
     /**
 328  
      * Return constraints suitable for a label label, a label
 329  
      * for a field that is a JLabel.
 330  
      *
 331  
      * @return constraints suitable for a label label
 332  
      */
 333  
     public Constraints labelLabel()
 334  
     {
 335  1
         c.anchor = GridBagConstraints.WEST;
 336  1
         c.fill = GridBagConstraints.HORIZONTAL;
 337  1
         c.gridheight = 1;
 338  1
         c.gridwidth = GridBagConstraints.RELATIVE;
 339  1
         c.insets = EMPTY_INSETS;
 340  
 
 341  1
         c.gridx = 0;
 342  1
         c.weighty = 0;
 343  1
         c.weightx = labelPercent;
 344  
 
 345  1
         return c;
 346  
     }
 347  
 
 348  
     /**
 349  
      * Return constraints suitable for a mac label label, a label
 350  
      * for a field that is a JLabel.
 351  
      *
 352  
      * @return constraints suitable for a mac label label
 353  
      */
 354  
     Constraints macLabelLabel()
 355  
     {
 356  3
         c.anchor = GridBagConstraints.WEST;
 357  3
         c.fill = GridBagConstraints.HORIZONTAL;
 358  3
         c.gridheight = 1;
 359  3
         c.gridwidth = GridBagConstraints.RELATIVE;
 360  3
         c.insets = MAC_EMPTY_INSETS;
 361  
 
 362  3
         c.gridx = 0;
 363  3
         c.weighty = 0;
 364  3
         c.weightx = labelPercent;
 365  
 
 366  3
         return c;
 367  
     }
 368  
 
 369  
     /**
 370  
      * Return constraints suitable for a wide label, a label
 371  
      * that stretches horizontally across both the label and field
 372  
      * columns.
 373  
      *
 374  
      * @return constraints suitable for a wide label
 375  
      */
 376  
     public Constraints wideLabel()
 377  
     {
 378  4
         c.anchor = GridBagConstraints.WEST;
 379  4
         c.fill = GridBagConstraints.HORIZONTAL;
 380  4
         c.gridheight = 1;
 381  4
         c.gridwidth = GridBagConstraints.REMAINDER;
 382  4
         c.insets = EMPTY_INSETS;
 383  
 
 384  4
         c.gridx = 0;
 385  4
         c.weighty = 0;
 386  4
         c.weightx = 1.0f;
 387  
 
 388  4
         return c;
 389  
     }
 390  
 
 391  
     /**
 392  
      * Return constraints suitable for a final wide label, a label
 393  
      * that stretches horizontally across both the label and field
 394  
      * columns and stretches vertically to cover space left at the
 395  
      * bottom of a container.
 396  
      *
 397  
      * @return constraints suitable for a final wide label
 398  
      */
 399  
     public Constraints finalWideLabel()
 400  
     {
 401  1
         c.anchor = GridBagConstraints.NORTHWEST;
 402  1
         c.fill = GridBagConstraints.HORIZONTAL;
 403  1
         c.gridheight = 1;
 404  1
         c.gridwidth = GridBagConstraints.REMAINDER;
 405  1
         c.insets = EMPTY_INSETS;
 406  
 
 407  1
         c.gridx = 0;
 408  1
         c.weighty = 1.0f;
 409  1
         c.weightx = 1.0f;
 410  
 
 411  1
         return c;
 412  
     }
 413  
 
 414  
     /**
 415  
      * Return constraints suitable for a field.
 416  
      *
 417  
      * @see #normalField
 418  
      * @return constraints suitable for a field
 419  
      */
 420  
     public Constraints field()
 421  
     {
 422  4
         return normalField();
 423  
     }
 424  
 
 425  
     /**
 426  
      * Return constraints suitable for a normal field, a field
 427  
      * that is not a JLabel.
 428  
      *
 429  
      * @return constraints suitable for a normal field
 430  
      */
 431  
     public Constraints normalField()
 432  
     {
 433  5
         c.anchor = GridBagConstraints.WEST;
 434  5
         c.fill = GridBagConstraints.HORIZONTAL;
 435  5
         c.gridheight = 1;
 436  5
         c.gridwidth = GridBagConstraints.RELATIVE;
 437  5
         c.insets = FIELD_INSETS;
 438  
 
 439  5
         c.gridx = 1;
 440  5
         c.weighty = 0;
 441  5
         c.weightx = fieldPercent;
 442  
 
 443  5
         return c;
 444  
     }
 445  
 
 446  
     /**
 447  
      * Return constraints suitable for a label field, a field
 448  
      * that is a JLabel.
 449  
      *
 450  
      * @return constraints suitable for a label field
 451  
      */
 452  
     public Constraints labelField()
 453  
     {
 454  4
         c.anchor = GridBagConstraints.WEST;
 455  4
         c.fill = GridBagConstraints.HORIZONTAL;
 456  4
         c.gridheight = 1;
 457  4
         c.gridwidth = GridBagConstraints.RELATIVE;
 458  4
         c.insets = EMPTY_INSETS;
 459  
 
 460  4
         c.gridx = 1;
 461  4
         c.weighty = 0;
 462  4
         c.weightx = fieldPercent;
 463  
 
 464  4
         return c;
 465  
     }
 466  
 
 467  
     /**
 468  
      * Return constraints suitable for a wide field, a field
 469  
      * that stretches horizontally across both the label and field
 470  
      * columns.
 471  
      *
 472  
      * @return constraints suitable for a wide field
 473  
      */
 474  
     public Constraints wideField()
 475  
     {
 476  2
         c.anchor = GridBagConstraints.WEST;
 477  2
         c.fill = GridBagConstraints.HORIZONTAL;
 478  2
         c.gridheight = 1;
 479  2
         c.gridwidth = GridBagConstraints.REMAINDER;
 480  2
         c.insets = FIELD_INSETS;
 481  
 
 482  2
         c.gridx = 0;
 483  2
         c.weighty = 0;
 484  2
         c.weightx = 1.0f;
 485  
 
 486  2
         return c;
 487  
     }
 488  
 
 489  
     /**
 490  
      * Return constraints suitable for a final wide field, a field
 491  
      * that stretches horizontally across both the label and field
 492  
      * columns and stretches vertically to cover space left at the
 493  
      * bottom of a container.
 494  
      *
 495  
      * @return constraints suitable for a final wide field
 496  
      */
 497  
     public Constraints finalWideField()
 498  
     {
 499  2
         c.anchor = GridBagConstraints.NORTHWEST;
 500  2
         c.fill = GridBagConstraints.BOTH;
 501  2
         c.gridheight = 1;
 502  2
         c.gridwidth = GridBagConstraints.REMAINDER;
 503  2
         c.insets = EMPTY_INSETS;
 504  
 
 505  2
         c.gridx = 0;
 506  2
         c.weighty = 1.0f;
 507  2
         c.weightx = 1.0f;
 508  
 
 509  2
         return c;
 510  
     }
 511  
 
 512  
     /**
 513  
      * Return constraints suitable for spacing.
 514  
      *
 515  
      * @return constraints suitable for spacing
 516  
      */
 517  
     public Constraints spacing()
 518  
     {
 519  3
         c.anchor = GridBagConstraints.WEST;
 520  3
         c.fill = GridBagConstraints.HORIZONTAL;
 521  3
         c.gridheight = 1;
 522  3
         c.gridwidth = GridBagConstraints.REMAINDER;
 523  3
         c.insets = EMPTY_INSETS;
 524  
 
 525  3
         c.gridx = 0;
 526  3
         c.weighty = 0;
 527  3
         c.weightx = 1.0f;
 528  
 
 529  3
         return c;
 530  
     }
 531  
 
 532  
     /**
 533  
      * Return constraints suitable for spacing that stretches
 534  
      * vertically to cover space left at the bottom of a container.
 535  
      *
 536  
      * @return constraints suitable for spacing that stretches
 537  
      *    vertically to cover space left at the bottom of a container
 538  
      */
 539  
     public Constraints finalSpacing()
 540  
     {
 541  4
         c.anchor = GridBagConstraints.NORTHWEST;
 542  4
         c.fill = GridBagConstraints.BOTH;
 543  4
         c.gridheight = 1;
 544  4
         c.gridwidth = GridBagConstraints.REMAINDER;
 545  4
         c.insets = EMPTY_INSETS;
 546  
 
 547  4
         c.gridx = 0;
 548  4
         c.weighty = 1.0f;
 549  4
         c.weightx = 1.0f;
 550  
 
 551  4
         return c;
 552  
     }
 553  
 
 554  
    /**
 555  
     * Constraints class that extends GridBagConstraints for
 556  
     * the single purpose of having the classname
 557  
     * <code>LabelFieldLayout.Constraints</code>.
 558  
     */
 559  19
     public static final class Constraints
 560  
         extends GridBagConstraints
 561  
     {
 562  
         // empty
 563  
     }
 564  
 }