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-2013 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  
  */
 100  
 public final class LabelFieldLayout
 101  
     extends GridBagLayout
 102  
 {
 103  
     /** Default inset size. */
 104  
     private static final int DEFAULT_INSET_SIZE = 6;
 105  
 
 106  
     /** Mac inset size. */
 107  
     private static final int MAC_INSET_SIZE = 8;
 108  
 
 109  
     /** Default label width, <code>33%</code>. */
 110  
     static final float DEFAULT_LABEL_WIDTH = 0.33f;
 111  
 
 112  
     /** Default field width, <code>66%</code>. */
 113  
     static final float DEFAULT_FIELD_WIDTH = 0.66f;
 114  
 
 115  
     /** Empty insets. */
 116  1
     private static final Insets EMPTY_INSETS = new Insets(0, 0, 0, 0);
 117  
 
 118  
     /** Mac empty insets. */
 119  1
     private static final Insets MAC_EMPTY_INSETS = new Insets(0, 0, 0, MAC_INSET_SIZE);
 120  
 
 121  
     /** Label insets. */
 122  1
     private static final Insets LABEL_INSETS = new Insets(0, 0, DEFAULT_INSET_SIZE, 0);
 123  
 
 124  
     /** Mac label insets. */
 125  1
     private static final Insets MAC_LABEL_INSETS = new Insets(0, 0, DEFAULT_INSET_SIZE, MAC_INSET_SIZE);
 126  
 
 127  
     /** Field insets. */
 128  1
     private static final Insets FIELD_INSETS = new Insets(0, 0, DEFAULT_INSET_SIZE, 0);
 129  
 
 130  
     /** Private constraints. */
 131  19
     private Constraints c = new Constraints();
 132  
 
 133  
     /** Percent of container width to use for labels. */
 134  
     private float labelPercent;
 135  
 
 136  
     /** Percent of container width to use for fields. */
 137  
     private float fieldPercent;
 138  
 
 139  
 
 140  
     /**
 141  
      * Create a new LabelFieldLayout in the default configuration,
 142  
      * split on thirds, with 33% of the container width for labels and 66%
 143  
      * for fields.
 144  
      */
 145  
     public LabelFieldLayout()
 146  
     {
 147  8
         this(DEFAULT_LABEL_WIDTH, DEFAULT_FIELD_WIDTH);
 148  8
     }
 149  
 
 150  
     /**
 151  
      * Create a new LabelFieldLayout with the specified percentages
 152  
      * of the container width to use for labels and fields respectively.
 153  
      * The sum of the label and field percentages must be less than or
 154  
      * equal to <code>1.0f</code>.
 155  
      *
 156  
      * @param labelPercent the percentage of the container width
 157  
      *    to use for labels, must be <code>&gt;= 0.0f</code>
 158  
      *   and <code>&lt;= 1.0f</code>
 159  
      * @param fieldPercent the percentage of the container width
 160  
      *    to use for fields, must be <code>&gt;= 0.0f</code>
 161  
      *   and <code>&lt;= 1.0f</code>
 162  
      */
 163  
     public LabelFieldLayout(final float labelPercent,
 164  
                             final float fieldPercent)
 165  
     {
 166  19
         super();
 167  
 
 168  19
         if ((labelPercent < 0.0f) || (labelPercent > 1.0f))
 169  
         {
 170  3
             throw new IllegalArgumentException("labelPercent must be >= 0.0f and <= 1.0f");
 171  
         }
 172  16
         if ((fieldPercent < 0.0f) || (fieldPercent > 1.0f))
 173  
         {
 174  2
             throw new IllegalArgumentException("fieldPercent must be >= 0.0f and <= 1.0f");
 175  
         }
 176  14
         if ((labelPercent + fieldPercent) > 1.0f)
 177  
         {
 178  1
             throw new IllegalArgumentException("the sum of labelPercent and fieldPercent must be <= 1.0f");
 179  
         }
 180  
 
 181  13
         c.gridy = 0;
 182  13
         this.labelPercent = labelPercent;
 183  13
         this.fieldPercent = fieldPercent;
 184  13
     }
 185  
 
 186  
 
 187  
     /**
 188  
      * Increment the layout cursor to the next line.  Returns
 189  
      * this instance of LabelFieldLayout, for use in chaining
 190  
      * calls.
 191  
      *
 192  
      * @return this instance of LabelFieldLayout, for use
 193  
      *    in chaining method calls
 194  
      */
 195  
     public LabelFieldLayout nextLine()
 196  
     {
 197  14
         c.gridy++;
 198  14
         return this;
 199  
     }
 200  
 
 201  
     /**
 202  
      * Set the percentage of the container width to
 203  
      * use for labels to <code>labelPercent</code>. The
 204  
      * sum of the label and field percentages must be less
 205  
      * than <code>1.0f</code>.
 206  
      *
 207  
      * @param labelPercent the percentage of the container
 208  
      *    width to use for labels, must be <code>&gt;= 0.0f</code>
 209  
      *   and <code>&lt;= 1.0f</code>
 210  
      */
 211  
     public void setLabelPercent(final float labelPercent)
 212  
     {
 213  7
         if ((labelPercent < 0.0f) || (labelPercent > 1.0f))
 214  
         {
 215  4
             throw new IllegalArgumentException("labelPercent must be >= 0.0f and <= 1.0f");
 216  
         }
 217  3
         if ((labelPercent + fieldPercent) > 1.0f)
 218  
         {
 219  1
             throw new IllegalArgumentException("the sum of labelPercent and fieldPercent must be <= 1.0f");
 220  
         }
 221  
 
 222  2
         this.labelPercent = labelPercent;
 223  2
     }
 224  
 
 225  
     /**
 226  
      * Return the percentage of the container width to
 227  
      * use for labels.
 228  
      *
 229  
      * @return the percentage of the container width
 230  
      *    to use for labels
 231  
      */
 232  
     public float getLabelPercent()
 233  
     {
 234  3
         return labelPercent;
 235  
     }
 236  
 
 237  
     /**
 238  
      * Set the percentage of the container width to use
 239  
      * for fields to <code>fieldPercent</code>.  The sum of
 240  
      * the label and field percentages must be less than or
 241  
      * equal to <code>1.0f</code>.
 242  
      *
 243  
      * @param fieldPercent the percentage of the container
 244  
      *    width to use for fields, must be <code>&gt;= 0.0f</code>
 245  
      *   and <code>&lt;= 1.0f</code>
 246  
      */
 247  
     public void setFieldPercent(final float fieldPercent)
 248  
     {
 249  6
         if ((fieldPercent < 0.0f) || (fieldPercent > 1.0f))
 250  
         {
 251  4
             throw new IllegalArgumentException("fieldPercent must be >= 0.0f and <= 1.0f");
 252  
         }
 253  2
         if ((labelPercent + fieldPercent) > 1.0f)
 254  
         {
 255  1
             throw new IllegalArgumentException("the sum of labelPercent and fieldPercent must be <= 1.0f");
 256  
         }
 257  
 
 258  1
         this.fieldPercent = fieldPercent;
 259  1
     }
 260  
 
 261  
     /**
 262  
      * Return the percentage of the container width to
 263  
      * use for fields.
 264  
      *
 265  
      * @return the percentage of the container width
 266  
      *    to use for fields
 267  
      */
 268  
     public float getFieldPercent()
 269  
     {
 270  3
         return fieldPercent;
 271  
     }
 272  
 
 273  
     /**
 274  
      * Return constraints suitable for a label.
 275  
      *
 276  
      * @see #normalLabel
 277  
      * @return constraints suitable for a label.
 278  
      */
 279  
     public Constraints label()
 280  
     {
 281  1
         return normalLabel();
 282  
     }
 283  
 
 284  
     /**
 285  
      * Return constraints suitable for a normal label, a label
 286  
      * for a field that is not a JLabel.
 287  
      *
 288  
      * @return constraints suitable for a normal label
 289  
      */
 290  
     public Constraints normalLabel()
 291  
     {
 292  2
         c.anchor = GridBagConstraints.WEST;
 293  2
         c.fill = GridBagConstraints.HORIZONTAL;
 294  2
         c.gridheight = 1;
 295  2
         c.gridwidth = GridBagConstraints.RELATIVE;
 296  2
         c.insets = LABEL_INSETS;
 297  
 
 298  2
         c.gridx = 0;
 299  2
         c.weighty = 0;
 300  2
         c.weightx = labelPercent;
 301  
 
 302  2
         return c;
 303  
     }
 304  
 
 305  
     /**
 306  
      * Return constraints suitable for a mac label, a label
 307  
      * for a field that is not a JLabel.
 308  
      *
 309  
      * @return constraints suitable for a mac label
 310  
      */
 311  
     Constraints macLabel()
 312  
     {
 313  3
         c.anchor = GridBagConstraints.WEST;
 314  3
         c.fill = GridBagConstraints.HORIZONTAL;
 315  3
         c.gridheight = 1;
 316  3
         c.gridwidth = GridBagConstraints.RELATIVE;
 317  3
         c.insets = MAC_LABEL_INSETS;
 318  
 
 319  3
         c.gridx = 0;
 320  3
         c.weighty = 0;
 321  3
         c.weightx = labelPercent;
 322  
 
 323  3
         return c;
 324  
     }
 325  
 
 326  
     /**
 327  
      * Return constraints suitable for a label label, a label
 328  
      * for a field that is a JLabel.
 329  
      *
 330  
      * @return constraints suitable for a label label
 331  
      */
 332  
     public Constraints labelLabel()
 333  
     {
 334  1
         c.anchor = GridBagConstraints.WEST;
 335  1
         c.fill = GridBagConstraints.HORIZONTAL;
 336  1
         c.gridheight = 1;
 337  1
         c.gridwidth = GridBagConstraints.RELATIVE;
 338  1
         c.insets = EMPTY_INSETS;
 339  
 
 340  1
         c.gridx = 0;
 341  1
         c.weighty = 0;
 342  1
         c.weightx = labelPercent;
 343  
 
 344  1
         return c;
 345  
     }
 346  
 
 347  
     /**
 348  
      * Return constraints suitable for a mac label label, a label
 349  
      * for a field that is a JLabel.
 350  
      *
 351  
      * @return constraints suitable for a mac label label
 352  
      */
 353  
     Constraints macLabelLabel()
 354  
     {
 355  3
         c.anchor = GridBagConstraints.WEST;
 356  3
         c.fill = GridBagConstraints.HORIZONTAL;
 357  3
         c.gridheight = 1;
 358  3
         c.gridwidth = GridBagConstraints.RELATIVE;
 359  3
         c.insets = MAC_EMPTY_INSETS;
 360  
 
 361  3
         c.gridx = 0;
 362  3
         c.weighty = 0;
 363  3
         c.weightx = labelPercent;
 364  
 
 365  3
         return c;
 366  
     }
 367  
 
 368  
     /**
 369  
      * Return constraints suitable for a wide label, a label
 370  
      * that stretches horizontally across both the label and field
 371  
      * columns.
 372  
      *
 373  
      * @return constraints suitable for a wide label
 374  
      */
 375  
     public Constraints wideLabel()
 376  
     {
 377  4
         c.anchor = GridBagConstraints.WEST;
 378  4
         c.fill = GridBagConstraints.HORIZONTAL;
 379  4
         c.gridheight = 1;
 380  4
         c.gridwidth = GridBagConstraints.REMAINDER;
 381  4
         c.insets = EMPTY_INSETS;
 382  
 
 383  4
         c.gridx = 0;
 384  4
         c.weighty = 0;
 385  4
         c.weightx = 1.0f;
 386  
 
 387  4
         return c;
 388  
     }
 389  
 
 390  
     /**
 391  
      * Return constraints suitable for a final wide label, a label
 392  
      * that stretches horizontally across both the label and field
 393  
      * columns and stretches vertically to cover space left at the
 394  
      * bottom of a container.
 395  
      *
 396  
      * @return constraints suitable for a final wide label
 397  
      */
 398  
     public Constraints finalWideLabel()
 399  
     {
 400  1
         c.anchor = GridBagConstraints.NORTHWEST;
 401  1
         c.fill = GridBagConstraints.HORIZONTAL;
 402  1
         c.gridheight = 1;
 403  1
         c.gridwidth = GridBagConstraints.REMAINDER;
 404  1
         c.insets = EMPTY_INSETS;
 405  
 
 406  1
         c.gridx = 0;
 407  1
         c.weighty = 1.0f;
 408  1
         c.weightx = 1.0f;
 409  
 
 410  1
         return c;
 411  
     }
 412  
 
 413  
     /**
 414  
      * Return constraints suitable for a field.
 415  
      *
 416  
      * @see #normalField
 417  
      * @return constraints suitable for a field
 418  
      */
 419  
     public Constraints field()
 420  
     {
 421  4
         return normalField();
 422  
     }
 423  
 
 424  
     /**
 425  
      * Return constraints suitable for a normal field, a field
 426  
      * that is not a JLabel.
 427  
      *
 428  
      * @return constraints suitable for a normal field
 429  
      */
 430  
     public Constraints normalField()
 431  
     {
 432  5
         c.anchor = GridBagConstraints.WEST;
 433  5
         c.fill = GridBagConstraints.HORIZONTAL;
 434  5
         c.gridheight = 1;
 435  5
         c.gridwidth = GridBagConstraints.RELATIVE;
 436  5
         c.insets = FIELD_INSETS;
 437  
 
 438  5
         c.gridx = 1;
 439  5
         c.weighty = 0;
 440  5
         c.weightx = fieldPercent;
 441  
 
 442  5
         return c;
 443  
     }
 444  
 
 445  
     /**
 446  
      * Return constraints suitable for a label field, a field
 447  
      * that is a JLabel.
 448  
      *
 449  
      * @return constraints suitable for a label field
 450  
      */
 451  
     public Constraints labelField()
 452  
     {
 453  4
         c.anchor = GridBagConstraints.WEST;
 454  4
         c.fill = GridBagConstraints.HORIZONTAL;
 455  4
         c.gridheight = 1;
 456  4
         c.gridwidth = GridBagConstraints.RELATIVE;
 457  4
         c.insets = EMPTY_INSETS;
 458  
 
 459  4
         c.gridx = 1;
 460  4
         c.weighty = 0;
 461  4
         c.weightx = fieldPercent;
 462  
 
 463  4
         return c;
 464  
     }
 465  
 
 466  
     /**
 467  
      * Return constraints suitable for a wide field, a field
 468  
      * that stretches horizontally across both the label and field
 469  
      * columns.
 470  
      *
 471  
      * @return constraints suitable for a wide field
 472  
      */
 473  
     public Constraints wideField()
 474  
     {
 475  2
         c.anchor = GridBagConstraints.WEST;
 476  2
         c.fill = GridBagConstraints.HORIZONTAL;
 477  2
         c.gridheight = 1;
 478  2
         c.gridwidth = GridBagConstraints.REMAINDER;
 479  2
         c.insets = FIELD_INSETS;
 480  
 
 481  2
         c.gridx = 0;
 482  2
         c.weighty = 0;
 483  2
         c.weightx = 1.0f;
 484  
 
 485  2
         return c;
 486  
     }
 487  
 
 488  
     /**
 489  
      * Return constraints suitable for a final wide field, a field
 490  
      * that stretches horizontally across both the label and field
 491  
      * columns and stretches vertically to cover space left at the
 492  
      * bottom of a container.
 493  
      *
 494  
      * @return constraints suitable for a final wide field
 495  
      */
 496  
     public Constraints finalWideField()
 497  
     {
 498  2
         c.anchor = GridBagConstraints.NORTHWEST;
 499  2
         c.fill = GridBagConstraints.BOTH;
 500  2
         c.gridheight = 1;
 501  2
         c.gridwidth = GridBagConstraints.REMAINDER;
 502  2
         c.insets = EMPTY_INSETS;
 503  
 
 504  2
         c.gridx = 0;
 505  2
         c.weighty = 1.0f;
 506  2
         c.weightx = 1.0f;
 507  
 
 508  2
         return c;
 509  
     }
 510  
 
 511  
     /**
 512  
      * Return constraints suitable for spacing.
 513  
      *
 514  
      * @return constraints suitable for spacing
 515  
      */
 516  
     public Constraints spacing()
 517  
     {
 518  3
         c.anchor = GridBagConstraints.WEST;
 519  3
         c.fill = GridBagConstraints.HORIZONTAL;
 520  3
         c.gridheight = 1;
 521  3
         c.gridwidth = GridBagConstraints.REMAINDER;
 522  3
         c.insets = EMPTY_INSETS;
 523  
 
 524  3
         c.gridx = 0;
 525  3
         c.weighty = 0;
 526  3
         c.weightx = 1.0f;
 527  
 
 528  3
         return c;
 529  
     }
 530  
 
 531  
     /**
 532  
      * Return constraints suitable for spacing that stretches
 533  
      * vertically to cover space left at the bottom of a container.
 534  
      *
 535  
      * @return constraints suitable for spacing that stretches
 536  
      *    vertically to cover space left at the bottom of a container
 537  
      */
 538  
     public Constraints finalSpacing()
 539  
     {
 540  4
         c.anchor = GridBagConstraints.NORTHWEST;
 541  4
         c.fill = GridBagConstraints.BOTH;
 542  4
         c.gridheight = 1;
 543  4
         c.gridwidth = GridBagConstraints.REMAINDER;
 544  4
         c.insets = EMPTY_INSETS;
 545  
 
 546  4
         c.gridx = 0;
 547  4
         c.weighty = 1.0f;
 548  4
         c.weightx = 1.0f;
 549  
 
 550  4
         return c;
 551  
     }
 552  
 
 553  
    /**
 554  
     * Constraints class that extends GridBagConstraints for
 555  
     * the single purpose of having the classname
 556  
     * <code>LabelFieldLayout.Constraints</code>.
 557  
     */
 558  19
     public static final class Constraints
 559  
         extends GridBagConstraints
 560  
     {
 561  
         // empty
 562  
     }
 563  
 }