All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jgoodies.forms.layout.CellConstraints Maven / Gradle / Ivy

Go to download

The JGoodies Forms framework helps you lay out and implement elegant Swing panels quickly and consistently. It makes simple things easy and the hard stuff possible, the good design easy and the bad difficult.

There is a newer version: 1.9.0
Show newest version
/*
 * Copyright (c) 2002-2014 JGoodies Software GmbH. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  o Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  o Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 *  o Neither the name of JGoodies Software GmbH nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.jgoodies.forms.layout;

import static com.jgoodies.common.base.Preconditions.checkArgument;
import static com.jgoodies.common.base.Preconditions.checkNotNull;

import java.awt.Component;
import java.awt.Insets;
import java.awt.Rectangle;
import java.io.Serializable;
import java.util.Locale;
import java.util.StringTokenizer;

import com.jgoodies.forms.factories.CC;

/**
 * Defines constraints for components that are laid out with the FormLayout.
 * Defines the components display area: grid x, grid y,
 * grid width (column span), grid height (row span), horizontal alignment
 * and vertical alignment.

* * Most methods return this object to enable method chaining.

* * You can set optional insets in a constructor. This is useful if you * need to use a pixel-size insets to align perceived component bounds * with pixel data, for example an icon. Anyway, this is rarely used. * The insets don't affect the size computation for columns and rows. * I consider renaming the insets to offsets to better indicate the * motivation for this option.

* * Examples:
* The following cell constraints locate a component in the third * column of the fifth row; column and row span are 1; the component * will be aligned with the column's right-hand side and the row's * bottom. *

 * CellConstraints cc = new CellConstraints();
 * cc.xy  (3, 5);
 * cc.xy  (3, 5, CellConstraints.RIGHT, CellConstraints.BOTTOM);
 * cc.xy  (3, 5, "right, bottom");
 *
 * cc.xyw (3, 5, 1);
 * cc.xyw (3, 5, 1, CellConstraints.RIGHT, CellConstraints.BOTTOM);
 * cc.xyw (3, 5, 1, "right, bottom");
 *
 * cc.xywh(3, 5, 1, 1);
 * cc.xywh(3, 5, 1, 1, CellConstraints.RIGHT, CellConstraints.BOTTOM);
 * cc.xywh(3, 5, 1, 1, "right, bottom");
 * 
* See also the examples in the {@link FormLayout} class comment.

* * TODO: Explain in the JavaDocs that the insets are actually offsets. * And describe that these offsets are not taken into account when * FormLayout computes the column and row sizes.

* * TODO: Rename the inset to offsets. * * @author Karsten Lentzsch * @version $Revision: 1.15 $ * * @see CC */ public final class CellConstraints implements Cloneable, Serializable { // Alignment Constants ************************************************* /* * Implementation Note: Do not change the order of the following constants. * The serialization of class Alignment is ordinal-based and relies on it. */ /** * Use the column's or row's default alignment. */ public static final Alignment DEFAULT = new Alignment("default", Alignment.BOTH); /** * Fill the cell either horizontally or vertically. */ public static final Alignment FILL = new Alignment("fill", Alignment.BOTH); /** * Put the component in the left. */ public static final Alignment LEFT = new Alignment("left", Alignment.HORIZONTAL); /** * Put the component in the right. */ public static final Alignment RIGHT = new Alignment("right", Alignment.HORIZONTAL); /** * Put the component in the center. */ public static final Alignment CENTER = new Alignment("center", Alignment.BOTH); /** * Put the component in the top. */ public static final Alignment TOP = new Alignment("top", Alignment.VERTICAL); /** * Put the component in the bottom. */ public static final Alignment BOTTOM = new Alignment("bottom", Alignment.VERTICAL); /** * An array of all enumeration values used to canonicalize * deserialized alignments. */ private static final Alignment[] VALUES = { DEFAULT, FILL, LEFT, RIGHT, CENTER, TOP, BOTTOM }; /** * A reusable {@code Insets} object to reduce object instantiation. */ private static final Insets EMPTY_INSETS = new Insets(0, 0, 0, 0); // Fields *************************************************************** /** * Describes the component's horizontal grid origin (starts at 1). */ public int gridX; /** * Describes the component's vertical grid origin (starts at 1). */ public int gridY; /** * Describes the component's horizontal grid extend (number of cells). */ public int gridWidth; /** * Describes the component's vertical grid extent (number of cells). */ public int gridHeight; /** * Describes the component's horizontal alignment. */ public Alignment hAlign; /** * Describes the component's vertical alignment. */ public Alignment vAlign; /** * Describes the component's {@code Insets} in it's display area. */ public Insets insets; /** * Describes whether individual components shall be taken into account * by the FormLayout if 1) they are invisible and 2) the FormLayout * does not honor the visibility. * * See {@link FormLayout#setHonorsVisibility(boolean)} and * {@link FormLayout#setHonorsVisibility(Component, Boolean)} for a * full description of this feature. */ public Boolean honorsVisibility; // Instance Creation **************************************************** /** * Constructs a default instance of {@code CellConstraints}. */ public CellConstraints() { this(1, 1); } /** * Constructs an instance of {@code CellConstraints} for the given * cell position.

* * Examples:

     * new CellConstraints(1, 3);
     * new CellConstraints(1, 3);
     * 
* * @param gridX the component's horizontal grid origin * @param gridY the component's vertical grid origin */ public CellConstraints(int gridX, int gridY) { this(gridX, gridY, 1, 1); } /** * Constructs an instance of {@code CellConstraints} for the given * cell position, anchor, and fill.

* * Examples:

     * new CellConstraints(1, 3, CellConstraints.LEFT,   CellConstraints.BOTTOM);
     * new CellConstraints(1, 3, CellConstraints.CENTER, CellConstraints.FILL);
     * 
* * @param gridX the component's horizontal grid origin * @param gridY the component's vertical grid origin * @param hAlign the component's horizontal alignment * @param vAlign the component's vertical alignment */ public CellConstraints(int gridX, int gridY, Alignment hAlign, Alignment vAlign) { this(gridX, gridY, 1, 1, hAlign, vAlign, EMPTY_INSETS); } /** * Constructs an instance of {@code CellConstraints} for the given * cell position and size.

* * Examples:

     * new CellConstraints(1, 3, 2, 1);
     * new CellConstraints(1, 3, 7, 3);
     * 
* * @param gridX the component's horizontal grid origin * @param gridY the component's vertical grid origin * @param gridWidth the component's horizontal extent * @param gridHeight the component's vertical extent */ public CellConstraints(int gridX, int gridY, int gridWidth, int gridHeight) { this(gridX, gridY, gridWidth, gridHeight, DEFAULT, DEFAULT); } /** * Constructs an instance of {@code CellConstraints} for the given * cell position and size, anchor, and fill.

* * Examples:

     * new CellConstraints(1, 3, 2, 1, CellConstraints.LEFT,   CellConstraints.BOTTOM);
     * new CellConstraints(1, 3, 7, 3, CellConstraints.CENTER, CellConstraints.FILL);
     * 
* * @param gridX the component's horizontal grid origin * @param gridY the component's vertical grid origin * @param gridWidth the component's horizontal extent * @param gridHeight the component's vertical extent * @param hAlign the component's horizontal alignment * @param vAlign the component's vertical alignment */ public CellConstraints(int gridX, int gridY, int gridWidth, int gridHeight, Alignment hAlign, Alignment vAlign) { this(gridX, gridY, gridWidth, gridHeight, hAlign, vAlign, EMPTY_INSETS); } /** * Constructs an instance of {@code CellConstraints} for * the complete set of available properties.

* * Examples:

     * new CellConstraints(1, 3, 2, 1, CellConstraints.LEFT,   CellConstraints.BOTTOM, new Insets(0, 1, 0, 3));
     * new CellConstraints(1, 3, 7, 3, CellConstraints.CENTER, CellConstraints.FILL,   new Insets(0, 1, 0, 0));
     * 
* * @param gridX the component's horizontal grid origin * @param gridY the component's vertical grid origin * @param gridWidth the component's horizontal extent * @param gridHeight the component's vertical extent * @param hAlign the component's horizontal alignment * @param vAlign the component's vertical alignment * @param insets the component's display area {@code Insets} * @throws IndexOutOfBoundsException if the grid origin or extent is negative * @throws NullPointerException if the horizontal or vertical alignment is null * @throws IllegalArgumentException if an alignment orientation is invalid */ public CellConstraints(int gridX, int gridY, int gridWidth, int gridHeight, Alignment hAlign, Alignment vAlign, Insets insets) { this.gridX = gridX; this.gridY = gridY; this.gridWidth = gridWidth; this.gridHeight = gridHeight; this.hAlign = hAlign; this.vAlign = vAlign; this.insets = insets; if (gridX <= 0) { throw new IndexOutOfBoundsException("The grid x must be a positive number."); } if (gridY <= 0) { throw new IndexOutOfBoundsException("The grid y must be a positive number."); } if (gridWidth <= 0) { throw new IndexOutOfBoundsException("The grid width must be a positive number."); } if (gridHeight <= 0) { throw new IndexOutOfBoundsException("The grid height must be a positive number."); } checkNotNull(hAlign, "The horizontal alignment must not be null."); checkNotNull(vAlign, "The vertical alignment must not be null."); ensureValidOrientations(hAlign, vAlign); } /** * Constructs an instance of {@code CellConstraints} from * the given encoded string properties.

* * Examples:

     * new CellConstraints("1, 3");
     * new CellConstraints("1, 3, left, bottom");
     * new CellConstraints("1, 3, 2, 1, left, bottom");
     * new CellConstraints("1, 3, 2, 1, l, b");
     * 
* * @param encodedConstraints the constraints encoded as string */ public CellConstraints(String encodedConstraints) { this(); initFromConstraints(encodedConstraints); } // Translation ************************************************************ /** * Creates and returns a new CellConstraints instance where the origin * has been moved along the X and Y axis as specified by {@code dx} * and {@code dy} respectively. * * @param dx the distance to move along the X axis * @param dy the distance to move along the Y axis * @return the new CellConstraints instance with a translated grid origin * * @since 1.8 */ public CellConstraints translate(int dx, int dy) { return new CellConstraints(gridX + dx, gridY + dy, gridWidth, gridHeight, hAlign, vAlign, insets); } // Setters with Column-Row Order ****************************************** /** * Sets column and row origins; sets width and height to 1; * uses the default alignments.

* * Examples:

     * cc.xy(1, 1);
     * cc.xy(1, 3);
     * 
* * @param col the new column index * @param row the new row index * @return this */ public CellConstraints xy(int col, int row) { return xywh(col, row, 1, 1); } /** * Sets column and row origins; sets width and height to 1; * decodes horizontal and vertical alignments from the given string.

* * Examples:

     * cc.xy(1, 3, "left, bottom");
     * cc.xy(1, 3, "l, b");
     * cc.xy(1, 3, "center, fill");
     * cc.xy(1, 3, "c, f");
     * 
* * @param col the new column index * @param row the new row index * @param encodedAlignments describes the horizontal and vertical alignments * @return this * * @throws IllegalArgumentException if an alignment orientation is invalid */ public CellConstraints xy(int col, int row, String encodedAlignments) { return xywh(col, row, 1, 1, encodedAlignments); } /** * Sets the column and row origins; sets width and height to 1; * set horizontal and vertical alignment using the specified objects.

* * Examples:

     * cc.xy(1, 3, CellConstraints.LEFT,   CellConstraints.BOTTOM);
     * cc.xy(1, 3, CellConstraints.CENTER, CellConstraints.FILL);
     * 
* * @param col the new column index * @param row the new row index * @param colAlign horizontal component alignment * @param rowAlign vertical component alignment * @return this */ public CellConstraints xy(int col, int row, Alignment colAlign, Alignment rowAlign) { return xywh(col, row, 1, 1, colAlign, rowAlign); } /** * Sets the column, row, width, and height; uses a height (row span) of 1 * and the horizontal and vertical default alignments.

* * Examples:

     * cc.xyw(1, 3, 7);
     * cc.xyw(1, 3, 2);
     * 
* * @param col the new column index * @param row the new row index * @param colSpan the column span or grid width * @return this */ public CellConstraints xyw(int col, int row, int colSpan) { return xywh(col, row, colSpan, 1, DEFAULT, DEFAULT); } /** * Sets the column, row, width, and height; * decodes the horizontal and vertical alignments from the given string. * The row span (height) is set to 1.

* * Examples:

     * cc.xyw(1, 3, 7, "left, bottom");
     * cc.xyw(1, 3, 7, "l, b");
     * cc.xyw(1, 3, 2, "center, fill");
     * cc.xyw(1, 3, 2, "c, f");
     * 
* * @param col the new column index * @param row the new row index * @param colSpan the column span or grid width * @param encodedAlignments describes the horizontal and vertical alignments * @return this * @throws IllegalArgumentException if an alignment orientation is invalid */ public CellConstraints xyw(int col, int row, int colSpan, String encodedAlignments) { return xywh(col, row, colSpan, 1, encodedAlignments); } /** * Sets the column, row, width, and height; sets the horizontal * and vertical alignment using the specified alignment objects. * The row span (height) is set to 1.

* * Examples:

     * cc.xyw(1, 3, 2, CellConstraints.LEFT,   CellConstraints.BOTTOM);
     * cc.xyw(1, 3, 7, CellConstraints.CENTER, CellConstraints.FILL);
     * 
* * @param col the new column index * @param row the new row index * @param colSpan the column span or grid width * @param colAlign horizontal component alignment * @param rowAlign vertical component alignment * @return this * @throws IllegalArgumentException if an alignment orientation is invalid */ public CellConstraints xyw(int col, int row, int colSpan, Alignment colAlign, Alignment rowAlign) { return xywh(col, row, colSpan, 1, colAlign, rowAlign); } /** * Sets the column, row, width, and height; uses default alignments.

* * Examples:

     * cc.xywh(1, 3, 2, 1);
     * cc.xywh(1, 3, 7, 3);
     * 
* * @param col the new column index * @param row the new row index * @param colSpan the column span or grid width * @param rowSpan the row span or grid height * @return this */ public CellConstraints xywh(int col, int row, int colSpan, int rowSpan) { return xywh(col, row, colSpan, rowSpan, DEFAULT, DEFAULT); } /** * Sets the column, row, width, and height; * decodes the horizontal and vertical alignments from the given string.

* * Examples:

     * cc.xywh(1, 3, 2, 1, "left, bottom");
     * cc.xywh(1, 3, 2, 1, "l, b");
     * cc.xywh(1, 3, 7, 3, "center, fill");
     * cc.xywh(1, 3, 7, 3, "c, f");
     * 
* * @param col the new column index * @param row the new row index * @param colSpan the column span or grid width * @param rowSpan the row span or grid height * @param encodedAlignments describes the horizontal and vertical alignments * @return this * @throws IllegalArgumentException if an alignment orientation is invalid */ public CellConstraints xywh(int col, int row, int colSpan, int rowSpan, String encodedAlignments) { CellConstraints result = xywh(col, row, colSpan, rowSpan); result.setAlignments(encodedAlignments, true); return result; } /** * Sets the column, row, width, and height; sets the horizontal * and vertical alignment using the specified alignment objects.

* * Examples:

     * cc.xywh(1, 3, 2, 1, CellConstraints.LEFT,   CellConstraints.BOTTOM);
     * cc.xywh(1, 3, 7, 3, CellConstraints.CENTER, CellConstraints.FILL);
     * 
* * @param col the new column index * @param row the new row index * @param colSpan the column span or grid width * @param rowSpan the row span or grid height * @param colAlign horizontal component alignment * @param rowAlign vertical component alignment * @return this * @throws IllegalArgumentException if an alignment orientation is invalid */ public CellConstraints xywh(int col, int row, int colSpan, int rowSpan, Alignment colAlign, Alignment rowAlign) { this.gridX = col; this.gridY = row; this.gridWidth = colSpan; this.gridHeight = rowSpan; this.hAlign = colAlign; this.vAlign = rowAlign; ensureValidOrientations(hAlign, vAlign); return this; } // Setters with Row-Column Order ****************************************** /** * Sets row and column origins; sets height and width to 1; * uses the default alignments.

* * Examples:

     * cc.rc(1, 1);
     * cc.rc(3, 1);
     * 
* * @param row the new row index * @param col the new column index * @return this * * @since 1.1 */ public CellConstraints rc(int row, int col) { return rchw(row, col, 1, 1); } /** * Sets row and column origins; sets height and width to 1; * decodes vertical and horizontal alignments from the given string.

* * Examples:

     * cc.rc(3, 1, "bottom, left");
     * cc.rc(3, 1, "b, l");
     * cc.rc(3, 1, "fill, center");
     * cc.rc(3, 1, "f, c");
     * 
* * @param row the new row index * @param col the new column index * @param encodedAlignments describes the vertical and horizontal alignments * @return this * * @throws IllegalArgumentException if an alignment orientation is invalid * * @since 1.1 */ public CellConstraints rc(int row, int col, String encodedAlignments) { return rchw(row, col, 1, 1, encodedAlignments); } /** * Sets the row and column origins; sets width and height to 1; * set horizontal and vertical alignment using the specified objects.

* * Examples:

     * cc.rc(3, 1, CellConstraints.BOTTOM, CellConstraints.LEFT);
     * cc.rc(3, 1, CellConstraints.FILL,   CellConstraints.CENTER);
     * 
* * @param row the new row index * @param col the new column index * @param rowAlign vertical component alignment * @param colAlign horizontal component alignment * @return this * * @since 1.1 */ public CellConstraints rc(int row, int col, Alignment rowAlign, Alignment colAlign) { return rchw(row, col, 1, 1, rowAlign, colAlign); } /** * Sets the row, column, height, and width; uses a height (row span) of 1 * and the vertical and horizontal default alignments.

* * Examples:

     * cc.rcw(3, 1, 7);
     * cc.rcw(3, 1, 2);
     * 
* * @param row the new row index * @param col the new column index * @param colSpan the column span or grid width * @return this * * @since 1.1 */ public CellConstraints rcw(int row, int col, int colSpan) { return rchw(row, col, 1, colSpan, DEFAULT, DEFAULT); } /** * Sets the row, column, height, and width; * decodes the vertical and horizontal alignments from the given string. * The row span (height) is set to 1.

* * Examples:

     * cc.rcw(3, 1, 7, "bottom, left");
     * cc.rcw(3, 1, 7, "b, l");
     * cc.rcw(3, 1, 2, "fill, center");
     * cc.rcw(3, 1, 2, "f, c");
     * 
* * @param row the new row index * @param col the new column index * @param colSpan the column span or grid width * @param encodedAlignments describes the vertical and horizontal alignments * @return this * * @throws IllegalArgumentException if an alignment orientation is invalid * * @since 1.1 */ public CellConstraints rcw(int row, int col, int colSpan, String encodedAlignments) { return rchw(row, col, 1, colSpan, encodedAlignments); } /** * Sets the row, column, height, and width; sets the vertical * and horizontal alignment using the specified alignment objects. * The row span (height) is set to 1.

* * Examples:

     * cc.rcw(3, 1, 2, CellConstraints.BOTTOM, CellConstraints.LEFT);
     * cc.rcw(3, 1, 7, CellConstraints.FILL,   CellConstraints.CENTER);
     * 
* * @param row the new row index * @param col the new column index * @param colSpan the column span or grid width * @param rowAlign vertical component alignment * @param colAlign horizontal component alignment * @return this * * @throws IllegalArgumentException if an alignment orientation is invalid * * @since 1.1 */ public CellConstraints rcw(int row, int col, int colSpan, Alignment rowAlign, Alignment colAlign) { return rchw(row, col, 1, colSpan, rowAlign, colAlign); } /** * Sets the row, column, height, and width; uses default alignments.

* * Examples:

     * cc.rchw(1, 3, 2, 1);
     * cc.rchw(1, 3, 7, 3);
     * 
* * @param row the new row index * @param col the new column index * @param rowSpan the row span or grid height * @param colSpan the column span or grid width * @return this * * @since 1.1 */ public CellConstraints rchw(int row, int col, int rowSpan, int colSpan) { return rchw(row, col, rowSpan, colSpan, DEFAULT, DEFAULT); } /** * Sets the row, column, height, and width; * decodes the vertical and horizontal alignments from the given string.

* * Examples:

     * cc.rchw(3, 1, 1, 2, "bottom, left");
     * cc.rchw(3, 1, 1, 2, "b, l");
     * cc.rchw(3, 1, 3, 7, "fill, center");
     * cc.rchw(3, 1, 3, 7, "f, c");
     * 
* * @param row the new row index * @param col the new column index * @param rowSpan the row span or grid height * @param colSpan the column span or grid width * @param encodedAlignments describes the vertical and horizontal alignments * @return this * @throws IllegalArgumentException if an alignment orientation is invalid * * @since 1.1 */ public CellConstraints rchw(int row, int col, int rowSpan, int colSpan, String encodedAlignments) { CellConstraints result = rchw(row, col, rowSpan, colSpan); result.setAlignments(encodedAlignments, false); return result; } /** * Sets the row, column, height, and width; sets the vertical and * horizontal alignment using the specified alignment objects.

* * Examples:

     * cc.rchw(3, 1, 1, 2, CellConstraints.BOTTOM, CellConstraints.LEFT);
     * cc.rchw(3, 1, 3, 7, CellConstraints.FILL,   CellConstraints.CENTER);
     * 
* * @param row the new row index * @param col the new column index * @param rowSpan the row span or grid height * @param colSpan the column span or grid width * @param rowAlign vertical component alignment * @param colAlign horizontal component alignment * @return this * * @throws IllegalArgumentException if an alignment orientation is invalid * * @since 1.1 */ public CellConstraints rchw(int row, int col, int rowSpan, int colSpan, Alignment rowAlign, Alignment colAlign) { return xywh(col, row, colSpan, rowSpan, colAlign, rowAlign); } // Parsing and Decoding String Descriptions ***************************** /** * Decodes and returns the grid bounds and alignments for this * constraints as an array of six integers. The string representation * is a comma separated sequence, one of *
     * "x, y"
     * "x, y, w, h"
     * "x, y, hAlign, vAlign"
     * "x, y, w, h, hAlign, vAlign"
     * 
* * @param encodedConstraints represents horizontal and vertical alignment * * @throws IllegalArgumentException if the encoded constraints do not * follow the constraint syntax */ @SuppressWarnings("null") private void initFromConstraints(String encodedConstraints) { StringTokenizer tokenizer = new StringTokenizer(encodedConstraints, " ,"); int argCount = tokenizer.countTokens(); checkArgument(argCount == 2 || argCount == 4 || argCount == 6, "You must provide 2, 4 or 6 arguments."); Integer nextInt = decodeInt(tokenizer.nextToken()); checkArgument(nextInt != null, "First cell constraint element must be a number."); gridX = nextInt.intValue(); checkArgument(gridX > 0, "The grid x must be a positive number."); nextInt = decodeInt(tokenizer.nextToken()); checkArgument(nextInt != null, "Second cell constraint element must be a number."); gridY = nextInt.intValue(); checkArgument(gridY > 0, "The grid y must be a positive number."); if (!tokenizer.hasMoreTokens()) { return; } String token = tokenizer.nextToken(); nextInt = decodeInt(token); if (nextInt != null) { // Case: "x, y, w, h" or // "x, y, w, h, hAlign, vAlign" gridWidth = nextInt.intValue(); if (gridWidth <= 0) { throw new IndexOutOfBoundsException( "The grid width must be a positive number."); } nextInt = decodeInt(tokenizer.nextToken()); if (nextInt == null) { throw new IllegalArgumentException( "Fourth cell constraint element must be like third."); } gridHeight = nextInt.intValue(); if (gridHeight <= 0) { throw new IndexOutOfBoundsException( "The grid height must be a positive number."); } if (!tokenizer.hasMoreTokens()) { return; } token = tokenizer.nextToken(); } hAlign = decodeAlignment(token); vAlign = decodeAlignment(tokenizer.nextToken()); ensureValidOrientations(hAlign, vAlign); } /** * Decodes a string description for the horizontal and vertical alignment * and sets this CellConstraints' alignment values. If the boolean is * {@code true} the horizontal alignment is the first token, * and the vertical alignment is the second token. if the boolean is * {@code false} the vertical alignment comes first.

* * Valid horizontal alignments are: left, center, right, default, and fill. * Valid vertical alignments are: top, center, bottom, default, and fill. * The anchor's string representation abbreviates the alignment: * l, c, r, d, f, t, and b.

* * Anchor examples: * "c, c" is centered, "l, t" is northwest, "c, t" is north, "r, c" east. * "c, d" is horizontally centered and uses the row's default alignment. * "d, t" is on top of the cell and uses the column's default alignment.

* * @param encodedAlignments represents horizontal and vertical alignment * @throws IllegalArgumentException if an alignment orientation is invalid */ private void setAlignments(String encodedAlignments, boolean horizontalThenVertical) { StringTokenizer tokenizer = new StringTokenizer(encodedAlignments, " ,"); Alignment first = decodeAlignment(tokenizer.nextToken()); Alignment second = decodeAlignment(tokenizer.nextToken()); hAlign = horizontalThenVertical ? first : second; vAlign = horizontalThenVertical ? second : first; ensureValidOrientations(hAlign, vAlign); } /** * Decodes an integer string representation and returns the * associated Integer or null in case of an invalid number format. * * @param token the encoded integer * @return the decoded Integer or null */ private static Integer decodeInt(String token) { try { return Integer.decode(token); } catch (NumberFormatException e) { return null; } } /** * Parses an alignment string description and * returns the corresponding alignment value. * * @param encodedAlignment the encoded alignment * @return the associated {@code Alignment} instance */ private static Alignment decodeAlignment(String encodedAlignment) { return Alignment.valueOf(encodedAlignment); } /** * Checks and verifies that this constraints object has valid grid * index values, i. e. the display area cells are inside the form's grid. * * @param colCount number of columns in the grid * @param rowCount number of rows in the grid * @throws IndexOutOfBoundsException if the display area described * by this constraints object is not inside the grid */ void ensureValidGridBounds(int colCount, int rowCount) { if (gridX <= 0) { throw new IndexOutOfBoundsException( "The column index " + gridX + " must be positive."); } if (gridX > colCount) { throw new IndexOutOfBoundsException( "The column index " + gridX + " must be less than or equal to " + colCount + "."); } if (gridX + gridWidth - 1 > colCount) { throw new IndexOutOfBoundsException( "The grid width " + gridWidth + " must be less than or equal to " + (colCount - gridX + 1) + "."); } if (gridY <= 0) { throw new IndexOutOfBoundsException( "The row index " + gridY + " must be positive."); } if (gridY > rowCount) { throw new IndexOutOfBoundsException( "The row index " + gridY + " must be less than or equal to " + rowCount + "."); } if (gridY + gridHeight - 1 > rowCount) { throw new IndexOutOfBoundsException( "The grid height " + gridHeight + " must be less than or equal to " + (rowCount - gridY + 1) + "."); } } /** * Checks and verifies that the horizontal alignment is a horizontal * and the vertical alignment is vertical. * * @param horizontalAlignment the horizontal alignment * @param verticalAlignment the vertical alignment * @throws IllegalArgumentException if an alignment is invalid */ private static void ensureValidOrientations(Alignment horizontalAlignment, Alignment verticalAlignment) { if (!horizontalAlignment.isHorizontal()) { throw new IllegalArgumentException("The horizontal alignment must be one of: left, center, right, fill, default."); } if (!verticalAlignment.isVertical()) { throw new IllegalArgumentException("The vertical alignment must be one of: top, center, bottom, fill, default."); } } // Settings Component Bounds ******************************************** /** * Sets the component's bounds using the given component and cell bounds. * * @param c the component to set bounds * @param layout the FormLayout instance that computes the bounds * @param cellBounds the cell's bounds * @param minWidthMeasure measures the minimum width * @param minHeightMeasure measures the minimum height * @param prefWidthMeasure measures the preferred width * @param prefHeightMeasure measures the preferred height */ void setBounds(Component c, FormLayout layout, Rectangle cellBounds, FormLayout.Measure minWidthMeasure, FormLayout.Measure minHeightMeasure, FormLayout.Measure prefWidthMeasure, FormLayout.Measure prefHeightMeasure) { ColumnSpec colSpec = gridWidth == 1 ? layout.getColumnSpec(gridX) : null; RowSpec rowSpec = gridHeight == 1 ? layout.getRowSpec(gridY) : null; Alignment concreteHAlign = concreteAlignment(this.hAlign, colSpec); Alignment concreteVAlign = concreteAlignment(this.vAlign, rowSpec); Insets concreteInsets = this.insets != null ? this.insets : EMPTY_INSETS; int cellX = cellBounds.x + concreteInsets.left; int cellY = cellBounds.y + concreteInsets.top; int cellW = cellBounds.width - concreteInsets.left - concreteInsets.right; int cellH = cellBounds.height - concreteInsets.top - concreteInsets.bottom; int compW = componentSize(c, colSpec, cellW, minWidthMeasure, prefWidthMeasure); int compH = componentSize(c, rowSpec, cellH, minHeightMeasure, prefHeightMeasure); int x = origin(concreteHAlign, cellX, cellW, compW); int y = origin(concreteVAlign, cellY, cellH, compH); int w = extent(concreteHAlign, cellW, compW); int h = extent(concreteVAlign, cellH, compH); c.setBounds(x, y, w, h); } /** * Computes and returns the concrete alignment. Takes into account * the cell alignment and the {@code FormSpec} if applicable.

* * If this constraints object doesn't belong to a single column or row, * the {@code formSpec} parameter is {@code null}. * In this case the cell alignment is answered, but {@code DEFAULT} * is mapped to {@code FILL}.

* * If the cell belongs to a single column or row, we use the cell * alignment, unless it is {@code DEFAULT}, where the alignment * is inherited from the column or row resp. * * @param cellAlignment this cell's alignment * @param formSpec the associated column or row specification * @return the concrete alignment */ private static Alignment concreteAlignment(Alignment cellAlignment, FormSpec formSpec) { return formSpec == null ? cellAlignment == DEFAULT ? FILL : cellAlignment : usedAlignment(cellAlignment, formSpec); } /** * Returns the alignment used for a given form constraints object. * The cell alignment overrides the column or row default, unless * it is {@code DEFAULT}. In the latter case, we use the * column or row alignment. * * @param cellAlignment this cell constraint's alignment * @param formSpec the associated column or row specification * @return the alignment used */ private static Alignment usedAlignment(Alignment cellAlignment, FormSpec formSpec) { if (cellAlignment != CellConstraints.DEFAULT) { // Cell alignments other than DEFAULT override col/row alignments return cellAlignment; } FormSpec.DefaultAlignment defaultAlignment = formSpec.getDefaultAlignment(); if (defaultAlignment == FormSpec.FILL_ALIGN) { return FILL; } if (defaultAlignment == ColumnSpec.LEFT) { return LEFT; } else if (defaultAlignment == FormSpec.CENTER_ALIGN) { return CENTER; } else if (defaultAlignment == ColumnSpec.RIGHT) { return RIGHT; } else if (defaultAlignment == RowSpec.TOP) { return TOP; } else { return BOTTOM; } } /** * Computes and returns the pixel size of the given component using the * given form specification, measures, and cell size. * * @param component the component to measure * @param formSpec the specification of the component's column/row * @param minMeasure the measure for the minimum size * @param prefMeasure the measure for the preferred size * @param cellSize the cell size * @return the component size as measured or a constant */ private static int componentSize(Component component, FormSpec formSpec, int cellSize, FormLayout.Measure minMeasure, FormLayout.Measure prefMeasure) { if (formSpec == null) { return prefMeasure.sizeOf(component); } else if (formSpec.getSize() == Sizes.MINIMUM) { return minMeasure.sizeOf(component); } else if (formSpec.getSize() == Sizes.PREFERRED) { return prefMeasure.sizeOf(component); } else { // default mode return Math.min(cellSize, prefMeasure.sizeOf(component)); } } /** * Computes and returns the component's pixel origin. * * @param alignment the component's alignment * @param cellOrigin the origin of the display area * @param cellSize the extent of the display area * @param componentSize the component's size * @return the component's pixel origin */ private static int origin(Alignment alignment, int cellOrigin, int cellSize, int componentSize) { if (alignment == RIGHT || alignment == BOTTOM) { return cellOrigin + cellSize - componentSize; } else if (alignment == CENTER) { return cellOrigin + (cellSize - componentSize) / 2; } else { // left, top, fill return cellOrigin; } } /** * Returns the component's pixel extent. * * @param alignment the component's alignment * @param cellSize the size of the display area * @param componentSize the component's size * @return the component's pixel extent */ private static int extent(Alignment alignment, int cellSize, int componentSize) { return alignment == FILL ? cellSize : componentSize; } // Misc ***************************************************************** /** * Creates a copy of this cell constraints object. * * @return a copy of this cell constraints object */ @Override public Object clone() { try { CellConstraints c = (CellConstraints) super.clone(); c.insets = (Insets) insets.clone(); return c; } catch (CloneNotSupportedException e) { // This shouldn't happen, since we are Cloneable. throw new InternalError(); } } /** * Constructs and returns a string representation of this constraints object. * * @return string representation of this constraints object */ @Override public String toString() { StringBuffer buffer = new StringBuffer("CellConstraints"); buffer.append("[x="); buffer.append(gridX); buffer.append("; y="); buffer.append(gridY); buffer.append("; w="); buffer.append(gridWidth); buffer.append("; h="); buffer.append(gridHeight); buffer.append("; hAlign="); buffer.append(hAlign); buffer.append("; vAlign="); buffer.append(vAlign); if (!EMPTY_INSETS.equals(insets)) { buffer.append("; insets="); buffer.append(insets); } buffer.append("; honorsVisibility="); buffer.append(honorsVisibility); buffer.append(']'); return buffer.toString(); } /** * Returns a short string representation of this constraints object. * * @return a short string representation of this constraints object */ public String toShortString() { return toShortString(null); } /** * Returns a short string representation of this constraints object. * This method can use the given {@code FormLayout} * to display extra information how default alignments * are mapped to concrete alignments. Therefore it asks the * related column and row as specified by this constraints object. * * @param layout the layout to be presented as a string * @return a short string representation of this constraints object */ public String toShortString(FormLayout layout) { StringBuffer buffer = new StringBuffer("("); buffer.append(formatInt(gridX)); buffer.append(", "); buffer.append(formatInt(gridY)); buffer.append(", "); buffer.append(formatInt(gridWidth)); buffer.append(", "); buffer.append(formatInt(gridHeight)); buffer.append(", \""); buffer.append(hAlign.abbreviation()); if (hAlign == DEFAULT && layout != null) { buffer.append('='); ColumnSpec colSpec = gridWidth == 1 ? layout.getColumnSpec(gridX) : null; buffer.append(concreteAlignment(hAlign, colSpec).abbreviation()); } buffer.append(", "); buffer.append(vAlign.abbreviation()); if (vAlign == DEFAULT && layout != null) { buffer.append('='); RowSpec rowSpec = gridHeight == 1 ? layout.getRowSpec(gridY) : null; buffer.append(concreteAlignment(vAlign, rowSpec).abbreviation()); } buffer.append("\""); if (!EMPTY_INSETS.equals(insets)) { buffer.append(", "); buffer.append(insets); } if (honorsVisibility != null) { buffer.append(honorsVisibility.booleanValue() ? "honors visibility" : "ignores visibility"); } buffer.append(')'); return buffer.toString(); } // Helper Class ********************************************************* /** * An ordinal-based serializable typesafe enumeration for component * alignment types as used by the {@link FormLayout}. */ public static final class Alignment implements Serializable { private static final int HORIZONTAL = 0; private static final int VERTICAL = 1; private static final int BOTH = 2; private final transient String name; private final transient int orientation; private Alignment(String name, int orientation) { this.name = name; this.orientation = orientation; } static Alignment valueOf(String nameOrAbbreviation) { String str = nameOrAbbreviation.toLowerCase(Locale.ENGLISH); if (str.equals("d") || str.equals("default")) { return DEFAULT; } else if (str.equals("f") || str.equals("fill")) { return FILL; } else if (str.equals("c") || str.equals("center")) { return CENTER; } else if (str.equals("l") || str.equals("left")) { return LEFT; } else if (str.equals("r") || str.equals("right")) { return RIGHT; } else if (str.equals("t") || str.equals("top")) { return TOP; } else if (str.equals("b") || str.equals("bottom")) { return BOTTOM; } else { throw new IllegalArgumentException( "Invalid alignment " + nameOrAbbreviation + ". Must be one of: left, center, right, top, bottom, " + "fill, default, l, c, r, t, b, f, d."); } } /** * Returns this Alignment's name. * * @return this alignment's name. */ @Override public String toString() { return name; } /** * Returns the first character of this Alignment's name. * Used to identify it in short format strings. * * @return the name's first character. */ public char abbreviation() { return name.charAt(0); } private boolean isHorizontal() { return orientation != VERTICAL; } private boolean isVertical() { return orientation != HORIZONTAL; } // Serialization ********************************************************* private static int nextOrdinal = 0; private final int ordinal = nextOrdinal++; private Object readResolve() { return VALUES[ordinal]; // Canonicalize } } /** * Returns an integer that has a minimum of two characters. * * @param number the number to format * @return a string representation for a number with a minimum of two chars */ private static String formatInt(int number) { String str = Integer.toString(number); return number < 10 ? " " + str : str; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy