0001: /*
0002: * Copyright (c) 2002-2007 JGoodies Karsten Lentzsch. All Rights Reserved.
0003: *
0004: * Redistribution and use in source and binary forms, with or without
0005: * modification, are permitted provided that the following conditions are met:
0006: *
0007: * o Redistributions of source code must retain the above copyright notice,
0008: * this list of conditions and the following disclaimer.
0009: *
0010: * o Redistributions in binary form must reproduce the above copyright notice,
0011: * this list of conditions and the following disclaimer in the documentation
0012: * and/or other materials provided with the distribution.
0013: *
0014: * o Neither the name of JGoodies Karsten Lentzsch nor the names of
0015: * its contributors may be used to endorse or promote products derived
0016: * from this software without specific prior written permission.
0017: *
0018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
0020: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
0021: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
0022: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
0023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
0024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
0025: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
0026: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
0027: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
0028: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0029: */
0030:
0031: package com.jgoodies.forms.layout;
0032:
0033: import java.awt.Component;
0034: import java.awt.Insets;
0035: import java.awt.Rectangle;
0036: import java.io.Serializable;
0037: import java.util.Locale;
0038: import java.util.StringTokenizer;
0039:
0040: /**
0041: * Defines constraints for components that are layed out with the FormLayout.
0042: * Defines the components display area: grid x, grid y,
0043: * grid width (column span), grid height (row span), horizontal alignment
0044: * and vertical alignment.<p>
0045: *
0046: * Most methods return <em>this</em> object to enable method chaining.<p>
0047: *
0048: * You can set optional insets in a constructor. This is useful if you
0049: * need to use a pixel-size insets to align perceived component bounds
0050: * with pixel data, for example an icon. Anyway, this is rarely used.
0051: * The insets don't affect the size computation for columns and rows.
0052: * I consider renaming the insets to offsets to better indicate the
0053: * motivation for this option.<p>
0054: *
0055: * <strong>Examples</strong>:<br>
0056: * The following cell constraints locate a component in the third
0057: * column of the fifth row; column and row span are 1; the component
0058: * will be aligned with the column's right-hand side and the row's
0059: * bottom.
0060: * <pre>
0061: * CellConstraints cc = new CellConstraints();
0062: * cc.xy (3, 5);
0063: * cc.xy (3, 5, CellConstraints.RIGHT, CellConstraints.BOTTOM);
0064: * cc.xy (3, 5, "right, bottom");
0065: *
0066: * cc.xyw (3, 5, 1);
0067: * cc.xyw (3, 5, 1, CellConstraints.RIGHT, CellConstraints.BOTTOM);
0068: * cc.xyw (3, 5, 1, "right, bottom");
0069: *
0070: * cc.xywh(3, 5, 1, 1);
0071: * cc.xywh(3, 5, 1, 1, CellConstraints.RIGHT, CellConstraints.BOTTOM);
0072: * cc.xywh(3, 5, 1, 1, "right, bottom");
0073: * </pre>
0074: * See also the examples in the {@link FormLayout} class comment.<p>
0075: *
0076: * <strong>Note:</strong> The new method sets <code>#rc</code>,
0077: * <code>#rcw</code>, and <code>#rchw</code> are experimental and
0078: * maybe removed from the 1.1 final.<p>
0079: *
0080: * TODO: Remove the above comment in the 1.1 final.<p>
0081: *
0082: * TODO: Explain in the JavaDocs that the insets are actually offsets.
0083: * And describe that these offsets are not taken into account when
0084: * FormLayout computes the column and row sizes.<p>
0085: *
0086: * TODO: Rename the inset to offsets.<p>
0087: *
0088: * TODO: In the Forms 1.0.x invisible components are not taken into account
0089: * when the FormLayout lays out the container. Add an optional setting for
0090: * this on both the container-level and component-level. So one can specify
0091: * that invisible components shall be taken into account, but may exclude
0092: * individual components. Or the other way round, exclude invisible components,
0093: * and include individual components. The API of both the FormLayout and
0094: * CellConstraints classes shall be extended to support this option.
0095: * This feature is planned for the Forms version 1.1 and is described in
0096: * <a href="https://forms.dev.java.net/issues/show_bug.cgi?id=28">issue #28</a>
0097: * of the Forms' issue tracker where you can track the progress.
0098: *
0099: * @author Karsten Lentzsch
0100: * @version $Revision: 1.4 $
0101: */
0102: public final class CellConstraints implements Cloneable, Serializable {
0103:
0104: // Alignment Constants *************************************************
0105:
0106: /*
0107: * Implementation Note: Do not change the order of the following constants.
0108: * The serialization of class Alignment is ordinal-based and relies on it.
0109: */
0110:
0111: /**
0112: * Use the column's or row's default alignment.
0113: */
0114: public static final Alignment DEFAULT = new Alignment("default",
0115: Alignment.BOTH);
0116:
0117: /**
0118: * Fill the cell either horizontally or vertically.
0119: */
0120: public static final Alignment FILL = new Alignment("fill",
0121: Alignment.BOTH);
0122:
0123: /**
0124: * Put the component in the left.
0125: */
0126: public static final Alignment LEFT = new Alignment("left",
0127: Alignment.HORIZONTAL);
0128:
0129: /**
0130: * Put the component in the right.
0131: */
0132: public static final Alignment RIGHT = new Alignment("right",
0133: Alignment.HORIZONTAL);
0134:
0135: /**
0136: * Put the component in the center.
0137: */
0138: public static final Alignment CENTER = new Alignment("center",
0139: Alignment.BOTH);
0140:
0141: /**
0142: * Put the component in the top.
0143: */
0144: public static final Alignment TOP = new Alignment("top",
0145: Alignment.VERTICAL);
0146:
0147: /**
0148: * Put the component in the bottom.
0149: */
0150: public static final Alignment BOTTOM = new Alignment("bottom",
0151: Alignment.VERTICAL);
0152:
0153: /**
0154: * An array of all enumeration values used to canonicalize
0155: * deserialized alignments.
0156: */
0157: private static final Alignment[] VALUES = { DEFAULT, FILL, LEFT,
0158: RIGHT, CENTER, TOP, BOTTOM };
0159:
0160: /**
0161: * A reusable <code>Insets</code> object to reduce object instantiation.
0162: */
0163: private static final Insets EMPTY_INSETS = new Insets(0, 0, 0, 0);
0164:
0165: // Fields ***************************************************************
0166:
0167: /**
0168: * Describes the component's horizontal grid origin (starts at 1).
0169: */
0170: public int gridX;
0171:
0172: /**
0173: * Describes the component's vertical grid origin (starts at 1).
0174: */
0175: public int gridY;
0176:
0177: /**
0178: * Describes the component's horizontal grid extend (number of cells).
0179: */
0180: public int gridWidth;
0181:
0182: /**
0183: * Describes the component's vertical grid extent (number of cells).
0184: */
0185: public int gridHeight;
0186:
0187: /**
0188: * Describes the component's horizontal alignment.
0189: */
0190: public Alignment hAlign;
0191:
0192: /**
0193: * Describes the component's vertical alignment.
0194: */
0195: public Alignment vAlign;
0196:
0197: /**
0198: * Describes the component's <code>Insets</code> in it's display area.
0199: */
0200: public Insets insets;
0201:
0202: // Instance Creation ****************************************************
0203:
0204: /**
0205: * Constructs a default instance of <code>CellConstraints</code>.
0206: */
0207: public CellConstraints() {
0208: this (1, 1);
0209: }
0210:
0211: /**
0212: * Constructs an instance of <code>CellConstraints</code> for the given
0213: * cell position.<p>
0214: *
0215: * <strong>Examples:</strong><pre>
0216: * new CellConstraints(1, 3);
0217: * new CellConstraints(1, 3);
0218: * </pre>
0219: *
0220: * @param gridX the component's horizontal grid origin
0221: * @param gridY the component's vertical grid origin
0222: */
0223: public CellConstraints(int gridX, int gridY) {
0224: this (gridX, gridY, 1, 1);
0225: }
0226:
0227: /**
0228: * Constructs an instance of <code>CellConstraints</code> for the given
0229: * cell position, anchor, and fill.<p>
0230: *
0231: * <strong>Examples:</strong><pre>
0232: * new CellConstraints(1, 3, CellConstraints.LEFT, CellConstraints.BOTTOM);
0233: * new CellConstraints(1, 3, CellConstraints.CENTER, CellConstraints.FILL);
0234: * </pre>
0235: *
0236: * @param gridX the component's horizontal grid origin
0237: * @param gridY the component's vertical grid origin
0238: * @param hAlign the component's horizontal alignment
0239: * @param vAlign the component's vertical alignment
0240: */
0241: public CellConstraints(int gridX, int gridY, Alignment hAlign,
0242: Alignment vAlign) {
0243: this (gridX, gridY, 1, 1, hAlign, vAlign, EMPTY_INSETS);
0244: }
0245:
0246: /**
0247: * Constructs an instance of <code>CellConstraints</code> for the given
0248: * cell position and size.<p>
0249: *
0250: * <strong>Examples:</strong><pre>
0251: * new CellConstraints(1, 3, 2, 1);
0252: * new CellConstraints(1, 3, 7, 3);
0253: * </pre>
0254: *
0255: * @param gridX the component's horizontal grid origin
0256: * @param gridY the component's vertical grid origin
0257: * @param gridWidth the component's horizontal extent
0258: * @param gridHeight the component's vertical extent
0259: */
0260: public CellConstraints(int gridX, int gridY, int gridWidth,
0261: int gridHeight) {
0262: this (gridX, gridY, gridWidth, gridHeight, DEFAULT, DEFAULT);
0263: }
0264:
0265: /**
0266: * Constructs an instance of <code>CellConstraints</code> for the given
0267: * cell position and size, anchor, and fill.<p>
0268: *
0269: * <strong>Examples:</strong><pre>
0270: * new CellConstraints(1, 3, 2, 1, CellConstraints.LEFT, CellConstraints.BOTTOM);
0271: * new CellConstraints(1, 3, 7, 3, CellConstraints.CENTER, CellConstraints.FILL);
0272: * </pre>
0273: *
0274: * @param gridX the component's horizontal grid origin
0275: * @param gridY the component's vertical grid origin
0276: * @param gridWidth the component's horizontal extent
0277: * @param gridHeight the component's vertical extent
0278: * @param hAlign the component's horizontal alignment
0279: * @param vAlign the component's vertical alignment
0280: */
0281: public CellConstraints(int gridX, int gridY, int gridWidth,
0282: int gridHeight, Alignment hAlign, Alignment vAlign) {
0283: this (gridX, gridY, gridWidth, gridHeight, hAlign, vAlign,
0284: EMPTY_INSETS);
0285: }
0286:
0287: /**
0288: * Constructs an instance of <code>CellConstraints</code> for
0289: * the complete set of available properties.<p>
0290: *
0291: * <strong>Examples:</strong><pre>
0292: * new CellConstraints(1, 3, 2, 1, CellConstraints.LEFT, CellConstraints.BOTTOM, new Insets(0, 1, 0, 3));
0293: * new CellConstraints(1, 3, 7, 3, CellConstraints.CENTER, CellConstraints.FILL, new Insets(0, 1, 0, 0));
0294: * </pre>
0295: *
0296: * @param gridX the component's horizontal grid origin
0297: * @param gridY the component's vertical grid origin
0298: * @param gridWidth the component's horizontal extent
0299: * @param gridHeight the component's vertical extent
0300: * @param hAlign the component's horizontal alignment
0301: * @param vAlign the component's vertical alignment
0302: * @param insets the component's display area <code>Insets</code>
0303: * @throws IndexOutOfBoundsException if the grid origin or extent is negative
0304: * @throws NullPointerException if the horizontal or vertical alignment is null
0305: * @throws IllegalArgumentException if an alignment orientation is invalid
0306: */
0307: public CellConstraints(int gridX, int gridY, int gridWidth,
0308: int gridHeight, Alignment hAlign, Alignment vAlign,
0309: Insets insets) {
0310: this .gridX = gridX;
0311: this .gridY = gridY;
0312: this .gridWidth = gridWidth;
0313: this .gridHeight = gridHeight;
0314: this .hAlign = hAlign;
0315: this .vAlign = vAlign;
0316: this .insets = insets;
0317: if (gridX <= 0)
0318: throw new IndexOutOfBoundsException(
0319: "The grid x must be a positive number.");
0320: if (gridY <= 0)
0321: throw new IndexOutOfBoundsException(
0322: "The grid y must be a positive number.");
0323: if (gridWidth <= 0)
0324: throw new IndexOutOfBoundsException(
0325: "The grid width must be a positive number.");
0326: if (gridHeight <= 0)
0327: throw new IndexOutOfBoundsException(
0328: "The grid height must be a positive number.");
0329: if (hAlign == null)
0330: throw new NullPointerException(
0331: "The horizontal alignment must not be null.");
0332: if (vAlign == null)
0333: throw new NullPointerException(
0334: "The vertical alignment must not be null.");
0335: ensureValidOrientations(hAlign, vAlign);
0336: }
0337:
0338: /**
0339: * Constructs an instance of <code>CellConstraints</code> from
0340: * the given encoded string properties.<p>
0341: *
0342: * <strong>Examples:</strong><pre>
0343: * new CellConstraints("1, 3");
0344: * new CellConstraints("1, 3, left, bottom");
0345: * new CellConstraints("1, 3, 2, 1, left, bottom");
0346: * new CellConstraints("1, 3, 2, 1, l, b");
0347: * </pre>
0348: *
0349: * @param encodedConstraints the constraints encoded as string
0350: */
0351: public CellConstraints(String encodedConstraints) {
0352: this ();
0353: initFromConstraints(encodedConstraints);
0354: }
0355:
0356: // Setters with Column-Row Order ******************************************
0357:
0358: /**
0359: * Sets column and row origins; sets width and height to 1;
0360: * uses the default alignments.<p>
0361: *
0362: * <strong>Examples:</strong><pre>
0363: * cc.xy(1, 1);
0364: * cc.xy(1, 3);
0365: * </pre>
0366: *
0367: * @param col the new column index
0368: * @param row the new row index
0369: * @return this
0370: */
0371: public CellConstraints xy(int col, int row) {
0372: return xywh(col, row, 1, 1);
0373: }
0374:
0375: /**
0376: * Sets column and row origins; sets width and height to 1;
0377: * decodes horizontal and vertical alignments from the given string.<p>
0378: *
0379: * <strong>Examples:</strong><pre>
0380: * cc.xy(1, 3, "left, bottom");
0381: * cc.xy(1, 3, "l, b");
0382: * cc.xy(1, 3, "center, fill");
0383: * cc.xy(1, 3, "c, f");
0384: * </pre>
0385: *
0386: * @param col the new column index
0387: * @param row the new row index
0388: * @param encodedAlignments describes the horizontal and vertical alignments
0389: * @return this
0390: *
0391: * @throws IllegalArgumentException if an alignment orientation is invalid
0392: */
0393: public CellConstraints xy(int col, int row, String encodedAlignments) {
0394: return xywh(col, row, 1, 1, encodedAlignments);
0395: }
0396:
0397: /**
0398: * Sets the column and row origins; sets width and height to 1;
0399: * set horizontal and vertical alignment using the specified objects.<p>
0400: *
0401: * <strong>Examples:</strong><pre>
0402: * cc.xy(1, 3, CellConstraints.LEFT, CellConstraints.BOTTOM);
0403: * cc.xy(1, 3, CellConstraints.CENTER, CellConstraints.FILL);
0404: * </pre>
0405: *
0406: * @param col the new column index
0407: * @param row the new row index
0408: * @param colAlign horizontal component alignment
0409: * @param rowAlign vertical component alignment
0410: * @return this
0411: */
0412: public CellConstraints xy(int col, int row, Alignment colAlign,
0413: Alignment rowAlign) {
0414: return xywh(col, row, 1, 1, colAlign, rowAlign);
0415: }
0416:
0417: /**
0418: * Sets the column, row, width, and height; uses a height (row span) of 1
0419: * and the horizontal and vertical default alignments.<p>
0420: *
0421: * <strong>Examples:</strong><pre>
0422: * cc.xyw(1, 3, 7);
0423: * cc.xyw(1, 3, 2);
0424: * </pre>
0425: *
0426: * @param col the new column index
0427: * @param row the new row index
0428: * @param colSpan the column span or grid width
0429: * @return this
0430: */
0431: public CellConstraints xyw(int col, int row, int colSpan) {
0432: return xywh(col, row, colSpan, 1, DEFAULT, DEFAULT);
0433: }
0434:
0435: /**
0436: * Sets the column, row, width, and height;
0437: * decodes the horizontal and vertical alignments from the given string.
0438: * The row span (height) is set to 1.<p>
0439: *
0440: * <strong>Examples:</strong><pre>
0441: * cc.xyw(1, 3, 7, "left, bottom");
0442: * cc.xyw(1, 3, 7, "l, b");
0443: * cc.xyw(1, 3, 2, "center, fill");
0444: * cc.xyw(1, 3, 2, "c, f");
0445: * </pre>
0446: *
0447: * @param col the new column index
0448: * @param row the new row index
0449: * @param colSpan the column span or grid width
0450: * @param encodedAlignments describes the horizontal and vertical alignments
0451: * @return this
0452: * @throws IllegalArgumentException if an alignment orientation is invalid
0453: */
0454: public CellConstraints xyw(int col, int row, int colSpan,
0455: String encodedAlignments) {
0456: return xywh(col, row, colSpan, 1, encodedAlignments);
0457: }
0458:
0459: /**
0460: * Sets the column, row, width, and height; sets the horizontal
0461: * and vertical aligment using the specified alignment objects.
0462: * The row span (height) is set to 1.<p>
0463: *
0464: * <strong>Examples:</strong><pre>
0465: * cc.xyw(1, 3, 2, CellConstraints.LEFT, CellConstraints.BOTTOM);
0466: * cc.xyw(1, 3, 7, CellConstraints.CENTER, CellConstraints.FILL);
0467: * </pre>
0468: *
0469: * @param col the new column index
0470: * @param row the new row index
0471: * @param colSpan the column span or grid width
0472: * @param colAlign horizontal component alignment
0473: * @param rowAlign vertical component alignment
0474: * @return this
0475: * @throws IllegalArgumentException if an alignment orientation is invalid
0476: */
0477: public CellConstraints xyw(int col, int row, int colSpan,
0478: Alignment colAlign, Alignment rowAlign) {
0479: return xywh(col, row, colSpan, 1, colAlign, rowAlign);
0480: }
0481:
0482: /**
0483: * Sets the column, row, width, and height; uses default alignments.<p>
0484: *
0485: * <strong>Examples:</strong><pre>
0486: * cc.xywh(1, 3, 2, 1);
0487: * cc.xywh(1, 3, 7, 3);
0488: * </pre>
0489: *
0490: * @param col the new column index
0491: * @param row the new row index
0492: * @param colSpan the column span or grid width
0493: * @param rowSpan the row span or grid height
0494: * @return this
0495: */
0496: public CellConstraints xywh(int col, int row, int colSpan,
0497: int rowSpan) {
0498: return xywh(col, row, colSpan, rowSpan, DEFAULT, DEFAULT);
0499: }
0500:
0501: /**
0502: * Sets the column, row, width, and height;
0503: * decodes the horizontal and vertical alignments from the given string.<p>
0504: *
0505: * <strong>Examples:</strong><pre>
0506: * cc.xywh(1, 3, 2, 1, "left, bottom");
0507: * cc.xywh(1, 3, 2, 1, "l, b");
0508: * cc.xywh(1, 3, 7, 3, "center, fill");
0509: * cc.xywh(1, 3, 7, 3, "c, f");
0510: * </pre>
0511: *
0512: * @param col the new column index
0513: * @param row the new row index
0514: * @param colSpan the column span or grid width
0515: * @param rowSpan the row span or grid height
0516: * @param encodedAlignments describes the horizontal and vertical alignments
0517: * @return this
0518: * @throws IllegalArgumentException if an alignment orientation is invalid
0519: */
0520: public CellConstraints xywh(int col, int row, int colSpan,
0521: int rowSpan, String encodedAlignments) {
0522: CellConstraints result = xywh(col, row, colSpan, rowSpan);
0523: result.setAlignments(encodedAlignments, true);
0524: return result;
0525: }
0526:
0527: /**
0528: * Sets the column, row, width, and height; sets the horizontal
0529: * and vertical aligment using the specified alignment objects.<p>
0530: *
0531: * <strong>Examples:</strong><pre>
0532: * cc.xywh(1, 3, 2, 1, CellConstraints.LEFT, CellConstraints.BOTTOM);
0533: * cc.xywh(1, 3, 7, 3, CellConstraints.CENTER, CellConstraints.FILL);
0534: * </pre>
0535: *
0536: * @param col the new column index
0537: * @param row the new row index
0538: * @param colSpan the column span or grid width
0539: * @param rowSpan the row span or grid height
0540: * @param colAlign horizontal component alignment
0541: * @param rowAlign vertical component alignment
0542: * @return this
0543: * @throws IllegalArgumentException if an alignment orientation is invalid
0544: */
0545: public CellConstraints xywh(int col, int row, int colSpan,
0546: int rowSpan, Alignment colAlign, Alignment rowAlign) {
0547: this .gridX = col;
0548: this .gridY = row;
0549: this .gridWidth = colSpan;
0550: this .gridHeight = rowSpan;
0551: this .hAlign = colAlign;
0552: this .vAlign = rowAlign;
0553: ensureValidOrientations(hAlign, vAlign);
0554: return this ;
0555: }
0556:
0557: // Setters with Row-Column Order ******************************************
0558:
0559: /**
0560: * Sets row and column origins; sets height and width to 1;
0561: * uses the default alignments.<p>
0562: *
0563: * <strong>Examples:</strong><pre>
0564: * cc.rc(1, 1);
0565: * cc.rc(3, 1);
0566: * </pre>
0567: *
0568: * @param row the new row index
0569: * @param col the new column index
0570: * @return this
0571: *
0572: * @since 1.1
0573: */
0574: public CellConstraints rc(int row, int col) {
0575: return rchw(row, col, 1, 1);
0576: }
0577:
0578: /**
0579: * Sets row and column origins; sets height and width to 1;
0580: * decodes vertical and horizontal alignments from the given string.<p>
0581: *
0582: * <strong>Examples:</strong><pre>
0583: * cc.rc(3, 1, "bottom, left");
0584: * cc.rc(3, 1, "b, l");
0585: * cc.rc(3, 1, "fill, center");
0586: * cc.rc(3, 1, "f, c");
0587: * </pre>
0588: *
0589: * @param row the new row index
0590: * @param col the new column index
0591: * @param encodedAlignments describes the vertical and horizontal alignments
0592: * @return this
0593: *
0594: * @throws IllegalArgumentException if an alignment orientation is invalid
0595: *
0596: * @since 1.1
0597: */
0598: public CellConstraints rc(int row, int col, String encodedAlignments) {
0599: return rchw(row, col, 1, 1, encodedAlignments);
0600: }
0601:
0602: /**
0603: * Sets the row and column origins; sets width and height to 1;
0604: * set horizontal and vertical alignment using the specified objects.<p>
0605: *
0606: * <strong>Examples:</strong><pre>
0607: * cc.rc(3, 1, CellConstraints.BOTTOM, CellConstraints.LEFT);
0608: * cc.rc(3, 1, CellConstraints.FILL, CellConstraints.CENTER);
0609: * </pre>
0610: *
0611: * @param row the new row index
0612: * @param col the new column index
0613: * @param rowAlign vertical component alignment
0614: * @param colAlign horizontal component alignment
0615: * @return this
0616: *
0617: * @since 1.1
0618: */
0619: public CellConstraints rc(int row, int col, Alignment rowAlign,
0620: Alignment colAlign) {
0621: return rchw(row, col, 1, 1, rowAlign, colAlign);
0622: }
0623:
0624: /**
0625: * Sets the row, column, height, and width; uses a height (row span) of 1
0626: * and the vertical and horizontal default alignments.<p>
0627: *
0628: * <strong>Examples:</strong><pre>
0629: * cc.rcw(3, 1, 7);
0630: * cc.rcw(3, 1, 2);
0631: * </pre>
0632: *
0633: * @param row the new row index
0634: * @param col the new column index
0635: * @param colSpan the column span or grid width
0636: * @return this
0637: *
0638: * @since 1.1
0639: */
0640: public CellConstraints rcw(int row, int col, int colSpan) {
0641: return rchw(row, col, 1, colSpan, DEFAULT, DEFAULT);
0642: }
0643:
0644: /**
0645: * Sets the row, column, height, and width;
0646: * decodes the vertical and horizontal alignments from the given string.
0647: * The row span (height) is set to 1.<p>
0648: *
0649: * <strong>Examples:</strong><pre>
0650: * cc.rcw(3, 1, 7, "bottom, left");
0651: * cc.rcw(3, 1, 7, "b, l");
0652: * cc.rcw(3, 1, 2, "fill, center");
0653: * cc.rcw(3, 1, 2, "f, c");
0654: * </pre>
0655: *
0656: * @param row the new row index
0657: * @param col the new column index
0658: * @param colSpan the column span or grid width
0659: * @param encodedAlignments describes the vertical and horizontal alignments
0660: * @return this
0661: *
0662: * @throws IllegalArgumentException if an alignment orientation is invalid
0663: *
0664: * @since 1.1
0665: */
0666: public CellConstraints rcw(int row, int col, int colSpan,
0667: String encodedAlignments) {
0668: return rchw(row, col, 1, colSpan, encodedAlignments);
0669: }
0670:
0671: /**
0672: * Sets the row, column, height, and width; sets the vertical
0673: * and horizontalaligment using the specified alignment objects.
0674: * The row span (height) is set to 1.<p>
0675: *
0676: * <strong>Examples:</strong><pre>
0677: * cc.rcw(3, 1, 2, CellConstraints.BOTTOM, CellConstraints.LEFT);
0678: * cc.rcw(3, 1, 7, CellConstraints.FILL, CellConstraints.CENTER);
0679: * </pre>
0680: *
0681: * @param row the new row index
0682: * @param col the new column index
0683: * @param colSpan the column span or grid width
0684: * @param rowAlign vertical component alignment
0685: * @param colAlign horizontal component alignment
0686: * @return this
0687: *
0688: * @throws IllegalArgumentException if an alignment orientation is invalid
0689: *
0690: * @since 1.1
0691: */
0692: public CellConstraints rcw(int row, int col, int colSpan,
0693: Alignment rowAlign, Alignment colAlign) {
0694: return rchw(row, col, 1, colSpan, rowAlign, colAlign);
0695: }
0696:
0697: /**
0698: * Sets the row, column, height, and width; uses default alignments.<p>
0699: *
0700: * <strong>Examples:</strong><pre>
0701: * cc.rchw(1, 3, 2, 1);
0702: * cc.rchw(1, 3, 7, 3);
0703: * </pre>
0704: *
0705: * @param row the new row index
0706: * @param col the new column index
0707: * @param rowSpan the row span or grid height
0708: * @param colSpan the column span or grid width
0709: * @return this
0710: *
0711: * @since 1.1
0712: */
0713: public CellConstraints rchw(int row, int col, int rowSpan,
0714: int colSpan) {
0715: return rchw(row, col, rowSpan, colSpan, DEFAULT, DEFAULT);
0716: }
0717:
0718: /**
0719: * Sets the row, column, height, and width;
0720: * decodes the vertical and horizontal alignments from the given string.<p>
0721: *
0722: * <strong>Examples:</strong><pre>
0723: * cc.rchw(3, 1, 1, 2, "bottom, left");
0724: * cc.rchw(3, 1, 1, 2, "b, l");
0725: * cc.rchw(3, 1, 3, 7, "fill, center");
0726: * cc.rchw(3, 1, 3, 7, "f, c");
0727: * </pre>
0728: *
0729: * @param row the new row index
0730: * @param col the new column index
0731: * @param rowSpan the row span or grid height
0732: * @param colSpan the column span or grid width
0733: * @param encodedAlignments describes the vertical and horizontal alignments
0734: * @return this
0735: * @throws IllegalArgumentException if an alignment orientation is invalid
0736: *
0737: * @since 1.1
0738: */
0739: public CellConstraints rchw(int row, int col, int rowSpan,
0740: int colSpan, String encodedAlignments) {
0741: CellConstraints result = rchw(row, col, rowSpan, colSpan);
0742: result.setAlignments(encodedAlignments, false);
0743: return result;
0744: }
0745:
0746: /**
0747: * Sets the row, column, height, and width; sets the vertical and
0748: * horizontal aligment using the specified alignment objects.<p>
0749: *
0750: * <strong>Examples:</strong><pre>
0751: * cc.rchw(3, 1, 1, 2, CellConstraints.BOTTOM, CellConstraints.LEFT);
0752: * cc.rchw(3, 1, 3, 7, CellConstraints.FILL, CellConstraints.CENTER);
0753: * </pre>
0754: *
0755: * @param row the new row index
0756: * @param col the new column index
0757: * @param rowSpan the row span or grid height
0758: * @param colSpan the column span or grid width
0759: * @param rowAlign vertical component alignment
0760: * @param colAlign horizontal component alignment
0761: * @return this
0762: *
0763: * @throws IllegalArgumentException if an alignment orientation is invalid
0764: *
0765: * @since 1.1
0766: */
0767: public CellConstraints rchw(int row, int col, int rowSpan,
0768: int colSpan, Alignment rowAlign, Alignment colAlign) {
0769: return xywh(col, row, colSpan, rowSpan, colAlign, rowAlign);
0770: }
0771:
0772: // Parsing and Decoding String Descriptions *****************************
0773:
0774: /**
0775: * Decodes and returns the grid bounds and alignments for this
0776: * constraints as an array of six integers. The string representation
0777: * is a comma separated sequence, one of
0778: * <pre>
0779: * "x, y"
0780: * "x, y, w, h"
0781: * "x, y, hAlign, vAlign"
0782: * "x, y, w, h, hAlign, vAlign"
0783: * </pre>
0784: *
0785: * @param encodedConstraints represents horizontal and vertical alignment
0786: *
0787: * @throws IllegalArgumentException if the encoded constraints do not
0788: * follow the constraint syntax
0789: */
0790: private void initFromConstraints(String encodedConstraints) {
0791: StringTokenizer tokenizer = new StringTokenizer(
0792: encodedConstraints, " ,");
0793: int argCount = tokenizer.countTokens();
0794: if (!(argCount == 2 || argCount == 4 || argCount == 6))
0795: throw new IllegalArgumentException(
0796: "You must provide 2, 4 or 6 arguments.");
0797:
0798: Integer nextInt = decodeInt(tokenizer.nextToken());
0799: if (nextInt == null) {
0800: throw new IllegalArgumentException(
0801: "First cell constraint element must be a number.");
0802: }
0803: gridX = nextInt.intValue();
0804: if (gridX <= 0)
0805: throw new IndexOutOfBoundsException(
0806: "The grid x must be a positive number.");
0807:
0808: nextInt = decodeInt(tokenizer.nextToken());
0809: if (nextInt == null) {
0810: throw new IllegalArgumentException(
0811: "Second cell constraint element must be a number.");
0812: }
0813: gridY = nextInt.intValue();
0814: if (gridY <= 0)
0815: throw new IndexOutOfBoundsException(
0816: "The grid y must be a positive number.");
0817:
0818: if (!tokenizer.hasMoreTokens())
0819: return;
0820:
0821: String token = tokenizer.nextToken();
0822: nextInt = decodeInt(token);
0823: if (nextInt != null) {
0824: // Case: "x, y, w, h" or
0825: // "x, y, w, h, hAlign, vAlign"
0826: gridWidth = nextInt.intValue();
0827: if (gridWidth <= 0)
0828: throw new IndexOutOfBoundsException(
0829: "The grid width must be a positive number.");
0830: nextInt = decodeInt(tokenizer.nextToken());
0831: if (nextInt == null)
0832: throw new IllegalArgumentException(
0833: "Fourth cell constraint element must be like third.");
0834: gridHeight = nextInt.intValue();
0835: if (gridHeight <= 0)
0836: throw new IndexOutOfBoundsException(
0837: "The grid height must be a positive number.");
0838:
0839: if (!tokenizer.hasMoreTokens())
0840: return;
0841: token = tokenizer.nextToken();
0842: }
0843:
0844: hAlign = decodeAlignment(token);
0845: vAlign = decodeAlignment(tokenizer.nextToken());
0846: ensureValidOrientations(hAlign, vAlign);
0847: }
0848:
0849: /**
0850: * Decodes a string description for the horizontal and vertical alignment
0851: * and sets this CellConstraints' alignment values. If the boolean is
0852: * <code>true</code> the horizontal alignment is the first token,
0853: * and the vertical alignment is the second token. if the boolean is
0854: * <code>false</code> the vertical alignment comes first. <p>
0855: *
0856: * Valid horizontal aligmnents are: left, middle, right, default, and fill.
0857: * Valid vertical alignments are: top, center, bottom, default, and fill.
0858: * The anchor's string representation abbreviates the alignment:
0859: * l, m, r, d, f, t, c, and b.<p>
0860: *
0861: * Anchor examples:
0862: * "m, c" is centered, "l, t" is northwest, "m, t" is north, "r, c" east.
0863: * "m, d" is horizontally centered and uses the row's default alignment.
0864: * "d, t" is on top of the cell and uses the column's default alignment.<p>
0865: *
0866: * @param encodedAlignments represents horizontal and vertical alignment
0867: * @throws IllegalArgumentException if an alignment orientation is invalid
0868: */
0869: private void setAlignments(String encodedAlignments,
0870: boolean horizontalThenVertical) {
0871: StringTokenizer tokenizer = new StringTokenizer(
0872: encodedAlignments, " ,");
0873: Alignment first = decodeAlignment(tokenizer.nextToken());
0874: Alignment second = decodeAlignment(tokenizer.nextToken());
0875: hAlign = horizontalThenVertical ? first : second;
0876: vAlign = horizontalThenVertical ? second : first;
0877: ensureValidOrientations(hAlign, vAlign);
0878: }
0879:
0880: /**
0881: * Decodes an integer string representation and returns the
0882: * associated Integer or null in case of an invalid number format.
0883: *
0884: * @param token the encoded integer
0885: * @return the decoded Integer or null
0886: */
0887: private Integer decodeInt(String token) {
0888: try {
0889: return Integer.decode(token);
0890: } catch (NumberFormatException e) {
0891: return null;
0892: }
0893: }
0894:
0895: /**
0896: * Parses an alignment string description and
0897: * returns the corresponding alignment value.
0898: *
0899: * @param encodedAlignment the encoded alignment
0900: * @return the associated <code>Alignment</code> instance
0901: */
0902: private Alignment decodeAlignment(String encodedAlignment) {
0903: return Alignment.valueOf(encodedAlignment);
0904: }
0905:
0906: /**
0907: * Checks and verifies that this constraints object has valid grid
0908: * index values, i. e. the display area cells are inside the form's grid.
0909: *
0910: * @param colCount number of columns in the grid
0911: * @param rowCount number of rows in the grid
0912: * @throws IndexOutOfBoundsException if the display area described
0913: * by this constraints object is not inside the grid
0914: */
0915: void ensureValidGridBounds(int colCount, int rowCount) {
0916: if (gridX <= 0) {
0917: throw new IndexOutOfBoundsException("The column index "
0918: + gridX + " must be positive.");
0919: }
0920: if (gridX > colCount) {
0921: throw new IndexOutOfBoundsException("The column index "
0922: + gridX + " must be less than or equal to "
0923: + colCount + ".");
0924: }
0925: if (gridX + gridWidth - 1 > colCount) {
0926: throw new IndexOutOfBoundsException("The grid width "
0927: + gridWidth + " must be less than or equal to "
0928: + (colCount - gridX + 1) + ".");
0929: }
0930: if (gridY <= 0) {
0931: throw new IndexOutOfBoundsException("The row index "
0932: + gridY + " must be positive.");
0933: }
0934: if (gridY > rowCount) {
0935: throw new IndexOutOfBoundsException("The row index "
0936: + gridY + " must be less than or equal to "
0937: + rowCount + ".");
0938: }
0939: if (gridY + gridHeight - 1 > rowCount) {
0940: throw new IndexOutOfBoundsException("The grid height "
0941: + gridHeight + " must be less than or equal to "
0942: + (rowCount - gridY + 1) + ".");
0943: }
0944: }
0945:
0946: /**
0947: * Checks and verifies that the horizontal alignment is a horizontal
0948: * and the vertical alignment is vertical.
0949: *
0950: * @param horizontalAlignment the horizontal alignment
0951: * @param verticalAlignment the vertical alignment
0952: * @throws IllegalArgumentException if an alignment is invalid
0953: */
0954: private void ensureValidOrientations(Alignment horizontalAlignment,
0955: Alignment verticalAlignment) {
0956: if (!horizontalAlignment.isHorizontal())
0957: throw new IllegalArgumentException(
0958: "The horizontal alignment must be one of: left, center, right, fill, default.");
0959: if (!verticalAlignment.isVertical())
0960: throw new IllegalArgumentException(
0961: "The vertical alignment must be one of: top, center, botto, fill, default.");
0962: }
0963:
0964: // Settings Component Bounds ********************************************
0965:
0966: /**
0967: * Sets the component's bounds using the given component and cell bounds.
0968: *
0969: * @param c the component to set bounds
0970: * @param layout the FormLayout instance that computes the bounds
0971: * @param cellBounds the cell's bounds
0972: * @param minWidthMeasure measures the minimum width
0973: * @param minHeightMeasure measures the minimum height
0974: * @param prefWidthMeasure measures the preferred width
0975: * @param prefHeightMeasure measures the preferred height
0976: */
0977: void setBounds(Component c, FormLayout layout,
0978: Rectangle cellBounds, FormLayout.Measure minWidthMeasure,
0979: FormLayout.Measure minHeightMeasure,
0980: FormLayout.Measure prefWidthMeasure,
0981: FormLayout.Measure prefHeightMeasure) {
0982: ColumnSpec colSpec = gridWidth == 1 ? layout
0983: .getColumnSpec(gridX) : null;
0984: RowSpec rowSpec = gridHeight == 1 ? layout.getRowSpec(gridY)
0985: : null;
0986: Alignment concreteHAlign = concreteAlignment(this .hAlign,
0987: colSpec);
0988: Alignment concreteVAlign = concreteAlignment(this .vAlign,
0989: rowSpec);
0990: Insets concreteInsets = this .insets != null ? this .insets
0991: : EMPTY_INSETS;
0992: int cellX = cellBounds.x + concreteInsets.left;
0993: int cellY = cellBounds.y + concreteInsets.top;
0994: int cellW = cellBounds.width - concreteInsets.left
0995: - concreteInsets.right;
0996: int cellH = cellBounds.height - concreteInsets.top
0997: - concreteInsets.bottom;
0998: int compW = componentSize(c, colSpec, cellW, minWidthMeasure,
0999: prefWidthMeasure);
1000: int compH = componentSize(c, rowSpec, cellH, minHeightMeasure,
1001: prefHeightMeasure);
1002: int x = origin(concreteHAlign, cellX, cellW, compW);
1003: int y = origin(concreteVAlign, cellY, cellH, compH);
1004: int w = extent(concreteHAlign, cellW, compW);
1005: int h = extent(concreteVAlign, cellH, compH);
1006: c.setBounds(x, y, w, h);
1007: }
1008:
1009: /**
1010: * Computes and returns the concrete alignment. Takes into account
1011: * the cell alignment and <i>the</i> <code>FormSpec</code> if applicable.<p>
1012: *
1013: * If this constraints object doesn't belong to a single column or row,
1014: * the <code>formSpec</code> parameter is <code>null</code>.
1015: * In this case the cell alignment is answered, but <code>DEFAULT</code>
1016: * is mapped to <code>FILL</code>.<p>
1017: *
1018: * If the cell belongs to a single column or row, we use the cell
1019: * alignment, unless it is <code>DEFAULT</code>, where the alignment
1020: * is inherited from the column or row resp.
1021: *
1022: * @param cellAlignment this cell's aligment
1023: * @param formSpec the associated column or row specification
1024: * @return the concrete alignment
1025: */
1026: private Alignment concreteAlignment(Alignment cellAlignment,
1027: FormSpec formSpec) {
1028: return formSpec == null ? (cellAlignment == DEFAULT ? FILL
1029: : cellAlignment) : usedAlignment(cellAlignment,
1030: formSpec);
1031: }
1032:
1033: /**
1034: * Returns the alignment used for a given form constraints object.
1035: * The cell alignment overrides the column or row default, unless
1036: * it is <code>DEFAULT</code>. In the latter case, we use the
1037: * column or row alignment.
1038: *
1039: * @param cellAlignment this cell constraint's alignment
1040: * @param formSpec the associated column or row specification
1041: * @return the alignment used
1042: */
1043: private Alignment usedAlignment(Alignment cellAlignment,
1044: FormSpec formSpec) {
1045: if (cellAlignment != CellConstraints.DEFAULT) {
1046: // Cell alignments other than DEFAULT override col/row alignments
1047: return cellAlignment;
1048: }
1049: FormSpec.DefaultAlignment defaultAlignment = formSpec
1050: .getDefaultAlignment();
1051: if (defaultAlignment == FormSpec.FILL_ALIGN)
1052: return FILL;
1053: if (defaultAlignment == ColumnSpec.LEFT)
1054: return LEFT;
1055: else if (defaultAlignment == FormSpec.CENTER_ALIGN)
1056: return CENTER;
1057: else if (defaultAlignment == ColumnSpec.RIGHT)
1058: return RIGHT;
1059: else if (defaultAlignment == RowSpec.TOP)
1060: return TOP;
1061: else
1062: return BOTTOM;
1063: }
1064:
1065: /**
1066: * Computes and returns the pixel size of the given component using the
1067: * given form specification, measures, and cell size.
1068: *
1069: * @param component the component to measure
1070: * @param formSpec the specification of the component's column/row
1071: * @param minMeasure the measure for the minimum size
1072: * @param prefMeasure the measure for the preferred size
1073: * @param cellSize the cell size
1074: * @return the component size as measured or a constant
1075: */
1076: private int componentSize(Component component, FormSpec formSpec,
1077: int cellSize, FormLayout.Measure minMeasure,
1078: FormLayout.Measure prefMeasure) {
1079: if (formSpec == null) {
1080: return prefMeasure.sizeOf(component);
1081: } else if (formSpec.getSize() == Sizes.MINIMUM) {
1082: return minMeasure.sizeOf(component);
1083: } else if (formSpec.getSize() == Sizes.PREFERRED) {
1084: return prefMeasure.sizeOf(component);
1085: } else { // default mode
1086: return Math.min(cellSize, prefMeasure.sizeOf(component));
1087: }
1088: }
1089:
1090: /**
1091: * Computes and returns the component's pixel origin.
1092: *
1093: * @param alignment the component's alignment
1094: * @param cellOrigin the origin of the display area
1095: * @param cellSize the extent of the display area
1096: * @param componentSize
1097: * @return the component's pixel origin
1098: */
1099: private int origin(Alignment alignment, int cellOrigin,
1100: int cellSize, int componentSize) {
1101: if (alignment == RIGHT || alignment == BOTTOM) {
1102: return cellOrigin + cellSize - componentSize;
1103: } else if (alignment == CENTER) {
1104: return cellOrigin + (cellSize - componentSize) / 2;
1105: } else { // left, top, fill
1106: return cellOrigin;
1107: }
1108: }
1109:
1110: /**
1111: * Returns the component's pixel extent.
1112: *
1113: * @param alignment the component's alignment
1114: * @param cellSize the size of the display area
1115: * @param componentSize the component's size
1116: * @return the component's pixel extent
1117: */
1118: private int extent(Alignment alignment, int cellSize,
1119: int componentSize) {
1120: return alignment == FILL ? cellSize : componentSize;
1121: }
1122:
1123: // Misc *****************************************************************
1124:
1125: /**
1126: * Creates a copy of this cell constraints object.
1127: *
1128: * @return a copy of this cell constraints object
1129: */
1130: public Object clone() {
1131: try {
1132: CellConstraints c = (CellConstraints) super .clone();
1133: c.insets = (Insets) insets.clone();
1134: return c;
1135: } catch (CloneNotSupportedException e) {
1136: // This shouldn't happen, since we are Cloneable.
1137: throw new InternalError();
1138: }
1139: }
1140:
1141: /**
1142: * Constructs and returns a string representation of this constraints object.
1143: *
1144: * @return string representation of this constraints object
1145: */
1146: public String toString() {
1147: StringBuffer buffer = new StringBuffer("CellConstraints");
1148: buffer.append("[x=");
1149: buffer.append(gridX);
1150: buffer.append("; y=");
1151: buffer.append(gridY);
1152: buffer.append("; w=");
1153: buffer.append(gridWidth);
1154: buffer.append("; h=");
1155: buffer.append(gridHeight);
1156: buffer.append("; hAlign=");
1157: buffer.append(hAlign);
1158: buffer.append("; vAlign=");
1159: buffer.append(vAlign);
1160: if (!(EMPTY_INSETS.equals(insets))) {
1161: buffer.append("; insets=");
1162: buffer.append(insets);
1163: }
1164:
1165: buffer.append(']');
1166: return buffer.toString();
1167: }
1168:
1169: /**
1170: * Returns a short string representation of this constraints object.
1171: *
1172: * @return a short string representation of this constraints object
1173: */
1174: public String toShortString() {
1175: return toShortString(null);
1176: }
1177:
1178: /**
1179: * Returns a short string representation of this constraints object.
1180: * This method can use the given <code>FormLayout</code>
1181: * to display extra information how default alignments
1182: * are mapped to concrete alignments. Therefore it asks the
1183: * related column and row as specified by this constraints object.
1184: *
1185: * @param layout the layout to be presented as a string
1186: * @return a short string representation of this constraints object
1187: */
1188: public String toShortString(FormLayout layout) {
1189: StringBuffer buffer = new StringBuffer("(");
1190: buffer.append(formatInt(gridX));
1191: buffer.append(", ");
1192: buffer.append(formatInt(gridY));
1193: buffer.append(", ");
1194: buffer.append(formatInt(gridWidth));
1195: buffer.append(", ");
1196: buffer.append(formatInt(gridHeight));
1197: buffer.append(", \"");
1198: buffer.append(hAlign.abbreviation());
1199: if (hAlign == DEFAULT && layout != null) {
1200: buffer.append('=');
1201: ColumnSpec colSpec = gridWidth == 1 ? layout
1202: .getColumnSpec(gridX) : null;
1203: buffer.append(concreteAlignment(hAlign, colSpec)
1204: .abbreviation());
1205: }
1206: buffer.append(", ");
1207: buffer.append(vAlign.abbreviation());
1208: if (vAlign == DEFAULT && layout != null) {
1209: buffer.append('=');
1210: RowSpec rowSpec = gridHeight == 1 ? layout
1211: .getRowSpec(gridY) : null;
1212: buffer.append(concreteAlignment(vAlign, rowSpec)
1213: .abbreviation());
1214: }
1215: buffer.append("\"");
1216: if (!(EMPTY_INSETS.equals(insets))) {
1217: buffer.append(", ");
1218: buffer.append(insets);
1219: }
1220:
1221: buffer.append(')');
1222: return buffer.toString();
1223: }
1224:
1225: // Helper Class *********************************************************
1226:
1227: /**
1228: * An ordinal-based serializable typesafe enumeration for component
1229: * alignment types as used by the {@link FormLayout}.
1230: */
1231: public static final class Alignment implements Serializable {
1232:
1233: private static final int HORIZONTAL = 0;
1234: private static final int VERTICAL = 1;
1235: private static final int BOTH = 2;
1236:
1237: private final transient String name;
1238: private final transient int orientation;
1239:
1240: private Alignment(String name, int orientation) {
1241: this .name = name;
1242: this .orientation = orientation;
1243: }
1244:
1245: static Alignment valueOf(String nameOrAbbreviation) {
1246: String str = nameOrAbbreviation.toLowerCase(Locale.ENGLISH);
1247: if (str.equals("d") || str.equals("default"))
1248: return DEFAULT;
1249: else if (str.equals("f") || str.equals("fill"))
1250: return FILL;
1251: else if (str.equals("c") || str.equals("center"))
1252: return CENTER;
1253: else if (str.equals("l") || str.equals("left"))
1254: return LEFT;
1255: else if (str.equals("r") || str.equals("right"))
1256: return RIGHT;
1257: else if (str.equals("t") || str.equals("top"))
1258: return TOP;
1259: else if (str.equals("b") || str.equals("bottom"))
1260: return BOTTOM;
1261: else
1262: throw new IllegalArgumentException(
1263: "Invalid alignment "
1264: + nameOrAbbreviation
1265: + ". Must be one of: left, center, right, top, bottom, "
1266: + "fill, default, l, c, r, t, b, f, d.");
1267: }
1268:
1269: /**
1270: * Returns this Alignment's name.
1271: *
1272: * @return this alignment's name.
1273: */
1274: public String toString() {
1275: return name;
1276: }
1277:
1278: /**
1279: * Returns the first character of this Alignment's name.
1280: * Used to identify it in short format strings.
1281: *
1282: * @return the name's first character.
1283: */
1284: public char abbreviation() {
1285: return name.charAt(0);
1286: }
1287:
1288: private boolean isHorizontal() {
1289: return orientation != VERTICAL;
1290: }
1291:
1292: private boolean isVertical() {
1293: return orientation != HORIZONTAL;
1294: }
1295:
1296: // Serialization *********************************************************
1297:
1298: private static int nextOrdinal = 0;
1299:
1300: private final int ordinal = nextOrdinal++;
1301:
1302: private Object readResolve() {
1303: return VALUES[ordinal]; // Canonicalize
1304: }
1305:
1306: }
1307:
1308: /**
1309: * Returns an integer that has a minimum of two characters.
1310: *
1311: * @param number the number to format
1312: * @return a string representation for a number with a minum of two chars
1313: */
1314: private String formatInt(int number) {
1315: String str = Integer.toString(number);
1316: return number < 10 ? " " + str : str;
1317: }
1318:
1319: }
|