0001: /*
0002: * $Id:$
0003: * IzPack - Copyright 2001-2008 Julien Ponge, All Rights Reserved.
0004: *
0005: * http://izpack.org/
0006: * http://izpack.codehaus.org/
0007: *
0008: * Copyright 2006 Klaus Bartz
0009: *
0010: * Licensed under the Apache License, Version 2.0 (the "License");
0011: * you may not use this file except in compliance with the License.
0012: * You may obtain a copy of the License at
0013: *
0014: * http://www.apache.org/licenses/LICENSE-2.0
0015: *
0016: * Unless required by applicable law or agreed to in writing, software
0017: * distributed under the License is distributed on an "AS IS" BASIS,
0018: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0019: * See the License for the specific language governing permissions and
0020: * limitations under the License.
0021: */
0022: package com.izforge.izpack.gui;
0023:
0024: import java.awt.Component;
0025: import java.awt.Container;
0026: import java.awt.Dimension;
0027: import java.awt.Insets;
0028: import java.awt.LayoutManager;
0029: import java.awt.LayoutManager2;
0030: import java.awt.Rectangle;
0031: import java.util.ArrayList;
0032:
0033: import javax.swing.JCheckBox;
0034: import javax.swing.JLabel;
0035: import javax.swing.JRadioButton;
0036: import javax.swing.JScrollPane;
0037: import javax.swing.JTextArea;
0038: import javax.swing.text.JTextComponent;
0039:
0040: import com.izforge.izpack.panels.PathSelectionPanel;
0041: import com.izforge.izpack.util.Log;
0042: import com.izforge.izpack.util.MultiLineLabel;
0043:
0044: /**
0045: * This is a special layout manager for IzPanels.
0046: *
0047: * @author Klaus Bartz
0048: *
0049: */
0050: public class IzPanelLayout implements LayoutManager, LayoutManager2,
0051: LayoutConstants {
0052:
0053: /** holds all the components and layout constraints. */
0054: private ArrayList<ArrayList<IzPanelConstraints>> components = new ArrayList<ArrayList<IzPanelConstraints>>();
0055:
0056: /** Maximum rows to handle symbolic values like NEXT_ROW in constraints. */
0057: private int currentYPos = 0;
0058:
0059: /** Current column to handle symbolic values like NEXT_COLUMN in constraints. */
0060: private int currentXPos = -1;
0061:
0062: /** Dimension object with prefered size. Will be computed new if invalidateLayout will be called. */
0063: private Dimension prefLayoutDim;
0064:
0065: private Dimension oldParentSize;
0066:
0067: private Insets oldParentInsets;
0068:
0069: private int columnFillOutRule;
0070:
0071: private double[] overallYStretch = { -1.0, 0.0 };
0072:
0073: protected static int[] DEFAULT_Y_GAPS = { -1, 0, 5, 5, 10, 5, 5, 5,
0074: 5, 5, 5, 5, 5, 5, 15, 12, 9, 6, 3, 0 };
0075:
0076: protected static int[] DEFAULT_X_GAPS = { -1, 0, 0, 0, 0, 0, 10,
0077: 10, 10, 10, 10, 10, 10, 15, 12, 9, 6, 3, 0 };
0078:
0079: protected static int[] DEFAULT_X_ALIGNMENT = { LEFT, LEFT, LEFT,
0080: LEFT };
0081:
0082: protected static int[] DEFAULT_Y_ALIGNMENT = { CENTER, CENTER,
0083: CENTER, CENTER };
0084:
0085: /** Array with some default constraints. */
0086: private static IzPanelConstraints DEFAULT_CONSTRAINTS[] = {
0087: // Default constraints for labels.
0088: new IzPanelConstraints(DEFAULT_LABEL_ALIGNMENT,
0089: DEFAULT_LABEL_ALIGNMENT, NEXT_COLUMN, CURRENT_ROW,
0090: 1, 1, AUTOMATIC_GAP, AUTOMATIC_GAP, 0.0, 0.0),
0091: // Default constraints for text fields.
0092: new IzPanelConstraints(DEFAULT_TEXT_ALIGNMENT,
0093: DEFAULT_TEXT_ALIGNMENT, NEXT_COLUMN, CURRENT_ROW,
0094: 1, 1, AUTOMATIC_GAP, AUTOMATIC_GAP, 0.0, 0.0),
0095: // Default constraints for other controls using two columns if possible.
0096: new IzPanelConstraints(DEFAULT_CONTROL_ALIGNMENT,
0097: DEFAULT_CONTROL_ALIGNMENT, NEXT_COLUMN,
0098: CURRENT_ROW, 1, 1, AUTOMATIC_GAP, AUTOMATIC_GAP,
0099: 0.0, 0.0),
0100: // Default constraints for full line controls.
0101: new IzPanelConstraints(DEFAULT_LABEL_ALIGNMENT,
0102: DEFAULT_LABEL_ALIGNMENT, 0, NEXT_ROW,
0103: Byte.MAX_VALUE, Byte.MAX_VALUE, AUTOMATIC_GAP,
0104: AUTOMATIC_GAP, FULL_LINE_STRETCH, 0.0),
0105: // Default constraints for constraints for controls/container which are variable in x
0106: // and y dimension.
0107: new IzPanelConstraints(DEFAULT_LABEL_ALIGNMENT,
0108: DEFAULT_LABEL_ALIGNMENT, 0, NEXT_ROW,
0109: Byte.MAX_VALUE, Byte.MAX_VALUE, AUTOMATIC_GAP,
0110: AUTOMATIC_GAP, FULL_LINE_STRETCH,
0111: FULL_COLUMN_STRETCH),
0112: // Default constraints for x filler.
0113: new IzPanelConstraints(DEFAULT_LABEL_ALIGNMENT,
0114: DEFAULT_LABEL_ALIGNMENT, NEXT_COLUMN, CURRENT_ROW,
0115: 1, 1, 0, 0, 0.0, 0.0),
0116: // Default constraints for y filler.
0117: new IzPanelConstraints(DEFAULT_LABEL_ALIGNMENT,
0118: DEFAULT_LABEL_ALIGNMENT, 0, NEXT_ROW, 1, 1, 0, 0,
0119: 0.0, 0.0),
0120: // Default constraints for other controls using the full line.
0121: new IzPanelConstraints(DEFAULT_CONTROL_ALIGNMENT,
0122: DEFAULT_CONTROL_ALIGNMENT, 0, NEXT_ROW,
0123: Byte.MAX_VALUE, Byte.MAX_VALUE, AUTOMATIC_GAP,
0124: AUTOMATIC_GAP, FULL_LINE_STRETCH, 0.0),
0125:
0126: };
0127:
0128: /** Anchor to be used for the controls in all panels. */
0129: private static int ANCHOR = CENTER;
0130:
0131: private static int X_STRETCH_TYPE = RELATIVE_STRETCH;
0132:
0133: private static int Y_STRETCH_TYPE = RELATIVE_STRETCH;
0134:
0135: private static double FULL_LINE_STRETCH_DEFAULT = 1.0;
0136:
0137: private static double FULL_COLUMN_STRETCH_DEFAULT = 1.0;
0138:
0139: private static int DEFAULT_TEXTFIELD_LENGTH = 12;
0140:
0141: private static final int[][] GAP_INTERMEDIAER_LOOKUP = {
0142: { LABEL_GAP, LABEL_TO_TEXT_GAP, LABEL_TO_CONTROL_GAP,
0143: LABEL_GAP, LABEL_TO_CONTROL_GAP, LABEL_GAP,
0144: LABEL_GAP },
0145: { TEXT_TO_LABEL_GAP, TEXT_GAP, TEXT_TO_CONTROL_GAP,
0146: TEXT_TO_LABEL_GAP, TEXT_TO_CONTROL_GAP, TEXT_GAP,
0147: TEXT_GAP },
0148: { CONTROL_TO_LABEL_GAP, CONTROL_TO_TEXT_GAP, CONTROL_GAP,
0149: CONTROL_TO_LABEL_GAP, CONTROL_GAP, CONTROL_GAP,
0150: CONTROL_GAP },
0151: { LABEL_GAP, LABEL_TO_TEXT_GAP, LABEL_TO_CONTROL_GAP,
0152: LABEL_GAP, LABEL_TO_CONTROL_GAP, LABEL_GAP,
0153: LABEL_GAP },
0154: { CONTROL_TO_LABEL_GAP, CONTROL_TO_TEXT_GAP, CONTROL_GAP,
0155: CONTROL_TO_LABEL_GAP, CONTROL_GAP, CONTROL_GAP,
0156: CONTROL_GAP },
0157: { NO_GAP, NO_GAP, NO_GAP, NO_GAP, NO_GAP, NO_GAP, NO_GAP,
0158: NO_GAP },
0159: { NO_GAP, NO_GAP, NO_GAP, NO_GAP, NO_GAP, NO_GAP, NO_GAP,
0160: NO_GAP },
0161: { NO_GAP, NO_GAP, NO_GAP, NO_GAP, NO_GAP, NO_GAP, NO_GAP,
0162: NO_GAP } };
0163:
0164: /**
0165: * Default constructor
0166: */
0167: public IzPanelLayout() {
0168: this (NO_FILL_OUT_COLUMN);
0169: }
0170:
0171: /**
0172: * Creates an layout manager which consider the given column fill out rule. Valid rules are
0173: * NO_FILL_OUT_COLUMN, FILL_OUT_COLUMN_WIDTH, FILL_OUT_HEIGHT and FILL_OUT_COLUMN_SIZE
0174: *
0175: * @param colFillOutRule
0176: */
0177: public IzPanelLayout(int colFillOutRule) {
0178: super ();
0179: columnFillOutRule = colFillOutRule;
0180: }
0181:
0182: /**
0183: * Returns the y gap for the given constraint dependant on the next y constraint.
0184: *
0185: * @param curConst constraint of the component for which the gap should be returnd
0186: * @param nextYConst constraint of the component which is the next in y direction
0187: * @return the y gap
0188: */
0189: private static int getYGap(IzPanelConstraints curConst,
0190: IzPanelConstraints nextYConst) {
0191:
0192: Class nextClass = (nextYConst != null) ? nextYConst.component
0193: .getClass() : FillerComponent.class;
0194: int interId = GAP_INTERMEDIAER_LOOKUP[getIntermediarId(
0195: curConst.component.getClass(), null)][getIntermediarId(
0196: nextClass, null)];
0197: if (interId < 0)
0198: interId = -interId;
0199: return (DEFAULT_Y_GAPS[interId]);
0200:
0201: }
0202:
0203: /**
0204: * Returns the x gap for the given constraint dependant on the next x constraint.
0205: *
0206: * @param curConst constraint of the component for which the gap should be returnd
0207: * @param nextXConst constraint of the component which is the next in x direction
0208: * @return the x gap
0209: */
0210: private static int getXGap(IzPanelConstraints curConst,
0211: IzPanelConstraints nextXConst) {
0212:
0213: Class nextClass = (nextXConst != null) ? nextXConst.component
0214: .getClass() : FillerComponent.class;
0215: int interId = GAP_INTERMEDIAER_LOOKUP[getIntermediarId(
0216: curConst.component.getClass(), null)][getIntermediarId(
0217: nextClass, null)];
0218: if (interId < 0)
0219: interId = -interId;
0220: return (DEFAULT_X_GAPS[interId]);
0221:
0222: }
0223:
0224: /**
0225: * Returns an index depending on the class type. Only for internal use.
0226: *
0227: * @param clazz class for which the index should be returned
0228: * @param comp component for which the index should be returned
0229: * @return an index depending on the class type
0230: */
0231: private static int getIntermediarId(Class clazz, Component comp) {
0232:
0233: if (comp != null) {
0234: if (MultiLineLabel.class.isAssignableFrom(clazz)
0235: || LabelFactory.FullLineLabel.class
0236: .isAssignableFrom(clazz))
0237: return (FULL_LINE_COMPONENT_CONSTRAINT);
0238: if (PathSelectionPanel.class.isAssignableFrom(clazz)
0239: || JCheckBox.class.isAssignableFrom(clazz)
0240: || JRadioButton.class.isAssignableFrom(clazz))
0241: return (FULL_LINE_CONTROL_CONSTRAINT);
0242: if (FillerComponent.class.isAssignableFrom(clazz)
0243: || javax.swing.Box.Filler.class
0244: .isAssignableFrom(clazz)) {
0245: Dimension size = comp.getPreferredSize();
0246: if (size.height >= Short.MAX_VALUE || size.height <= 0) {
0247: size.height = 0;
0248: comp.setSize(size);
0249: return (XDUMMY_CONSTRAINT);
0250: } else if (size.width >= Short.MAX_VALUE
0251: || size.width <= 0) {
0252: size.width = 0;
0253: comp.setSize(size);
0254: return (YDUMMY_CONSTRAINT);
0255: }
0256: }
0257: }
0258: if (JScrollPane.class.isAssignableFrom(clazz))
0259: return (XY_VARIABLE_CONSTRAINT);
0260: if (JLabel.class.isAssignableFrom(clazz))
0261: return (LABEL_CONSTRAINT);
0262: if (JTextComponent.class.isAssignableFrom(clazz))
0263: return (TEXT_CONSTRAINT);
0264: if (FillerComponent.class.isAssignableFrom(clazz))
0265: return (XDUMMY_CONSTRAINT);
0266: if (javax.swing.Box.Filler.class.isAssignableFrom(clazz))
0267: return (XDUMMY_CONSTRAINT);
0268: return (CONTROL_CONSTRAINT); // Other controls.
0269: }
0270:
0271: /*
0272: * (non-Javadoc)
0273: *
0274: * @see java.awt.LayoutManager#addLayoutComponent(java.lang.String, java.awt.Component)
0275: */
0276: public void addLayoutComponent(String name, Component comp) {
0277: // Has to be implemented, but not supported in this class.
0278: }
0279:
0280: /*
0281: * (non-Javadoc)
0282: *
0283: * @see java.awt.LayoutManager#removeLayoutComponent(java.awt.Component)
0284: */
0285: public void removeLayoutComponent(Component comp) {
0286: // Has to be implemented, but not supported in this class.
0287: }
0288:
0289: /*
0290: * (non-Javadoc)
0291: *
0292: * @see java.awt.LayoutManager#minimumLayoutSize(java.awt.Container)
0293: */
0294: public Dimension minimumLayoutSize(Container parent) {
0295: return preferredLayoutSize(parent);
0296: }
0297:
0298: /*
0299: * (non-Javadoc)
0300: *
0301: * @see java.awt.LayoutManager#preferredLayoutSize(java.awt.Container)
0302: */
0303: public Dimension preferredLayoutSize(Container parent) {
0304: return (determineSize());
0305: }
0306:
0307: /**
0308: * Method which determine minimum with and height of this layout. The size will be stored after
0309: * cumputing in a class member. With a call to invalidateLayout this will be deleted and at the
0310: * next call to this method the values are computed again.
0311: *
0312: * @return current minimum size
0313: */
0314: private Dimension determineSize() {
0315: if (prefLayoutDim == null) {
0316: int width = minimumAllColumnsWidth();
0317: int height = minimumOverallHeight();
0318: prefLayoutDim = new Dimension(width, height);
0319: }
0320: return (Dimension) (prefLayoutDim.clone());
0321: }
0322:
0323: /**
0324: * Returns the number of rows that need to be laid out.
0325: *
0326: * @return the number of rows that need to be laid out
0327: */
0328: private int rows() {
0329: int maxRows = 0;
0330: for (Object component : components) {
0331: int curRows = ((ArrayList) component).size();
0332: if (curRows > maxRows) {
0333: maxRows = curRows;
0334: }
0335:
0336: }
0337: return (maxRows);
0338: }
0339:
0340: /**
0341: * Returns the number of columns that need to be laid out.
0342: *
0343: * @return the number of columns that need to be laid out
0344: */
0345: private int columns() {
0346: return (components.size());
0347: }
0348:
0349: /**
0350: * Minimum height of all rows.
0351: *
0352: * @return minimum height of all rows
0353: */
0354: private int minimumOverallHeight() {
0355: int height = 0;
0356:
0357: for (int i = 0; i < rows(); i++) {
0358: height += rowHeight(i);
0359: }
0360:
0361: return (height);
0362: }
0363:
0364: /**
0365: * Measures and returns the minimum height required to render the components in the indicated
0366: * row.
0367: *
0368: * @param row the index of the row to measure
0369: * @return minimum height of a row
0370: */
0371: private int rowHeight(int row) {
0372: int height = 0;
0373: for (int i = 0; i < components.size(); ++i) {
0374: int curHeight = getCellSize(i, row, null).height;
0375: if (curHeight > height)
0376: height = curHeight;
0377: }
0378: return (height);
0379: }
0380:
0381: /**
0382: * Measures and returns the minimum height required to render the components in the indicated
0383: * row.
0384: *
0385: * @param row the index of the row to measure
0386: * @param maxOverallHeight
0387: * @param minOverallHeight
0388: * @return minimum height of a row
0389: */
0390: private int rowHeight(int row, int minOverallHeight,
0391: int maxOverallHeight) {
0392: // First determine minimum row height and whether there is a y stretch or not.
0393: int height = 0;
0394: double[] yStretch = getOverallYStretch();
0395: if (yStretch[0] <= 0.0)
0396: return (rowHeight(row));
0397: double maxStretch = 0.0;
0398: double[] stretchParts = new double[components.size()];
0399: for (int i = 0; i < components.size(); ++i) {
0400: IzPanelConstraints constraints = getConstraints(i, row);
0401: double stretch = constraints.getYStretch();
0402: stretchParts[i] = stretch;
0403: if (stretch > maxStretch)
0404: maxStretch = stretch;
0405: int curHeight = getCellSize(i, row, constraints).height;
0406: if (curHeight > height)
0407: height = curHeight;
0408: }
0409: if (maxOverallHeight <= minOverallHeight)
0410: return (height);
0411: // We have a y stretch and place. Let us disperse it.
0412: int pixels = (int) (maxOverallHeight - yStretch[1] - minOverallHeight);
0413: int stretchPart = (int) (pixels * maxStretch);
0414: if (stretchPart > 0) {
0415: for (int i = 0; i < components.size(); ++i) {
0416: if (stretchParts[i] < 0.00000001)
0417: continue;
0418: IzPanelConstraints constraints = getConstraints(i, row);
0419: Dimension size = constraints.component
0420: .getPreferredSize();
0421: if (size.height + stretchPart * stretchParts[i] < height)
0422: size.height = (int) (height + stretchPart
0423: * stretchParts[i]);
0424: else
0425: size.height = height + stretchPart;
0426: if (constraints.component instanceof JScrollPane) { // This is a hack for text areas which uses word wrap. At tests
0427: // they have a preferred width of 100 pixel which breaks the layout.
0428:
0429: if (((JScrollPane) constraints.component)
0430: .getViewport().getView() instanceof JTextArea) {
0431: if (((JTextArea) ((JScrollPane) constraints.component)
0432: .getViewport().getView()).getLineWrap())
0433: size.width = 1000;
0434: }
0435: }
0436: constraints.component.setPreferredSize(size);
0437:
0438: }
0439: height += stretchPart;
0440:
0441: }
0442: return (height);
0443: }
0444:
0445: /**
0446: * Returns the sum of the maximum y stretch of each row.
0447: *
0448: * @return the sum of the maximum y stretch of each row
0449: */
0450: private double[] getOverallYStretch() {
0451: if (overallYStretch[0] >= 0.0)
0452: return (overallYStretch); // Stretch already computed.
0453: overallYStretch[0] = 0.0;
0454: for (int row = 0; row < rows(); ++row) {
0455: double maxStretch = 0.0;
0456: double maxGap = 0.0;
0457: for (int i = 0; i < components.size(); ++i) {
0458: IzPanelConstraints constraints = getConstraints(i, row);
0459: resolveDefaultSettings(i, row);
0460: if (constraints.getYStretch() == FULL_COLUMN_STRETCH)
0461: constraints.setYStretch(IzPanelLayout
0462: .getFullColumnStretch());
0463: double curStretch = constraints.getYStretch();
0464: if (curStretch > maxStretch)
0465: maxStretch = curStretch;
0466: double curYGap = constraints.getYGap();
0467: if (curYGap > maxGap)
0468: maxGap = curYGap;
0469: }
0470: overallYStretch[0] += maxStretch;
0471: overallYStretch[1] += maxGap;
0472: }
0473: // Modify y stretch depending on the current Y-Stretch type.
0474: if (overallYStretch[0] > 0.0) {
0475: switch (IzPanelLayout.getYStretchType()) {
0476: case RELATIVE_STRETCH:
0477: break;
0478: case ABSOLUTE_STRETCH:
0479: overallYStretch[0] = 1.0;
0480: break;
0481: case NO_STRETCH:
0482: default:
0483: overallYStretch[0] = 0.0;
0484: break;
0485: }
0486: }
0487:
0488: return (overallYStretch);
0489: }
0490:
0491: /**
0492: * Measures and returns the minimum size required to render the component in the indicated row
0493: * and column. The constraints can be null.
0494: *
0495: * @param row the index of the row to measure
0496: * @param column the column of the component
0497: * @param constraints constraints of current component
0498: * @return size of the given cell
0499: */
0500: private Dimension getCellSize(int column, int row,
0501: IzPanelConstraints constraints) {
0502: Dimension retval = new Dimension();
0503: Component component;
0504:
0505: try {
0506: if (constraints == null)
0507: constraints = getConstraints(column, row);
0508: if (constraints != null) {
0509: component = constraints.component;
0510: // Some components returns the needed size with getPreferredSize
0511: // some with getMinimumSize. Therefore following code...
0512: Dimension dim = component.getPreferredSize();
0513: Dimension dim2 = component.getMinimumSize();
0514: retval.height = (dim.height > dim2.height) ? dim.height
0515: : dim2.height;
0516: retval.width = (dim.width > dim2.width) ? dim.width
0517: : dim2.width;
0518: if (component instanceof JScrollPane) { // But at a JScrollPane we have to use the minimum size because
0519: // preferred size is the size of the view.
0520: retval.height = dim2.height;
0521: retval.width = dim2.width;
0522: }
0523: if (needsReEvaluation(component))
0524: retval.width = 0;
0525:
0526: }
0527: } catch (Throwable exception) {
0528: // ----------------------------------------------------
0529: // we might get an exception if one of the array list is
0530: // shorter, because we index out of bounds. If there
0531: // is nothing there then the height is 0, nothing
0532: // further to worry about!
0533: // ----------------------------------------------------
0534: }
0535:
0536: return (retval);
0537: }
0538:
0539: /**
0540: * Returns the minimum width of the column requested. This contains not the gaps.
0541: *
0542: * @param column the columns to measure
0543: *
0544: * @return the minimum width required to fit the components in this column
0545: */
0546: private int minimumColumnWidth(int column) {
0547: int maxWidth = 0;
0548: Dimension[] cs = new Dimension[rows()];
0549: for (int i = 0; i < rows(); ++i) {
0550: IzPanelConstraints constraints = getConstraints(column, i);
0551: cs[i] = getCellSize(column, i, constraints);
0552: if (constraints.getXWeight() <= 1)
0553: if (maxWidth < cs[i].width)
0554: maxWidth = cs[i].width;
0555: }
0556: if (maxWidth == 0) {
0557: for (int i = 0; i < rows(); ++i) {
0558: if (maxWidth < cs[i].width)
0559: maxWidth = cs[i].width;
0560: }
0561: }
0562: return (maxWidth);
0563: }
0564:
0565: /**
0566: * Returns the minimum width needed by all columns.
0567: *
0568: * @return the minimum width needed by all columns
0569: */
0570: private int minimumAllColumnsWidth() {
0571: int width = 0;
0572: for (int i = 0; i < this .components.size(); ++i)
0573: width += minimumColumnWidth(i);
0574: return (width);
0575: }
0576:
0577: /**
0578: * Returns the constraint object of the component at the given place.
0579: *
0580: * @param col column of the component
0581: * @param row row of the component
0582: * @return the constraint object of the component at the given place
0583: */
0584: private IzPanelConstraints getConstraints(int col, int row) {
0585: if (col >= columns() || row >= rows())
0586: return (null);
0587: Object obj = components.get(col);
0588: if (obj != null && obj instanceof ArrayList) {
0589: try {
0590: obj = (components.get(col)).get(row);
0591: } catch (Throwable t) {
0592: obj = null;
0593: }
0594: if (obj != null)
0595: return ((IzPanelConstraints) obj);
0596: // no constraints is possible if no valid component
0597: // was added under this component.
0598: // Put dummy components into the array.
0599:
0600: ArrayList<IzPanelConstraints> colA = components.get(col);
0601: for (int curRow = colA.size(); row >= curRow; ++curRow) {
0602:
0603: IzPanelConstraints currentConst = IzPanelLayout
0604: .getDefaultConstraint(XDUMMY_CONSTRAINT);
0605: currentConst.setXPos(col);
0606: currentConst.setYPos(curRow);
0607: currentConst.component = new FillerComponent();
0608: try {
0609: (components.get(col)).add(row, currentConst);
0610: } catch (Throwable t) {
0611: return (null);
0612: }
0613: }
0614: return (getConstraints(col, row));
0615: }
0616: return (null);
0617: }
0618:
0619: private int getAdaptedXPos(int xpos, int curWidth,
0620: Dimension curDim, IzPanelConstraints currentConst) {
0621: int adaptedXPos = xpos;// currentConst.getXGap();
0622: if ((columnFillOutRule & FILL_OUT_COLUMN_WIDTH) > 0)
0623: return (adaptedXPos);
0624: switch (currentConst.getXCellAlignment()) {
0625: case LEFT:
0626: break;
0627: case RIGHT:
0628: adaptedXPos += curWidth - curDim.width;
0629: break;
0630: case CENTER:
0631: default:
0632: adaptedXPos += (curWidth - curDim.width) / 2;
0633: break;
0634:
0635: }
0636: return (adaptedXPos);
0637: }
0638:
0639: private int getAdaptedYPos(int ypos, int curHeight,
0640: Dimension curDim, IzPanelConstraints currentConst) {
0641: int adaptedYPos = ypos;// + currentConst.getYGap();
0642: if ((columnFillOutRule & FILL_OUT_COLUMN_HEIGHT) > 0)
0643: return (adaptedYPos);
0644: int height = curDim.height;
0645: switch (currentConst.getYCellAlignment()) {
0646: case TOP:
0647: break;
0648: case BOTTOM:
0649: adaptedYPos += curHeight - height;
0650: break;
0651: case CENTER:
0652: default:
0653: adaptedYPos += (curHeight - height) / 2;
0654: break;
0655:
0656: }
0657: if (adaptedYPos < ypos)
0658: return (ypos);
0659: return (adaptedYPos);
0660: }
0661:
0662: private void resolveDefaultSettings(int col, int row) {
0663: IzPanelConstraints currentConst = getConstraints(col, row);
0664: IzPanelConstraints nextYConst = getConstraints(col, row + 1);
0665: IzPanelConstraints nextXConst = getConstraints(col + 1, row);
0666: if (currentConst == null)
0667: return;
0668: int gap = currentConst.getYGap();
0669: if (gap == AUTOMATIC_GAP) { // Automatic gap; determine now.
0670: currentConst.setYGap(getYGap(currentConst, nextYConst));
0671: } else if (gap < 0) {
0672: currentConst.setYGap(DEFAULT_Y_GAPS[-gap]);
0673: }
0674: gap = currentConst.getXGap();
0675: if (gap == AUTOMATIC_GAP) { // Automatic gap; determine now.
0676: currentConst.setXGap(getXGap(currentConst, nextXConst));
0677: } else if (gap < 0) {
0678: currentConst.setXGap(DEFAULT_X_GAPS[-gap]);
0679: }
0680:
0681: if (currentConst.getXCellAlignment() < 0) {
0682: currentConst
0683: .setXCellAlignment(DEFAULT_X_ALIGNMENT[-currentConst
0684: .getXCellAlignment()]);
0685: }
0686: if (currentConst.getYCellAlignment() < 0) {
0687: currentConst
0688: .setYCellAlignment(DEFAULT_Y_ALIGNMENT[-currentConst
0689: .getYCellAlignment()]);
0690: }
0691:
0692: }
0693:
0694: /*
0695: * (non-Javadoc)
0696: *
0697: * @see java.awt.LayoutManager#layoutContainer(java.awt.Container)
0698: */
0699: public void layoutContainer(Container parent) {
0700: if (!needNewLayout(parent)) {
0701: fastLayoutContainer(parent);
0702: return;
0703: }
0704: prefLayoutDim = null;
0705: preferredLayoutSize(parent);
0706: Dimension realSizeDim = parent.getSize();
0707: Log.getInstance().addDebugMessage(
0708: "IzPanelLayout.layoutContainer parent size: {0}",
0709: new String[] { parent.getSize().toString() },
0710: "LayoutTrace", null);
0711: Insets insets = parent.getInsets();
0712:
0713: int rowHeight = 0;
0714: int onceAgain = 0;
0715: int[] generellOffset = new int[] { 0, 0 };
0716: // int generellYOffset = 0;
0717: // int generellXOffset = 0;
0718: int maxWidth = 0;
0719: int overallHeight = 0;
0720: int anchorNeedsReEval = 0;
0721: Rectangle curRect = new Rectangle();
0722: int minOverallHeight = minimumOverallHeight();
0723: int maxOverallHeight = realSizeDim.height - insets.top
0724: - insets.bottom;
0725: while (anchorNeedsReEval < 2) {
0726: int ypos = insets.top;
0727:
0728: int row = 0;
0729: int minWidth = 0xffff;
0730: int minHeight = 0xffff;
0731: maxWidth = 0;
0732: overallHeight = 0;
0733: while (row < rows()) {
0734: int outerRowHeight = 0;
0735: int xpos = insets.left;
0736: // rowHeight = rowHeight(row, minOverallHeight, maxOverallHeight);
0737: int col = 0;
0738: IzPanelConstraints[] colConstraints = new IzPanelConstraints[columns()];
0739: int usedWidth = 0;
0740: Dimension curDim;
0741: while (col < columns()) {
0742: if (col == 0)
0743: rowHeight = rowHeight(row, minOverallHeight,
0744: maxOverallHeight);
0745: IzPanelConstraints currentConst = getConstraints(
0746: col, row);
0747: colConstraints[col] = currentConst;
0748: Component currentComp = currentConst.component;
0749: curDim = currentComp.getPreferredSize();
0750: int curWidth = minimumColumnWidth(col);
0751: col++;
0752: if (currentConst.getXWeight() > 1) {
0753: int weight = currentConst.getXWeight();
0754: while (weight > 1 && col < columns()) {
0755: colConstraints[col] = getConstraints(col,
0756: row);
0757: if (!(colConstraints[col].component instanceof FillerComponent))
0758: break;
0759: curWidth += minimumColumnWidth(col);
0760: col++;
0761: weight--;
0762: }
0763: }
0764: // width known
0765: int adaptedXPos = getAdaptedXPos(xpos, curWidth,
0766: curDim, currentConst);
0767: int adaptedYPos = getAdaptedYPos(ypos, rowHeight,
0768: curDim, currentConst);
0769: // currentComp.setBounds(adaptedXPos + generellOffset[0], adaptedYPos
0770: // + currentConst.getYGap() + generellOffset[1], curWidth, rowHeight);
0771: // + generellOffset[1], curWidth, rowHeight);
0772: int useWidth = curDim.width;
0773: int useHeight = curDim.height;
0774: if ((columnFillOutRule & FILL_OUT_COLUMN_WIDTH) > 0)
0775: useWidth = curWidth;
0776: if ((columnFillOutRule & FILL_OUT_COLUMN_HEIGHT) > 0)
0777: useHeight = rowHeight;
0778: if (curWidth < useWidth)
0779: useWidth = curWidth;
0780: // First setBounds using computed offsets and the size which exist previous.
0781: currentComp.setBounds(adaptedXPos
0782: + generellOffset[0], adaptedYPos
0783: + generellOffset[1], useWidth, useHeight);
0784: currentComp.getBounds(curRect);
0785: if (curRect.height > 100)
0786: curRect.height = useHeight;
0787: if (!(currentComp instanceof FillerComponent)) {
0788: if (curRect.x < minWidth)
0789: minWidth = curRect.x;
0790: if (curRect.y < minHeight)
0791: minHeight = curRect.y;
0792: }
0793: int curMax = (int) curRect.getMaxX();
0794: if (curMax - minWidth > maxWidth)
0795: maxWidth = curMax - minWidth;
0796: curMax = (int) curRect.getMaxY();
0797: currentConst.setBounds(curRect);
0798: if (curMax - minHeight > overallHeight)
0799: overallHeight = curMax - minHeight;
0800: // xpos += currentComp.getSize().width + currentConst.getXGap();
0801: xpos += curWidth + currentConst.getXGap();
0802: usedWidth += curWidth;
0803: if (outerRowHeight < rowHeight
0804: + currentConst.getYGap())
0805: outerRowHeight = rowHeight
0806: + currentConst.getYGap();
0807: }
0808: // Now we have made a row, but may be there are place across or/and a component
0809: // needs a reevaluation.
0810: double rowStretch = 0.0;
0811: int i;
0812: // Determine hole stretch of this row.
0813: for (i = 0; i < colConstraints.length; ++i) {
0814: if (colConstraints[i].getXStretch() == FULL_LINE_STRETCH)
0815: colConstraints[i].setXStretch(IzPanelLayout
0816: .getFullLineStretch());
0817: rowStretch += colConstraints[i].getXStretch();
0818: }
0819: // Modify rowStretch depending on the current X-Stretch type.
0820: if (rowStretch > 0.0) {
0821: switch (IzPanelLayout.getXStretchType()) {
0822: case RELATIVE_STRETCH:
0823: break;
0824: case ABSOLUTE_STRETCH:
0825: rowStretch = 1.0;
0826: break;
0827: case NO_STRETCH:
0828: default:
0829: rowStretch = 0.0;
0830: break;
0831: }
0832: }
0833: if (realSizeDim.width - insets.right != xpos
0834: && rowStretch > 0.0) { // Compute only if there is space to share and at least one control should be
0835: // stretched.
0836: int pixel = realSizeDim.width - insets.right - xpos; // How many pixel we
0837: // can use for stretching.
0838: int offset = 0;
0839: int oldOnceAgain = onceAgain;
0840: for (i = 0; i < colConstraints.length; ++i) {
0841: int curPixel = (int) ((colConstraints[i]
0842: .getXStretch() / rowStretch) * pixel);
0843:
0844: Rectangle curBounds = colConstraints[i].component
0845: .getBounds();
0846: // The width of some components differ from time to time. E.g. a JScrollPane
0847: // with a JEditorPane as viewport has sometimes the minimum column width and
0848: // some times the width of the scroll bar. Therefore we use the minimum
0849: // column width.
0850: int curWidth = this .minimumColumnWidth(i);
0851: if (curBounds.width < curWidth)
0852: curBounds.width = curWidth;
0853: int newWidth = curPixel + curBounds.width;
0854: Log
0855: .getInstance()
0856: .addDebugMessage(
0857: "IzPanelLayout.layoutContainer resize bounds for {2}|{3} old width {0} new width {1}",
0858: new String[] {
0859: Integer
0860: .toString(curBounds.width),
0861: Integer
0862: .toString(newWidth),
0863: Integer.toString(row),
0864: Integer.toString(i) },
0865: "LayoutTrace", null);
0866: colConstraints[i].component.setBounds(
0867: curBounds.x + offset, curBounds.y,
0868: newWidth, curBounds.height);
0869: colConstraints[i].component.getBounds(curRect);
0870: if (curRect.x > 0 && curRect.x < minWidth)
0871: minWidth = curRect.x;
0872: if (curRect.y > 0 && curRect.y < minHeight)
0873: minHeight = curRect.y;
0874: int curMax = (int) curRect.getMaxX();
0875: if (curMax - minWidth > maxWidth)
0876: maxWidth = curMax - minWidth;
0877: curMax = (int) curRect.getMaxY();
0878: colConstraints[i].setBounds(curRect);
0879:
0880: if (curMax - minHeight > overallHeight)
0881: overallHeight = curMax - minHeight;
0882:
0883: Log
0884: .getInstance()
0885: .addDebugMessage(
0886: "IzPanelLayout.layoutContainer resize bounds for {2}|{3} ({0}): {1}",
0887: new String[] {
0888: colConstraints[i].component
0889: .getClass()
0890: .getName(),
0891: curRect.toString(),
0892: Integer.toString(row),
0893: Integer.toString(i) },
0894: "LayoutTrace", null);
0895:
0896: Log
0897: .getInstance()
0898: .addDebugMessage(
0899: "IzPanelLayout.layoutContainer resize bounds for {2}|{3}: maxWidth = {0} maxHeight = {1}",
0900: new String[] {
0901: Integer
0902: .toString(maxWidth),
0903: Integer
0904: .toString(overallHeight),
0905: Integer.toString(row),
0906: Integer.toString(i) },
0907: "LayoutTrace", null);
0908:
0909: offset += curPixel;
0910: if (needsReEvaluation(colConstraints[i].component)) {
0911: if (oldOnceAgain == onceAgain)
0912: onceAgain++;
0913: }
0914: }
0915:
0916: }
0917: // Seems so that height has changed. Reevaluate only one time else it is possible
0918: // to go in a endless loop.
0919:
0920: if (onceAgain == 1)
0921: continue;
0922: onceAgain = 0;
0923: ypos += outerRowHeight;
0924: row++;
0925: }
0926: anchorNeedsReEval += resolveGenerellOffsets(generellOffset,
0927: realSizeDim, insets, maxWidth, overallHeight);
0928:
0929: }
0930: }
0931:
0932: private void fastLayoutContainer(Container parent) {
0933: for (int row = 0; row < rows(); ++row) {
0934: for (int col = 0; col < columns(); ++col) {
0935: IzPanelConstraints currentConst = getConstraints(col,
0936: row);
0937: if (currentConst != null) {
0938: Log
0939: .getInstance()
0940: .addDebugMessage(
0941: "IzPanelLayout.fastLayoutContainer bounds: {0}",
0942: new String[] { currentConst
0943: .getBounds().toString() },
0944: "LayoutTrace", null);
0945: currentConst.component.setBounds(currentConst
0946: .getBounds());
0947: }
0948:
0949: }
0950:
0951: }
0952: }
0953:
0954: private boolean needNewLayout(Container parent) {
0955: Dimension ops = oldParentSize;
0956: Insets opi = oldParentInsets;
0957: oldParentSize = parent.getSize();
0958: oldParentInsets = parent.getInsets();
0959: if (opi == null)
0960: return (true);
0961: if (ops.equals(parent.getSize())
0962: && opi.equals(parent.getInsets()))
0963: return (false);
0964: return (true);
0965:
0966: }
0967:
0968: private int resolveGenerellOffsets(int[] generellOffset,
0969: Dimension realSizeDim, Insets insets, int maxWidth,
0970: int overallHeight) {
0971: int retval = 1;
0972: switch (getAnchor()) {
0973: case CENTER:
0974: generellOffset[0] = (realSizeDim.width - insets.left
0975: - insets.right - maxWidth) / 2;
0976: generellOffset[1] = (realSizeDim.height - insets.top
0977: - insets.bottom - overallHeight) / 2;
0978: break;
0979: case WEST:
0980: generellOffset[0] = 0;
0981: generellOffset[1] = (realSizeDim.height - insets.top
0982: - insets.bottom - overallHeight) / 2;
0983: break;
0984: case EAST:
0985: generellOffset[0] = realSizeDim.width - insets.left
0986: - insets.right - maxWidth;
0987: generellOffset[1] = (realSizeDim.height - insets.top
0988: - insets.bottom - overallHeight) / 2;
0989: break;
0990: case NORTH:
0991: generellOffset[0] = (realSizeDim.width - insets.left
0992: - insets.right - maxWidth) / 2;
0993: generellOffset[1] = 0;
0994: break;
0995: case SOUTH:
0996: generellOffset[0] = (realSizeDim.width - insets.left
0997: - insets.right - maxWidth) / 2;
0998: generellOffset[1] = realSizeDim.height - insets.top
0999: - insets.bottom - overallHeight;
1000: break;
1001: case NORTH_WEST:
1002: generellOffset[0] = 0;
1003: generellOffset[1] = 0;
1004: retval = 2;
1005: break;
1006: case NORTH_EAST:
1007: generellOffset[0] = realSizeDim.width - insets.left
1008: - insets.right - maxWidth;
1009: generellOffset[1] = 0;
1010: break;
1011: case SOUTH_WEST:
1012: generellOffset[0] = 0;
1013: generellOffset[1] = realSizeDim.height - insets.top
1014: - insets.bottom - overallHeight;
1015: break;
1016: case SOUTH_EAST:
1017: generellOffset[0] = realSizeDim.width - insets.left
1018: - insets.right - maxWidth;
1019: generellOffset[1] = realSizeDim.height - insets.top
1020: - insets.bottom - overallHeight;
1021: break;
1022:
1023: }
1024: if (generellOffset[0] < 0)
1025: generellOffset[0] = 0;
1026: if (generellOffset[1] < 0)
1027: generellOffset[1] = 0;
1028: return (retval);
1029: }
1030:
1031: /**
1032: * Returns whether the type of component needs potential a reevaluation or not.
1033: *
1034: * @param comp component to check
1035: * @return whether the type of component needs potential a reevaluation or not
1036: */
1037: private boolean needsReEvaluation(Component comp) {
1038: if ((comp instanceof com.izforge.izpack.util.MultiLineLabel)
1039: || (comp instanceof com.izforge.izpack.panels.PathSelectionPanel))
1040: return (true);
1041: return (false);
1042: }
1043:
1044: /*
1045: * (non-Javadoc)
1046: *
1047: * @see java.awt.LayoutManager2#getLayoutAlignmentX(java.awt.Container)
1048: */
1049: public float getLayoutAlignmentX(Container target) {
1050: return 0;
1051: }
1052:
1053: /*
1054: * (non-Javadoc)
1055: *
1056: * @see java.awt.LayoutManager2#getLayoutAlignmentY(java.awt.Container)
1057: */
1058: public float getLayoutAlignmentY(Container target) {
1059: return 0;
1060: }
1061:
1062: /*
1063: * (non-Javadoc)
1064: *
1065: * @see java.awt.LayoutManager2#invalidateLayout(java.awt.Container)
1066: */
1067: public void invalidateLayout(Container target) {
1068: // prefLayoutDim = null;
1069: }
1070:
1071: /*
1072: * (non-Javadoc)
1073: *
1074: * @see java.awt.LayoutManager2#maximumLayoutSize(java.awt.Container)
1075: */
1076: public Dimension maximumLayoutSize(Container target) {
1077: return (minimumLayoutSize(target));
1078: }
1079:
1080: /*
1081: * (non-Javadoc)
1082: *
1083: * @see java.awt.LayoutManager2#addLayoutComponent(java.awt.Component, java.lang.Object)
1084: */
1085: public void addLayoutComponent(Component comp, Object constraints) {
1086: if (comp == null)
1087: throw new NullPointerException(
1088: "component has to be not null");
1089: IzPanelConstraints cc;
1090: if (!(constraints instanceof IzPanelConstraints)) {
1091: if ((comp instanceof FillerComponent)
1092: && ((FillerComponent) comp).getConstraints() != null)
1093: cc = (IzPanelConstraints) ((FillerComponent) comp)
1094: .getConstraints().clone();
1095: else
1096: cc = (IzPanelConstraints) IzPanelLayout.DEFAULT_CONSTRAINTS[getIntermediarId(
1097: comp.getClass(), comp)].clone();
1098: if (NEXT_LINE.equals(constraints)) {
1099: cc.setXPos(0);
1100: cc.setYPos(NEXT_ROW);
1101: }
1102: } else
1103: cc = (IzPanelConstraints) ((IzPanelConstraints) constraints)
1104: .clone();
1105: cc.component = comp;
1106: int i;
1107: // Modify positions if constraint value is one of the symbolic ints.
1108: int yPos = cc.getYPos();
1109: if (yPos == LayoutConstants.NEXT_ROW)
1110: yPos = currentYPos + 1;
1111: if (yPos == LayoutConstants.CURRENT_ROW)
1112: yPos = currentYPos;
1113: cc.setYPos(yPos);
1114: int xPos = cc.getXPos();
1115: if (xPos == LayoutConstants.NEXT_COLUMN)
1116: xPos = currentXPos + 1;
1117: if (xPos == LayoutConstants.CURRENT_COLUMN)
1118: xPos = currentXPos;
1119: cc.setXPos(xPos);
1120: // Now we know real x and y position. If needed, expand array or
1121: // array of array.
1122: int perfCol = cc.getXWeight() < Byte.MAX_VALUE ? cc
1123: .getXWeight() : 1;
1124: if (components.size() < cc.getXPos() + perfCol) {
1125: for (i = components.size() - 1; i < cc.getXPos() + perfCol
1126: - 1; ++i)
1127: components.add(new ArrayList<IzPanelConstraints>());
1128: }
1129: IzPanelConstraints curConst = cc;
1130: for (int j = 0; j < perfCol; ++j) {
1131: ArrayList<IzPanelConstraints> xComp = components.get(xPos);
1132: if (xComp.size() < yPos) {
1133: for (i = xComp.size() - 1; i < yPos - 1; ++i) {
1134: IzPanelConstraints dc = getDefaultConstraint(XDUMMY_CONSTRAINT);
1135: dc.component = new FillerComponent();
1136: xComp.add(dc);
1137:
1138: }
1139: }
1140:
1141: xComp.add(yPos, curConst);
1142: if (j < perfCol - 1) {
1143: curConst = getDefaultConstraint(XDUMMY_CONSTRAINT);
1144: curConst.component = new FillerComponent();
1145: xPos++;
1146: }
1147: }
1148: int xcsize = (components.get(xPos)).size() - 1;
1149: if (currentYPos < xcsize)
1150: currentYPos = xcsize;
1151: currentXPos = xPos;
1152:
1153: }
1154:
1155: /**
1156: * Creates an invisible, component with a defined width. This component will be placed in the
1157: * given cell of an IzPackLayout. If no constraint will be set (the default) a default
1158: * constraint with NEXT_COLUMN and CURRENT_ROW will be used. This component has the height 0.
1159: * The height of the row will be determined by other components in the same row.
1160: *
1161: * @param width the width of the invisible component
1162: * @return the component
1163: */
1164: public static Component createHorizontalStrut(int width) {
1165: return (new FillerComponent(new Dimension(width, 0)));
1166: }
1167:
1168: /**
1169: * Creates an invisible, component with a defined height. This component will be placed in the
1170: * given cell of an IzPackLayout. If no constraint will be set (the default) a default
1171: * constraint with column 0 and NEXT_ROW will be used. If the next component also uses NEXT_ROW,
1172: * this strut goes over the hole width with the declared height. If more components are in the
1173: * row, the highest of them determines the height of the row. This component has the width 0.
1174: * The width of a row will be determined by other rows.
1175: *
1176: * @param height the height of the invisible component, in pixels >= 0
1177: * @return the component
1178: */
1179: public static Component createVerticalStrut(int height) {
1180: return (new FillerComponent(new Dimension(0, height)));
1181: }
1182:
1183: /**
1184: * Returns a filler component which has self the size 0|0. Additional there is a constraints
1185: * which has the x position 0,y position NEXT_ROW, x and y weight 10, x-stretch 1.0 and the y
1186: * gap PARAGRAPH_GAP. Add the returned component to the IzPanel. Use NEXT_LINE (or NEXT_ROW in
1187: * the constraints) for the next added control, else the layout will be confused.
1188: *
1189: * @return a filler component with the height of the defined paragraph gap
1190: */
1191: public static Component createParagraphGap() {
1192: return (createGap(PARAGRAPH_GAP, VERTICAL));
1193: }
1194:
1195: /**
1196: * Returns a filler component which has self the size 0|0. Additional there is a constraints
1197: * which has the x position 0,y position NEXT_ROW, x and y weight 10, x-stretch 1.0 and the y
1198: * gap FILLER<given filler number>_GAP. Add the returned component to the IzPanel. Use
1199: * NEXT_LINE (or NEXT_ROW in the constraints) for the next added control, else the layout will
1200: * be confused. Attention! fillerNumber determines not directly the size of filler else the
1201: * filler type. The size can be determined in the config file as modifier in the info section
1202: * defining from filler1YGap to filler5YGap.
1203: *
1204: * @param fillerNumber number of the filler which should be used
1205: * @return a filler component with the height of the defined paragraph gap
1206: */
1207: public static Component createVerticalFiller(int fillerNumber) {
1208: // The symbolic numbers all are negative. Therefore a higher filler needs
1209: // a less number.
1210: return (createGap(FILLER1_GAP + 1 - fillerNumber, VERTICAL));
1211: }
1212:
1213: /**
1214: * Returns a filler component which has self the size 0|0. Additional there is a constraints
1215: * which has the position NEXT_COLUMN ,y position CURRENT_ROW, x and y weight 1, stretch 0.0 and
1216: * the gap FILLER<given filler number>_GAP. Add the returned component to the IzPanel.
1217: * Attention! fillerNumber determines not directly the size of filler else the filler type. The
1218: * size can be determined in the config file as modifier in the info section defining from
1219: * filler1XGap to filler5XGap.
1220: *
1221: * @param fillerNumber number of the filler which should be used
1222: * @return a filler component with the width of the defined paragraph gap
1223: */
1224: public static Component createHorizontalFiller(int fillerNumber) {
1225: // The symbolic numbers all are negative. Therefore a higher filler needs
1226: // a less number.
1227: return (createGap(FILLER1_GAP + 1 - fillerNumber, HORIZONTAL));
1228: }
1229:
1230: /**
1231: * Returns a filler component which has self the size 0|0. Additional there is a constraints
1232: * which has the gap defined for the given gap type. If direction is HORIZONTAL, the x position
1233: * is NEXT_COLUMN ,y position CURRENT_ROW, x and y weight 1, stretch 0.0. If direction is
1234: * VERTICAL, the x position will by 0,y position NEXT_ROW, x and y weight 10, x-stretch 1.0. Add
1235: * the returned component to the IzPanel. The result will be that a gap will be inserted into
1236: * the layout at the current place with the width equal to the defined paragraph gap.
1237: *
1238: * @param gapType type of gap to be used
1239: * @param direction direction to be used
1240: *
1241: * @return a filler component with the width of the defined paragraph gap
1242: */
1243:
1244: public static Component createGap(int gapType, int direction) {
1245: if (direction == HORIZONTAL)
1246: return (new FillerComponent(new Dimension(0, 0),
1247: new IzPanelConstraints(DEFAULT_CONTROL_ALIGNMENT,
1248: DEFAULT_CONTROL_ALIGNMENT, NEXT_COLUMN,
1249: CURRENT_ROW, 1, 1, gapType, 0, 0.0, 0.0)));
1250: return (new FillerComponent(new Dimension(0, 0),
1251: new IzPanelConstraints(DEFAULT_CONTROL_ALIGNMENT,
1252: DEFAULT_CONTROL_ALIGNMENT, 0, NEXT_ROW, 10, 10,
1253: 0, gapType, 1.0, 0.0)));
1254: }
1255:
1256: /**
1257: * Returns the constraint for the given type. Valid types are declared in the interface
1258: * <code>LayoutConstraints</code>. Possible are LABEL_CONSTRAINT, TEXT_CONSTRAINT and
1259: * CONTROL_CONSTRAINT.
1260: *
1261: * @param type for which the constraint should be returned
1262: * @return a copy of the default constraint for the given type
1263: */
1264: public static IzPanelConstraints getDefaultConstraint(int type) {
1265: return ((IzPanelConstraints) DEFAULT_CONSTRAINTS[type].clone());
1266: }
1267:
1268: /**
1269: * Component which will be used as placeholder if not extern component will be set or as filler
1270: * for struts.
1271: *
1272: * @author Klaus Bartz
1273: *
1274: */
1275: public static class FillerComponent extends Component {
1276:
1277: /** */
1278: private static final long serialVersionUID = 7270064864038287900L;
1279:
1280: private Dimension size;
1281:
1282: private IzPanelConstraints constraints;
1283:
1284: /**
1285: * Default constructor creating an filler with the size 0|0.
1286: */
1287: public FillerComponent() {
1288: this (new Dimension(0, 0));
1289: }
1290:
1291: /**
1292: * Constructor with giving the filler a size.
1293: *
1294: * @param size dimension to be used as size for this filler.
1295: */
1296: public FillerComponent(Dimension size) {
1297: this (size, null);
1298: }
1299:
1300: /**
1301: * Constructor with giving the filler a size and set the constraints.
1302: *
1303: * @param size
1304: * @param constraints
1305: */
1306: public FillerComponent(Dimension size,
1307: IzPanelConstraints constraints) {
1308: super ();
1309: this .size = size;
1310: this .constraints = constraints;
1311: }
1312:
1313: public Dimension getMinimumSize() {
1314: return (Dimension) (size.clone());
1315: }
1316:
1317: /*
1318: * (non-Javadoc)
1319: *
1320: * @see java.awt.Component#getPreferredSize()
1321: */
1322: public Dimension getPreferredSize() {
1323: return getMinimumSize();
1324: }
1325:
1326: /*
1327: * (non-Javadoc)
1328: *
1329: * @see java.awt.Component#getMaximumSize()
1330: */
1331: public Dimension getMaximumSize() {
1332: return getMinimumSize();
1333: }
1334:
1335: /*
1336: * (non-Javadoc)
1337: *
1338: * @see java.awt.Component#getBounds()
1339: */
1340: public Rectangle getBounds() {
1341: return (getBounds(new Rectangle()));
1342: }
1343:
1344: /*
1345: * (non-Javadoc)
1346: *
1347: * @see java.awt.Component#getBounds(java.awt.Rectangle)
1348: */
1349: public Rectangle getBounds(Rectangle rect) {
1350: Rectangle rv = (rect != null) ? rect : new Rectangle();
1351: rv.setBounds(0, 0, size.width, size.height);
1352: return (rv);
1353: }
1354:
1355: /**
1356: * Returns the constraints defined for this component. Often this will be null.
1357: *
1358: * @return the constraints defined for this component
1359: */
1360: public IzPanelConstraints getConstraints() {
1361: return constraints;
1362: }
1363:
1364: /**
1365: * Sets the constraints which should be used by this component.
1366: *
1367: * @param constraints constraints to be used
1368: */
1369: public void setConstraints(IzPanelConstraints constraints) {
1370: this .constraints = constraints;
1371: }
1372: }
1373:
1374: /**
1375: * Returns the anchor constant.
1376: *
1377: * @return the anchor constant
1378: */
1379: public static int getAnchor() {
1380: return ANCHOR;
1381: }
1382:
1383: /**
1384: * Sets the anchor constant.
1385: *
1386: * @param anchor symbolic constant to be used
1387: */
1388: public static void setAnchor(int anchor) {
1389: ANCHOR = anchor;
1390: }
1391:
1392: /**
1393: * Returns the current used type of stretching for the X-direction. Possible values are NO,
1394: * RELATIVE and ABSOLUTE.
1395: *
1396: * @return the current used type of stretching for the X-direction
1397: */
1398: public static int getXStretchType() {
1399: return X_STRETCH_TYPE;
1400: }
1401:
1402: /**
1403: * Sets the type of stretching to be used for the X-Direction. Possible values are NO, RELATIVE
1404: * and ABSOLUTE.
1405: *
1406: * @param x_stretch constant to be used for stretch type
1407: */
1408: public static void setXStretchType(int x_stretch) {
1409: X_STRETCH_TYPE = x_stretch;
1410: }
1411:
1412: /**
1413: * Returns the current used type of stretching for the Y-direction. Possible values are NO,
1414: * RELATIVE and ABSOLUTE.
1415: *
1416: * @return the current used type of stretching for the Y-direction
1417: */
1418: public static int getYStretchType() {
1419: return Y_STRETCH_TYPE;
1420: }
1421:
1422: /**
1423: * Sets the type of stretching to be used for the Y-Direction. Possible values are NO, RELATIVE
1424: * and ABSOLUTE.
1425: *
1426: * @param y_stretch constant to be used for stretch type
1427: */
1428: public static void setYStretchType(int y_stretch) {
1429: Y_STRETCH_TYPE = y_stretch;
1430: }
1431:
1432: /**
1433: * Returns the value which should be used stretching to a full line.
1434: *
1435: * @return the value which should be used stretching to a full line
1436: */
1437: public static double getFullLineStretch() {
1438: return FULL_LINE_STRETCH_DEFAULT;
1439: }
1440:
1441: /**
1442: * Sets the value which should be used as default for stretching to a full line.
1443: *
1444: * @param fullLineStretch value to be used as full line stretching default
1445: */
1446: public static void setFullLineStretch(double fullLineStretch) {
1447: FULL_LINE_STRETCH_DEFAULT = fullLineStretch;
1448:
1449: }
1450:
1451: /**
1452: * Returns the value which should be used stretching to a full column.
1453: *
1454: * @return the value which should be used stretching to a full column
1455: */
1456: public static double getFullColumnStretch() {
1457: return FULL_COLUMN_STRETCH_DEFAULT;
1458: }
1459:
1460: /**
1461: * Sets the value which should be used as default for stretching to a full column.
1462: *
1463: * @param fullStretch value to be used as full column stretching default
1464: */
1465: public static void setFullColumnStretch(double fullStretch) {
1466: FULL_COLUMN_STRETCH_DEFAULT = fullStretch;
1467:
1468: }
1469:
1470: /**
1471: * Verifies whether a gap id is valid or not. If the id is less than zero, the sign will be
1472: * removed. If the id is out of range, an IndexOutOfBoundsException will be thrown. The return
1473: * value is the verified unsigned id.
1474: *
1475: * @param gapId to be verified
1476: * @return the verified gap id
1477: */
1478: public static int verifyGapId(int gapId) {
1479: if (gapId < 0)
1480: gapId = -gapId;
1481: if (gapId >= DEFAULT_X_GAPS.length)
1482: throw new IndexOutOfBoundsException(
1483: "gapId is not in the default gap container.");
1484: return (gapId);
1485: }
1486:
1487: /**
1488: * Returns the default x gap for the given gap id.
1489: *
1490: * @param gapId for which the default x gap should be returned
1491: * @return the default x gap for the given gap id
1492: */
1493: public static int getDefaultXGap(int gapId) {
1494: gapId = verifyGapId(gapId);
1495: return DEFAULT_X_GAPS[gapId];
1496: }
1497:
1498: /**
1499: * Set the gap for the given gap id for the x default gaps.
1500: *
1501: * @param gap to be used as default
1502: * @param gapId for which the default should be set
1503: */
1504: public static void setDefaultXGap(int gap, int gapId) {
1505: gapId = verifyGapId(gapId);
1506: DEFAULT_X_GAPS[gapId] = gap;
1507: }
1508:
1509: /**
1510: * Returns the default y gap for the given gap id.
1511: *
1512: * @param gapId for which the default y gap should be returned
1513: * @return the default x gap for the given gap id
1514: */
1515: public static int getDefaultYGap(int gapId) {
1516: gapId = verifyGapId(gapId);
1517: return DEFAULT_Y_GAPS[gapId];
1518: }
1519:
1520: /**
1521: * Set the gap for the given gap id for the y default gaps.
1522: *
1523: * @param gap to be used as default
1524: * @param gapId for which the default should be set
1525: */
1526: public static void setDefaultYGap(int gap, int gapId) {
1527: gapId = verifyGapId(gapId);
1528: DEFAULT_Y_GAPS[gapId] = gap;
1529: }
1530:
1531: /**
1532: * Returns the default length used by textfields.
1533: *
1534: * @return the default length used by textfields
1535: */
1536: public static int getDefaultTextfieldLength() {
1537: return DEFAULT_TEXTFIELD_LENGTH;
1538: }
1539:
1540: /**
1541: * Sets the value for the default length of textfields.
1542: *
1543: * @param val to be set as default length for textfields
1544: */
1545: public static void setDefaultTextfieldLength(int val) {
1546: DEFAULT_TEXTFIELD_LENGTH = val;
1547: }
1548:
1549: }
|