/* * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com), * modifications by Nikolaus Moll * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list * of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or other * materials provided with the distribution. * Neither the name of the MiG InfoCom AB nor the names of its contributors may be * used to endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * * @version 1.0 * @author Mikael Grev, MiG InfoCom AB * Date: 2006-sep-08 */ package org.jowidgets.impl.layout.miglayout; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.io.ObjectStreamException; import java.util.ArrayList; /** * A constraint that holds the column <b>or</b> row constraints for the grid. It also holds the gaps between the rows and columns. * <p> * This class is a holder and builder for a number of {@link DimConstraintCommon.miginfocom.layout.DimConstraint}s. * <p> * For a more thorough explanation of what these constraints do, and how to build the constraints, see the White Paper or Cheat * Sheet at www.migcomponents.com. * <p> * Note that there are two way to build this constraint. Through String (e.g. <code>"[100]3[200,fill]"</code> or through API (E.g. * <code>new AxisConstraint().size("100").gap("3").size("200").fill()</code>. */ final class ACCommon implements Externalizable { private final ArrayList<DimConstraintCommon> cList = new ArrayList<DimConstraintCommon>(8); private transient int curIx = 0; /** * Constructor. Creates an instance that can be configured manually. Will be initialized with a default * {@link DimConstraintCommon.miginfocom.layout.DimConstraint}. */ ACCommon() { cList.add(new DimConstraintCommon()); } /** * Property. The different {@link DimConstraintCommon.miginfocom.layout.DimConstraint}s that this object consists of. * These <code><DimConstraints/code> contains all information in this class. * <p> * Yes, we are embarrassingly aware that the method is misspelled. * * @return The different {@link DimConstraintCommon.miginfocom.layout.DimConstraint}s that this object consists of. A new list * and * never <code>null</code>. */ public DimConstraintCommon[] getConstaints() { return cList.toArray(new DimConstraintCommon[cList.size()]); } /** * Sets the different {@link DimConstraintCommon.miginfocom.layout.DimConstraint}s that this object should consists of. * <p> * Yes, we are embarrassingly aware that the method is misspelled. * * @param constr The different {@link DimConstraintCommon.miginfocom.layout.DimConstraint}s that this object consists of. The * list * will be copied for storage. <code>null</code> or and emty array will reset the constraints to one * <code>DimConstraint</code> with default values. */ public void setConstaints(DimConstraintCommon[] constr) { if (constr == null || constr.length < 1) { constr = new DimConstraintCommon[] {new DimConstraintCommon()}; } cList.clear(); cList.ensureCapacity(constr.length); for (final DimConstraintCommon c : constr) { cList.add(c); } } /** * Returns the number of rows/columns that this constraints currently have. * * @return The number of rows/columns that this constraints currently have. At least 1. */ public int getCount() { return cList.size(); } /** * Sets the total number of rows/columns to <code>size</code>. If the number of rows/columns is already more * than <code>size</code> nothing will happen. * * @param size The total number of rows/columns * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>. */ public ACCommon count(final int size) { makeSize(size); return this; } /** * Specifies that the current row/column should not be grid-like. The while row/colum will have its components layed out * in one single cell. It is the same as to say that the cells in this column/row will all be merged (a.k.a spanned). * <p> * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>. */ public ACCommon noGrid() { return noGrid(curIx); } /** * Specifies that the indicated rows/columns should not be grid-like. The while row/colum will have its components layed out * in one single cell. It is the same as to say that the cells in this column/row will all be merged (a.k.a spanned). * <p> * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * * @param indexes The index(es) (0-based) of the columns/rows that should be affected by this constraint. * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>. */ public ACCommon noGrid(final int... indexes) { for (int i = indexes.length - 1; i >= 0; i--) { final int ix = indexes[i]; makeSize(ix); cList.get(ix).setNoGrid(true); } return this; } /** * Sets the current row/column to <code>i</code>. If the current number of rows/columns is less than <code>i</code> a call * to {@link #count(int)} will set the size accordingly. * <p> * The next call to any of the constraint methods (e.g. {@link ACCommon.miginfocom.layout.AC#noGrid}) will be carried out on * this new row/column. * <p> * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * * @param i The new current row/column. * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>. */ public ACCommon index(final int i) { makeSize(i); curIx = i; return this; } /** * Specifies that the current row/column's component should grow by default. It does not affect the size of the row/column. * <p> * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>. */ public ACCommon fill() { return fill(curIx); } /** * Specifies that the indicated rows'/columns' component should grow by default. It does not affect the size of the * row/column. * <p> * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * * @param indexes The index(es) (0-based) of the columns/rows that should be affected by this constraint. * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>. */ public ACCommon fill(final int... indexes) { for (int i = indexes.length - 1; i >= 0; i--) { final int ix = indexes[i]; makeSize(ix); cList.get(ix).setFill(true); } return this; } // /** Specifies that the current row/column should be put in the end group <code>s</code> and will thus share the same ending // * coordinate within the group. // * <p> // * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. // * @param s A name to associate on the group that should be the same for other rows/columns in the same group. // * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>. // */ // public final AxisConstraint endGroup(String s) // { // return endGroup(s, curIx); // } // // /** Specifies that the indicated rows/columns should be put in the end group <code>s</code> and will thus share the same ending // * coordinate within the group. // * <p> // * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. // * @param s A name to associate on the group that should be the same for other rows/columns in the same group. // * @param indexes The index(es) (0-based) of the columns/rows that should be affected by this constraint. // * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>. // */ // public final AxisConstraint endGroup(String s, int... indexes) // { // for (int i = indexes.length - 1; i >= 0; i--) { // int ix = indexes[i]; // makeSize(ix); // cList.get(ix).setEndGroup(s); // } // return this; // } /** * Specifies that the current row/column should be put in the size group <code>s</code> and will thus share the same size * constraints as the other components in the group. * <p> * Same as <code>sizeGroup("")</code> * <p> * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>. * @since 3.7.2 */ public ACCommon sizeGroup() { return sizeGroup("", curIx); } /** * Specifies that the current row/column should be put in the size group <code>s</code> and will thus share the same size * constraints as the other components in the group. * <p> * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * * @param s A name to associate on the group that should be the same for other rows/columns in the same group. * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>. */ public ACCommon sizeGroup(final String s) { return sizeGroup(s, curIx); } /** * Specifies that the indicated rows/columns should be put in the size group <code>s</code> and will thus share the same size * constraints as the other components in the group. * <p> * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * * @param s A name to associate on the group that should be the same for other rows/columns in the same group. * @param indexes The index(es) (0-based) of the columns/rows that should be affected by this constraint. * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>. */ public ACCommon sizeGroup(final String s, final int... indexes) { for (int i = indexes.length - 1; i >= 0; i--) { final int ix = indexes[i]; makeSize(ix); cList.get(ix).setSizeGroup(s); } return this; } /** * Specifies the current row/column's min and/or preferred and/or max size. E.g. <code>"10px"</code> or * <code>"50:100:200"</code>. * <p> * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * * @param s The minimum and/or preferred and/or maximum size of this row. The string will be interpreted * as a <b>BoundSize</b>. For more info on how <b>BoundSize</b> is formatted see the documentation. * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>. */ public ACCommon size(final String s) { return size(s, curIx); } /** * Specifies the indicated rows'/columns' min and/or preferred and/or max size. E.g. <code>"10px"</code> or * <code>"50:100:200"</code>. * <p> * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * * @param size The minimum and/or preferred and/or maximum size of this row. The string will be interpreted * as a <b>BoundSize</b>. For more info on how <b>BoundSize</b> is formatted see the documentation. * @param indexes The index(es) (0-based) of the columns/rows that should be affected by this constraint. * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>. */ public ACCommon size(final String size, final int... indexes) { final BoundSizeCommon bs = ConstraintParserCommon.parseBoundSize(size, false, true); for (int i = indexes.length - 1; i >= 0; i--) { final int ix = indexes[i]; makeSize(ix); cList.get(ix).setSize(bs); } return this; } /** * Specifies the gap size to be the default one <b>AND</b> moves to the next column/row. The method is called * <code>.gap()</code> rather the more natural <code>.next()</code> to indicate that it is very much related to the other * <code>.gap(..)</code> methods. * <p> * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>. */ public ACCommon gap() { curIx++; return this; } /** * Specifies the gap size to <code>size</code> <b>AND</b> moves to the next column/row. * <p> * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * * @param size minimum and/or preferred and/or maximum size of the gap between this and the next row/column. * The string will be interpreted as a <b>BoundSize</b>. For more info on how <b>BoundSize</b> is formatted see the * documentation. * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>. */ public ACCommon gap(final String size) { return gap(size, curIx++); } /** * Specifies the indicated rows'/columns' gap size to <code>size</code>. * <p> * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * * @param size minimum and/or preferred and/or maximum size of the gap between this and the next row/column. * The string will be interpreted as a <b>BoundSize</b>. For more info on how <b>BoundSize</b> is formatted see the * documentation. * @param indexes The index(es) (0-based) of the columns/rows that should be affected by this constraint. * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>. */ public ACCommon gap(final String size, final int... indexes) { final BoundSizeCommon bsa = size != null ? ConstraintParserCommon.parseBoundSize(size, true, true) : null; for (int i = indexes.length - 1; i >= 0; i--) { final int ix = indexes[i]; makeSize(ix); if (bsa != null) { cList.get(ix).setGapAfter(bsa); } } return this; } /** * Specifies the current row/column's columns default alignment <b>for its components</b>. It does not affect the positioning * or size of the columns/row itself. For columns it is the horizonal alignment (e.g. "left") and for rows it is the vertical * alignment (e.g. "top"). * <p> * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * * @param side The default side to align the components. E.g. "top" or "left", or "leading" or "trailing" or "bottom" or * "right". * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>. */ public ACCommon align(final String side) { return align(side, curIx); } /** * Specifies the indicated rows'/columns' columns default alignment <b>for its components</b>. It does not affect the * positioning * or size of the columns/row itself. For columns it is the horizonal alignment (e.g. "left") and for rows it is the vertical * alignment (e.g. "top"). * <p> * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * * @param side The default side to align the components. E.g. "top" or "left", or "before" or "after" or "bottom" or "right". * @param indexes The index(es) (0-based) of the columns/rows that should be affected by this constraint. * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>. */ public ACCommon align(final String side, final int... indexes) { UnitValueCommon al = ConstraintParserCommon.parseAlignKeywords(side, true); if (al == null) { al = ConstraintParserCommon.parseAlignKeywords(side, false); } for (int i = indexes.length - 1; i >= 0; i--) { final int ix = indexes[i]; makeSize(ix); cList.get(ix).setAlign(al); } return this; } /** * Specifies the current row/column's grow priority. * <p> * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * * @param p The new grow priority. * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>. */ public ACCommon growPrio(final int p) { return growPrio(p, curIx); } /** * Specifies the indicated rows'/columns' grow priority. * <p> * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * * @param p The new grow priority. * @param indexes The index(es) (0-based) of the columns/rows that should be affected by this constraint. * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>. */ public ACCommon growPrio(final int p, final int... indexes) { for (int i = indexes.length - 1; i >= 0; i--) { final int ix = indexes[i]; makeSize(ix); cList.get(ix).setGrowPriority(p); } return this; } /** * Specifies the current row/column's grow weight within columns/rows with the <code>grow priority</code> 100f. * <p> * Same as <code>grow(100f)</code> * <p> * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>. * @since 3.7.2 */ public ACCommon grow() { return grow(1f, curIx); } /** * Specifies the current row/column's grow weight within columns/rows with the same <code>grow priority</code>. * <p> * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * * @param w The new grow weight. * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>. */ public ACCommon grow(final float w) { return grow(w, curIx); } /** * Specifies the indicated rows'/columns' grow weight within columns/rows with the same <code>grow priority</code>. * <p> * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * * @param w The new grow weight. * @param indexes The index(es) (0-based) of the columns/rows that should be affected by this constraint. * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>. */ public ACCommon grow(final float w, final int... indexes) { final Float gw = new Float(w); for (int i = indexes.length - 1; i >= 0; i--) { final int ix = indexes[i]; makeSize(ix); cList.get(ix).setGrow(gw); } return this; } /** * Specifies the current row/column's shrink priority. * <p> * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * * @param p The new shrink priority. * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>. */ public ACCommon shrinkPrio(final int p) { return shrinkPrio(p, curIx); } /** * Specifies the indicated rows'/columns' shrink priority. * <p> * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * * @param p The new shrink priority. * @param indexes The index(es) (0-based) of the columns/rows that should be affected by this constraint. * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>. */ public ACCommon shrinkPrio(final int p, final int... indexes) { for (int i = indexes.length - 1; i >= 0; i--) { final int ix = indexes[i]; makeSize(ix); cList.get(ix).setShrinkPriority(p); } return this; } /** * Specifies that the current row/column's shrink weight withing the columns/rows with the <code>shrink priority</code> 100f. * <p> * Same as <code>shrink(100f)</code>. * <p> * For a more thorough explanation of what this constraint does see the White Paper or Cheat Sheet at www.migcomponents.com. * * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>. * @since 3.7.2 */ public ACCommon shrink() { return shrink(100f, curIx); } /** * Specifies that the current row/column's shrink weight withing the columns/rows with the same <code>shrink priority</code>. * <p> * For a more thorough explanation of what this constraint does see the White Paper or Cheat Sheet at www.migcomponents.com. * * @param w The shrink weight. * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>. * @since 3.7.2 */ public ACCommon shrink(final float w) { return shrink(w, curIx); } /** * Specifies the indicated rows'/columns' shrink weight withing the columns/rows with the same <code>shrink priority</code>. * <p> * For a more thorough explanation of what this constraint does see the White Paper or Cheat Sheet at www.migcomponents.com. * * @param w The shrink weight. * @param indexes The index(es) (0-based) of the columns/rows that should be affected by this constraint. * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>. * @since 3.7.2 */ public ACCommon shrink(final float w, final int... indexes) { final Float sw = new Float(w); for (int i = indexes.length - 1; i >= 0; i--) { final int ix = indexes[i]; makeSize(ix); cList.get(ix).setShrink(sw); } return this; } /** * Specifies that the current row/column's shrink weight withing the columns/rows with the same <code>shrink priority</code>. * <p> * For a more thorough explanation of what this constraint does see the White Paper or Cheat Sheet at www.migcomponents.com. * * @param w The shrink weight. * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>. * @deprecated in 3.7.2. Use {@link #shrink(float)} instead. */ @Deprecated public ACCommon shrinkWeight(final float w) { return shrink(w); } /** * Specifies the indicated rows'/columns' shrink weight withing the columns/rows with the same <code>shrink priority</code>. * <p> * For a more thorough explanation of what this constraint does see the White Paper or Cheat Sheet at www.migcomponents.com. * * @param w The shrink weight. * @param indexes The index(es) (0-based) of the columns/rows that should be affected by this constraint. * @return <code>this</code> so it is possible to chain calls. E.g. <code>new AxisConstraint().noGrid().gap().fill()</code>. * @deprecated in 3.7.2. Use {@link #shrink(float, int...)} instead. */ @Deprecated public ACCommon shrinkWeight(final float w, final int... indexes) { return shrink(w, indexes); } private void makeSize(final int sz) { if (cList.size() <= sz) { cList.ensureCapacity(sz); for (int i = cList.size(); i <= sz; i++) { cList.add(new DimConstraintCommon()); } } } // ************************************************ // Persistence Delegate and Serializable combined. // ************************************************ private Object readResolve() throws ObjectStreamException { return MigLayoutToolkitImpl.getMigLayoutUtil().getSerializedObject(this); } @Override public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException { final LayoutUtilCommon layoutUtil = MigLayoutToolkitImpl.getMigLayoutUtil(); layoutUtil.setSerializedObject(this, layoutUtil.readAsXML(in)); } @Override public void writeExternal(final ObjectOutput out) throws IOException { if (getClass() == ACCommon.class) { MigLayoutToolkitImpl.getMigLayoutUtil().writeAsXML(out, this); } } }