pax_global_header00006660000000000000000000000064132410156320014507gustar00rootroot0000000000000052 comment=391752a7c1878873f2d487956dfaa417754e56d7 miglayout-5.1/000077500000000000000000000000001324101563200133665ustar00rootroot00000000000000miglayout-5.1/.gitignore000077500000000000000000000011661324101563200153650ustar00rootroot00000000000000 /core/.settings /core/target /core/.project /core/.classpath /demo/.project /demo/.settings /demo/target /demo/.classpath /examples/.project /examples/.settings /examples/target /examples/.classpath /ideutil/.project /ideutil/.settings /ideutil/target /ideutil/.classpath /swing/.project /swing/.settings /swing/target /swing/.classpath /swt/.project /swt/.settings /swt/target /swt/.classpath /target /release.properties /javafx/.project /javafx/.settings /javafx/target /javafx/.classpath # # ignore target folders in the build tree # **/target # # ignore eclipse local settings files # **/.project **/.classpath **/.settings miglayout-5.1/README.md000066400000000000000000000016021324101563200146440ustar00rootroot00000000000000# miglayout Official MiG Layout for Swing, SWT and JavaFX For Java developers writing GUI layouts by hand that wants simplicity, power and automatic per platform fidelity, that are dissatisfied with the current layout managers in Swing, JavaFX and SWT, MigLayout solves your layout problems. User interfaces created with MigLayout is easy to maintain, you will understand how the layout will look like just by looking at the source code. MigLayout is a superbly versatile JavaFX/SWT/Swing layout manager that makes layout problems trivial. It is using String or API type-checked constraints to format the layout. MigLayout can produce flowing, grid based, absolute (with links), grouped and docking layouts. You will never have to switch to another layout manager ever again! MigLayout is created to be to manually coded layouts what Matisse/GroupLayout is to IDE supported visual layouts. miglayout-5.1/core/000077500000000000000000000000001324101563200143165ustar00rootroot00000000000000miglayout-5.1/core/pom.xml000077500000000000000000000012021324101563200156310ustar00rootroot00000000000000 4.0.0 com.miglayout miglayout-parent 5.1-SNAPSHOT ../pom.xml miglayout-core jar MiGLayout Core MiGLayout - core layout logic miglayout-5.1/core/src/000077500000000000000000000000001324101563200151055ustar00rootroot00000000000000miglayout-5.1/core/src/main/000077500000000000000000000000001324101563200160315ustar00rootroot00000000000000miglayout-5.1/core/src/main/java/000077500000000000000000000000001324101563200167525ustar00rootroot00000000000000miglayout-5.1/core/src/main/java/net/000077500000000000000000000000001324101563200175405ustar00rootroot00000000000000miglayout-5.1/core/src/main/java/net/miginfocom/000077500000000000000000000000001324101563200216675ustar00rootroot00000000000000miglayout-5.1/core/src/main/java/net/miginfocom/layout/000077500000000000000000000000001324101563200232045ustar00rootroot00000000000000miglayout-5.1/core/src/main/java/net/miginfocom/layout/AC.java000077500000000000000000000620571324101563200243470ustar00rootroot00000000000000package net.miginfocom.layout; import java.io.*; import java.util.ArrayList; /* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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 */ /** A constraint that holds the column or row constraints for the grid. It also holds the gaps between the rows and columns. *

* This class is a holder and builder for a number of {@link net.miginfocom.layout.DimConstraint}s. *

* 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. *

* Note that there are two way to build this constraint. Through String (e.g. "[100]3[200,fill]" or through API (E.g. * new AC().size("100").gap("3").size("200").fill(). */ public final class AC implements Externalizable { private final ArrayList cList = new ArrayList(1); private transient int curIx = 0; /** Constructor. Creates an instance that can be configured manually. Will be initialized with a default * {@link net.miginfocom.layout.DimConstraint}. */ public AC() { cList.add(new DimConstraint()); } /** Property. The different {@link net.miginfocom.layout.DimConstraint}s that this object consists of. * These DimConstraints contains all information in this class. *

* Yes, we are embarrassingly aware that the method is misspelled. * @return The different {@link net.miginfocom.layout.DimConstraint}s that this object consists of. A new list and * never null. */ public final DimConstraint[] getConstaints() { return cList.toArray(new DimConstraint[cList.size()]); } /** Sets the different {@link net.miginfocom.layout.DimConstraint}s that this object should consists of. *

* Yes, we are embarrassingly aware that the method is misspelled. * @param constr The different {@link net.miginfocom.layout.DimConstraint}s that this object consists of. The list * will be copied for storage. null or and empty array will reset the constraints to one DimConstraint * with default values. */ public final void setConstaints(DimConstraint[] constr) { if (constr == null || constr.length < 1 ) constr = new DimConstraint[] {new DimConstraint()}; cList.clear(); cList.ensureCapacity(constr.length); for (DimConstraint 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 size. If the number of rows/columns is already more * than size nothing will happen. * @param size The total number of rows/columns * @return this so it is possible to chain calls. E.g. new AxisConstraint().noGrid().gap().fill(). */ public final AC count(int size) { makeSize(size); return this; } /** Specifies that the current row/column should not be grid-like. The while row/column 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). *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new AxisConstraint().noGrid().gap().fill(). */ public final AC noGrid() { return noGrid(curIx); } /** Specifies that the indicated rows/columns should not be grid-like. The while row/column 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). *

* 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 this so it is possible to chain calls. E.g. new AxisConstraint().noGrid().gap().fill(). */ public final AC noGrid(int... indexes) { for (int i = indexes.length - 1; i >= 0; i--) { int ix = indexes[i]; makeSize(ix); cList.get(ix).setNoGrid(true); } return this; } /** Sets the current row/column to i. If the current number of rows/columns is less than i a call * to {@link #count(int)} will set the size accordingly. *

* The next call to any of the constraint methods (e.g. {@link net.miginfocom.layout.AC#noGrid}) will be carried * out on this new row/column. *

* 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 this so it is possible to chain calls. E.g. new AxisConstraint().noGrid().gap().fill(). */ public final AC index(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. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new AxisConstraint().noGrid().gap().fill(). */ public final AC 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. *

* 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 this so it is possible to chain calls. E.g. new AxisConstraint().noGrid().gap().fill(). */ public final AC fill(int... indexes) { for (int i = indexes.length - 1; i >= 0; i--) { 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 s and will thus share the same ending // * coordinate within the group. // *

// * 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 this so it is possible to chain calls. E.g. new AxisConstraint().noGrid().gap().fill(). // */ // public final AxisConstraint endGroup(String s) // { // return endGroup(s, curIx); // } // // /** Specifies that the indicated rows/columns should be put in the end group s and will thus share the same ending // * coordinate within the group. // *

// * 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 this so it is possible to chain calls. E.g. new AxisConstraint().noGrid().gap().fill(). // */ // 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 s and will thus share the same size * constraints as the other components in the group. *

* Same as sizeGroup("") *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new AxisConstraint().noGrid().gap().fill(). * @since 3.7.2 */ public final AC sizeGroup() { return sizeGroup("", curIx); } /** Specifies that the current row/column should be put in the size group s and will thus share the same size * constraints as the other components in the group. *

* 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 this so it is possible to chain calls. E.g. new AxisConstraint().noGrid().gap().fill(). */ public final AC sizeGroup(String s) { return sizeGroup(s, curIx); } /** Specifies that the indicated rows/columns should be put in the size group s and will thus share the same size * constraints as the other components in the group. *

* 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 this so it is possible to chain calls. E.g. new AxisConstraint().noGrid().gap().fill(). */ public final AC sizeGroup(String s, int... indexes) { for (int i = indexes.length - 1; i >= 0; i--) { 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. "10px" or "50:100:200". *

* 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 BoundSize. For more info on how BoundSize is formatted see the documentation. * @return this so it is possible to chain calls. E.g. new AxisConstraint().noGrid().gap().fill(). */ public final AC size(String s) { return size(s, curIx); } /** Specifies the indicated rows'/columns' min and/or preferred and/or max size. E.g. "10px" or "50:100:200". *

* 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 BoundSize. For more info on how BoundSize is formatted see the documentation. * @param indexes The index(es) (0-based) of the columns/rows that should be affected by this constraint. * @return this so it is possible to chain calls. E.g. new AxisConstraint().noGrid().gap().fill(). */ public final AC size(String size, int... indexes) { BoundSize bs = ConstraintParser.parseBoundSize(size, false, true); for (int i = indexes.length - 1; i >= 0; i--) { int ix = indexes[i]; makeSize(ix); cList.get(ix).setSize(bs); } return this; } /** Specifies the gap size to be the default one AND moves to the next column/row. The method is called .gap() * rather the more natural .next() to indicate that it is very much related to the other .gap(..) methods. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new AxisConstraint().noGrid().gap().fill(). */ public final AC gap() { curIx++; makeSize(curIx); return this; } /** Specifies the gap size to size AND moves to the next column/row. *

* 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 BoundSize. For more info on how BoundSize is formatted see the documentation. * @return this so it is possible to chain calls. E.g. new AxisConstraint().noGrid().gap().fill(). */ public final AC gap(String size) { return gap(size, curIx++); } /** Specifies the indicated rows'/columns' gap size to size. *

* 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 BoundSize. For more info on how BoundSize is formatted see the documentation. * @param indexes The index(es) (0-based) of the columns/rows that should be affected by this constraint. * @return this so it is possible to chain calls. E.g. new AxisConstraint().noGrid().gap().fill(). */ public final AC gap(String size, int... indexes) { BoundSize bsa = size != null ? ConstraintParser.parseBoundSize(size, true, true) : null; for (int i = indexes.length - 1; i >= 0; i--) { int ix = indexes[i]; makeSize(ix + 1); if (bsa != null) cList.get(ix).setGapAfter(bsa); } return this; } /** Specifies the current row/column's columns default alignment for its components. It does not affect the positioning * or size of the columns/row itself. For columns it is the horizontal alignment (e.g. "left") and for rows it is the vertical * alignment (e.g. "top"). *

* 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 this so it is possible to chain calls. E.g. new AxisConstraint().noGrid().gap().fill(). */ public final AC align(String side) { return align(side, curIx); } /** Specifies the indicated rows'/columns' columns default alignment for its components. It does not affect the positioning * or size of the columns/row itself. For columns it is the horizontal alignment (e.g. "left") and for rows it is the vertical * alignment (e.g. "top"). *

* 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 this so it is possible to chain calls. E.g. new AxisConstraint().noGrid().gap().fill(). */ public final AC align(String side, int... indexes) { UnitValue al = ConstraintParser.parseAlignKeywords(side, true); if (al == null) al = ConstraintParser.parseAlignKeywords(side, false); for (int i = indexes.length - 1; i >= 0; i--) { int ix = indexes[i]; makeSize(ix); cList.get(ix).setAlign(al); } return this; } /** Specifies the current row/column's grow priority. *

* 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 this so it is possible to chain calls. E.g. new AxisConstraint().noGrid().gap().fill(). */ public final AC growPrio(int p) { return growPrio(p, curIx); } /** Specifies the indicated rows'/columns' grow priority. *

* 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 this so it is possible to chain calls. E.g. new AxisConstraint().noGrid().gap().fill(). */ public final AC growPrio(int p, int... indexes) { for (int i = indexes.length - 1; i >= 0; i--) { 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 grow priority 100f. *

* Same as grow(100f) *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new AxisConstraint().noGrid().gap().fill(). * @since 3.7.2 */ public final AC grow() { return grow(100f, curIx); } /** Specifies the current row/column's grow weight within columns/rows with the same grow priority. *

* 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 this so it is possible to chain calls. E.g. new AxisConstraint().noGrid().gap().fill(). */ public final AC grow(float w) { return grow(w, curIx); } /** Specifies the indicated rows'/columns' grow weight within columns/rows with the same grow priority. *

* 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 this so it is possible to chain calls. E.g. new AxisConstraint().noGrid().gap().fill(). */ public final AC grow(float w, int... indexes) { Float gw = new Float(w); for (int i = indexes.length - 1; i >= 0; i--) { int ix = indexes[i]; makeSize(ix); cList.get(ix).setGrow(gw); } return this; } /** Specifies the current row/column's shrink priority. *

* 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 this so it is possible to chain calls. E.g. new AxisConstraint().noGrid().gap().fill(). */ public final AC shrinkPrio(int p) { return shrinkPrio(p, curIx); } /** Specifies the indicated rows'/columns' shrink priority. *

* 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 this so it is possible to chain calls. E.g. new AxisConstraint().noGrid().gap().fill(). */ public final AC shrinkPrio(int p, int... indexes) { for (int i = indexes.length - 1; i >= 0; i--) { int ix = indexes[i]; makeSize(ix); cList.get(ix).setShrinkPriority(p); } return this; } /** Specifies that the current row/column's shrink weight within the columns/rows with the shrink priority 100f. *

* Same as shrink(100f). *

* For a more thorough explanation of what this constraint does see the White Paper or Cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new AxisConstraint().noGrid().gap().fill(). * @since 3.7.2 */ public final AC shrink() { return shrink(100f, curIx); } /** Specifies that the current row/column's shrink weight within the columns/rows with the same shrink priority. *

* 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 this so it is possible to chain calls. E.g. new AxisConstraint().noGrid().gap().fill(). * @since 3.7.2 */ public final AC shrink(float w) { return shrink(w, curIx); } /** Specifies the indicated rows'/columns' shrink weight within the columns/rows with the same shrink priority. *

* 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 this so it is possible to chain calls. E.g. new AxisConstraint().noGrid().gap().fill(). * @since 3.7.2 */ public final AC shrink(float w, int... indexes) { Float sw = new Float(w); for (int i = indexes.length - 1; i >= 0; i--) { int ix = indexes[i]; makeSize(ix); cList.get(ix).setShrink(sw); } return this; } /** Specifies that the current row/column's shrink weight within the columns/rows with the same shrink priority. *

* 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 this so it is possible to chain calls. E.g. new AxisConstraint().noGrid().gap().fill(). * @deprecated in 3.7.2. Use {@link #shrink(float)} instead. */ public final AC shrinkWeight(float w) { return shrink(w); } /** Specifies the indicated rows'/columns' shrink weight within the columns/rows with the same shrink priority. *

* 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 this so it is possible to chain calls. E.g. new AxisConstraint().noGrid().gap().fill(). * @deprecated in 3.7.2. Use {@link #shrink(float, int...)} instead. */ public final AC shrinkWeight(float w, int... indexes) { return shrink(w, indexes); } private void makeSize(int sz) { if (cList.size() <= sz) { cList.ensureCapacity(sz); for (int i = cList.size(); i <= sz; i++) cList.add(new DimConstraint()); } } // ************************************************ // Persistence Delegate and Serializable combined. // ************************************************ private Object readResolve() throws ObjectStreamException { return LayoutUtil.getSerializedObject(this); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { LayoutUtil.setSerializedObject(this, LayoutUtil.readAsXML(in)); } @Override public void writeExternal(ObjectOutput out) throws IOException { if (getClass() == AC.class) LayoutUtil.writeAsXML(out, this); } }miglayout-5.1/core/src/main/java/net/miginfocom/layout/AnimSpec.java000066400000000000000000000073141324101563200255530ustar00rootroot00000000000000package net.miginfocom.layout; /* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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 */ import java.io.Serializable; /** * @author Mikael Grev, MiG InfoCom AB * Date: 14-09-24 * Time: 17:05 */ public class AnimSpec implements Serializable { // public static final AnimSpec OFF = new AnimSpec(-1, 0, 0); public static final AnimSpec DEF = new AnimSpec(0, 0, 0.2f, 0.2f); private final int prio; private final int durMillis; private final float easeIn, easeOut; /** * @param prio The animation priority. When added with the general animation priority of the layout the animation will * be done if the resulting value is > 0. * @param durMillis Duration in milliseconds. <=0 means default value should be used and > 0 is the number of millis * @param easeIn 0 is linear (no ease). 1 is max ease. Always clamped between these values. * @param easeOut 0 is linear (no ease). 1 is max ease. Always clamped between these values. */ public AnimSpec(int prio, int durMillis, float easeIn, float easeOut) { this.prio = prio; this.durMillis = durMillis; this.easeIn = LayoutUtil.clamp(easeIn, 0, 1); this.easeOut = LayoutUtil.clamp(easeOut, 0, 1); } /** * @return The animation priority. When added with the general animation priority of the layout the animation will * be done if the resulting value is > 0. */ public int getPriority() { return prio; } /** * @param defMillis Default used if the millis in the spec is set to "default". * @return Duration in milliseconds. <=0 means default value should be used and > 0 is the number of millis */ public int getDurationMillis(int defMillis) { return durMillis > 0 ? durMillis : defMillis; } /** * @return Duration in milliseconds. <= 0 means default value should be used and > 0 is the number of millis */ public int getDurationMillis() { return durMillis; } /** * @return A value between 0 and 1 where 0 is no ease in and 1 is maximum ease in. */ public float getEaseIn() { return easeIn; } /** * @return A value between 0 and 1 where 0 is no ease out and 1 is maximum ease out. */ public float getEaseOut() { return easeOut; } } miglayout-5.1/core/src/main/java/net/miginfocom/layout/BoundSize.java000077500000000000000000000245251324101563200257640ustar00rootroot00000000000000package net.miginfocom.layout; import java.beans.Encoder; import java.beans.Expression; import java.beans.PersistenceDelegate; import java.io.*; /* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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 */ /** A size that contains minimum, preferred and maximum size of type {@link UnitValue}. *

* This class is a simple value container and it is immutable. *

* If a size is missing (i.e., null) that boundary should be considered "not in use". *

* You can create a BoundSize from a String with the use of {@link ConstraintParser#parseBoundSize(String, boolean, boolean)} */ public class BoundSize implements Serializable { public static final BoundSize NULL_SIZE = new BoundSize(null, null); public static final BoundSize ZERO_PIXEL = new BoundSize(UnitValue.ZERO, "0px"); private final transient UnitValue min; private final transient UnitValue pref; private final transient UnitValue max; private final transient boolean gapPush; /** Constructor that use the same value for min/preferred/max size. * @param minMaxPref The value to use for min/preferred/max size. * @param createString The string used to create the BoundsSize. */ public BoundSize(UnitValue minMaxPref, String createString) { this(minMaxPref, minMaxPref, minMaxPref, createString); } /** Constructor. This method is here for serialization only and should normally not be used. Use * {@link ConstraintParser#parseBoundSize(String, boolean, boolean)} instead. * @param min The minimum size. May be null. * @param preferred The preferred size. May be null. * @param max The maximum size. May be null. * @param createString The string used to create the BoundsSize. */ public BoundSize(UnitValue min, UnitValue preferred, UnitValue max, String createString) // Bound to old delegate!!!!! { this(min, preferred, max, false, createString); } /** Constructor. This method is here for serialization only and should normally not be used. Use * {@link ConstraintParser#parseBoundSize(String, boolean, boolean)} instead. * @param min The minimum size. May be null. * @param preferred The preferred size. May be null. * @param max The maximum size. May be null. * @param gapPush If the size should be hinted as "pushing" and thus want to occupy free space if no one else is claiming it. * @param createString The string used to create the BoundsSize. */ public BoundSize(UnitValue min, UnitValue preferred, UnitValue max, boolean gapPush, String createString) { this.min = min; this.pref = preferred; this.max = max; this.gapPush = gapPush; LayoutUtil.putCCString(this, createString); // this escapes!! } /** Returns the minimum size as sent into the constructor. * @return The minimum size as sent into the constructor. May be null. */ public final UnitValue getMin() { return min; } /** Returns the preferred size as sent into the constructor. * @return The preferred size as sent into the constructor. May be null. */ public final UnitValue getPreferred() { return pref; } /** Returns the maximum size as sent into the constructor. * @return The maximum size as sent into the constructor. May be null. */ public final UnitValue getMax() { return max; } /** If the size should be hinted as "pushing" and thus want to occupy free space if no one else is claiming it. * @return The value. */ public boolean getGapPush() { return gapPush; } /** Returns if this bound size has no min, preferred and maximum size set (they are all null) * @return If unset. */ public boolean isUnset() { // Most common case by far is this == ZERO_PIXEL... return this == ZERO_PIXEL || (pref == null && min == null && max == null && gapPush == false); } /** Makes sure that size is within min and max of this size. * @param size The size to constrain. * @param refValue The reference to use for relative sizes. * @param parent The parent container. * @return The size, constrained within min and max. */ public int constrain(int size, float refValue, ContainerWrapper parent) { if (max != null) size = Math.min(size, max.getPixels(refValue, parent, parent)); if (min != null) size = Math.max(size, min.getPixels(refValue, parent, parent)); return size; } /** Returns the minimum, preferred or maximum size for this bounded size. * @param sizeType The type. LayoutUtil.MIN, LayoutUtil.PREF or LayoutUtil.MAX. * @return */ final UnitValue getSize(int sizeType) { switch(sizeType) { case LayoutUtil.MIN: return min; case LayoutUtil.PREF: return pref; case LayoutUtil.MAX: return max; default: throw new IllegalArgumentException("Unknown size: " + sizeType); } } /** Convert the bound sizes to pixels. *

* null bound sizes will be 0 for min and preferred and {@link net.miginfocom.layout.LayoutUtil#INF} for max. * @param refSize The reference size. * @param parent The parent. Not null. * @param comp The component, if applicable, can be null. * @return An array of length three (min,pref,max). */ final int[] getPixelSizes(float refSize, ContainerWrapper parent, ComponentWrapper comp) { return new int[] { min != null ? min.getPixels(refSize, parent, comp) : 0, pref != null ? pref.getPixels(refSize, parent, comp) : 0, max != null ? max.getPixels(refSize, parent, comp) : LayoutUtil.INF }; } /** Returns the a constraint string that can be re-parsed to be the exact same UnitValue. * @return A String. Never null. */ String getConstraintString() { String cs = LayoutUtil.getCCString(this); if (cs != null) return cs; if (min == pref && pref == max) return min != null ? (min.getConstraintString() + "!") : "null"; StringBuilder sb = new StringBuilder(16); if (min != null) sb.append(min.getConstraintString()).append(':'); if (pref != null) { if (min == null && max != null) sb.append(":"); sb.append(pref.getConstraintString()); } else if (min != null) { sb.append('n'); } if (max != null) sb.append(sb.length() == 0 ? "::" : ":").append(max.getConstraintString()); if (gapPush) { if (sb.length() > 0) sb.append(':'); sb.append("push"); } return sb.toString(); } void checkNotLinked() { if (isLinked()) throw new IllegalArgumentException("Size may not contain links"); } boolean isLinked() { return min != null && min.isLinkedDeep() || pref != null && pref.isLinkedDeep() || max != null && max.isLinkedDeep(); } boolean isAbsolute() { return (min == null || min.isAbsoluteDeep()) && (pref == null || pref.isAbsoluteDeep()) && (max == null || max.isAbsoluteDeep()); } public String toString() { return "BoundSize{" + "min=" + min + ", pref=" + pref + ", max=" + max + ", gapPush=" + gapPush +'}'; } static { if(LayoutUtil.HAS_BEANS){ LayoutUtil.setDelegate(BoundSize.class, new PersistenceDelegate() { @Override protected Expression instantiate(Object oldInstance, Encoder out) { BoundSize bs = (BoundSize) oldInstance; if (Grid.TEST_GAPS) { return new Expression(oldInstance, BoundSize.class, "new", new Object[] { bs.getMin(), bs.getPreferred(), bs.getMax(), bs.getGapPush(), bs.getConstraintString() }); } else { return new Expression(oldInstance, BoundSize.class, "new", new Object[] { bs.getMin(), bs.getPreferred(), bs.getMax(), bs.getConstraintString() }); } } }); } } // ************************************************ // Persistence Delegate and Serializable combined. // ************************************************ private static final long serialVersionUID = 1L; protected Object readResolve() throws ObjectStreamException { return LayoutUtil.getSerializedObject(this); } private void writeObject(ObjectOutputStream out) throws IOException { if (getClass() == BoundSize.class) LayoutUtil.writeAsXML(out, this); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { LayoutUtil.setSerializedObject(this, LayoutUtil.readAsXML(in)); } } miglayout-5.1/core/src/main/java/net/miginfocom/layout/CC.java000077500000000000000000002362321324101563200243470ustar00rootroot00000000000000package net.miginfocom.layout; import java.io.*; import java.util.ArrayList; /* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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 */ /** A simple value holder for one component's constraint. */ public final class CC implements Externalizable { private static final BoundSize DEF_GAP = BoundSize.NULL_SIZE; // Only used to denote default wrap/newline gap. static final String[] DOCK_SIDES = {"north", "west", "south", "east"}; // See the getters and setters for information about the properties below. private int dock = -1; private UnitValue[] pos = null; // [x1, y1, x2, y2] private UnitValue[] padding = null; // top, left, bottom, right private UnitValue[] visualPadding = null; // top, left, bottom, right private Boolean flowX = null; private int skip = 0; private int split = 1; private int spanX = 1, spanY = 1; private int cellX = -1, cellY = 0; // If cellX is -1 then cellY is also considered -1. cellY is never negative. private String tag = null; private String id = null; private int hideMode = -1; private DimConstraint hor = new DimConstraint(); private DimConstraint ver = new DimConstraint(); private BoundSize newline = null; private BoundSize wrap = null; private boolean boundsInGrid = true; private boolean external = false; private Float pushX = null, pushY = null; private AnimSpec animSpec = AnimSpec.DEF; // ***** Tmp cache field private static final String[] EMPTY_ARR = new String[0]; private transient String[] linkTargets = null; /** Empty constructor. */ public CC() { } String[] getLinkTargets() { if (linkTargets == null) { final ArrayList targets = new ArrayList(2); if (pos != null) { for (int i = 0; i < pos.length ; i++) addLinkTargetIDs(targets, pos[i]); } linkTargets = targets.size() == 0 ? EMPTY_ARR : targets.toArray(new String[targets.size()]); } return linkTargets; } private void addLinkTargetIDs(ArrayList targets, UnitValue uv) { if (uv != null) { String linkId = uv.getLinkTargetId(); if (linkId != null) { targets.add(linkId); } else { for (int i = uv.getSubUnitCount() - 1; i >= 0; i--) { UnitValue subUv = uv.getSubUnitValue(i); if (subUv.isLinkedDeep()) addLinkTargetIDs(targets, subUv); } } } } // ********************************************************** // Chaining constraint setters // ********************************************************** /** Specifies that the component should be put in the end group s and will thus share the same ending * coordinate as them within the group. *

* 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 this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). */ public final CC endGroupX(String s) { hor.setEndGroup(s); return this; } /** Specifies that the component should be put in the size group s and will thus share the same size * as them within the group. *

* 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 this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). */ public final CC sizeGroupX(String s) { hor.setSizeGroup(s); return this; } /** The minimum size for the component. The value will override any value that is set on the component itself. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param size The size expressed as a UnitValue. E.g. "100px" or "200mm". * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). */ public final CC minWidth(String size) { hor.setSize(LayoutUtil.derive(hor.getSize(), ConstraintParser.parseUnitValue(size, true), null, null)); return this; } /** The size for the component as a min and/or preferred and/or maximum size. The value will override any value that is set on * the component itself. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param size The size expressed as a BoundSize. E.g. "50:100px:200mm" or "100px". * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). */ public final CC width(String size) { hor.setSize(ConstraintParser.parseBoundSize(size, false, true)); return this; } /** The maximum size for the component. The value will override any value that is set on the component itself. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param size The size expressed as a UnitValue. E.g. "100px" or "200mm". * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). */ public final CC maxWidth(String size) { hor.setSize(LayoutUtil.derive(hor.getSize(), null, null, ConstraintParser.parseUnitValue(size, true))); return this; } /** The horizontal gap before and/or after the component. The gap is towards cell bounds and/or other component bounds. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param before The size of the gap expressed as a BoundSize. E.g. "50:100px:200mm" or "100px!". * @param after The size of the gap expressed as a BoundSize. E.g. "50:100px:200mm" or "100px!". * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). */ public final CC gapX(String before, String after) { if (before != null) hor.setGapBefore(ConstraintParser.parseBoundSize(before, true, true)); if (after != null) hor.setGapAfter(ConstraintParser.parseBoundSize(after, true, true)); return this; } /** Same functionality as getHorizontal().setAlign(ConstraintParser.parseUnitValue(unitValue, true)) only this method * returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param align The align keyword or for instance "100px". E.g "left", "right", "leading" or "trailing". * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). */ public final CC alignX(String align) { hor.setAlign(ConstraintParser.parseUnitValueOrAlign(align, true, null)); return this; } /** The grow priority compared to other components in the same cell. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param p The grow priority. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). */ public final CC growPrioX(int p) { hor.setGrowPriority(p); return this; } /** Grow priority for the component horizontally and optionally vertically. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param widthHeight The new shrink weight and height. 1-2 arguments, never null. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @since 3.7.2 */ public final CC growPrio(int ... widthHeight) { switch (widthHeight.length) { default: throw new IllegalArgumentException("Illegal argument count: " + widthHeight.length); case 2: growPrioY(widthHeight[1]); case 1: growPrioX(widthHeight[0]); } return this; } /** Grow weight for the component horizontally. It default to weight 100. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @see #growX(float) */ public final CC growX() { hor.setGrow(ResizeConstraint.WEIGHT_100); return this; } /** Grow weight for the component horizontally. *

* 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 this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). */ public final CC growX(float w) { hor.setGrow(new Float(w)); return this; } /** grow weight for the component horizontally and optionally vertically. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param widthHeight The new shrink weight and height. 1-2 arguments, never null. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @since 3.7.2 */ public final CC grow(float ... widthHeight) { switch (widthHeight.length) { default: throw new IllegalArgumentException("Illegal argument count: " + widthHeight.length); case 2: growY(widthHeight[1]); case 1: growX(widthHeight[0]); } return this; } /** The shrink priority compared to other components in the same cell. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param p The shrink priority. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). */ public final CC shrinkPrioX(int p) { hor.setShrinkPriority(p); return this; } /** Shrink priority for the component horizontally and optionally vertically. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param widthHeight The new shrink weight and height. 1-2 arguments, never null. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @since 3.7.2 */ public final CC shrinkPrio(int ... widthHeight) { switch (widthHeight.length) { default: throw new IllegalArgumentException("Illegal argument count: " + widthHeight.length); case 2: shrinkPrioY(widthHeight[1]); case 1: shrinkPrioX(widthHeight[0]); } return this; } /** Shrink weight for the component horizontally. *

* 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 shrink weight. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). */ public final CC shrinkX(float w) { hor.setShrink(new Float(w)); return this; } /** Shrink weight for the component horizontally and optionally vertically. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param widthHeight The new shrink weight and height. 1-2 arguments, never null. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @since 3.7.2 */ public final CC shrink(float ... widthHeight) { switch (widthHeight.length) { default: throw new IllegalArgumentException("Illegal argument count: " + widthHeight.length); case 2: shrinkY(widthHeight[1]); case 1: shrinkX(widthHeight[0]); } return this; } /** The end group that this component should be placed in. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param s The name of the group. If null that means no group (default) * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). */ public final CC endGroupY(String s) { ver.setEndGroup(s); return this; } /** The end group(s) that this component should be placed in. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param xy The end group for x and y respectively. 1-2 arguments, not null. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @since 3.7.2 */ public final CC endGroup(String ... xy) { switch (xy.length) { default: throw new IllegalArgumentException("Illegal argument count: " + xy.length); case 2: endGroupY(xy[1]); case 1: endGroupX(xy[0]); } return this; } /** The size group that this component should be placed in. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param s The name of the group. If null that means no group (default) * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). */ public final CC sizeGroupY(String s) { ver.setSizeGroup(s); return this; } /** The size group(s) that this component should be placed in. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param xy The size group for x and y respectively. 1-2 arguments, not null. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @since 3.7.2 */ public final CC sizeGroup(String ... xy) { switch (xy.length) { default: throw new IllegalArgumentException("Illegal argument count: " + xy.length); case 2: sizeGroupY(xy[1]); case 1: sizeGroupX(xy[0]); } return this; } /** The minimum size for the component. The value will override any value that is set on the component itself. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param size The size expressed as a UnitValue. E.g. "100px" or "200mm". * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). */ public final CC minHeight(String size) { ver.setSize(LayoutUtil.derive(ver.getSize(), ConstraintParser.parseUnitValue(size, false), null, null)); return this; } /** The size for the component as a min and/or preferred and/or maximum size. The value will override any value that is set on * the component itself. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param size The size expressed as a BoundSize. E.g. "50:100px:200mm" or "100px". * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). */ public final CC height(String size) { ver.setSize(ConstraintParser.parseBoundSize(size, false, false)); return this; } /** The maximum size for the component. The value will override any value that is set on the component itself. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param size The size expressed as a UnitValue. E.g. "100px" or "200mm". * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). */ public final CC maxHeight(String size) { ver.setSize(LayoutUtil.derive(ver.getSize(), null, null, ConstraintParser.parseUnitValue(size, false))); return this; } /** The vertical gap before (normally above) and/or after (normally below) the component. The gap is towards cell bounds and/or other component bounds. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param before The size of the gap expressed as a BoundSize. E.g. "50:100px:200mm" or "100px!". * @param after The size of the gap expressed as a BoundSize. E.g. "50:100px:200mm" or "100px!". * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). */ public final CC gapY(String before, String after) { if (before != null) ver.setGapBefore(ConstraintParser.parseBoundSize(before, true, false)); if (after != null) ver.setGapAfter(ConstraintParser.parseBoundSize(after, true, false)); return this; } /** Same functionality as getVertical().setAlign(ConstraintParser.parseUnitValue(unitValue, true)) only this method * returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param align The align keyword or for instance "100px". E.g "top" or "bottom". * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). */ public final CC alignY(String align) { ver.setAlign(ConstraintParser.parseUnitValueOrAlign(align, false, null)); return this; } /** The grow priority compared to other components in the same cell. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param p The grow priority. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). */ public final CC growPrioY(int p) { ver.setGrowPriority(p); return this; } /** Grow weight for the component vertically. Defaults to 100. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @see #growY(Float) */ public final CC growY() { ver.setGrow(ResizeConstraint.WEIGHT_100); return this; } /** Grow weight for the component vertically. *

* 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 this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). */ public final CC growY(float w) { ver.setGrow(w); return this; } /** Grow weight for the component vertically. *

* 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 this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). */ @Deprecated public final CC growY(Float w) { ver.setGrow(w); return this; } /** The shrink priority compared to other components in the same cell. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param p The shrink priority. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). */ public final CC shrinkPrioY(int p) { ver.setShrinkPriority(p); return this; } /** Shrink weight for the component horizontally. *

* 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 shrink weight. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). */ public final CC shrinkY(float w) { ver.setShrink(new Float(w)); return this; } /** How this component, if hidden (not visible), should be treated. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param mode The mode. Default to the mode in the {@link net.miginfocom.layout.LC}. * 0 == Normal. Bounds will be calculated as if the component was visible.
* 1 == If hidden the size will be 0, 0 but the gaps remain.
* 2 == If hidden the size will be 0, 0 and gaps set to zero.
* 3 == If hidden the component will be disregarded completely and not take up a cell in the grid.. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). */ public final CC hideMode(int mode) { setHideMode(mode); return this; } /** The id used to reference this component in some constraints. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param s The id or null. May consist of a groupID and an componentID which are separated by a dot: ".". E.g. "grp1.id1". * The dot should never be first or last if present. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). */ public final CC id(String s) { setId(s); return this; } /** Same functionality as {@link #setTag(String tag)} only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param tag The new tag. May be null. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @see #setTag(String) */ public final CC tag(String tag) { setTag(tag); return this; } /** Set the cell(s) that the component should occupy in the grid. Same functionality as {@link #setCellX(int col)} and * {@link #setCellY(int row)} together with {@link #setSpanX(int width)} and {@link #setSpanY(int height)}. This method * returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param colRowWidthHeight cellX, cellY, spanX, spanY respectively. 1-4 arguments, not null. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @see #setCellX(int) * @see #setCellY(int) * @see #setSpanX(int) * @see #setSpanY(int) * @since 3.7.2. Replacing cell(int, int) and cell(int, int, int, int) */ public final CC cell(int ... colRowWidthHeight) { switch (colRowWidthHeight.length) { default: throw new IllegalArgumentException("Illegal argument count: " + colRowWidthHeight.length); case 4: setSpanY(colRowWidthHeight[3]); case 3: setSpanX(colRowWidthHeight[2]); case 2: setCellY(colRowWidthHeight[1]); case 1: setCellX(colRowWidthHeight[0]); } return this; } /** Same functionality as spanX(cellsX).spanY(cellsY) which means this cell will span cells in both x and y. * This method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * Since 3.7.2 this takes an array/vararg whereas it previously only took two specific values, xSpan and ySpan. * @param cells spanX and spanY, when present, and in that order. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @see #setSpanY(int) * @see #setSpanX(int) * @see #spanY() * @see #spanX() * @since 3.7.2 Replaces span(int, int). */ public final CC span(int ... cells) { if (cells == null || cells.length == 0) { setSpanX(LayoutUtil.INF); setSpanY(1); } else if (cells.length == 1) { setSpanX(cells[0]); setSpanY(1); } else { setSpanX(cells[0]); setSpanY(cells[1]); } return this; } /** Corresponds exactly to the "gap left right top bottom" keyword. * @param args Same as for the "gap" keyword. Length 1-4, never null buf elements can be null. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @since 3.7.2 */ public final CC gap(String ... args) { switch (args.length) { default: throw new IllegalArgumentException("Illegal argument count: " + args.length); case 4: gapBottom(args[3]); case 3: gapTop(args[2]); case 2: gapRight(args[1]); case 1: gapLeft(args[0]); } return this; } /** Sets the horizontal gap before the component. *

* Note! This is currently same as gapLeft(). This might change in 4.x. * @param boundsSize The size of the gap expressed as a BoundSize. E.g. "50:100px:200mm" or "100px!". * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @since 3.7.2 */ public final CC gapBefore(String boundsSize) { hor.setGapBefore(ConstraintParser.parseBoundSize(boundsSize, true, true)); return this; } /** Sets the horizontal gap after the component. *

* Note! This is currently same as gapRight(). This might change in 4.x. * @param boundsSize The size of the gap expressed as a BoundSize. E.g. "50:100px:200mm" or "100px!". * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @since 3.7.2 */ public final CC gapAfter(String boundsSize) { hor.setGapAfter(ConstraintParser.parseBoundSize(boundsSize, true, true)); return this; } /** Sets the gap above the component. * @param boundsSize The size of the gap expressed as a BoundSize. E.g. "50:100px:200mm" or "100px!". * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @since 3.7.2 */ public final CC gapTop(String boundsSize) { ver.setGapBefore(ConstraintParser.parseBoundSize(boundsSize, true, false)); return this; } /** Sets the gap to the left the component. * @param boundsSize The size of the gap expressed as a BoundSize. E.g. "50:100px:200mm" or "100px!". * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @since 3.7.2 */ public final CC gapLeft(String boundsSize) { hor.setGapBefore(ConstraintParser.parseBoundSize(boundsSize, true, true)); return this; } /** Sets the gap below the component. * @param boundsSize The size of the gap expressed as a BoundSize. E.g. "50:100px:200mm" or "100px!". * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @since 3.7.2 */ public final CC gapBottom(String boundsSize) { ver.setGapAfter(ConstraintParser.parseBoundSize(boundsSize, true, false)); return this; } /** Sets the gap to the right of the component. * @param boundsSize The size of the gap expressed as a BoundSize. E.g. "50:100px:200mm" or "100px!". * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @since 3.7.2 */ public final CC gapRight(String boundsSize) { hor.setGapAfter(ConstraintParser.parseBoundSize(boundsSize, true, true)); return this; } /** Same functionality as calling {@link #setSpanY(int)} with LayoutUtil.INF which means this cell will span the rest of the column. * This method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @see #setSpanY(int) * @see #spanY() */ public final CC spanY() { return spanY(LayoutUtil.INF); } /** Same functionality as {@link #setSpanY(int)} only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param cells The number of cells to span (i.e. merge). * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @see #setSpanY(int) */ public final CC spanY(int cells) { setSpanY(cells); return this; } /** Same functionality as {@link #setSpanX(int)} which means this cell will span the rest of the row. * This method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @see #setSpanX(int) * @see #spanX() */ public final CC spanX() { return spanX(LayoutUtil.INF); } /** Same functionality as {@link #setSpanX(int)} only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param cells The number of cells to span (i.e. merge). * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @see #setSpanY(int) */ public final CC spanX(int cells) { setSpanX(cells); return this; } /** Same functionality as pushX().pushY() which means this cell will push in both x and y dimensions. * This method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @see #setPushX(Float) * @see #setPushX(Float) * @see #pushY() * @see #pushX() */ public final CC push() { return pushX().pushY(); } /** Same functionality as pushX(weightX).pushY(weightY) which means this cell will push in both x and y dimensions. * This method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param weightX The weight used in the push. * @param weightY The weight used in the push. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @see #setPushY(Float) * @see #setPushX(Float) * @see #pushY() * @see #pushX() */ public final CC push(Float weightX, Float weightY) { return pushX(weightX).pushY(weightY); } /** Same functionality as {@link #setPushY(Float)} which means this cell will push the rest of the column. * This method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @see #setPushY(Float) */ public final CC pushY() { return pushY(ResizeConstraint.WEIGHT_100); } /** Same functionality as {@link #setPushY(Float weight)} only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param weight The weight used in the push. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @see #setPushY(Float) */ public final CC pushY(Float weight) { setPushY(weight); return this; } /** Same functionality as {@link #setPushX(Float)} which means this cell will push the rest of the row. * This method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @see #setPushX(Float) */ public final CC pushX() { return pushX(ResizeConstraint.WEIGHT_100); } /** Same functionality as {@link #setPushX(Float weight)} only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param weight The weight used in the push. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @see #setPushY(Float) */ public final CC pushX(Float weight) { setPushX(weight); return this; } /** Same functionality as {@link #setSplit(int parts)} only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param parts The number of parts (i.e. component slots) the cell should be divided into. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @see #setSplit(int) */ public final CC split(int parts) { setSplit(parts); return this; } /** Same functionality as split(LayoutUtil.INF), which means split until one of the keywords that breaks the split is found for * a component after this one (e.g. wrap, newline and skip). *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @see #setSplit(int) * @since 3.7.2 */ public final CC split() { setSplit(LayoutUtil.INF); return this; } /** Same functionality as {@link #setSkip(int)} only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param cells How many cells in the grid that should be skipped before the component that this constraint belongs to * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @see #setSkip(int) */ public final CC skip(int cells) { setSkip(cells); return this; } /** Same functionality as skip(1). *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @see #setSkip(int) * @since 3.7.2 */ public final CC skip() { setSkip(1); return this; } /** Same functionality as calling {@link #setExternal(boolean)} with true only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @see #setExternal(boolean) */ public final CC external() { setExternal(true); return this; } /** Same functionality as calling {@link #setFlowX(Boolean)} with Boolean.TRUE only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @see #setFlowX(Boolean) */ public final CC flowX() { setFlowX(Boolean.TRUE); return this; } /** Same functionality as calling {@link #setFlowX(Boolean)} with Boolean.FALSE only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @see #setFlowX(Boolean) */ public final CC flowY() { setFlowX(Boolean.FALSE); return this; } /** Same functionality as {@link #growX()} and {@link #growY()}. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @see #growX() * @see #growY() */ public final CC grow() { growX(); growY(); return this; } /** Same functionality as calling {@link #setNewline(boolean)} with true only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @see #setNewline(boolean) */ public final CC newline() { setNewline(true); return this; } /** Same functionality as {@link #setNewlineGapSize(BoundSize)} only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param gapSize The gap size that will override the gap size in the row/column constraints if != null. E.g. "5px" or "unrel". * If null or "" the newline size will be set to the default size and turned on. This is different compared to * {@link #setNewlineGapSize(BoundSize)}. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @see #setNewlineGapSize(BoundSize) */ public final CC newline(String gapSize) { BoundSize bs = ConstraintParser.parseBoundSize(gapSize, true, (flowX != null && flowX == false)); if (bs != null) { setNewlineGapSize(bs); } else { setNewline(true); } return this; } /** Same functionality as calling {@link #setWrap(boolean)} with true only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @see #setWrap(boolean) */ public final CC wrap() { setWrap(true); return this; } /** Same functionality as {@link #setWrapGapSize(BoundSize)} only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param gapSize The gap size that will override the gap size in the row/column constraints if != null. E.g. "5px" or "unrel". * If null or "" the wrap size will be set to the default size and turned on. This is different compared to * {@link #setWrapGapSize(BoundSize)}. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @see #setWrapGapSize(BoundSize) */ public final CC wrap(String gapSize) { BoundSize bs = ConstraintParser.parseBoundSize(gapSize, true, (flowX != null && flowX == false)); if (bs != null) { setWrapGapSize(bs); } else { setWrap(true); } return this; } /** Same functionality as calling {@link #setDockSide(int)} with 0 only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @see #setDockSide(int) */ public final CC dockNorth() { setDockSide(0); return this; } /** Same functionality as calling {@link #setDockSide(int)} with 1 only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @see #setDockSide(int) */ public final CC dockWest() { setDockSide(1); return this; } /** Same functionality as calling {@link #setDockSide(int)} with 2 only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @see #setDockSide(int) */ public final CC dockSouth() { setDockSide(2); return this; } /** Same functionality as calling {@link #setDockSide(int)} with 3 only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @see #setDockSide(int) */ public final CC dockEast() { setDockSide(3); return this; } /** Sets the x-coordinate for the component. This is used to set the x coordinate position to a specific value. The component * bounds is still precalculated to the grid cell and this method should be seen as a way to correct the x position. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param x The x position as a UnitValue. E.g. "10" or "40mm" or "container.x+10". * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @see #setPos(UnitValue[]) * @see #setBoundsInGrid(boolean) */ public final CC x(String x) { return corrPos(x, 0); } /** Sets the y-coordinate for the component. This is used to set the y coordinate position to a specific value. The component * bounds is still precalculated to the grid cell and this method should be seen as a way to correct the y position. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param y The y position as a UnitValue. E.g. "10" or "40mm" or "container.x+10". * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @see #setPos(UnitValue[]) * @see #setBoundsInGrid(boolean) */ public final CC y(String y) { return corrPos(y, 1); } /** Sets the x2-coordinate for the component (right side). This is used to set the x2 coordinate position to a specific value. The component * bounds is still precalculated to the grid cell and this method should be seen as a way to correct the x position. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param x2 The x2 side's position as a UnitValue. E.g. "10" or "40mm" or "container.x2 - 10". * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @see #setPos(UnitValue[]) * @see #setBoundsInGrid(boolean) */ public final CC x2(String x2) { return corrPos(x2, 2); } /** Sets the y2-coordinate for the component (bottom side). This is used to set the y2 coordinate position to a specific value. The component * bounds is still precalculated to the grid cell and this method should be seen as a way to correct the y position. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param y2 The y2 side's position as a UnitValue. E.g. "10" or "40mm" or "container.x2 - 10". * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @see #setPos(UnitValue[]) * @see #setBoundsInGrid(boolean) */ public final CC y2(String y2) { return corrPos(y2, 3); } private final CC corrPos(String uv, int ix) { UnitValue[] b = getPos(); if (b == null) b = new UnitValue[4]; b[ix] = ConstraintParser.parseUnitValue(uv, (ix % 2 == 0)); setPos(b); setBoundsInGrid(true); return this; } /** Same functionality as {@link #x(String x)} and {@link #y(String y)} together. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param x The x position as a UnitValue. E.g. "10" or "40mm" or "container.x+10". * @param y The y position as a UnitValue. E.g. "10" or "40mm" or "container.x+10". * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @see #setPos(UnitValue[]) */ public final CC pos(String x, String y) { UnitValue[] b = getPos(); if (b == null) b = new UnitValue[4]; b[0] = ConstraintParser.parseUnitValue(x, true); b[1] = ConstraintParser.parseUnitValue(y, false); setPos(b); setBoundsInGrid(false); return this; } /** Same functionality as {@link #x(String x)}, {@link #y(String y)}, {@link #y2(String y)} and {@link #y2(String y)} together. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param x The x position as a UnitValue. E.g. "10" or "40mm" or "container.x+10". * @param y The y position as a UnitValue. E.g. "10" or "40mm" or "container.x+10". * @param x2 The x2 side's position as a UnitValue. E.g. "10" or "40mm" or "container.x2 - 10". * @param y2 The y2 side's position as a UnitValue. E.g. "10" or "40mm" or "container.x2 - 10". * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @see #setPos(UnitValue[]) */ public final CC pos(String x, String y, String x2, String y2) { setPos(new UnitValue[] { ConstraintParser.parseUnitValue(x, true), ConstraintParser.parseUnitValue(y, false), ConstraintParser.parseUnitValue(x2, true), ConstraintParser.parseUnitValue(y2, false), }); setBoundsInGrid(false); return this; } /** Same functionality as {@link #setPadding(UnitValue[])} but the unit values as absolute pixels. This method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param top The top padding that will be added to the y coordinate at the last stage in the layout. * @param left The top padding that will be added to the x coordinate at the last stage in the layout. * @param bottom The top padding that will be added to the y2 coordinate at the last stage in the layout. * @param right The top padding that will be added to the x2 coordinate at the last stage in the layout. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @see #setTag(String) */ public final CC pad(int top, int left, int bottom, int right) { setPadding(new UnitValue[] { new UnitValue(top), new UnitValue(left), new UnitValue(bottom), new UnitValue(right) }); return this; } /** Same functionality as setPadding(ConstraintParser.parseInsets(pad, false))} only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param pad The string to parse. E.g. "10 10 10 10" or "20". If less than 4 groups the last will be used for the missing. * @return this so it is possible to chain calls. E.g. new ComponentConstraint().noGrid().gap().fill(). * @see #setTag(String) */ public final CC pad(String pad) { setPadding(pad != null ? ConstraintParser.parseInsets(pad, false) : null); return this; } // ********************************************************** // Bean properties // ********************************************************** /** Returns the horizontal dimension constraint for this component constraint. It has constraints for the horizontal size * and grow/shrink priorities and weights. *

* Note! If any changes is to be made it must be made direct when the object is returned. It is not allowed to save the * constraint for later use. * @return The current dimension constraint. Never null. */ public DimConstraint getHorizontal() { return hor; } /** Sets the horizontal dimension constraint for this component constraint. It has constraints for the horizontal size * and grow/shrink priorities and weights. * @param h The new dimension constraint. If null it will be reset to new DimConstraint(); */ public void setHorizontal(DimConstraint h) { hor = h != null ? h : new DimConstraint(); } /** Returns the vertical dimension constraint for this component constraint. It has constraints for the vertical size * and grow/shrink priorities and weights. *

* Note! If any changes is to be made it must be made direct when the object is returned. It is not allowed to save the * constraint for later use. * @return The current dimension constraint. Never null. */ public DimConstraint getVertical() { return ver; } /** Sets the vertical dimension constraint for this component constraint. It has constraints for the vertical size * and grow/shrink priorities and weights. * @param v The new dimension constraint. If null it will be reset to new DimConstraint(); */ public void setVertical(DimConstraint v) { ver = v != null ? v : new DimConstraint(); } /** Returns the vertical or horizontal dim constraint. *

* Note! If any changes is to be made it must be made direct when the object is returned. It is not allowed to save the * constraint for later use. * @param isHor If the horizontal constraint should be returned. * @return The dim constraint. Never null. */ public DimConstraint getDimConstraint(boolean isHor) { return isHor ? hor : ver; } /** Returns the absolute positioning of one or more of the edges. This will be applied last in the layout cycle and will not * affect the flow or grid positions. The positioning is relative to the parent and can not (as padding) be used * to adjust the edges relative to the old value. May be null and elements may be null. * null value(s) for the x2 and y2 will be interpreted as to keep the preferred size and thus the x1 * and x2 will just absolutely positions the component. *

* Note that {@link #setBoundsInGrid(boolean)} changes the interpretation of this property slightly. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return The current value as a new array, free to modify. */ public UnitValue[] getPos() { return pos != null ? new UnitValue[] {pos[0], pos[1], pos[2], pos[3]} : null; } /** Sets absolute positioning of one or more of the edges. This will be applied last in the layout cycle and will not * affect the flow or grid positions. The positioning is relative to the parent and can not (as padding) be used * to adjust the edges relative to the old value. May be null and elements may be null. * null value(s) for the x2 and y2 will be interpreted as to keep the preferred size and thus the x1 * and x2 will just absolutely positions the component. *

* Note that {@link #setBoundsInGrid(boolean)} changes the interpretation of this property slightly. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param pos UnitValue[] {x, y, x2, y2}. Must be null or of length 4. Elements can be null. */ public void setPos(UnitValue[] pos) { this.pos = pos != null ? new UnitValue[] {pos[0], pos[1], pos[2], pos[3]} : null; linkTargets = null; } /** Returns if the absolute pos value should be corrections to the component that is in a normal cell. If false * the value of pos is truly absolute in that it will not affect the grid or have a default bounds in the grid. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return The current value. * @see #getPos() */ public boolean isBoundsInGrid() { return boundsInGrid; } /** Sets if the absolute pos value should be corrections to the component that is in a normal cell. If false * the value of pos is truly absolute in that it will not affect the grid or have a default bounds in the grid. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param b true for bounds taken from the grid position. false is default. * @see #setPos(UnitValue[]) */ void setBoundsInGrid(boolean b) { this.boundsInGrid = b; } /** Returns the absolute cell position in the grid or -1 if cell positioning is not used. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return The current value. */ public int getCellX() { return cellX; } /** Set an absolute cell x-position in the grid. If >= 0 this point points to the absolute cell that this constaint's component should occupy. * If there's already a component in that cell they will split the cell. The flow will then continue after this cell. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param x The x-position or -1 to disable cell positioning. */ public void setCellX(int x) { cellX = x; } /** Returns the absolute cell position in the grid or -1 if cell positioning is not used. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return The current value. */ public int getCellY() { return cellX < 0 ? -1 : cellY; } /** Set an absolute cell x-position in the grid. If >= 0 this point points to the absolute cell that this constaint's component should occupy. * If there's already a component in that cell they will split the cell. The flow will then continue after this cell. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param y The y-position or -1 to disable cell positioning. */ public void setCellY(int y) { if (y < 0) cellX = -1; cellY = y < 0 ? 0 : y; } /** Sets the docking side. -1 means no docking.
* Valid sides are: north = 0, west = 1, south = 2, east = 3. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return The current side. */ public int getDockSide() { return dock; } /** Sets the docking side. -1 means no docking.
* Valid sides are: north = 0, west = 1, south = 2, east = 3. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param side -1 or 0-3. */ public void setDockSide(int side) { if (side < -1 || side > 3) throw new IllegalArgumentException("Illegal dock side: " + side); dock = side; } /** Returns if this component should have its bounds handled by an external source and not this layout manager. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return The current value. */ public boolean isExternal() { return external; } /** If this boolean is true this component is not handled in any way by the layout manager and the component can have its bounds set by an external * handler which is normally by the use of some component.setBounds(x, y, width, height) directly (for Swing). *

* The bounds will not affect the minimum and preferred size of the container. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param b true means that the bounds are not changed. */ public void setExternal(boolean b) { this.external = b; } /** Returns if the flow in the cell is in the horizontal dimension. Vertical if false. Only the first * component is a cell can set the flow. *

* If null the flow direction is inherited by from the {@link net.miginfocom.layout.LC}. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return The current value. */ public Boolean getFlowX() { return flowX; } /** Sets if the flow in the cell is in the horizontal dimension. Vertical if false. Only the first * component is a cell can set the flow. *

* If null the flow direction is inherited by from the {@link net.miginfocom.layout.LC}. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param b Boolean.TRUE means horizontal flow in the cell. */ public void setFlowX(Boolean b) { this.flowX = b; } /** Sets how a component that is hidden (not visible) should be treated by default. * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return The mode:
* 0 == Normal. Bounds will be calculated as if the component was visible.
* 1 == If hidden the size will be 0, 0 but the gaps remain.
* 2 == If hidden the size will be 0, 0 and gaps set to zero.
* 3 == If hidden the component will be disregarded completely and not take up a cell in the grid.. */ public int getHideMode() { return hideMode; } /** Sets how a component that is hidden (not visible) should be treated by default. * @param mode The mode:
* 0 == Normal. Bounds will be calculated as if the component was visible.
* 1 == If hidden the size will be 0, 0 but the gaps remain.
* 2 == If hidden the size will be 0, 0 and gaps set to zero.
* 3 == If hidden the component will be disregarded completely and not take up a cell in the grid.. */ public void setHideMode(int mode) { if (mode < -1 || mode > 3) throw new IllegalArgumentException("Wrong hideMode: " + mode); hideMode = mode; } /** Returns the id used to reference this component in some constraints. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return The id or null. May consist of a groupID and an componentID which are separated by a dot: ".". E.g. "grp1.id1". * The dot should never be first or last if present. */ public String getId() { return id; } /** Sets the id used to reference this component in some constraints. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param id The id or null. May consist of a groupID and an componentID which are separated by a dot: ".". E.g. "grp1.id1". * The dot should never be first or last if present. */ public void setId(String id) { this.id = id; } /** Returns the absolute resizing in the last stage of the layout cycle. May be null and elements may be null. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return The current value. null or of length 4. */ public UnitValue[] getPadding() { return padding != null ? new UnitValue[] {padding[0], padding[1], padding[2], padding[3]} : null; } /** Sets the absolute resizing in the last stage of the layout cycle. These values are added to the edges and can thus for * instance be used to grow or reduce the size or move the component an absolute number of pixels. May be null * and elements may be null. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param sides top, left, bottom right. Must be null or of length 4. */ public void setPadding(UnitValue[] sides) { this.padding = sides != null ? new UnitValue[] {sides[0], sides[1], sides[2], sides[3]} : null; } /** Returns the visual padding used when laying out this Component. May be null and elements may be null. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return The current value. null or of length 4. */ public UnitValue[] getVisualPadding() { return visualPadding != null ? new UnitValue[] {visualPadding[0], visualPadding[1], visualPadding[2], visualPadding[3]} : null; } /** Sets the visual padding used when laying out this Component. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param sides top, left, bottom right. Must be null or of length 4. */ public void setVisualPadding(UnitValue[] sides) { this.visualPadding = sides != null ? new UnitValue[] {sides[0], sides[1], sides[2], sides[3]} : null; } /** Returns how many cells in the grid that should be skipped before the component that this constraint belongs to. *

* Note that only the first component will be checked for this property. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return The current value. 0 if no skip. */ public int getSkip() { return skip; } /** Sets how many cells in the grid that should be skipped before the component that this constraint belongs to. *

* Note that only the first component will be checked for this property. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param cells How many cells in the grid that should be skipped before the component that this constraint belongs to */ public void setSkip(int cells) { this.skip = cells; } /** Returns the number of cells the cell that this constraint's component will span in the indicated dimension. 1 is default and * means that it only spans the current cell. LayoutUtil.INF is used to indicate a span to the end of the column/row. *

* Note that only the first component will be checked for this property. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return The current value. */ public int getSpanX() { return spanX; } /** Sets the number of cells the cell that this constraint's component will span in the indicated dimension. 1 is default and * means that it only spans the current cell. LayoutUtil.INF is used to indicate a span to the end of the column/row. *

* Note that only the first component will be checked for this property. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param cells The number of cells to span (i.e. merge). */ public void setSpanX(int cells) { this.spanX = cells; } /** Returns the number of cells the cell that this constraint's component will span in the indicated dimension. 1 is default and * means that it only spans the current cell. LayoutUtil.INF is used to indicate a span to the end of the column/row. *

* Note that only the first component will be checked for this property. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return The current value. */ public int getSpanY() { return spanY; } /** Sets the number of cells the cell that this constraint's component will span in the indicated dimension. 1 is default and * means that it only spans the current cell. LayoutUtil.INF is used to indicate a span to the end of the column/row. *

* Note that only the first component will be checked for this property. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param cells The number of cells to span (i.e. merge). */ public void setSpanY(int cells) { this.spanY = cells; } /** "pushx" indicates that the column that this component is in (this first if the component spans) should default to growing. * If any other column has been set to grow this push value on the component does nothing as the column's explicit grow weight * will take precedence. Push is normally used when the grid has not been defined in the layout. *

* If multiple components in a column has push weights set the largest one will be used for the column. * @return The current push value. Default is null. */ public Float getPushX() { return pushX; } /** "pushx" indicates that the column that this component is in (this first if the component spans) should default to growing. * If any other column has been set to grow this push value on the component does nothing as the column's explicit grow weight * will take precedence. Push is normally used when the grid has not been defined in the layout. *

* If multiple components in a column has push weights set the largest one will be used for the column. * @param weight The new push value. Default is null. */ public void setPushX(Float weight) { this.pushX = weight; } /** "pushx" indicates that the row that this component is in (this first if the component spans) should default to growing. * If any other row has been set to grow this push value on the component does nothing as the row's explicit grow weight * will take precedence. Push is normally used when the grid has not been defined in the layout. *

* If multiple components in a row has push weights set the largest one will be used for the row. * @return The current push value. Default is null. */ public Float getPushY() { return pushY; } /** "pushx" indicates that the row that this component is in (this first if the component spans) should default to growing. * If any other row has been set to grow this push value on the component does nothing as the row's explicit grow weight * will take precedence. Push is normally used when the grid has not been defined in the layout. *

* If multiple components in a row has push weights set the largest one will be used for the row. * @param weight The new push value. Default is null. */ public void setPushY(Float weight) { this.pushY = weight; } /** Returns in how many parts the current cell (that this constraint's component will be in) should be split in. If for instance * it is split in two, the next component will also share the same cell. Note that the cell can also span a number of * cells, which means that you can for instance span three cells and split that big cell for two components. Split can be * set to a very high value to make all components in the same row/column share the same cell (e.g. LayoutUtil.INF). *

* Note that only the first component will be checked for this property. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return The current value. */ public int getSplit() { return split; } /** Sets in how many parts the current cell (that this constraint's component will be in) should be split in. If for instance * it is split in two, the next component will also share the same cell. Note that the cell can also span a number of * cells, which means that you can for instance span three cells and split that big cell for two components. Split can be * set to a very high value to make all components in the same row/column share the same cell (e.g. LayoutUtil.INF). *

* Note that only the first component will be checked for this property. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param parts The number of parts (i.e. component slots) the cell should be divided into. */ public void setSplit(int parts) { this.split = parts; } /** Tags the component with metadata. Currently only used to tag buttons with for instance "cancel" or "ok" to make them * show up in the correct order depending on platform. See {@link PlatformDefaults#setButtonOrder(String)} for information. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return The current value. May be null. */ public String getTag() { return tag; } /** Optional tag that gives more context to this constraint's component. It is for instance used to tag buttons in a * button bar with the button type such as "ok", "help" or "cancel". *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param tag The new tag. May be null. */ public void setTag(String tag) { this.tag = tag; } /** Returns if the flow should wrap to the next line/column after the component that this constraint belongs to. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return The current value. */ public boolean isWrap() { return wrap != null; } /** Sets if the flow should wrap to the next line/column after the component that this constraint belongs to. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param b true means wrap after. */ public void setWrap(boolean b) { wrap = b ? (wrap == null ? DEF_GAP : wrap) : null; } /** Returns the wrap size if it is a custom size. If wrap was set to true with {@link #setWrap(boolean)} then this method will * return null since that means that the gap size should be the default one as defined in the rows spec. * @return The custom gap size. NOTE! Will return null for both no wrap and default wrap. * @see #isWrap() * @see #setWrap(boolean) * @since 2.4.2 */ public BoundSize getWrapGapSize() { return wrap == DEF_GAP ? null : wrap; } /** Set the wrap size and turns wrap on if != null. * @param s The custom gap size. NOTE! null will not turn on or off wrap, it will only set the wrap gap size to "default". * A non-null value will turn on wrap though. * @see #isWrap() * @see #setWrap(boolean) * @since 2.4.2 */ public void setWrapGapSize(BoundSize s) { wrap = s == null ? (wrap != null ? DEF_GAP : null) : s; } /** Returns if the flow should wrap to the next line/column before the component that this constraint belongs to. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return The current value. */ public boolean isNewline() { return newline != null; } /** Sets if the flow should wrap to the next line/column before the component that this constraint belongs to. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param b true means wrap before. */ public void setNewline(boolean b) { newline = b ? (newline == null ? DEF_GAP : newline) : null; } /** Returns the newline size if it is a custom size. If newline was set to true with {@link #setNewline(boolean)} then this method will * return null since that means that the gap size should be the default one as defined in the rows spec. * @return The custom gap size. NOTE! Will return null for both no newline and default newline. * @see #isNewline() * @see #setNewline(boolean) * @since 2.4.2 */ public BoundSize getNewlineGapSize() { return newline == DEF_GAP ? null : newline; } /** Set the newline size and turns newline on if != null. * @param s The custom gap size. NOTE! null will not turn on or off newline, it will only set the newline gap size to "default". * A non-null value will turn on newline though. * @see #isNewline() * @see #setNewline(boolean) * @since 2.4.2 */ public void setNewlineGapSize(BoundSize s) { newline = s == null ? (newline != null ? DEF_GAP : null) : s; } /** Returns the animation spec. Default is a spec where animation is off (prio 0). * @return Never null. */ public AnimSpec getAnimSpec() { return animSpec; } // ************************************************ // Persistence Delegate and Serializable combined. // ************************************************ private Object readResolve() throws ObjectStreamException { return LayoutUtil.getSerializedObject(this); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { LayoutUtil.setSerializedObject(this, LayoutUtil.readAsXML(in)); } @Override public void writeExternal(ObjectOutput out) throws IOException { if (getClass() == CC.class) LayoutUtil.writeAsXML(out, this); } }miglayout-5.1/core/src/main/java/net/miginfocom/layout/ComponentWrapper.java000077500000000000000000000351001324101563200273540ustar00rootroot00000000000000package net.miginfocom.layout; /* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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 */ /** A class that wraps the important parts of a Component. *

* NOTE!.equals() and .hashcode() should be forwarded to the wrapped component. E.g. *

 * 	public int hashCode()
	{
		return getComponent().hashCode();
	}

	public final boolean equals(Object o)
	{
		 if (o instanceof ComponentWrapper == false)
			 return false;

		 return getComponent().equals(((ComponentWrapper) o).getComponent());
	}
 * 
*/ public interface ComponentWrapper { static final int TYPE_UNSET = -1; public static final int TYPE_UNKNOWN = 0; public static final int TYPE_CONTAINER = 1; public static final int TYPE_LABEL = 2; public static final int TYPE_TEXT_FIELD = 3; public static final int TYPE_TEXT_AREA = 4; public static final int TYPE_BUTTON = 5; public static final int TYPE_LIST = 6; public static final int TYPE_TABLE = 7; public static final int TYPE_SCROLL_PANE = 8; public static final int TYPE_IMAGE = 9; public static final int TYPE_PANEL = 10; public static final int TYPE_COMBO_BOX = 11; public static final int TYPE_SLIDER = 12; public static final int TYPE_SPINNER = 13; public static final int TYPE_PROGRESS_BAR = 14; public static final int TYPE_TREE = 15; public static final int TYPE_CHECK_BOX = 16; public static final int TYPE_SCROLL_BAR = 17; public static final int TYPE_SEPARATOR = 18; public static final int TYPE_TABBED_PANE = 19; /** Returns the actual object that this wrapper is aggregating. This might be needed for getting * information about the object that the wrapper interface does not provide. *

* If this is a container the container should be returned instead. * @return The actual object that this wrapper is aggregating. Not null. */ public abstract Object getComponent(); /** Returns the current x coordinate for this component. * @return The current x coordinate for this component. */ public abstract int getX(); /** Returns the current y coordinate for this component. * @return The current y coordinate for this component. */ public abstract int getY(); /** Returns the current width for this component. * @return The current width for this component. */ public abstract int getWidth(); /** Returns the current height for this component. * @return The current height for this component. */ public abstract int getHeight(); /** Returns the screen x-coordinate for the upper left coordinate of the component layout-able bounds. * @return The screen x-coordinate for the upper left coordinate of the component layout-able bounds. */ public abstract int getScreenLocationX(); /** Returns the screen y-coordinate for the upper left coordinate of the component layout-able bounds. * @return The screen y-coordinate for the upper left coordinate of the component layout-able bounds. */ public abstract int getScreenLocationY(); /** Returns the minimum width of the component. * @param hHint The Size hint for the other dimension. An implementation can use this value or the * current size for the widget in this dimension, or a combination of both, to calculate the correct size.
* Use -1 to denote that there is no hint. This corresponds with SWT.DEFAULT. * @return The minimum width of the component. * @since 3.5. Added the hint as a parameter knowing that a correction and recompilation is necessary for * any implementing classes. This change was worth it though. */ public abstract int getMinimumWidth(int hHint); /** Returns the minimum height of the component. * @param wHint The Size hint for the other dimension. An implementation can use this value or the * current size for the widget in this dimension, or a combination of both, to calculate the correct size.
* Use -1 to denote that there is no hint. This corresponds with SWT.DEFAULT. * @return The minimum height of the component. * @since 3.5. Added the hint as a parameter knowing that a correction and recompilation is necessary for * any implementing classes. This change was worth it though. */ public abstract int getMinimumHeight(int wHint); /** Returns the preferred width of the component. * @param hHint The Size hint for the other dimension. An implementation can use this value or the * current size for the widget in this dimension, or a combination of both, to calculate the correct size.
* Use -1 to denote that there is no hint. This corresponds with SWT.DEFAULT. * @return The preferred width of the component. * @since 3.5. Added the hint as a parameter knowing that a correction and recompilation is necessary for * any implementing classes. This change was worth it though. */ public abstract int getPreferredWidth(int hHint); /** Returns the preferred height of the component. * @param wHint The Size hint for the other dimension. An implementation can use this value or the * current size for the widget in this dimension, or a combination of both, to calculate the correct size.
* Use -1 to denote that there is no hint. This corresponds with SWT.DEFAULT. * @return The preferred height of the component. * @since 3.5. Added the hint as a parameter knowing that a correction and recompilation is necessary for * any implementing classes. This change was worth it though. */ public abstract int getPreferredHeight(int wHint); /** Returns the maximum width of the component. * @param hHint The Size hint for the other dimension. An implementation can use this value or the * current size for the widget in this dimension, or a combination of both, to calculate the correct size.
* Use -1 to denote that there is no hint. This corresponds with SWT.DEFAULT. * @return The maximum width of the component. * @since 3.5. Added the hint as a parameter knowing that a correction and recompilation is necessary for * any implementing classes. This change was worth it though. */ public abstract int getMaximumWidth(int hHint); /** Returns the maximum height of the component. * @param wHint The Size hint for the other dimension. An implementation can use this value or the * current size for the widget in this dimension, or a combination of both, to calculate the correct size.
* Use -1 to denote that there is no hint. This corresponds with SWT.DEFAULT. * @return The maximum height of the component. * @since 3.5. Added the hint as a parameter knowing that a correction and recompilation is necessary for * any implementing classes. This change was worth it though. */ public abstract int getMaximumHeight(int wHint); /** Sets the component's bounds. * @param x The x coordinate. * @param y The y coordinate. * @param width The width. * @param height The height. */ public abstract void setBounds(int x, int y, int width, int height); /** Returns if the component's visibility is set to true. This should not return if the component is * actually visible, but if the visibility is set to true or not. * @return true means visible. */ public abstract boolean isVisible(); /** Returns the baseline for the component given the suggested height. * @param width The width to calculate for if other than the current. If -1 the current size should be used. * @param height The height to calculate for if other than the current. If -1 the current size should be used. * @return The baseline from the top or -1 if not applicable. */ public abstract int getBaseline(int width, int height); /** Returns if the component has a baseline and if it can be retrieved. Should for instance return * false for Swing before mustang. * @return If the component has a baseline and if it can be retrieved. */ public abstract boolean hasBaseline(); /** Returns the container for this component. * @return The container for this component. Will return null if the component has no parent. */ public abstract ContainerWrapper getParent(); /** Returns the pixel unit factor for the horizontal or vertical dimension. *

* The factor is 1 for both dimensions on the normal font in a JPanel on Windows. The factor should increase with a bigger "X". *

* This is the Swing version: *

	 * Rectangle2D r = fm.getStringBounds("X", parent.getGraphics());
	 * wFactor = r.getWidth() / 6;
	 * hFactor = r.getHeight() / 13.27734375f;
	 * 
* @param isHor If it is the horizontal factor that should be returned. * @return The factor. */ public abstract float getPixelUnitFactor(boolean isHor); /** Returns the DPI (Dots Per Inch) of the screen the component is currently in or for the default * screen if the component is not visible. *

* If headless mode {@link net.miginfocom.layout.PlatformDefaults#getDefaultDPI} will be returned. * @return The DPI. */ public abstract int getHorizontalScreenDPI(); /** Returns the DPI (Dots Per Inch) of the screen the component is currently in or for the default * screen if the component is not visible. *

* If headless mode {@link net.miginfocom.layout.PlatformDefaults#getDefaultDPI} will be returned. * @return The DPI. */ public abstract int getVerticalScreenDPI(); /** Returns the pixel size of the screen that the component is currently in or for the default * screen if the component is not visible or null. *

* If in headless mode 1024 is returned. * @return The screen size. E.g. 1280. */ public abstract int getScreenWidth(); /** Returns the pixel size of the screen that the component is currently in or for the default * screen if the component is not visible or null. *

* If in headless mode 768 is returned. * @return The screen size. E.g. 1024. */ public abstract int getScreenHeight(); /** Returns a String id that can be used to reference the component in link constraints. This value should * return the default id for the component. The id can be set for a component in the constraints and if * so the value returned by this method will never be used. If there are no sensible id for the component * null should be returned. *

* For instance the Swing implementation returns the string returned from Component.getName(). * @return The string link id or null. */ public abstract String getLinkId(); /** Returns a hash code that should be reasonably different for anything that might change the layout. This value is used to * know if the component layout needs to clear any caches. * @return A hash code that should be reasonably different for anything that might change the layout. Returns -1 if the widget is * disposed. */ public abstract int getLayoutHashCode(); /** Returns the padding on a component by component basis. This method can be overridden to return padding to compensate for example for * borders that have shadows or where the outer most pixel is not the visual "edge" to align to. *

* Default implementation returns null for all components except for Windows XP's JTabbedPane which will return new Insets(0, 0, 2, 2). *

* NOTE! To reduce generated garbage the returned padding should never be changed so that the same insets can be returned many times. * @return null if no padding. NOTE! To reduce generated garbage the returned padding should never be changed so that * the same insets can be returned many times. [top, left, bottom, right] */ public int[] getVisualPadding(); /** Paints component outline to indicate where it is. * @param showVisualPadding If the visual padding should be shown in the debug drawing. */ public abstract void paintDebugOutline(boolean showVisualPadding); /** Returns the type of component that this wrapper is wrapping. *

* This method can be invoked often so the result should be cached. *

* @param disregardScrollPane Is true any wrapping scroll pane should be disregarded and the type * of the scrolled component should be returned. * @return The type of component that this wrapper is wrapping. E.g. {@link #TYPE_LABEL}. */ public abstract int getComponentType(boolean disregardScrollPane); /** Returns in what way the min/pref/max sizes relates to it's height or width for the current settings of the component (like wrapText). * If the min/pref/max height depends on it's width return {@link net.miginfocom.layout.LayoutUtil#HORIZONTAL} * If the min/pref/max width depends on it's height (not common) return {@link net.miginfocom.layout.LayoutUtil#VERTICAL} * If there is no connection between the preferred min/pref/max and the size of the component return -1. * @since 5.0 */ public abstract int getContentBias(); }miglayout-5.1/core/src/main/java/net/miginfocom/layout/ConstraintParser.java000077500000000000000000001434161324101563200273640ustar00rootroot00000000000000package net.miginfocom.layout; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; /* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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 */ /** Parses string constraints. */ public final class ConstraintParser { private ConstraintParser() { } /** Parses the layout constraints and stores the parsed values in the transient (cache) member variables. * @param s The String to parse. Should not be null and must be lower case and trimmed. * @throws RuntimeException if the constraint was not valid. * @return The parsed constraint. Never null. */ public static LC parseLayoutConstraint(String s) { LC lc = new LC(); if (s.isEmpty()) return lc; String[] parts = toTrimmedTokens(s, ','); // First check for "ltr" or "rtl" since that will affect the interpretation of the other constraints. for (int i = 0; i < parts.length; i++) { String part = parts[i]; if (part == null) continue; int len = part.length(); if (len == 3 || len == 11) { // Optimization if (part.equals("ltr") || part.equals("rtl") || part.equals("lefttoright") || part.equals("righttoleft")) { lc.setLeftToRight(part.charAt(0) == 'l' ? Boolean.TRUE : Boolean.FALSE); parts[i] = null; // So we will not try to interpret it again } if (part.equals("ttb") || part.equals("btt") || part.equals("toptobottom") || part.equals("bottomtotop")) { lc.setTopToBottom(part.charAt(0) == 't'); parts[i] = null; // So we will not try to interpret it again } } } for (String part : parts) { if (part == null || part.length() == 0) continue; try { int ix = -1; char c = part.charAt(0); if (c == 'w' || c == 'h') { ix = startsWithLenient(part, "wrap", -1, true); if (ix > -1) { String num = part.substring(ix).trim(); lc.setWrapAfter(num.length() != 0 ? Integer.parseInt(num) : 0); continue; } boolean isHor = c == 'w'; if (isHor && (part.startsWith("w ") || part.startsWith("width "))) { String sz = part.substring(part.charAt(1) == ' ' ? 2 : 6).trim(); lc.setWidth(parseBoundSize(sz, false, true)); continue; } if (!isHor && (part.startsWith("h ") || part.startsWith("height "))) { String uvStr = part.substring(part.charAt(1) == ' ' ? 2 : 7).trim(); lc.setHeight(parseBoundSize(uvStr, false, false)); continue; } if (part.length() > 5) { String sz = part.substring(5).trim(); if (part.startsWith("wmin ")) { lc.minWidth(sz); continue; } else if (part.startsWith("wmax ")) { lc.maxWidth(sz); continue; } else if (part.startsWith("hmin ")) { lc.minHeight(sz); continue; } else if (part.startsWith("hmax ")) { lc.maxHeight(sz); continue; } } if (part.startsWith("hidemode ")) { lc.setHideMode(Integer.parseInt(part.substring(9))); continue; } } if (c == 'g') { if (part.startsWith("gapx ")) { lc.setGridGapX(parseBoundSize(part.substring(5).trim(), true, true)); continue; } if (part.startsWith("gapy ")) { lc.setGridGapY(parseBoundSize(part.substring(5).trim(), true, false)); continue; } if (part.startsWith("gap ")) { String[] gaps = toTrimmedTokens(part.substring(4).trim(), ' '); lc.setGridGapX(parseBoundSize(gaps[0], true, true)); lc.setGridGapY(gaps.length > 1 ? parseBoundSize(gaps[1], true, false) : lc.getGridGapX()); continue; } } if (c == 'd') { ix = startsWithLenient(part, "debug", 5, true); if (ix > -1) { String millis = part.substring(ix).trim(); lc.setDebugMillis(millis.length() > 0 ? Integer.parseInt(millis) : 1000); continue; } } if (c == 'n') { if (part.equals("nogrid")) { lc.setNoGrid(true); continue; } if (part.equals("nocache")) { lc.setNoCache(true); continue; } if (part.equals("novisualpadding")) { lc.setVisualPadding(false); continue; } } if (c == 'f') { if (part.equals("fill") || part.equals("fillx") || part.equals("filly")) { lc.setFillX(part.length() == 4 || part.charAt(4) == 'x'); lc.setFillY(part.length() == 4 || part.charAt(4) == 'y'); continue; } if (part.equals("flowy")) { lc.setFlowX(false); continue; } if (part.equals("flowx")) { lc.setFlowX(true); // This is the default but added for consistency continue; } } if (c == 'i') { ix = startsWithLenient(part, "insets", 3, true); if (ix > -1) { String insStr = part.substring(ix).trim(); UnitValue[] ins = parseInsets(insStr, true); LayoutUtil.putCCString(ins, insStr); lc.setInsets(ins); continue; } } if (c == 'a') { ix = startsWithLenient(part, new String[]{"aligny", "ay"}, new int[]{6, 2}, true); if (ix > -1) { UnitValue align = parseUnitValueOrAlign(part.substring(ix).trim(), false, null); if (align == UnitValue.BASELINE_IDENTITY) throw new IllegalArgumentException("'baseline' can not be used to align the whole component group."); lc.setAlignY(align); continue; } ix = startsWithLenient(part, new String[]{"alignx", "ax"}, new int[]{6, 2}, true); if (ix > -1) { lc.setAlignX(parseUnitValueOrAlign(part.substring(ix).trim(), true, null)); continue; } ix = startsWithLenient(part, "align", 2, true); if (ix > -1) { String[] gaps = toTrimmedTokens(part.substring(ix).trim(), ' '); lc.setAlignX(parseUnitValueOrAlign(gaps[0], true, null)); if (gaps.length > 1) { UnitValue align = parseUnitValueOrAlign(gaps[1], false, null); if (align == UnitValue.BASELINE_IDENTITY) throw new IllegalArgumentException("'baseline' can not be used to align the whole component group."); lc.setAlignY(align); } continue; } } if (c == 'p') { if (part.startsWith("packalign ")) { String[] packs = toTrimmedTokens(part.substring(10).trim(), ' '); lc.setPackWidthAlign(packs[0].length() > 0 ? Float.parseFloat(packs[0]) : 0.5f); if (packs.length > 1) lc.setPackHeightAlign(Float.parseFloat(packs[1])); continue; } if (part.startsWith("pack ") || part.equals("pack")) { String ps = part.substring(4).trim(); String[] packs = toTrimmedTokens(ps.length() > 0 ? ps : "pref pref", ' '); lc.setPackWidth(parseBoundSize(packs[0], false, true)); if (packs.length > 1) lc.setPackHeight(parseBoundSize(packs[1], false, false)); continue; } } if (lc.getAlignX() == null) { UnitValue alignX = parseAlignKeywords(part, true); if (alignX != null) { lc.setAlignX(alignX); continue; } } UnitValue alignY = parseAlignKeywords(part, false); if (alignY != null) { lc.setAlignY(alignY); continue; } throw new IllegalArgumentException("Unknown Constraint: '" + part + "'\n"); } catch (Exception ex) { throw new IllegalArgumentException("Illegal Constraint: '" + part + "'\n" + ex.getMessage()); } } // lc = (LC) serializeTest(lc); return lc; } /** Parses the column or rows constraints. They normally looks something like "[min:pref]rel[10px][]". * @param s The string to parse. Not null. * @return An array of {@link DimConstraint}s that is as many are there exist "[...]" sections in the string that is parsed. * @throws RuntimeException if the constraint was not valid. */ public static AC parseRowConstraints(String s) { return parseAxisConstraint(s, false); } /** Parses the column or rows constraints. They normally looks something like "[min:pref]rel[10px][]". * @param s The string to parse. Not null. * @return An array of {@link DimConstraint}s that is as many are there exist "[...]" sections in the string that is parsed. * @throws RuntimeException if the constraint was not valid. */ public static AC parseColumnConstraints(String s) { return parseAxisConstraint(s, true); } /** Parses the column or rows constraints. They normally looks something like "[min:pref]rel[10px][]". * @param s The string to parse. Not null. * @param isCols If this for columns rather than rows. * @return An array of {@link DimConstraint}s that is as many are there exist "[...]" sections in the string that is parsed. * @throws RuntimeException if the constraint was not valid. */ private static AC parseAxisConstraint(String s, boolean isCols) { s = s.trim(); if (s.length() == 0) return new AC(); // Short circuit for performance. s = s.toLowerCase(); ArrayList parts = getRowColAndGapsTrimmed(s); BoundSize[] gaps = new BoundSize[(parts.size() >> 1) + 1]; for (int i = 0, iSz = parts.size(), gIx = 0; i < iSz; i += 2, gIx++) gaps[gIx] = parseBoundSize(parts.get(i), true, isCols); DimConstraint[] colSpecs = new DimConstraint[parts.size() >> 1]; for (int i = 0, gIx = 0; i < colSpecs.length; i++, gIx++) { if (gIx >= gaps.length - 1) gIx = gaps.length - 2; colSpecs[i] = parseDimConstraint(parts.get((i << 1) + 1), gaps[gIx], gaps[gIx + 1], isCols); } AC ac = new AC(); ac.setConstaints(colSpecs); // ac = (AC) serializeTest(ac); return ac; } /** Parses a single column or row constraint. * @param s The single constraint to parse. May look something like "min:pref,fill,grow". Should not be null and must * be lower case and trimmed. * @param gapBefore The default gap "before" the column/row constraint. Can be overridden with a "gap" section within s. * @param gapAfter The default gap "after" the column/row constraint. Can be overridden with a "gap" section within s. * @param isCols If the constraints are column constraints rather than row constraints. * @return A single constraint. Never null. * @throws RuntimeException if the constraint was not valid. */ private static DimConstraint parseDimConstraint(String s, BoundSize gapBefore, BoundSize gapAfter, boolean isCols) { DimConstraint dimConstraint = new DimConstraint(); // Default values. dimConstraint.setGapBefore(gapBefore); dimConstraint.setGapAfter(gapAfter); String[] parts = toTrimmedTokens(s, ','); for (int i = 0; i < parts.length; i++) { String part = parts[i]; try { if (part.length() == 0) continue; if (part.equals("fill")) { dimConstraint.setFill(true); // dimConstraint.setAlign(null); // Can not have both fill and alignment (changed for 3.5 since it can have "growy 0") continue; } if (part.equals("nogrid")) { dimConstraint.setNoGrid(true); continue; } int ix = -1; char c = part.charAt(0); if (c == 's') { ix = startsWithLenient(part, new String[] {"sizegroup", "sg"}, new int[] {5, 2}, true); if (ix > -1) { dimConstraint.setSizeGroup(part.substring(ix).trim()); continue; } ix = startsWithLenient(part, new String[] {"shrinkprio", "shp"}, new int[] {10, 3}, true); if (ix > -1) { dimConstraint.setShrinkPriority(Integer.parseInt(part.substring(ix).trim())); continue; } ix = startsWithLenient(part, "shrink", 6, true); if (ix > -1) { dimConstraint.setShrink(parseFloat(part.substring(ix).trim(), ResizeConstraint.WEIGHT_100)); continue; } } if (c == 'g') { ix = startsWithLenient(part, new String[] {"growpriority", "gp"}, new int[] {5, 2}, true); if (ix > -1) { dimConstraint.setGrowPriority(Integer.parseInt(part.substring(ix).trim())); continue; } ix = startsWithLenient(part, "grow", 4, true); if (ix > -1) { dimConstraint.setGrow(parseFloat(part.substring(ix).trim(), ResizeConstraint.WEIGHT_100)); continue; } } if (c == 'a') { ix = startsWithLenient(part, "align", 2, true); if (ix > -1) { // if (dimConstraint.isFill() == false) // Swallow, but ignore if fill is set. (changed for 3.5 since it can have "growy 0") dimConstraint.setAlign(parseUnitValueOrAlign(part.substring(ix).trim(), isCols, null)); continue; } } UnitValue align = parseAlignKeywords(part, isCols); if (align != null) { // if (dimConstraint.isFill() == false) // Swallow, but ignore if fill is set. (changed for 3.5 since it can have "growy 0") dimConstraint.setAlign(align); continue; } // Only min:pref:max still left that is ok dimConstraint.setSize(parseBoundSize(part, false, isCols)); } catch (Exception ex) { throw new IllegalArgumentException("Illegal constraint: '" + part + "'\n" + ex.getMessage()); } } return dimConstraint; } /** Parses all component constraints and stores the parsed values in the transient (cache) member variables. * @param constrMap The constraints as Strings. Strings must be lower case and trimmed * @return The parsed constraints. Never null. */ public static Map parseComponentConstraints(Map constrMap) { HashMap flowConstrMap = new HashMap(); for (Iterator> it = constrMap.entrySet().iterator(); it.hasNext();) { Map.Entry entry = it.next(); flowConstrMap.put(entry.getKey(), parseComponentConstraint(entry.getValue())); } return flowConstrMap; } /** Parses one component constraint and returns the parsed value. * @param s The string to parse. Must be lower case and trimmed. * @throws RuntimeException if the constraint was not valid. * @return The parsed constraint. Never null. */ public static CC parseComponentConstraint(String s) { CC cc = new CC(); if (s == null || s.isEmpty()) return cc; String[] parts = toTrimmedTokens(s, ','); for (String part : parts) { try { if (part.length() == 0) continue; int ix = -1; char c = part.charAt(0); if (c == 'n') { if (part.equals("north")) { cc.setDockSide(0); continue; } if (part.equals("newline")) { cc.setNewline(true); continue; } if (part.startsWith("newline ")) { String gapSz = part.substring(7).trim(); cc.setNewlineGapSize(parseBoundSize(gapSz, true, true)); continue; } } if (c == 'f' && (part.equals("flowy") || part.equals("flowx"))) { cc.setFlowX(part.charAt(4) == 'x' ? Boolean.TRUE : Boolean.FALSE); continue; } if (c == 's') { ix = startsWithLenient(part, "skip", 4, true); if (ix > -1) { String num = part.substring(ix).trim(); cc.setSkip(num.length() != 0 ? Integer.parseInt(num) : 1); continue; } ix = startsWithLenient(part, "split", 5, true); if (ix > -1) { String split = part.substring(ix).trim(); cc.setSplit(split.length() > 0 ? Integer.parseInt(split) : LayoutUtil.INF); continue; } if (part.equals("south")) { cc.setDockSide(2); continue; } ix = startsWithLenient(part, new String[]{"spany", "sy"}, new int[]{5, 2}, true); if (ix > -1) { cc.setSpanY(parseSpan(part.substring(ix).trim())); continue; } ix = startsWithLenient(part, new String[]{"spanx", "sx"}, new int[]{5, 2}, true); if (ix > -1) { cc.setSpanX(parseSpan(part.substring(ix).trim())); continue; } ix = startsWithLenient(part, "span", 4, true); if (ix > -1) { String[] spans = toTrimmedTokens(part.substring(ix).trim(), ' '); cc.setSpanX(spans[0].length() > 0 ? Integer.parseInt(spans[0]) : LayoutUtil.INF); cc.setSpanY(spans.length > 1 ? Integer.parseInt(spans[1]) : 1); continue; } ix = startsWithLenient(part, "shrinkx", 7, true); if (ix > -1) { cc.getHorizontal().setShrink(parseFloat(part.substring(ix).trim(), ResizeConstraint.WEIGHT_100)); continue; } ix = startsWithLenient(part, "shrinky", 7, true); if (ix > -1) { cc.getVertical().setShrink(parseFloat(part.substring(ix).trim(), ResizeConstraint.WEIGHT_100)); continue; } ix = startsWithLenient(part, "shrink", 6, false); if (ix > -1) { String[] shrinks = toTrimmedTokens(part.substring(ix).trim(), ' '); cc.getHorizontal().setShrink(parseFloat(shrinks[0], ResizeConstraint.WEIGHT_100)); if (shrinks.length > 1) cc.getVertical().setShrink(parseFloat(shrinks[1], ResizeConstraint.WEIGHT_100)); continue; } ix = startsWithLenient(part, new String[]{"shrinkprio", "shp"}, new int[]{10, 3}, true); if (ix > -1) { String sp = part.substring(ix).trim(); if (sp.startsWith("x") || sp.startsWith("y")) { // To handle "gpx", "gpy", "shrinkpriorityx", shrinkpriorityy" (sp.startsWith("x") ? cc.getHorizontal() : cc.getVertical()).setShrinkPriority(Integer.parseInt(sp.substring(2))); } else { String[] shrinks = toTrimmedTokens(sp, ' '); cc.getHorizontal().setShrinkPriority(Integer.parseInt(shrinks[0])); if (shrinks.length > 1) cc.getVertical().setShrinkPriority(Integer.parseInt(shrinks[1])); } continue; } ix = startsWithLenient(part, new String[]{"sizegroupx", "sizegroupy", "sgx", "sgy"}, new int[]{9, 9, 2, 2}, true); if (ix > -1) { String sg = part.substring(ix).trim(); char lc = part.charAt(ix - 1); if (lc != 'y') cc.getHorizontal().setSizeGroup(sg); if (lc != 'x') cc.getVertical().setSizeGroup(sg); continue; } } if (c == 'g') { ix = startsWithLenient(part, "growx", 5, true); if (ix > -1) { cc.getHorizontal().setGrow(parseFloat(part.substring(ix).trim(), ResizeConstraint.WEIGHT_100)); continue; } ix = startsWithLenient(part, "growy", 5, true); if (ix > -1) { cc.getVertical().setGrow(parseFloat(part.substring(ix).trim(), ResizeConstraint.WEIGHT_100)); continue; } ix = startsWithLenient(part, "grow", 4, false); if (ix > -1) { String[] grows = toTrimmedTokens(part.substring(ix).trim(), ' '); cc.getHorizontal().setGrow(parseFloat(grows[0], ResizeConstraint.WEIGHT_100)); cc.getVertical().setGrow(parseFloat(grows.length > 1 ? grows[1] : "", ResizeConstraint.WEIGHT_100)); continue; } ix = startsWithLenient(part, new String[]{"growprio", "gp"}, new int[]{8, 2}, true); if (ix > -1) { String gp = part.substring(ix).trim(); char c0 = gp.length() > 0 ? gp.charAt(0) : ' '; if (c0 == 'x' || c0 == 'y') { // To handle "gpx", "gpy", "growpriorityx", growpriorityy" (c0 == 'x' ? cc.getHorizontal() : cc.getVertical()).setGrowPriority(Integer.parseInt(gp.substring(2))); } else { String[] grows = toTrimmedTokens(gp, ' '); cc.getHorizontal().setGrowPriority(Integer.parseInt(grows[0])); if (grows.length > 1) cc.getVertical().setGrowPriority(Integer.parseInt(grows[1])); } continue; } if (part.startsWith("gap")) { BoundSize[] gaps = parseGaps(part); // Changes order!! if (gaps[0] != null) cc.getVertical().setGapBefore(gaps[0]); if (gaps[1] != null) cc.getHorizontal().setGapBefore(gaps[1]); if (gaps[2] != null) cc.getVertical().setGapAfter(gaps[2]); if (gaps[3] != null) cc.getHorizontal().setGapAfter(gaps[3]); continue; } } if (c == 'a') { ix = startsWithLenient(part, new String[]{"aligny", "ay"}, new int[]{6, 2}, true); if (ix > -1) { cc.getVertical().setAlign(parseUnitValueOrAlign(part.substring(ix).trim(), false, null)); continue; } ix = startsWithLenient(part, new String[]{"alignx", "ax"}, new int[]{6, 2}, true); if (ix > -1) { cc.getHorizontal().setAlign(parseUnitValueOrAlign(part.substring(ix).trim(), true, null)); continue; } ix = startsWithLenient(part, "align", 2, true); if (ix > -1) { String[] gaps = toTrimmedTokens(part.substring(ix).trim(), ' '); cc.getHorizontal().setAlign(parseUnitValueOrAlign(gaps[0], true, null)); if (gaps.length > 1) cc.getVertical().setAlign(parseUnitValueOrAlign(gaps[1], false, null)); continue; } } if ((c == 'x' || c == 'y') && part.length() > 2) { char c2 = part.charAt(1); if (c2 == ' ' || (c2 == '2' && part.charAt(2) == ' ')) { if (cc.getPos() == null) { cc.setPos(new UnitValue[4]); } else if (cc.isBoundsInGrid() == false) { throw new IllegalArgumentException("Cannot combine 'position' with 'x/y/x2/y2' keywords."); } int edge = (c == 'x' ? 0 : 1) + (c2 == '2' ? 2 : 0); UnitValue[] pos = cc.getPos(); pos[edge] = parseUnitValue(part.substring(2).trim(), null, c == 'x'); cc.setPos(pos); cc.setBoundsInGrid(true); continue; } } if (c == 'c') { ix = startsWithLenient(part, "cell", 4, true); if (ix > -1) { String[] grs = toTrimmedTokens(part.substring(ix).trim(), ' '); if (grs.length < 2) throw new IllegalArgumentException("At least two integers must follow " + part); cc.setCellX(Integer.parseInt(grs[0])); cc.setCellY(Integer.parseInt(grs[1])); if (grs.length > 2) cc.setSpanX(Integer.parseInt(grs[2])); if (grs.length > 3) cc.setSpanY(Integer.parseInt(grs[3])); continue; } } if (c == 'p') { ix = startsWithLenient(part, "pos", 3, true); if (ix > -1) { if (cc.getPos() != null && cc.isBoundsInGrid()) throw new IllegalArgumentException("Can not combine 'pos' with 'x/y/x2/y2' keywords."); String[] pos = toTrimmedTokens(part.substring(ix).trim(), ' '); UnitValue[] bounds = new UnitValue[4]; for (int j = 0; j < pos.length; j++) bounds[j] = parseUnitValue(pos[j], null, j % 2 == 0); if (bounds[0] == null && bounds[2] == null || bounds[1] == null && bounds[3] == null) throw new IllegalArgumentException("Both x and x2 or y and y2 can not be null!"); cc.setPos(bounds); cc.setBoundsInGrid(false); continue; } ix = startsWithLenient(part, "pad", 3, true); if (ix > -1) { UnitValue[] p = parseInsets(part.substring(ix).trim(), false); cc.setPadding(new UnitValue[]{ p[0], p.length > 1 ? p[1] : null, p.length > 2 ? p[2] : null, p.length > 3 ? p[3] : null}); continue; } ix = startsWithLenient(part, "pushx", 5, true); if (ix > -1) { cc.setPushX(parseFloat(part.substring(ix).trim(), ResizeConstraint.WEIGHT_100)); continue; } ix = startsWithLenient(part, "pushy", 5, true); if (ix > -1) { cc.setPushY(parseFloat(part.substring(ix).trim(), ResizeConstraint.WEIGHT_100)); continue; } ix = startsWithLenient(part, "push", 4, false); if (ix > -1) { String[] pushs = toTrimmedTokens(part.substring(ix).trim(), ' '); cc.setPushX(parseFloat(pushs[0], ResizeConstraint.WEIGHT_100)); cc.setPushY(parseFloat(pushs.length > 1 ? pushs[1] : "", ResizeConstraint.WEIGHT_100)); continue; } } if (c == 't') { ix = startsWithLenient(part, "tag", 3, true); if (ix > -1) { cc.setTag(part.substring(ix).trim()); continue; } } if (c == 'w' || c == 'h') { if (part.equals("wrap")) { cc.setWrap(true); continue; } if (part.startsWith("wrap ")) { String gapSz = part.substring(5).trim(); cc.setWrapGapSize(parseBoundSize(gapSz, true, true)); continue; } boolean isHor = c == 'w'; if (isHor && (part.startsWith("w ") || part.startsWith("width "))) { String uvStr = part.substring(part.charAt(1) == ' ' ? 2 : 6).trim(); cc.getHorizontal().setSize(parseBoundSize(uvStr, false, true)); continue; } if (!isHor && (part.startsWith("h ") || part.startsWith("height "))) { String uvStr = part.substring(part.charAt(1) == ' ' ? 2 : 7).trim(); cc.getVertical().setSize(parseBoundSize(uvStr, false, false)); continue; } if (part.startsWith("wmin ") || part.startsWith("wmax ") || part.startsWith("hmin ") || part.startsWith("hmax ")) { String uvStr = part.substring(5).trim(); if (uvStr.length() > 0) { UnitValue uv = parseUnitValue(uvStr, null, isHor); boolean isMin = part.charAt(3) == 'n'; DimConstraint dc = isHor ? cc.getHorizontal() : cc.getVertical(); dc.setSize(new BoundSize( isMin ? uv : dc.getSize().getMin(), dc.getSize().getPreferred(), isMin ? (dc.getSize().getMax()) : uv, uvStr )); continue; } } if (part.equals("west")) { cc.setDockSide(1); continue; } if (part.startsWith("hidemode ")) { cc.setHideMode(Integer.parseInt(part.substring(9))); continue; } } if (c == 'i' && part.startsWith("id ")) { cc.setId(part.substring(3).trim()); int dIx = cc.getId().indexOf('.'); if (dIx == 0 || dIx == cc.getId().length() - 1) throw new IllegalArgumentException("Dot must not be first or last!"); continue; } if (c == 'e') { if (part.equals("east")) { cc.setDockSide(3); continue; } if (part.equals("external")) { cc.setExternal(true); continue; } ix = startsWithLenient(part, new String[]{"endgroupx", "endgroupy", "egx", "egy"}, new int[]{-1, -1, -1, -1}, true); if (ix > -1) { String sg = part.substring(ix).trim(); char lc = part.charAt(ix - 1); DimConstraint dc = (lc == 'x' ? cc.getHorizontal() : cc.getVertical()); dc.setEndGroup(sg); continue; } } if (c == 'd') { if (part.equals("dock north")) { cc.setDockSide(0); continue; } if (part.equals("dock west")) { cc.setDockSide(1); continue; } if (part.equals("dock south")) { cc.setDockSide(2); continue; } if (part.equals("dock east")) { cc.setDockSide(3); continue; } if (part.equals("dock center")) { cc.getHorizontal().setGrow(100f); cc.getVertical().setGrow(100f); cc.setPushX(100f); cc.setPushY(100f); continue; } } if (c == 'v') { ix = startsWithLenient(part, new String[] {"visualpadding", "vp"}, new int[] {3, 2}, true); if (ix > -1) { UnitValue[] p = parseInsets(part.substring(ix).trim(), false); cc.setVisualPadding(new UnitValue[] { p[0], p.length > 1 ? p[1] : null, p.length > 2 ? p[2] : null, p.length > 3 ? p[3] : null}); continue; } } UnitValue horAlign = parseAlignKeywords(part, true); if (horAlign != null) { cc.getHorizontal().setAlign(horAlign); continue; } UnitValue verAlign = parseAlignKeywords(part, false); if (verAlign != null) { cc.getVertical().setAlign(verAlign); continue; } throw new IllegalArgumentException("Unknown keyword."); } catch (Exception ex) { throw new IllegalArgumentException("Error parsing Constraint: '" + part + "'", ex); } } // cc = (CC) serializeTest(cc); return cc; } /** Parses insets which consists of 1-4 UnitValues. * @param s The string to parse. E.g. "10 10 10 10" or "20". If less than 4 groups the last will be used for the missing. * @param acceptPanel If "panel" and "dialog" should be accepted. They are used to access platform defaults. * @return An array of length 4 with the parsed insets. * @throws IllegalArgumentException if the parsing could not be done. */ public static UnitValue[] parseInsets(String s, boolean acceptPanel) { if (s.length() == 0 || s.equals("dialog") || s.equals("panel")) { if (acceptPanel == false) throw new IllegalArgumentException("Insets now allowed: " + s + "\n"); boolean isPanel = s.startsWith("p"); UnitValue[] ins = new UnitValue[4]; for (int j = 0; j < 4; j++) ins[j] = isPanel ? PlatformDefaults.getPanelInsets(j) : PlatformDefaults.getDialogInsets(j); return ins; } else { String[] insS = toTrimmedTokens(s, ' '); UnitValue[] ins = new UnitValue[4]; for (int j = 0; j < 4; j++) { UnitValue insSz = parseUnitValue(insS[j < insS.length ? j : insS.length - 1], UnitValue.ZERO, j % 2 == 1); ins[j] = insSz != null ? insSz : PlatformDefaults.getPanelInsets(j); } return ins; } } /** Parses gaps. * @param s The string that contains gap information. Should start with "gap". * @return The gaps as specified in s. Indexed: [top,left,bottom,right][min,pref,max] or * [before,after][min,pref,max] if oneDim is true. */ private static BoundSize[] parseGaps(String s) { BoundSize[] ret = new BoundSize[4]; int ix = startsWithLenient(s, "gaptop", -1, true); if (ix > -1) { s = s.substring(ix).trim(); ret[0] = parseBoundSize(s, true, false); return ret; } ix = startsWithLenient(s, "gapleft", -1, true); if (ix > -1) { s = s.substring(ix).trim(); ret[1] = parseBoundSize(s, true, true); return ret; } ix = startsWithLenient(s, "gapbottom", -1, true); if (ix > -1) { s = s.substring(ix).trim(); ret[2] = parseBoundSize(s, true, false); return ret; } ix = startsWithLenient(s, "gapright", -1, true); if (ix > -1) { s = s.substring(ix).trim(); ret[3] = parseBoundSize(s, true, true); return ret; } ix = startsWithLenient(s, "gapbefore", -1, true); if (ix > -1) { s = s.substring(ix).trim(); ret[1] = parseBoundSize(s, true, true); return ret; } ix = startsWithLenient(s, "gapafter", -1, true); if (ix > -1) { s = s.substring(ix).trim(); ret[3] = parseBoundSize(s, true, true); return ret; } ix = startsWithLenient(s, new String[] {"gapx", "gapy"}, null, true); if (ix > -1) { boolean x = s.charAt(3) == 'x'; String[] gaps = toTrimmedTokens(s.substring(ix).trim(), ' '); ret[x ? 1 : 0] = parseBoundSize(gaps[0], true, x); if (gaps.length > 1) ret[x ? 3 : 2] = parseBoundSize(gaps[1], true, !x); return ret; } ix = startsWithLenient(s, "gap ", 1, true); if (ix > -1) { String[] gaps = toTrimmedTokens(s.substring(ix).trim(), ' '); ret[1] = parseBoundSize(gaps[0], true, true); // left if (gaps.length > 1) { ret[3] = parseBoundSize(gaps[1], true, false); // right if (gaps.length > 2) { ret[0] = parseBoundSize(gaps[2], true, true); // top if (gaps.length > 3) ret[2] = parseBoundSize(gaps[3], true, false); // bottom } } return ret; } throw new IllegalArgumentException("Unknown Gap part: '" + s + "'"); } private static int parseSpan(String s) { return s.length() > 0 ? Integer.parseInt(s) : LayoutUtil.INF; } private static Float parseFloat(String s, Float nullVal) { return s.length() > 0 ? new Float(Float.parseFloat(s)) : nullVal; } /** Parses a single "min:pref:max" value. May look something like "10px:20lp:30%" or "pref!". * @param s The string to parse. Not null. * @param isGap If this bound size is a gap (different empty string handling). * @param isHor If the size is for the horizontal dimension. * @return A bound size that may be null if the string was "null", "n" or null. */ public static BoundSize parseBoundSize(String s, boolean isGap, boolean isHor) { if (s.length() == 0 || s.equals("null") || s.equals("n")) return null; String cs = s; boolean push = false; if (s.endsWith("push")) { push = true; int l = s.length(); s = s.substring(0, l - (s.endsWith(":push") ? 5 : 4)); if (s.length() == 0) return new BoundSize(null, null, null, true, cs); } String[] sizes = toTrimmedTokens(s, ':'); String s0 = sizes[0]; if (sizes.length == 1) { boolean hasEM = s0.endsWith("!"); if (hasEM) s0 = s0.substring(0, s0.length() - 1); UnitValue uv = parseUnitValue(s0, null, isHor); return new BoundSize(((isGap || hasEM) ? uv : null), uv, (hasEM ? uv : null), push, cs); } else if (sizes.length == 2) { return new BoundSize(parseUnitValue(s0, null, isHor), parseUnitValue(sizes[1], null, isHor), null, push, cs); } else if (sizes.length == 3) { return new BoundSize(parseUnitValue(s0, null, isHor), parseUnitValue(sizes[1], null, isHor), parseUnitValue(sizes[2], null, isHor), push, cs); } else { throw new IllegalArgumentException("Min:Preferred:Max size section must contain 0, 1 or 2 colons. '" + cs + "'"); } } /** Parses a single unit value that may also be an alignment as parsed by {@link #parseAlignKeywords(String, boolean)}. * @param s The string to parse. Not null. May look something like "10px" or "5dlu". * @param isHor If the value is for the horizontal dimension. * @param emptyReplacement A replacement if s is empty. May be null. * @return The parsed unit value. May be null. */ public static UnitValue parseUnitValueOrAlign(String s, boolean isHor, UnitValue emptyReplacement) { if (s.length() == 0) return emptyReplacement; UnitValue align = parseAlignKeywords(s, isHor); if (align != null) return align; return parseUnitValue(s, emptyReplacement, isHor); } /** Parses a single unit value. E.g. "10px" or "5in" * @param s The string to parse. Not null. May look something like "10px" or "5dlu". * @param isHor If the value is for the horizontal dimension. * @return The parsed unit value. null is empty string, */ public static UnitValue parseUnitValue(String s, boolean isHor) { return parseUnitValue(s, null, isHor); } /** Parses a single unit value. * @param s The string to parse. May be null. May look something like "10px" or "5dlu". * @param emptyReplacement A replacement s is empty or null. May be null. * @param isHor If the value is for the horizontal dimension. * @return The parsed unit value. May be null. */ private static UnitValue parseUnitValue(String s, UnitValue emptyReplacement, boolean isHor) { if (s == null || s.length() == 0) return emptyReplacement; String cs = s; // Save creation string. char c0 = s.charAt(0); // Remove start and end parentheses, if there. if (c0 == '(' && s.charAt(s.length() - 1) == ')') s = s.substring(1, s.length() - 1); if (c0 == 'n' && (s.equals("null") || s.equals("n"))) return null; if (c0 == 'i' && s.equals("inf")) return UnitValue.INF; int oper = getOper(s); boolean inline = oper == UnitValue.ADD || oper == UnitValue.SUB || oper == UnitValue.MUL || oper == UnitValue.DIV; if (oper != UnitValue.STATIC) { // It is a multi-value String[] uvs; if (inline == false) { // If the format is of type "opr(xxx,yyy)" (compared to in-line "10%+15px") String sub = s.substring(4, s.length() - 1).trim(); uvs = toTrimmedTokens(sub, ','); if (uvs.length == 1) return parseUnitValue(sub, null, isHor); } else { char delim; if (oper == UnitValue.ADD) { delim = '+'; } else if (oper == UnitValue.SUB) { delim = '-'; } else if (oper == UnitValue.MUL) { delim = '*'; } else { // div left delim = '/'; } uvs = toTrimmedTokens(s, delim); if (uvs.length > 2) { // More than one +-*/. String last = uvs[uvs.length - 1]; String first = s.substring(0, s.length() - last.length() - 1); uvs = new String[] {first, last}; } } if (uvs.length != 2) throw new IllegalArgumentException("Malformed UnitValue: '" + s + "'"); UnitValue sub1 = parseUnitValue(uvs[0], null, isHor); UnitValue sub2 = parseUnitValue(uvs[1], null, isHor); if (sub1 == null || sub2 == null) throw new IllegalArgumentException("Malformed UnitValue. Must be two sub-values: '" + s + "'"); return new UnitValue(isHor, oper, sub1, sub2, cs); } else { try { String[] numParts = getNumTextParts(s); float value = numParts[0].length() > 0 ? Float.parseFloat(numParts[0]) : 1; // e.g. "related" has no number part.. return new UnitValue(value, numParts[1], isHor, oper, cs); } catch(Exception e) { throw new IllegalArgumentException("Malformed UnitValue: '" + s + "'", e); } } } /** Parses alignment keywords and returns the appropriate UnitValue. * @param s The string to parse. Not null. * @param isHor If alignments for horizontal is checked. false means vertical. * @return The unit value or null if not recognized (no exception). */ static UnitValue parseAlignKeywords(String s, boolean isHor) { if (startsWithLenient(s, "center", 1, false) != -1) return UnitValue.CENTER; if (isHor) { if (startsWithLenient(s, "left", 1, false) != -1) return UnitValue.LEFT; if (startsWithLenient(s, "right", 1, false) != -1) return UnitValue.RIGHT; if (startsWithLenient(s, "leading", 4, false) != -1) return UnitValue.LEADING; if (startsWithLenient(s, "trailing", 5, false) != -1) return UnitValue.TRAILING; if (startsWithLenient(s, "label", 5, false) != -1) return UnitValue.LABEL; } else { if (startsWithLenient(s, "baseline", 4, false) != -1) return UnitValue.BASELINE_IDENTITY; if (startsWithLenient(s, "top", 1, false) != -1) return UnitValue.TOP; if (startsWithLenient(s, "bottom", 1, false) != -1) return UnitValue.BOTTOM; } return null; } /** Splits a text-number combination such as "hello 10.0" into {"hello", "10.0"}. * @param s The string to split. Not null. Needs be be reasonably formatted since the method * only finds the first 0-9 or . and cuts the string in half there. * @return Always length 2 and no null elements. Elements are "" if no part found. */ private static String[] getNumTextParts(String s) { for (int i = 0, iSz = s.length(); i < iSz; i++) { char c = s.charAt(i); if (c == ' ') throw new IllegalArgumentException("Space in UnitValue: '" + s + "'"); if ((c < '0' || c > '9') && c != '.' && c != '-') return new String[] {s.substring(0, i).trim(), s.substring(i).trim()}; } return new String[] {s, ""}; } /** Returns the operation depending on the start character. * @param s The string to check. Not null. * @return E.g. UnitValue.ADD, UnitValue.SUB or UnitValue.STATIC. Returns negative value for in-line operations. */ private static int getOper(String s) { int len = s.length(); if (len < 3) return UnitValue.STATIC; if (len > 5 && s.charAt(3) == '(' && s.charAt(len - 1) == ')') { if (s.startsWith("min(")) return UnitValue.MIN; if (s.startsWith("max(")) return UnitValue.MAX; if (s.startsWith("mid(")) return UnitValue.MID; } // Try in-line add/sub. E.g. "pref+10px". for (int j = 0; j < 2; j++) { // First +- then */ (precedence) for (int i = len - 1, p = 0; i > 0; i--) { char c = s.charAt(i); if (c == ')') { p++; } else if (c == '(') { p--; } else if (p == 0) { if (j == 0) { if (c == '+') return UnitValue.ADD; if (c == '-') return UnitValue.SUB; } else { if (c == '*') return UnitValue.MUL; if (c == '/') return UnitValue.DIV; } } } } return UnitValue.STATIC; } /** Returns if a string shares at least a specified numbers starting characters with a number of matches. *

* This method just exercise {@link #startsWithLenient(String, String, int, boolean)} with every one of * matches and minChars. * @param s The string to check. Not null. * @param matches A number of possible starts for s. * @param minChars The minimum number of characters to match for every element in matches. Needs * to be of same length as matches. Can be null. * @param acceptTrailing If after the required number of characters are matched on recognized characters that are not * in one of the the matches string should be accepted. For instance if "abczz" should be matched with * "abcdef" and min chars 3. * @return The index of the first unmatched character if minChars was reached or -1 if a match was not * found. */ private static int startsWithLenient(String s, String[] matches, int[] minChars, boolean acceptTrailing) { for (int i = 0; i < matches.length; i++) { int minChar = minChars != null ? minChars[i] : -1; int ix = startsWithLenient(s, matches[i], minChar, acceptTrailing); if (ix > -1) return ix; } return -1; } /** Returns if a string shares at least a specified numbers starting characters with a match. * @param s The string to check. Not null and must be trimmed. * @param match The possible start for s. Not null and must be trimmed. * @param minChars The mimimum number of characters to match to s for it this to be considered a match. -1 means * the full length of match. * @param acceptTrailing If after the required number of charecters are matched unrecognized characters that are not * in one of the the matches string should be accepted. For instance if "abczz" should be matched with * "abcdef" and min chars 3. * @return The index of the first unmatched character if minChars was reached or -1 if a match was not * found. */ private static int startsWithLenient(String s, String match, int minChars, boolean acceptTrailing) { if (s.charAt(0) != match.charAt(0)) // Fast sanity check. return -1; if (minChars == -1) minChars = match.length(); int sSz = s.length(); if (sSz < minChars) return -1; int mSz = match.length(); int sIx = 0; for (int mIx = 0; mIx < mSz; sIx++, mIx++) { while (sIx < sSz && (s.charAt(sIx) == ' ' || s.charAt(sIx) == '_')) // Disregard spaces and _ sIx++; if (sIx >= sSz || s.charAt(sIx) != match.charAt(mIx)) return mIx >= minChars && (acceptTrailing || sIx >= sSz) && (sIx >= sSz || s.charAt(sIx - 1) == ' ') ? sIx : -1; } return sIx >= sSz || acceptTrailing ||s.charAt(sIx) == ' ' ? sIx : -1; } /** Parses a string and returns it in those parts of the string that are separated with a sep character. *

* separator characters within parentheses will not be counted or handled in any way, whatever the depth. *

* A space separator will be a hit to one or more spaces and thus not return empty strings. * @param s The string to parse. If it starts and/or ends with a sep the first and/or last element returned will be "". If * two sep are next to each other and empty element will be "between" the periods. The sep themselves will never be returned. * @param sep The separator char. * @return Those parts of the string that are separated with sep. Never null and at least of size 1 * @since 6.7.2 Changed so more than one space in a row works as one space. */ private static String[] toTrimmedTokens(String s, char sep) { int toks = 0, sSize = s.length(); boolean disregardDoubles = sep == ' '; // Count the sep:s int p = 0; for(int i = 0; i < sSize; i++) { char c = s.charAt(i); if (c == '(') { p++; } else if (c == ')') { p--; } else if (p == 0 && c == sep) { toks++; while (disregardDoubles && i < sSize - 1 && s.charAt(i + 1) == ' ') i++; } if (p < 0) throw new IllegalArgumentException("Unbalanced parentheses: '" + s + "'"); } if (p != 0) throw new IllegalArgumentException("Unbalanced parentheses: '" + s + "'"); if (toks == 0) return new String [] {s.trim()}; String[] retArr = new String[toks + 1]; int st = 0, pNr = 0; p = 0; for (int i = 0; i < sSize; i++) { char c = s.charAt(i); if (c == '(') { p++; } else if (c == ')') { p--; } else if (p == 0 && c == sep) { retArr[pNr++] = s.substring(st, i).trim(); st = i + 1; while (disregardDoubles && i < sSize - 1 && s.charAt(i + 1) == ' ') i++; } } retArr[pNr++] = s.substring(st, sSize).trim(); return retArr; } /** Parses "AAA[BBB]CCC[DDD]EEE" into {"AAA", "BBB", "CCC", "DDD", "EEE", "FFF"}. Handles empty parts. Will always start and end outside * a [] block so that the number of returned elemets will always be uneven and at least of length 3. *

* "|" is interpreted as "][". * @param s The string. Might be "" but not null. Should be trimmed. * @return The string divided into elements. Never null and at least of length 3. * @throws IllegalArgumentException If a [] mismatch of some kind. (If not same [ as ] count or if the interleave.) */ private static ArrayList getRowColAndGapsTrimmed(String s) { if (s.indexOf('|') != -1) s = s.replaceAll("\\|", "]["); ArrayList retList = new ArrayList(Math.max(s.length() >> 2 + 1, 3)); // Approx return length. int s0 = 0, s1 = 0; // '[' and ']' count. int st = 0; // Start of "next token to add". for (int i = 0, iSz = s.length(); i < iSz; i++) { char c = s.charAt(i); if (c == '[') { s0++; } else if (c == ']') { s1++; } else { continue; } if (s0 != s1 && (s0 - 1) != s1) break; // Wrong [ or ] found. Break for throw. retList.add(s.substring(st, i).trim()); st = i + 1; } if (s0 != s1) throw new IllegalArgumentException("'[' and ']' mismatch in row/column format string: " + s); if (s0 == 0) { retList.add(""); retList.add(s); retList.add(""); } else if (retList.size() % 2 == 0) { retList.add(s.substring(st, s.length())); } return retList; } /** Makes null "", trims and converts to lower case. * @param s The string * @return Not null. */ public static String prepare(String s) { return s != null ? s.trim().toLowerCase() : ""; } // /** Tests to serialize and deserialize the object with both XMLEncoder/Decoder and through Serializable // * @param o The object to serialize // * @return The same object after a tri through the process. // */ // public static final Object serializeTest(Object o) // { // try { // ByteArrayOutputStream barr = new ByteArrayOutputStream(); // XMLEncoder enc = new XMLEncoder(barr); // enc.writeObject(o); // enc.close(); // // XMLDecoder dec = new XMLDecoder(new ByteArrayInputStream(barr.toByteArray())); // o = dec.readObject(); // dec.close(); // } catch (Exception e) { // e.printStackTrace(); // } // // try { // ByteArrayOutputStream barr = new ByteArrayOutputStream(); // ObjectOutputStream oos = new ObjectOutputStream(barr); // oos.writeObject(o); // oos.close(); // // ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray())); // o = ois.readObject(); // ois.close(); // } catch (Exception e) { // e.printStackTrace(); // } // // return o; // } } miglayout-5.1/core/src/main/java/net/miginfocom/layout/ContainerWrapper.java000077500000000000000000000061761324101563200273470ustar00rootroot00000000000000package net.miginfocom.layout; /* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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 */ /** A class that wraps a container that contains components. */ public interface ContainerWrapper extends ComponentWrapper { /** Returns the components of the container that wrapper is wrapping. * @return The components of the container that wrapper is wrapping. Never null. */ public abstract ComponentWrapper[] getComponents(); /** Returns the number of components that this parent has. * @return The number of components that this parent has. */ public abstract int getComponentCount(); /** Returns the LayoutHandler (in Swing terms) that is handling the layout of this container. * If there exist no such class the method should return the same as {@link #getComponent()}, which is the * container itself. * @return The layout handler instance. Never null. */ public abstract Object getLayout(); /** Returns if this container is using left-to-right component ordering. * @return If this container is using left-to-right component ordering. */ public abstract boolean isLeftToRight(); /** Paints a cell to indicate where it is. * @param x The x coordinate to start the drawing. * @param y The x coordinate to start the drawing. * @param width The width to draw/fill * @param height The height to draw/fill */ public abstract void paintDebugCell(int x, int y, int width, int height); } miglayout-5.1/core/src/main/java/net/miginfocom/layout/DimConstraint.java000077500000000000000000000467371324101563200266510ustar00rootroot00000000000000package net.miginfocom.layout; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.io.ObjectStreamException; /* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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 */ /** A simple value holder for a constraint for one dimension. */ public final class DimConstraint implements Externalizable { /** How this entity can be resized in the dimension that this constraint represents. */ final ResizeConstraint resize = new ResizeConstraint(); // Look at the properties' getter/setter methods for explanation private String sizeGroup = null; // A "context" compared with equals. private BoundSize size = BoundSize.NULL_SIZE; // Min, pref, max. Never null, but sizes can be null. private BoundSize gapBefore = null, gapAfter = null; private UnitValue align = null; // ************** Only applicable on components! ******************* private String endGroup = null; // A "context" compared with equals. // ************** Only applicable on rows/columns! ******************* private boolean fill = false; private boolean noGrid = false; /** Empty constructor. */ public DimConstraint() { } /** Returns the grow priority. Relative priority is used for determining which entities gets the extra space first. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return The grow priority. */ public int getGrowPriority() { return resize.growPrio; } /** Sets the grow priority. Relative priority is used for determining which entities gets the extra space first. *

* 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. */ public void setGrowPriority(int p) { resize.growPrio = p; } /** Returns the grow weight.

* Grow weight is how flexible the entity should be, relative to other entities, when it comes to growing. null or * zero mean it will never grow. An entity that has twice the grow weight compared to another entity will get twice * as much of available space. *

* GrowWeight are only compared within the same GrowPrio. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return The current grow weight. */ public Float getGrow() { return resize.grow; } /** Sets the grow weight.

* Grow weight is how flexible the entity should be, relative to other entities, when it comes to growing. null or * zero mean it will never grow. An entity that has twice the grow weight compared to another entity will get twice * as much of available space. *

* GrowWeight are only compared within the same GrowPrio. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param weight The new grow weight. */ public void setGrow(Float weight) { resize.grow = weight; } /** Returns the shrink priority. Relative priority is used for determining which entities gets smaller first when space is scarce. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return The shrink priority. */ public int getShrinkPriority() { return resize.shrinkPrio; } /** Sets the shrink priority. Relative priority is used for determining which entities gets smaller first when space is scarce. *

* 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. */ public void setShrinkPriority(int p) { resize.shrinkPrio = p; } /** Returns the shrink priority. Relative priority is used for determining which entities gets smaller first when space is scarce. * Shrink weight is how flexible the entity should be, relative to other entities, when it comes to shrinking. null or * zero mean it will never shrink (default). An entity that has twice the shrink weight compared to another entity will get twice * as much of available space. *

* Shrink(Weight) are only compared within the same ShrinkPrio. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return The current shrink weight. */ public Float getShrink() { return resize.shrink; } /** Sets the shrink priority. Relative priority is used for determining which entities gets smaller first when space is scarce. * Shrink weight is how flexible the entity should be, relative to other entities, when it comes to shrinking. null or * zero mean it will never shrink (default). An entity that has twice the shrink weight compared to another entity will get twice * as much of available space. *

* Shrink(Weight) are only compared within the same ShrinkPrio. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param weight The new shrink weight. */ public void setShrink(Float weight) { resize.shrink = weight; } public UnitValue getAlignOrDefault(boolean isCols) { if (align != null) return align; if (isCols) return UnitValue.LEADING; return fill || PlatformDefaults.getDefaultRowAlignmentBaseline() == false ? UnitValue.CENTER : UnitValue.BASELINE_IDENTITY; } /** Returns the alignment used either as a default value for sub-entities or for this entity. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return The alignment. */ public UnitValue getAlign() { return align; } /** Sets the alignment used wither as a default value for sub-entities or for this entity. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param uv The new shrink priority. E.g. {@link UnitValue#CENTER} or {@link net.miginfocom.layout.UnitValue#LEADING}. */ public void setAlign(UnitValue uv) { this.align = uv; } /** Returns the gap after this entity. The gap is an empty space and can have a min/preferred/maximum size so that it can shrink and * grow depending on available space. Gaps are against other entities' edges and not against other entities' gaps. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return The gap after this entity */ public BoundSize getGapAfter() { return gapAfter; } /** Sets the gap after this entity. The gap is an empty space and can have a min/preferred/maximum size so that it can shrink and * grow depending on available space. Gaps are against other entities' edges and not against other entities' gaps. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param size The new gap. * @see net.miginfocom.layout.ConstraintParser#parseBoundSize(String, boolean, boolean) */ public void setGapAfter(BoundSize size) { this.gapAfter = size; } boolean hasGapAfter() { return gapAfter != null && gapAfter.isUnset() == false; } boolean isGapAfterPush() { return gapAfter != null && gapAfter.getGapPush(); } /** Returns the gap before this entity. The gap is an empty space and can have a min/preferred/maximum size so that it can shrink and * grow depending on available space. Gaps are against other entities' edges and not against other entities' gaps. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return The gap before this entity */ public BoundSize getGapBefore() { return gapBefore; } /** Sets the gap before this entity. The gap is an empty space and can have a min/preferred/maximum size so that it can shrink and * grow depending on available space. Gaps are against other entities' edges and not against other entities' gaps. *

* See also {@link net.miginfocom.layout.ConstraintParser#parseBoundSize(String, boolean, boolean)}. * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param size The new gap. */ public void setGapBefore(BoundSize size) { this.gapBefore = size; } boolean hasGapBefore() { return gapBefore != null && gapBefore.isUnset() == false; } boolean isGapBeforePush() { return gapBefore != null && gapBefore.getGapPush(); } /** Returns the min/preferred/max size for the entity in the dimension that this object describes. *

* See also {@link net.miginfocom.layout.ConstraintParser#parseBoundSize(String, boolean, boolean)}. * For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return The current size. Never null since v3.5. */ public BoundSize getSize() { return size; } /** Sets the min/preferred/max size for the entity in the dimension that this object describes. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param size The new size. May be null. */ public void setSize(BoundSize size) { if (size != null) size.checkNotLinked(); this.size = size; } /** Returns the size group that this entity should be in for the dimension that this object is describing. * If this constraint is in a size group that is specified here. null means no size group * and all other values are legal. Comparison with .equals(). Components/columns/rows in the same size group * will have the same min/preferred/max size; that of the largest in the group for the first two and the * smallest for max. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return The current size group. May be null. */ public String getSizeGroup() { return sizeGroup; } /** Sets the size group that this entity should be in for the dimension that this object is describing. * If this constraint is in a size group that is specified here. null means no size group * and all other values are legal. Comparison with .equals(). Components/columns/rows in the same size group * will have the same min/preferred/max size; that of the largest in the group for the first two and the * smallest for max. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param s The new size group. null disables size grouping. */ public void setSizeGroup(String s) { sizeGroup = s; } // ************** Only applicable on components ! ******************* /** Returns the end group that this entity should be in for the dimension that this object is describing. * If this constraint is in an end group that is specified here. null means no end group * and all other values are legal. Comparison with .equals(). Components in the same end group * will have the same end coordinate. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return The current end group. null may be returned. */ public String getEndGroup() { return endGroup; } /** Sets the end group that this entity should be in for the dimension that this object is describing. * If this constraint is in an end group that is specified here. null means no end group * and all other values are legal. Comparison with .equals(). Components in the same end group * will have the same end coordinate. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param s The new end group. null disables end grouping. */ public void setEndGroup(String s) { endGroup = s; } // ************** Not applicable on components below ! ******************* /** Returns if the component in the row/column that this constraint should default be grown in the same dimension that * this constraint represents (width for column and height for a row). *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return true means that components should grow. */ public boolean isFill() { return fill; } /** Sets if the component in the row/column that this constraint should default be grown in the same dimension that * this constraint represents (width for column and height for a row). *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param b true means that components should grow. */ public void setFill(boolean b) { fill = b; } /** Returns if the row/column should default to flow and not to grid behaviour. This means that the whole row/column * will be one cell and all components will end up in that cell. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return true means that the whole row/column should be one cell. */ public boolean isNoGrid() { return noGrid; } /** Sets if the row/column should default to flow and not to grid behaviour. This means that the whole row/column * will be one cell and all components will end up in that cell. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param b true means that the whole row/column should be one cell. */ public void setNoGrid(boolean b) { this.noGrid = b; } /** Returns the gaps as pixel values. * @param parent The parent. Used to get the pixel values. * @param defGap The default gap to use if there is no gap set on this object (i.e. it is null). * @param refSize The reference size used to get the pixel sizes. * @param before IF it is the gap before rather than the gap after to return. * @return The [min,preferred,max] sizes for the specified gap. Uses {@link net.miginfocom.layout.LayoutUtil#NOT_SET} * for gap sizes that are null. Returns null if there was no gap specified. A new and free to use array. */ int[] getRowGaps(ContainerWrapper parent, BoundSize defGap, int refSize, boolean before) { BoundSize gap = before ? gapBefore : gapAfter; if (gap == null || gap.isUnset()) gap = defGap; if (gap == null || gap.isUnset()) return null; int[] ret = new int[3]; for (int i = LayoutUtil.MIN; i <= LayoutUtil.MAX; i++) { UnitValue uv = gap.getSize(i); ret[i] = uv != null ? uv.getPixels(refSize, parent, null) : LayoutUtil.NOT_SET; } return ret; } /** Returns the gaps as pixel values. * @param parent The parent. Used to get the pixel values. * @param comp The component that the gap is for. If not for a component it is null. * @param adjGap The gap that the adjacent component, if any, has towards comp. * @param adjacentComp The adjacent component if any. May be null. * @param refSize The reference size used to get the pixel sizes. * @param adjacentSide What side the adjacentComp is on. 0 = top, 1 = left, 2 = bottom, 3 = right. * @param tag The tag string that the component might be tagged with in the component constraints. May be null. * @param isLTR If it is left-to-right. * @return The [min,preferred,max] sizes for the specified gap. Uses {@link net.miginfocom.layout.LayoutUtil#NOT_SET} * for gap sizes that are null. Returns null if there was no gap specified. A new and free to use array. */ int[] getComponentGaps(ContainerWrapper parent, ComponentWrapper comp, BoundSize adjGap, ComponentWrapper adjacentComp, String tag, int refSize, int adjacentSide, boolean isLTR) { BoundSize gap = adjacentSide < 2 ? gapBefore : gapAfter; boolean hasGap = gap != null && gap.getGapPush(); if ((gap == null || gap.isUnset()) && (adjGap == null || adjGap.isUnset()) && comp != null) gap = PlatformDefaults.getDefaultComponentGap(comp, adjacentComp, adjacentSide + 1, tag, isLTR); if (gap == null) return hasGap ? new int[] {0, 0, LayoutUtil.NOT_SET} : null; int[] ret = new int[3]; for (int i = LayoutUtil.MIN; i <= LayoutUtil.MAX; i++) { UnitValue uv = gap.getSize(i); ret[i] = uv != null ? uv.getPixels(refSize, parent, null) : LayoutUtil.NOT_SET; } return ret; } // ************************************************ // Persistence Delegate and Serializable combined. // ************************************************ private Object readResolve() throws ObjectStreamException { return LayoutUtil.getSerializedObject(this); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { LayoutUtil.setSerializedObject(this, LayoutUtil.readAsXML(in)); } @Override public void writeExternal(ObjectOutput out) throws IOException { if (getClass() == DimConstraint.class) LayoutUtil.writeAsXML(out, this); } } miglayout-5.1/core/src/main/java/net/miginfocom/layout/Grid.java000077500000000000000000002552621324101563200247530ustar00rootroot00000000000000package net.miginfocom.layout; import java.lang.ref.WeakReference; import java.util.*; /* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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 */ /** Holds components in a grid. Does most of the logic behind the layout manager. */ public final class Grid { public static final boolean TEST_GAPS = true; private static final Float[] GROW_100 = new Float[] {ResizeConstraint.WEIGHT_100}; private static final DimConstraint DOCK_DIM_CONSTRAINT = new DimConstraint(); static { DOCK_DIM_CONSTRAINT.setGrowPriority(0); } /** This is the maximum grid position for "normal" components. Docking components use the space out to * MAX_DOCK_GRID and below 0. */ private static final int MAX_GRID = 30000; /** Docking components will use the grid coordinates -MAX_DOCK_GRID -> 0 and MAX_GRID -> MAX_DOCK_GRID. */ private static final int MAX_DOCK_GRID = 32767; /** A constraint used for gaps. */ private static final ResizeConstraint GAP_RC_CONST = new ResizeConstraint(200, ResizeConstraint.WEIGHT_100, 50, null); private static final ResizeConstraint GAP_RC_CONST_PUSH = new ResizeConstraint(200, ResizeConstraint.WEIGHT_100, 50, ResizeConstraint.WEIGHT_100); /** Used for components that doesn't have a CC set. Not that it's really really important that the CC is never changed in this Grid class. */ private static final CC DEF_CC = new CC(); /** The constraints. Never null. */ private final LC lc; /** The parent that is layout out and this grid is done for. Never null. */ private final ContainerWrapper container; /** An x, y array implemented as a sparse array to accommodate for any grid size without wasting memory (or rather 15 bit (0-MAX_GRID * 0-MAX_GRID). */ private final LinkedHashMap grid = new LinkedHashMap(); // [(y << 16) + x] -> Cell. null key for absolute positioned compwraps private HashMap wrapGapMap = null; // Row or Column index depending in the dimension that "wraps". Normally row indexes but may be column indexes if "flowy". 0 means before first row/col. /** The size of the grid. Row count and column count. */ private final TreeSet rowIndexes = new TreeSet(), colIndexes = new TreeSet(); /** The row and column specifications. */ private final AC rowConstr, colConstr; /** The in the constructor calculated min/pref/max sizes of the rows and columns. */ private FlowSizeSpec colFlowSpecs = null, rowFlowSpecs = null; /** Components that are connections in one dimension (such as baseline alignment for instance) are grouped together and stored here. * One for each row/column. */ private final ArrayList[] colGroupLists, rowGroupLists; //[(start)row/col number] /** The in the constructor calculated min/pref/max size of the whole grid. */ private int[] width = null, height = null; /** If debug is on contains the bounds for things to paint when calling {@link ContainerWrapper#paintDebugCell(int, int, int, int)} */ private ArrayList debugRects = null; // [x, y, width, height] /** If any of the absolute coordinates for component bounds has links the name of the target is in this Set. * Since it requires some memory and computations this is checked at the creation so that * the link information is only created if needed later. *

* The boolean is true for groups id:s and null for normal id:s. */ private HashMap linkTargetIDs = null; private final int dockOffY, dockOffX; private final Float[] pushXs, pushYs; private final ArrayList callbackList; /** Constructor. * @param container The container that will be laid out. * @param lc The form flow constraints. * @param rowConstr The rows specifications. If more cell rows are required, the last element will be used for when there is no corresponding element in this array. * @param colConstr The columns specifications. If more cell rows are required, the last element will be used for when there is no corresponding element in this array. * @param ccMap The map containing the parsed constraints for each child component of parent. Will not be altered. Can have null CC which will use a common * cached one. * @param callbackList A list of callbacks or null if none. Will not be altered. */ public Grid(ContainerWrapper container, LC lc, AC rowConstr, AC colConstr, Map ccMap, ArrayList callbackList) { this.lc = lc; this.rowConstr = rowConstr; this.colConstr = colConstr; this.container = container; this.callbackList = callbackList; int wrap = lc.getWrapAfter() != 0 ? lc.getWrapAfter() : (lc.isFlowX() ? colConstr : rowConstr).getConstaints().length; boolean useVisualPadding = lc.isVisualPadding(); final ComponentWrapper[] comps = container.getComponents(); boolean hasTagged = false; // So we do not have to sort if it will not do any good boolean hasPushX = false, hasPushY = false; boolean hitEndOfRow = false; final int[] cellXY = new int[2]; final ArrayList spannedRects = new ArrayList(2); final DimConstraint[] specs = (lc.isFlowX() ? rowConstr : colConstr).getConstaints(); int sizeGroupsX = 0, sizeGroupsY = 0; int[] dockInsets = null; // top, left, bottom, right insets for docks. LinkHandler.clearTemporaryBounds(container.getLayout()); for (int i = 0; i < comps.length;) { ComponentWrapper comp = comps[i]; CC rootCc = getCC(comp, ccMap); addLinkIDs(rootCc); int hideMode = comp.isVisible() ? -1 : rootCc.getHideMode() != -1 ? rootCc.getHideMode() : lc.getHideMode(); if (hideMode == 3) { // To work with situations where there are components that does not have a layout manager, or not this one. setLinkedBounds(comp, rootCc, comp.getX(), comp.getY(), comp.getWidth(), comp.getHeight(), rootCc.isExternal()); i++; continue; // The "external" component should not be handled further. } if (rootCc.getHorizontal().getSizeGroup() != null) sizeGroupsX++; if (rootCc.getVertical().getSizeGroup() != null) sizeGroupsY++; // Special treatment of absolute positioned components. if (getPos(comp, rootCc) != null || rootCc.isExternal()) { CompWrap cw = new CompWrap(comp, rootCc, hideMode, useVisualPadding); Cell cell = grid.get(null); if (cell == null) { grid.put(null, new Cell(cw)); } else { cell.compWraps.add(cw); } if (!rootCc.isBoundsInGrid() || rootCc.isExternal()) { setLinkedBounds(comp, rootCc, comp.getX(), comp.getY(), comp.getWidth(), comp.getHeight(), rootCc.isExternal()); i++; continue; } } if (rootCc.getDockSide() != -1) { if (dockInsets == null) dockInsets = new int[] {-MAX_DOCK_GRID, -MAX_DOCK_GRID, MAX_DOCK_GRID, MAX_DOCK_GRID}; addDockingCell(dockInsets, rootCc.getDockSide(), new CompWrap(comp, rootCc, hideMode, useVisualPadding)); i++; continue; } Boolean cellFlowX = rootCc.getFlowX(); Cell cell = null; if (rootCc.isNewline()) { wrap(cellXY, rootCc.getNewlineGapSize()); } else if (hitEndOfRow) { wrap(cellXY, null); } hitEndOfRow = false; final boolean rowNoGrid = lc.isNoGrid() || ((DimConstraint) LayoutUtil.getIndexSafe(specs, lc.isFlowX() ? cellXY[1] : cellXY[0])).isNoGrid(); // Move to a free y, x if no absolute grid specified int cx = rootCc.getCellX(); int cy = rootCc.getCellY(); if ((cx < 0 || cy < 0) && rowNoGrid == false && rootCc.getSkip() == 0) { // 3.7.2: If skip, don't find an empty cell first. while (isCellFree(cellXY[1], cellXY[0], spannedRects) == false) { if (Math.abs(increase(cellXY, 1)) >= wrap) wrap(cellXY, null); } } else { if (cx >= 0 && cy >= 0) { if (cy >= 0) { cellXY[0] = cx; cellXY[1] = cy; } else { // Only one coordinate is specified. Use the current row (flowx) or column (flowy) to fill in. if (lc.isFlowX()) { cellXY[0] = cx; } else { cellXY[1] = cx; } } ensureIndexSizes(cx, cy); } cell = getCell(cellXY[1], cellXY[0]); // Might be null } // Skip a number of cells. Changed for 3.6.1 to take wrap into account and thus "skip" to the next and possibly more rows. for (int s = 0, skipCount = rootCc.getSkip(); s < skipCount; s++) { do { if (Math.abs(increase(cellXY, 1)) >= wrap) wrap(cellXY, null); } while (isCellFree(cellXY[1], cellXY[0], spannedRects) == false); } // If cell is not created yet, create it and set it. if (cell == null) { int spanx = Math.min(rowNoGrid && lc.isFlowX() ? LayoutUtil.INF : rootCc.getSpanX(), MAX_GRID - cellXY[0]); int spany = Math.min(rowNoGrid && !lc.isFlowX() ? LayoutUtil.INF : rootCc.getSpanY(), MAX_GRID - cellXY[1]); cell = new Cell(spanx, spany, cellFlowX != null ? cellFlowX : lc.isFlowX()); setCell(cellXY[1], cellXY[0], cell); // Add a rectangle so we can know that spanned cells occupy more space. if (spanx > 1 || spany > 1) spannedRects.add(new int[] {cellXY[0], cellXY[1], spanx, spany}); } // Add the one, or all, components that split the grid position to the same Cell. boolean wrapHandled = false; int splitLeft = rowNoGrid ? LayoutUtil.INF : rootCc.getSplit() - 1; boolean splitExit = false; final boolean spanRestOfRow = (lc.isFlowX() ? rootCc.getSpanX() : rootCc.getSpanY()) == LayoutUtil.INF; for (; splitLeft >= 0 && i < comps.length; splitLeft--) { ComponentWrapper compAdd = comps[i]; CC cc = getCC(compAdd, ccMap); addLinkIDs(cc); boolean visible = compAdd.isVisible(); hideMode = visible ? -1 : cc.getHideMode() != -1 ? cc.getHideMode() : lc.getHideMode(); if (cc.isExternal() || hideMode == 3) { i++; splitLeft++; // Added for 3.5.5 so that these components does not "take" a split slot. continue; // To work with situations where there are components that does not have a layout manager, or not this one. } hasPushX |= (visible || hideMode > 1) && (cc.getPushX() != null); hasPushY |= (visible || hideMode > 1) && (cc.getPushY() != null); if (cc != rootCc) { // If not first in a cell if (cc.isNewline() || cc.isBoundsInGrid() == false || cc.getDockSide() != -1) break; if (splitLeft > 0 && cc.getSkip() > 0) { splitExit = true; break; } } CompWrap cw = new CompWrap(compAdd, cc, hideMode, useVisualPadding); cell.compWraps.add(cw); cell.hasTagged |= cc.getTag() != null; hasTagged |= cell.hasTagged; if (cc != rootCc) { if (cc.getHorizontal().getSizeGroup() != null) sizeGroupsX++; if (cc.getVertical().getSizeGroup() != null) sizeGroupsY++; } i++; if ((cc.isWrap() || (spanRestOfRow && splitLeft == 0))) { if (cc.isWrap()) { wrap(cellXY, cc.getWrapGapSize()); } else { hitEndOfRow = true; } wrapHandled = true; break; } } if (wrapHandled == false && rowNoGrid == false) { int span = lc.isFlowX() ? cell.spanx : cell.spany; if (Math.abs((lc.isFlowX() ? cellXY[0] : cellXY[1])) + span >= wrap) { hitEndOfRow = true; } else { increase(cellXY, splitExit ? span - 1 : span); } } } // If there were size groups, calculate the largest values in the groups (for min/pref/max) and enforce them on the rest in the group. if (sizeGroupsX > 0 || sizeGroupsY > 0) { HashMap sizeGroupMapX = sizeGroupsX > 0 ? new HashMap(sizeGroupsX) : null; HashMap sizeGroupMapY = sizeGroupsY > 0 ? new HashMap(sizeGroupsY) : null; ArrayList sizeGroupCWs = new ArrayList(Math.max(sizeGroupsX, sizeGroupsY)); for (Cell cell : grid.values()) { for (int i = 0; i < cell.compWraps.size(); i++) { CompWrap cw = cell.compWraps.get(i); String sgx = cw.cc.getHorizontal().getSizeGroup(); String sgy = cw.cc.getVertical().getSizeGroup(); if (sgx != null || sgy != null) { if (sgx != null && sizeGroupMapX != null) addToSizeGroup(sizeGroupMapX, sgx, cw.getSizes(true)); if (sgy != null && sizeGroupMapY != null) addToSizeGroup(sizeGroupMapY, sgy, cw.getSizes(false)); sizeGroupCWs.add(cw); } } } // Set/equalize the sizeGroups to same the values. for (CompWrap cw : sizeGroupCWs) { if (sizeGroupMapX != null) cw.setForcedSizes(sizeGroupMapX.get(cw.cc.getHorizontal().getSizeGroup()), true); // Target method handles null sizes if (sizeGroupMapY != null) cw.setForcedSizes(sizeGroupMapY.get(cw.cc.getVertical().getSizeGroup()), false); // Target method handles null sizes } } // Component loop if (hasTagged) sortCellsByPlatform(grid.values(), container); // Calculate gaps now that the cells are filled and we know all adjacent components. boolean ltr = LayoutUtil.isLeftToRight(lc, container); for (Cell cell : grid.values()) { ArrayList cws = cell.compWraps; for (int i = 0, lastI = cws.size() - 1; i <= lastI; i++) { CompWrap cw = cws.get(i); ComponentWrapper cwBef = i > 0 ? cws.get(i - 1).comp : null; ComponentWrapper cwAft = i < lastI ? cws.get(i + 1).comp : null; String tag = getCC(cw.comp, ccMap).getTag(); CC ccBef = cwBef != null ? getCC(cwBef, ccMap) : null; CC ccAft = cwAft != null ? getCC(cwAft, ccMap) : null; cw.calcGaps(cwBef, ccBef, cwAft, ccAft, tag, cell.flowx, ltr); } } dockOffX = getDockInsets(colIndexes); dockOffY = getDockInsets(rowIndexes); // Add synthetic indexes for empty rows and columns so they can get a size ensureIndexSizes(colConstr.getCount(), rowConstr.getCount()); colGroupLists = divideIntoLinkedGroups(false); rowGroupLists = divideIntoLinkedGroups(true); pushXs = hasPushX || lc.isFillX() ? getDefaultPushWeights(false) : null; pushYs = hasPushY || lc.isFillY() ? getDefaultPushWeights(true) : null; if (LayoutUtil.isDesignTime(container)) saveGrid(container, grid); } private void ensureIndexSizes(int colCount, int rowCount) { for (int i = 0; i < colCount; i++) colIndexes.add(i); for (int i = 0; i < rowCount; i++) rowIndexes.add(i); } private static CC getCC(ComponentWrapper comp, Map ccMap) { CC cc = ccMap.get(comp); return cc != null ? cc : DEF_CC; } private void addLinkIDs(CC cc) { String[] linkIDs = cc.getLinkTargets(); for (String linkID : linkIDs) { if (linkTargetIDs == null) linkTargetIDs = new HashMap(); linkTargetIDs.put(linkID, null); } } /** If the container (parent) that this grid is laying out has changed its bounds, call this method to * clear any cached values min/pref/max sizes of the components and rows/columns. *

* If any component can have changed cell the grid needs to be recreated. */ public void invalidateContainerSize() { colFlowSpecs = null; invalidateComponentSizes(); } private void invalidateComponentSizes() { for (Cell cell : grid.values()) { for (CompWrap compWrap : cell.compWraps) compWrap.invalidateSizes(); } } /** * @deprecated since 5.0 Last boolean is not needed and is gotten from the new {@link net.miginfocom.layout.ComponentWrapper#getContentBias()} instead; */ public boolean layout(int[] bounds, UnitValue alignX, UnitValue alignY, boolean debug, boolean notUsed) { return layoutImpl(bounds, alignX, alignY, debug, false); } /** Does the actual layout. Uses many values calculated in the constructor. * @param bounds The bounds to layout against. Normally that of the parent. [x, y, width, height]. * @param alignX The alignment for the x-axis. Can be null. * @param alignY The alignment for the y-axis. Can be null. * @param debug If debug information should be saved in {@link #debugRects}. * @return If the layout has changed the preferred size and there is need for a new layout. This can happen if one or more components * in the grid has a content bias according to {@link net.miginfocom.layout.ComponentWrapper#getContentBias()}. * @since 5.0 */ public boolean layout(int[] bounds, UnitValue alignX, UnitValue alignY, boolean debug) { return layoutImpl(bounds, alignX, alignY, debug, false); } /** Does the actual layout. Uses many values calculated in the constructor. * @param bounds The bounds to layout against. Normally that of the parent. [x, y, width, height]. * @param alignX The alignment for the x-axis. Can be null. * @param alignY The alignment for the y-axis. Can be null. * @param debug If debug information should be saved in {@link #debugRects}. * @param trialRun If true the bounds calculated will not be transferred to the components. Only the internal size * of the components will be calculated. * @return If the layout has changed the preferred size and there is need for a new layout. This can happen if one or more components * in the grid has a content bias according to {@link net.miginfocom.layout.ComponentWrapper#getContentBias()}. * @since 5.0 */ private boolean layoutImpl(int[] bounds, UnitValue alignX, UnitValue alignY, boolean debug, boolean trialRun) { if (debug) debugRects = new ArrayList(); if (colFlowSpecs == null) checkSizeCalcs(bounds[2], bounds[3]); resetLinkValues(true, true); layoutInOneDim(bounds[2], alignX, false, pushXs); layoutInOneDim(bounds[3], alignY, true, pushYs); HashMap endGrpXMap = null, endGrpYMap = null; int compCount = container.getComponentCount(); // Transfer the calculated bound from the ComponentWrappers to the actual Components. boolean addVisualPadding = lc.isVisualPadding(); boolean layoutAgain = false; if (compCount > 0) { for (int j = 0; j < (linkTargetIDs != null ? 2 : 1); j++) { // First do the calculations (maybe more than once) then set the bounds when done boolean doAgain; int count = 0; do { doAgain = false; for (Cell cell : grid.values()) { for (CompWrap cw : cell.compWraps) { if (j == 0) { doAgain |= doAbsoluteCorrections(cw, bounds); if (!doAgain) { // If we are going to do this again, do not bother this time around if (cw.cc.getHorizontal().getEndGroup() != null) endGrpXMap = addToEndGroup(endGrpXMap, cw.cc.getHorizontal().getEndGroup(), cw.x + cw.w); if (cw.cc.getVertical().getEndGroup() != null) endGrpYMap = addToEndGroup(endGrpYMap, cw.cc.getVertical().getEndGroup(), cw.y + cw.h); } // @since 3.7.2 Needed or absolute "pos" pointing to "visual" or "container" didn't work if // their bounds changed during the layout cycle. At least not in SWT. if (linkTargetIDs != null && (linkTargetIDs.containsKey("visual") || linkTargetIDs.containsKey("container"))) { layoutAgain = true; } } if (linkTargetIDs == null || j == 1) { if (cw.cc.getHorizontal().getEndGroup() != null) cw.w = endGrpXMap.get(cw.cc.getHorizontal().getEndGroup()) - cw.x; if (cw.cc.getVertical().getEndGroup() != null) cw.h = endGrpYMap.get(cw.cc.getVertical().getEndGroup()) - cw.y; cw.x += bounds[0]; cw.y += bounds[1]; if (!trialRun) cw.transferBounds(addVisualPadding); if (callbackList != null) { for (LayoutCallback callback : callbackList) callback.correctBounds(cw.comp); } } } } clearGroupLinkBounds(); if (++count > ((compCount << 3) + 10)) { System.err.println("Unstable cyclic dependency in absolute linked values."); break; } } while (doAgain); } } // Add debug shapes for the "cells". Use the CompWraps as base for inding the cells. if (debug) { for (Cell cell : grid.values()) { ArrayList compWraps = cell.compWraps; for (CompWrap cw : compWraps) { LinkedDimGroup hGrp = getGroupContaining(colGroupLists, cw); LinkedDimGroup vGrp = getGroupContaining(rowGroupLists, cw); if (hGrp != null && vGrp != null) debugRects.add(new int[]{hGrp.lStart + bounds[0] - (hGrp.fromEnd ? hGrp.lSize : 0), vGrp.lStart + bounds[1] - (vGrp.fromEnd ? vGrp.lSize : 0), hGrp.lSize, vGrp.lSize}); } } } return layoutAgain; } public void paintDebug() { if (debugRects != null) { container.paintDebugOutline(lc.isVisualPadding()); ArrayList painted = new ArrayList(); for (int[] r : debugRects) { if (!painted.contains(r)) { container.paintDebugCell(r[0], r[1], r[2], r[3]); painted.add(r); } } for (Cell cell : grid.values()) { ArrayList compWraps = cell.compWraps; for (CompWrap compWrap : compWraps) compWrap.comp.paintDebugOutline(lc.isVisualPadding()); } } } public ContainerWrapper getContainer() { return container; } public final int[] getWidth() { return getWidth(lastRefHeight); } public final int[] getWidth(int refHeight) { checkSizeCalcs(lastRefWidth, refHeight); return width.clone(); } public final int[] getHeight() { return getHeight(lastRefWidth); } public final int[] getHeight(int refWidth) { checkSizeCalcs(refWidth, lastRefHeight); return height.clone(); } private int lastRefWidth = 0, lastRefHeight = 0; private void checkSizeCalcs(int refWidth, int refHeight) { if (colFlowSpecs == null) calcGridSizes(refWidth, refHeight); if ((refWidth > 0 && refWidth != lastRefWidth) || (refHeight > 0 && refHeight != lastRefHeight)) { int[] refBounds = new int[] {0, 0, (refWidth > 0 ? refWidth : width[LayoutUtil.PREF]), (refHeight > 0 ? refHeight : height[LayoutUtil.PREF])}; layoutImpl(refBounds, null, null, false, true); calcGridSizes(refWidth, refHeight); } lastRefWidth = refWidth; lastRefHeight = refHeight; } private void calcGridSizes(int refWidth, int refHeight) { // Note, in these calls the grid can be invalidated and specs set to null. Therefore use local versions. FlowSizeSpec colSpecs = calcRowsOrColsSizes(true, refWidth); FlowSizeSpec rowSpecs = calcRowsOrColsSizes(false, refHeight); colFlowSpecs = colSpecs; rowFlowSpecs = rowSpecs; width = getMinPrefMaxSumSize(true, colSpecs.sizes); height = getMinPrefMaxSumSize(false, rowSpecs.sizes); if (linkTargetIDs == null) { resetLinkValues(false, true); } else { // This call makes some components flicker on SWT. They get their bounds changed twice since // the change might affect the absolute size adjustment below. There's no way around this that // I know of. layout(new int[]{0, 0, refWidth, refHeight}, null, null, false); resetLinkValues(false, false); } adjustSizeForAbsolute(true); adjustSizeForAbsolute(false); } private UnitValue[] getPos(ComponentWrapper cw, CC cc) { UnitValue[] callbackPos = null; if (callbackList != null) { for (int i = 0; i < callbackList.size() && callbackPos == null; i++) callbackPos = callbackList.get(i).getPosition(cw); // NOT a copy! } // If one is null, return the other (which many also be null) UnitValue[] ccPos = cc.getPos(); // A copy!! if (callbackPos == null || ccPos == null) return callbackPos != null ? callbackPos : ccPos; // Merge for (int i = 0; i < 4; i++) { UnitValue cbUv = callbackPos[i]; if (cbUv != null) ccPos[i] = cbUv; } return ccPos; } private BoundSize[] getCallbackSize(ComponentWrapper cw) { if (callbackList != null) { for (LayoutCallback callback : callbackList) { BoundSize[] bs = callback.getSize(cw); // NOT a copy! if (bs != null) return bs; } } return null; } private static int getDockInsets(TreeSet set) { int c = 0; for (Integer i : set) { if (i < -MAX_GRID) { c++; } else { break; // Since they are sorted we can break } } return c; } /** * @param cw Never null. * @param cc Never null. * @param external The bounds should be stored even if they are not in {@link #linkTargetIDs}. * @return If a change has been made. */ private boolean setLinkedBounds(ComponentWrapper cw, CC cc, int x, int y, int w, int h, boolean external) { String id = cc.getId() != null ? cc.getId() : cw.getLinkId(); if (id == null) return false; String gid = null; int grIx = id.indexOf('.'); if (grIx != -1 ) { gid = id.substring(0, grIx); id = id.substring(grIx + 1); } Object lay = container.getLayout(); boolean changed = false; if (external || (linkTargetIDs != null && linkTargetIDs.containsKey(id))) changed = LinkHandler.setBounds(lay, id, x, y, w, h, !external, false); if (gid != null && (external || (linkTargetIDs != null && linkTargetIDs.containsKey(gid)))) { if (linkTargetIDs == null) linkTargetIDs = new HashMap(4); linkTargetIDs.put(gid, Boolean.TRUE); changed |= LinkHandler.setBounds(lay, gid, x, y, w, h, !external, true); } return changed; } /** Go to next cell. * @param p The point to increase * @param cnt How many cells to advance. * @return The new value in the "increasing" dimension. */ private int increase(int[] p, int cnt) { return lc.isFlowX() ? (p[0] += cnt) : (p[1] += cnt); } /** Wraps to the next row or column depending on if horizontal flow or vertical flow is used. * @param cellXY The point to wrap and thus set either x or y to 0 and increase the other one. * @param gapSize The gaps size specified in a "wrap XXX" or "newline XXX" or null if none. */ private void wrap(int[] cellXY, BoundSize gapSize) { boolean flowx = lc.isFlowX(); cellXY[0] = flowx ? 0 : cellXY[0] + 1; cellXY[1] = flowx ? cellXY[1] + 1 : 0; if (gapSize != null) { if (wrapGapMap == null) wrapGapMap = new HashMap(8); wrapGapMap.put(cellXY[flowx ? 1 : 0], gapSize); } // add the row/column so that the gap in the last row/col will not be removed. if (flowx) { rowIndexes.add(cellXY[1]); } else { colIndexes.add(cellXY[0]); } } /** Sort components (normally buttons in a button bar) so they appear in the correct order. * @param cells The cells to sort. * @param parent The parent. */ private static void sortCellsByPlatform(Collection cells, ContainerWrapper parent) { String order = PlatformDefaults.getButtonOrder(); String orderLo = order.toLowerCase(); int unrelSize = PlatformDefaults.convertToPixels(1, "u", true, 0, parent, null); if (unrelSize == UnitConverter.UNABLE) throw new IllegalArgumentException("'unrelated' not recognized by PlatformDefaults!"); int[] gapUnrel = new int[] {unrelSize, unrelSize, LayoutUtil.NOT_SET}; int[] flGap = new int[] {0, 0, LayoutUtil.NOT_SET}; for (Cell cell : cells) { if (cell.hasTagged == false) continue; CompWrap prevCW = null; boolean nextUnrel = false; boolean nextPush = false; ArrayList sortedList = new ArrayList(cell.compWraps.size()); for (int i = 0, iSz = orderLo.length(); i < iSz; i++) { char c = orderLo.charAt(i); if (c == '+' || c == '_') { nextUnrel = true; if (c == '+') nextPush = true; } else { String tag = PlatformDefaults.getTagForChar(c); if (tag != null) { for (int j = 0, jSz = cell.compWraps.size(); j < jSz; j++) { CompWrap cw = cell.compWraps.get(j); if (tag.equals(cw.cc.getTag())) { if (Character.isUpperCase(order.charAt(i))) cw.adjustMinHorSizeUp((int) PlatformDefaults.getMinimumButtonWidthIncludingPadding(0, parent, cw.comp)); sortedList.add(cw); if (nextUnrel) { (prevCW != null ? prevCW : cw).mergeGapSizes(gapUnrel, cell.flowx, prevCW == null); if (nextPush) { cw.forcedPushGaps = 1; nextUnrel = false; nextPush = false; } } // "unknown" components will always get an Unrelated gap. if (c == 'u') nextUnrel = true; prevCW = cw; } } } } } // If we have a gap that was supposed to push but no more components was found to but the "gap before" then compensate. if (sortedList.size() > 0) { CompWrap cw = sortedList.get(sortedList.size() - 1); if (nextUnrel) { cw.mergeGapSizes(gapUnrel, cell.flowx, false); if (nextPush) cw.forcedPushGaps |= 2; } // Remove first and last gap if not set explicitly. if (cw.cc.getHorizontal().getGapAfter() == null) cw.setGaps(flGap, 3); cw = sortedList.get(0); if (cw.cc.getHorizontal().getGapBefore() == null) cw.setGaps(flGap, 1); } // Exchange the unsorted CompWraps for the sorted one. if (cell.compWraps.size() == sortedList.size()) { cell.compWraps.clear(); } else { cell.compWraps.removeAll(sortedList); } cell.compWraps.addAll(sortedList); } } private Float[] getDefaultPushWeights(boolean isRows) { ArrayList[] groupLists = isRows ? rowGroupLists : colGroupLists; Float[] pushWeightArr = GROW_100; // Only create specific if any of the components have grow. for (int i = 0, ix = 1; i < groupLists.length; i++, ix += 2) { ArrayList grps = groupLists[i]; Float rowPushWeight = null; for (LinkedDimGroup grp : grps) { for (int c = 0; c < grp._compWraps.size(); c++) { CompWrap cw = grp._compWraps.get(c); int hideMode = cw.comp.isVisible() ? -1 : cw.cc.getHideMode() != -1 ? cw.cc.getHideMode() : lc.getHideMode(); Float pushWeight = hideMode < 2 ? (isRows ? cw.cc.getPushY() : cw.cc.getPushX()) : null; if (rowPushWeight == null || (pushWeight != null && pushWeight.floatValue() > rowPushWeight.floatValue())) rowPushWeight = pushWeight; } } if (rowPushWeight != null) { if (pushWeightArr == GROW_100) pushWeightArr = new Float[(groupLists.length << 1) + 1]; pushWeightArr[ix] = rowPushWeight; } } return pushWeightArr; } private void clearGroupLinkBounds() { if (linkTargetIDs == null) return; for (Map.Entry o : linkTargetIDs.entrySet()) { if (o.getValue() == Boolean.TRUE) LinkHandler.clearBounds(container.getLayout(), o.getKey()); } } private void resetLinkValues(boolean parentSize, boolean compLinks) { Object lay = container.getLayout(); if (compLinks) LinkHandler.clearTemporaryBounds(lay); boolean defIns = !hasDocks(); int parW = parentSize ? lc.getWidth().constrain(container.getWidth(), getParentSize(container, true), container) : 0; int parH = parentSize ? lc.getHeight().constrain(container.getHeight(), getParentSize(container, false), container) : 0; int insX = LayoutUtil.getInsets(lc, 0, defIns).getPixels(0, container, null); int insY = LayoutUtil.getInsets(lc, 1, defIns).getPixels(0, container, null); int visW = parW - insX - LayoutUtil.getInsets(lc, 2, defIns).getPixels(0, container, null); int visH = parH - insY - LayoutUtil.getInsets(lc, 3, defIns).getPixels(0, container, null); LinkHandler.setBounds(lay, "visual", insX, insY, visW, visH, true, false); LinkHandler.setBounds(lay, "container", 0, 0, parW, parH, true, false); } /** Returns the {@link net.miginfocom.layout.Grid.LinkedDimGroup} that has the {@link net.miginfocom.layout.Grid.CompWrap} * cw. * @param groupLists The lists to search in. * @param cw The component wrap to find. * @return The linked group or null if none had the component wrap. */ private static LinkedDimGroup getGroupContaining(ArrayList[] groupLists, CompWrap cw) { for (ArrayList groups : groupLists) { for (int j = 0, jSz = groups.size(); j < jSz; j++) { ArrayList cwList = groups.get(j)._compWraps; for (int k = 0, kSz = cwList.size(); k < kSz; k++) { if (cwList.get(k) == cw) return groups.get(j); } } } return null; } private boolean doAbsoluteCorrections(CompWrap cw, int[] bounds) { boolean changed = false; int[] stSz = getAbsoluteDimBounds(cw, bounds[2], true); if (stSz != null) cw.setDimBounds(stSz[0], stSz[1], true); stSz = getAbsoluteDimBounds(cw, bounds[3], false); if (stSz != null) cw.setDimBounds(stSz[0], stSz[1], false); // If there is a link id, store the new bounds. if (linkTargetIDs != null) changed = setLinkedBounds(cw.comp, cw.cc, cw.x, cw.y, cw.w, cw.h, false); return changed; } /** Adjust grid's width or height for the absolute components' positions. */ private void adjustSizeForAbsolute(boolean isHor) { int[] curSizes = isHor ? width : height; Cell absCell = grid.get(null); if (absCell == null || absCell.compWraps.size() == 0) return; ArrayList cws = absCell.compWraps; int maxEnd = 0; for (int j = 0, cwSz = absCell.compWraps.size(); j < cwSz + 3; j++) { // "Do Again" max absCell.compWraps.size() + 3 times. boolean doAgain = false; for (int i = 0; i < cwSz; i++) { CompWrap cw = cws.get(i); int[] stSz = getAbsoluteDimBounds(cw, 0, isHor); int end = stSz[0] + stSz[1]; if (maxEnd < end) maxEnd = end; // If there is a link id, store the new bounds. if (linkTargetIDs != null) doAgain |= setLinkedBounds(cw.comp, cw.cc, stSz[0], stSz[0], stSz[1], stSz[1], false); } if (doAgain == false) break; // We need to check this again since the coords may be smaller this round. maxEnd = 0; clearGroupLinkBounds(); } maxEnd += LayoutUtil.getInsets(lc, isHor ? 3 : 2, !hasDocks()).getPixels(0, container, null); if (curSizes[LayoutUtil.MIN] < maxEnd) curSizes[LayoutUtil.MIN] = maxEnd; if (curSizes[LayoutUtil.PREF] < maxEnd) curSizes[LayoutUtil.PREF] = maxEnd; } private int[] getAbsoluteDimBounds(CompWrap cw, int refSize, boolean isHor) { if (cw.cc.isExternal()) { if (isHor) { return new int[] {cw.comp.getX(), cw.comp.getWidth()}; } else { return new int[] {cw.comp.getY(), cw.comp.getHeight()}; } } UnitValue[] pad = cw.cc.getPadding(); // If no changes do not create a lot of objects UnitValue[] pos = getPos(cw.comp, cw.cc); if (pos == null && pad == null) return null; // Set start int st = isHor ? cw.x : cw.y; int sz = isHor ? cw.w : cw.h; // If absolute, use those coordinates instead. if (pos != null) { UnitValue stUV = pos != null ? pos[isHor ? 0 : 1] : null; UnitValue endUV = pos != null ? pos[isHor ? 2 : 3] : null; int minSz = cw.getSize(LayoutUtil.MIN, isHor); int maxSz = cw.getSize(LayoutUtil.MAX, isHor); sz = Math.min(Math.max(cw.getSize(LayoutUtil.PREF, isHor), minSz), maxSz); if (stUV != null) { st = stUV.getPixels(stUV.getUnit() == UnitValue.ALIGN ? sz : refSize, container, cw.comp); if (endUV != null) // if (endUV == null && cw.cc.isBoundsIsGrid() == true) sz = Math.min(Math.max((isHor ? (cw.x + cw.w) : (cw.y + cw.h)) - st, minSz), maxSz); } if (endUV != null) { if (stUV != null) { // if (stUV != null || cw.cc.isBoundsIsGrid()) { sz = Math.min(Math.max(endUV.getPixels(refSize, container, cw.comp) - st, minSz), maxSz); } else { st = endUV.getPixels(refSize, container, cw.comp) - sz; } } } // If constraint has padding -> correct the start/size if (pad != null) { UnitValue uv = pad[isHor ? 1 : 0]; int p = uv != null ? uv.getPixels(refSize, container, cw.comp) : 0; st += p; uv = pad[isHor ? 3 : 2]; sz += -p + (uv != null ? uv.getPixels(refSize, container, cw.comp) : 0); } return new int[] {st, sz}; } private void layoutInOneDim(int refSize, UnitValue align, boolean isRows, Float[] defaultPushWeights) { boolean fromEnd = !(isRows ? lc.isTopToBottom() : LayoutUtil.isLeftToRight(lc, container)); DimConstraint[] primDCs = (isRows ? rowConstr : colConstr).getConstaints(); FlowSizeSpec fss = isRows ? rowFlowSpecs : colFlowSpecs; ArrayList[] rowCols = isRows ? rowGroupLists : colGroupLists; int[] rowColSizes = LayoutUtil.calculateSerial(fss.sizes, fss.resConstsInclGaps, defaultPushWeights, LayoutUtil.PREF, refSize); if (LayoutUtil.isDesignTime(container)) { TreeSet indexes = isRows ? rowIndexes : colIndexes; int[] ixArr = new int[indexes.size()]; int ix = 0; for (Integer i : indexes) ixArr[ix++] = i; putSizesAndIndexes(container.getComponent(), rowColSizes, ixArr, isRows); } int curPos = align != null ? align.getPixels(refSize - LayoutUtil.sum(rowColSizes), container, null) : 0; if (fromEnd) curPos = refSize - curPos; for (int i = 0 ; i < rowCols.length; i++) { ArrayList linkedGroups = rowCols[i]; int scIx = i - (isRows ? dockOffY : dockOffX); int bIx = i << 1; int bIx2 = bIx + 1; curPos += (fromEnd ? -rowColSizes[bIx] : rowColSizes[bIx]); DimConstraint primDC = scIx >= 0 ? primDCs[scIx >= primDCs.length ? primDCs.length - 1 : scIx] : DOCK_DIM_CONSTRAINT; int rowSize = rowColSizes[bIx2]; for (LinkedDimGroup group : linkedGroups) { int groupSize = rowSize; if (group.span > 1) groupSize = LayoutUtil.sum(rowColSizes, bIx2, Math.min((group.span << 1) - 1, rowColSizes.length - bIx2 - 1)); group.layout(primDC, curPos, groupSize, group.span); } curPos += (fromEnd ? -rowSize : rowSize); } } private static void addToSizeGroup(HashMap sizeGroups, String sizeGroup, int[] size) { int[] sgSize = sizeGroups.get(sizeGroup); if (sgSize == null) { sizeGroups.put(sizeGroup, new int[] {size[LayoutUtil.MIN], size[LayoutUtil.PREF], size[LayoutUtil.MAX]}); } else { sgSize[LayoutUtil.MIN] = Math.max(size[LayoutUtil.MIN], sgSize[LayoutUtil.MIN]); sgSize[LayoutUtil.PREF] = Math.max(size[LayoutUtil.PREF], sgSize[LayoutUtil.PREF]); sgSize[LayoutUtil.MAX] = Math.min(size[LayoutUtil.MAX], sgSize[LayoutUtil.MAX]); } } private static HashMap addToEndGroup(HashMap endGroups, String endGroup, int end) { if (endGroup != null) { if (endGroups == null) endGroups = new HashMap(4); Integer oldEnd = endGroups.get(endGroup); if (oldEnd == null || end > oldEnd) endGroups.put(endGroup, end); } return endGroups; } /** Calculates Min, Preferred and Max size for the columns OR rows. * @param isHor If it is the horizontal dimension to calculate. * @param containerSize The reference container size in the dimension. If <= 0 it will be replaced by the actual container's size. * @return The sizes in a {@link net.miginfocom.layout.Grid.FlowSizeSpec}. */ private FlowSizeSpec calcRowsOrColsSizes(boolean isHor, int containerSize) { ArrayList[] groupsLists = isHor ? colGroupLists : rowGroupLists; Float[] defPush = isHor ? pushXs : pushYs; if (containerSize <= 0) containerSize = isHor ? container.getWidth() : container.getHeight(); BoundSize cSz = isHor ? lc.getWidth() : lc.getHeight(); if (!cSz.isUnset()) containerSize = cSz.constrain(containerSize, getParentSize(container, isHor), container); DimConstraint[] primDCs = (isHor? colConstr : rowConstr).getConstaints(); TreeSet primIndexes = isHor ? colIndexes : rowIndexes; int[][] rowColBoundSizes = new int[primIndexes.size()][]; HashMap sizeGroupMap = new HashMap(4); DimConstraint[] allDCs = new DimConstraint[primIndexes.size()]; Iterator primIt = primIndexes.iterator(); for (int r = 0; r < rowColBoundSizes.length; r++) { int cellIx = primIt.next(); int[] rowColSizes = new int[3]; if (cellIx >= -MAX_GRID && cellIx <= MAX_GRID) { // If not dock cell allDCs[r] = primDCs[cellIx >= primDCs.length ? primDCs.length - 1 : cellIx]; } else { allDCs[r] = DOCK_DIM_CONSTRAINT; } ArrayList groups = groupsLists[r]; int[] groupSizes = new int[] { getTotalGroupsSizeParallel(groups, LayoutUtil.MIN, false), getTotalGroupsSizeParallel(groups, LayoutUtil.PREF, false), LayoutUtil.INF}; correctMinMax(groupSizes); BoundSize dimSize = allDCs[r].getSize(); for (int sType = LayoutUtil.MIN; sType <= LayoutUtil.MAX; sType++) { int rowColSize = groupSizes[sType]; UnitValue uv = dimSize.getSize(sType); if (uv != null) { // If the size of the column is a link to some other size, use that instead int unit = uv.getUnit(); if (unit == UnitValue.PREF_SIZE) { rowColSize = groupSizes[LayoutUtil.PREF]; } else if (unit == UnitValue.MIN_SIZE) { rowColSize = groupSizes[LayoutUtil.MIN]; } else if (unit == UnitValue.MAX_SIZE) { rowColSize = groupSizes[LayoutUtil.MAX]; } else { rowColSize = uv.getPixels(containerSize, container, null); } } else if (cellIx >= -MAX_GRID && cellIx <= MAX_GRID && rowColSize == 0) { rowColSize = LayoutUtil.isDesignTime(container) ? LayoutUtil.getDesignTimeEmptySize() : 0; // Empty rows with no size set gets XX pixels if design time } rowColSizes[sType] = rowColSize; } correctMinMax(rowColSizes); addToSizeGroup(sizeGroupMap, allDCs[r].getSizeGroup(), rowColSizes); rowColBoundSizes[r] = rowColSizes; } // Set/equalize the size groups to same the values. if (sizeGroupMap.size() > 0) { for (int r = 0; r < rowColBoundSizes.length; r++) { if (allDCs[r].getSizeGroup() != null) rowColBoundSizes[r] = sizeGroupMap.get(allDCs[r].getSizeGroup()); } } // Add the gaps ResizeConstraint[] resConstrs = getRowResizeConstraints(allDCs); boolean[] fillInPushGaps = new boolean[allDCs.length + 1]; int[][] gapSizes = getRowGaps(allDCs, containerSize, isHor, fillInPushGaps); FlowSizeSpec fss = mergeSizesGapsAndResConstrs(resConstrs, fillInPushGaps, rowColBoundSizes, gapSizes); // Spanning components are not handled yet. Check and adjust the multi-row min/pref they enforce. adjustMinPrefForSpanningComps(allDCs, defPush, fss, groupsLists); return fss; } private static int getParentSize(ComponentWrapper cw, boolean isHor) { ContainerWrapper p = cw.getParent(); return p != null ? (isHor ? cw.getWidth() : cw.getHeight()) : 0; } private int[] getMinPrefMaxSumSize(boolean isHor, int[][] sizes) { int[] retSizes = new int[3]; BoundSize sz = isHor ? lc.getWidth() : lc.getHeight(); for (int i = 0; i < sizes.length; i++) { if (sizes[i] != null) { int[] size = sizes[i]; for (int sType = LayoutUtil.MIN; sType <= LayoutUtil.MAX; sType++) { if (sz.getSize(sType) != null) { if (i == 0) retSizes[sType] = sz.getSize(sType).getPixels(getParentSize(container, isHor), container, null); } else { int s = size[sType]; if (s != LayoutUtil.NOT_SET) { if (sType == LayoutUtil.PREF) { int bnd = size[LayoutUtil.MAX]; if (bnd != LayoutUtil.NOT_SET && bnd < s) s = bnd; bnd = size[LayoutUtil.MIN]; if (bnd > s) // Includes s == LayoutUtil.NOT_SET since < 0. s = bnd; } retSizes[sType] += s; // MAX compensated below. } // So that MAX is always correct. if (size[LayoutUtil.MAX] == LayoutUtil.NOT_SET || retSizes[LayoutUtil.MAX] > LayoutUtil.INF) retSizes[LayoutUtil.MAX] = LayoutUtil.INF; } } } } correctMinMax(retSizes); return retSizes; } private static ResizeConstraint[] getRowResizeConstraints(DimConstraint[] specs) { ResizeConstraint[] resConsts = new ResizeConstraint[specs.length]; for (int i = 0; i < resConsts.length; i++) resConsts[i] = specs[i].resize; return resConsts; } private static ResizeConstraint[] getComponentResizeConstraints(ArrayList compWraps, boolean isHor) { ResizeConstraint[] resConsts = new ResizeConstraint[compWraps.size()]; for (int i = 0; i < resConsts.length; i++) { CC fc = compWraps.get(i).cc; resConsts[i] = fc.getDimConstraint(isHor).resize; // Always grow docking components in the correct dimension. int dock = fc.getDockSide(); if (isHor ? (dock == 0 || dock == 2) : (dock == 1 || dock == 3)) { ResizeConstraint dc = resConsts[i]; resConsts[i] = new ResizeConstraint(dc.shrinkPrio, dc.shrink, dc.growPrio, ResizeConstraint.WEIGHT_100); } } return resConsts; } private static boolean[] getComponentGapPush(ArrayList compWraps, boolean isHor) { // Make one element bigger and or the after gap with the next before gap. boolean[] barr = new boolean[compWraps.size() + 1]; for (int i = 0; i < barr.length; i++) { boolean push = i > 0 && compWraps.get(i - 1).isPushGap(isHor, false); if (push == false && i < (barr.length - 1)) push = compWraps.get(i).isPushGap(isHor, true); barr[i] = push; } return barr; } /** Returns the row gaps in pixel sizes. One more than there are specs sent in. * @param specs * @param refSize * @param isHor * @param fillInPushGaps If the gaps are pushing. NOTE! this argument will be filled in and thus changed! * @return The row gaps in pixel sizes. One more than there are specs sent in. */ private int[][] getRowGaps(DimConstraint[] specs, int refSize, boolean isHor, boolean[] fillInPushGaps) { BoundSize defGap = isHor ? lc.getGridGapX() : lc.getGridGapY(); if (defGap == null) defGap = isHor ? PlatformDefaults.getGridGapX() : PlatformDefaults.getGridGapY(); int[] defGapArr = defGap.getPixelSizes(refSize, container, null); boolean defIns = !hasDocks(); UnitValue firstGap = LayoutUtil.getInsets(lc, isHor ? 1 : 0, defIns); UnitValue lastGap = LayoutUtil.getInsets(lc, isHor ? 3 : 2, defIns); int[][] retValues = new int[specs.length + 1][]; for (int i = 0, wgIx = 0; i < retValues.length; i++) { DimConstraint specBefore = i > 0 ? specs[i - 1] : null; DimConstraint specAfter = i < specs.length ? specs[i] : null; // No gap if between docking components. boolean edgeBefore = (specBefore == DOCK_DIM_CONSTRAINT || specBefore == null); boolean edgeAfter = (specAfter == DOCK_DIM_CONSTRAINT || specAfter == null); if (edgeBefore && edgeAfter) continue; BoundSize wrapGapSize = (wrapGapMap == null || isHor == lc.isFlowX() ? null : wrapGapMap.get(Integer.valueOf(wgIx++))); if (wrapGapSize == null) { int[] gapBefore = specBefore != null ? specBefore.getRowGaps(container, null, refSize, false) : null; int[] gapAfter = specAfter != null ? specAfter.getRowGaps(container, null, refSize, true) : null; if (edgeBefore && gapAfter == null && firstGap != null) { int bef = firstGap.getPixels(refSize, container, null); retValues[i] = new int[] {bef, bef, bef}; } else if (edgeAfter && gapBefore == null && firstGap != null) { int aft = lastGap.getPixels(refSize, container, null); retValues[i] = new int[] {aft, aft, aft}; } else { retValues[i] = gapAfter != gapBefore ? mergeSizes(gapAfter, gapBefore) : new int[] {defGapArr[0], defGapArr[1], defGapArr[2]}; } if (specBefore != null && specBefore.isGapAfterPush() || specAfter != null && specAfter.isGapBeforePush()) fillInPushGaps[i] = true; } else { if (wrapGapSize.isUnset()) { retValues[i] = new int[] {defGapArr[0], defGapArr[1], defGapArr[2]}; } else { retValues[i] = wrapGapSize.getPixelSizes(refSize, container, null); } fillInPushGaps[i] = wrapGapSize.getGapPush(); } } return retValues; } private static int[][] getGaps(ArrayList compWraps, boolean isHor) { int compCount = compWraps.size(); int[][] retValues = new int[compCount + 1][]; retValues[0] = compWraps.get(0).getGaps(isHor, true); for (int i = 0; i < compCount; i++) { int[] gap1 = compWraps.get(i).getGaps(isHor, false); int[] gap2 = i < compCount - 1 ? compWraps.get(i + 1).getGaps(isHor, true) : null; retValues[i + 1] = mergeSizes(gap1, gap2); } return retValues; } private boolean hasDocks() { return (dockOffX > 0 || dockOffY > 0 || rowIndexes.last() > MAX_GRID || colIndexes.last() > MAX_GRID); } /** Adjust min/pref size for columns(or rows) that has components that spans multiple columns (or rows). * @param specs The specs for the columns or rows. Last index will be used if count is greater than this array's length. * @param defPush The default grow weight if the specs does not have anyone that will grow. Comes from "push" in the CC. * @param fss * @param groupsLists */ private void adjustMinPrefForSpanningComps(DimConstraint[] specs, Float[] defPush, FlowSizeSpec fss, ArrayList[] groupsLists) { for (int r = groupsLists.length - 1; r >= 0; r--) { // Since 3.7.3 Iterate from end to start. Will solve some multiple spanning components hard to solve problems. ArrayList groups = groupsLists[r]; for (LinkedDimGroup group : groups) { if (group.span == 1) continue; int[] sizes = group.getMinPrefMax(); for (int s = LayoutUtil.MIN; s <= LayoutUtil.PREF; s++) { int cSize = sizes[s]; if (cSize == LayoutUtil.NOT_SET) continue; int rowSize = 0; int sIx = (r << 1) + 1; int len = Math.min((group.span << 1), fss.sizes.length - sIx) - 1; for (int j = sIx; j < sIx + len; j++) { int sz = fss.sizes[j][s]; if (sz != LayoutUtil.NOT_SET) rowSize += sz; } if (rowSize < cSize && len > 0) { for (int eagerness = 0, newRowSize = 0; eagerness < 4 && newRowSize < cSize; eagerness++) newRowSize = fss.expandSizes(specs, defPush, cSize, sIx, len, s, eagerness); } } } } } /** For one dimension divide the component wraps into logical groups. One group for component wraps that share a common something, * line the property to layout by base line. * @param isRows If rows, and not columns, are to be divided. * @return One ArrayList for every row/column. */ private ArrayList[] divideIntoLinkedGroups(boolean isRows) { boolean fromEnd = !(isRows ? lc.isTopToBottom() : LayoutUtil.isLeftToRight(lc, container)); TreeSet primIndexes = isRows ? rowIndexes : colIndexes; TreeSet secIndexes = isRows ? colIndexes : rowIndexes; DimConstraint[] primDCs = (isRows ? rowConstr : colConstr).getConstaints(); @SuppressWarnings("unchecked") ArrayList[] groupLists = new ArrayList[primIndexes.size()]; int gIx = 0; for (int i : primIndexes) { DimConstraint dc; if (i >= -MAX_GRID && i <= MAX_GRID) { // If not dock cell dc = primDCs[i >= primDCs.length ? primDCs.length - 1 : i]; } else { dc = DOCK_DIM_CONSTRAINT; } ArrayList groupList = new ArrayList(4); groupLists[gIx++] = groupList; for (Integer ix : secIndexes) { Cell cell = isRows ? getCell(i, ix) : getCell(ix, i); if (cell == null || cell.compWraps.size() == 0) continue; int span = (isRows ? cell.spany : cell.spanx); if (span > 1) span = convertSpanToSparseGrid(i, span, primIndexes); boolean isPar = (cell.flowx == isRows); if ((isPar == false && cell.compWraps.size() > 1) || span > 1) { int linkType = isPar ? LinkedDimGroup.TYPE_PARALLEL : LinkedDimGroup.TYPE_SERIAL; LinkedDimGroup lg = new LinkedDimGroup("p," + ix, span, linkType, !isRows, fromEnd); lg.setCompWraps(cell.compWraps); groupList.add(lg); } else { for (int cwIx = 0; cwIx < cell.compWraps.size(); cwIx++) { CompWrap cw = cell.compWraps.get(cwIx); boolean rowBaselineAlign = (isRows && lc.isTopToBottom() && dc.getAlignOrDefault(!isRows) == UnitValue.BASELINE_IDENTITY); // Disable baseline for bottomToTop since I can not verify it working. boolean isBaseline = isRows && cw.isBaselineAlign(rowBaselineAlign); String linkCtx = isBaseline ? "baseline" : null; // Find a group with same link context and put it in that group. boolean foundList = false; for (int glIx = 0, lastGl = groupList.size() - 1; glIx <= lastGl; glIx++) { LinkedDimGroup group = groupList.get(glIx); if (group.linkCtx == linkCtx || linkCtx != null && linkCtx.equals(group.linkCtx)) { group.addCompWrap(cw); foundList = true; break; } } // If none found and at last add a new group. if (foundList == false) { int linkType = isBaseline ? LinkedDimGroup.TYPE_BASELINE : LinkedDimGroup.TYPE_PARALLEL; LinkedDimGroup lg = new LinkedDimGroup(linkCtx, 1, linkType, !isRows, fromEnd); lg.addCompWrap(cw); groupList.add(lg); } } } } } return groupLists; } /** Spanning is specified in the uncompressed grid number. They can for instance be more than 60000 for the outer * edge dock grid cells. When the grid is compressed and indexed after only the cells that area occupied the span * is erratic. This method use the row/col indexes and corrects the span to be correct for the compressed grid. * @param span The span in the uncompressed grid. LayoutUtil.INF will be interpreted to span the rest * of the column/row excluding the surrounding docking components. * @param indexes The indexes in the correct dimension. * @return The converted span. */ private static int convertSpanToSparseGrid(int curIx, int span, TreeSet indexes) { int lastIx = curIx + span; int retSpan = 1; for (Integer ix : indexes) { if (ix <= curIx) continue; // We have not arrived to the correct index yet if (ix >= lastIx) break; retSpan++; } return retSpan; } private boolean isCellFree(int r, int c, ArrayList occupiedRects) { if (getCell(r, c) != null) return false; for (int[] rect : occupiedRects) { if (rect[0] <= c && rect[1] <= r && rect[0] + rect[2] > c && rect[1] + rect[3] > r) return false; } return true; } private Cell getCell(int r, int c) { return grid.get(Integer.valueOf((r << 16) + (c & 0xffff))); } private void setCell(int r, int c, Cell cell) { if (c < 0 || r < 0) throw new IllegalArgumentException("Cell position cannot be negative. row: " + r + ", col: " + c); if (c > MAX_GRID || r > MAX_GRID) throw new IllegalArgumentException("Cell position out of bounds. Out of cells. row: " + r + ", col: " + c); rowIndexes.add(r); colIndexes.add(c); grid.put((r << 16) + (c & 0xffff), cell); } /** Adds a docking cell. That cell is outside the normal cell indexes. * @param dockInsets The current dock insets. Will be updated! * @param side top == 0, left == 1, bottom = 2, right = 3. * @param cw The compwrap to put in a cell and add. */ private void addDockingCell(int[] dockInsets, int side, CompWrap cw) { int r, c, spanx = 1, spany = 1; switch (side) { case 0: case 2: r = side == 0 ? dockInsets[0]++ : dockInsets[2]--; c = dockInsets[1]; spanx = dockInsets[3] - dockInsets[1] + 1; // The +1 is for cell 0. colIndexes.add(dockInsets[3]); // Make sure there is a receiving cell break; case 1: case 3: c = side == 1 ? dockInsets[1]++ : dockInsets[3]--; r = dockInsets[0]; spany = dockInsets[2] - dockInsets[0] + 1; // The +1 is for cell 0. rowIndexes.add(dockInsets[2]); // Make sure there is a receiving cell break; default: throw new IllegalArgumentException("Internal error 123."); } rowIndexes.add(r); colIndexes.add(c); grid.put((r << 16) + (c & 0xffff), new Cell(cw, spanx, spany, spanx > 1)); } /** A simple representation of a cell in the grid. Contains a number of component wraps, if they span more than one cell. */ private static class Cell { private final int spanx, spany; private final boolean flowx; private final ArrayList compWraps = new ArrayList(2); private boolean hasTagged = false; // If one or more components have styles and need to be checked by the component sorter private Cell(CompWrap cw) { this(cw, 1, 1, true); } private Cell(int spanx, int spany, boolean flowx) { this(null, spanx, spany, flowx); } private Cell(CompWrap cw, int spanx, int spany, boolean flowx) { if (cw != null) compWraps.add(cw); this.spanx = spanx; this.spany = spany; this.flowx = flowx; } } /** A number of component wraps that share a layout "something" in one dimension */ private static class LinkedDimGroup { private static final int TYPE_SERIAL = 0; private static final int TYPE_PARALLEL = 1; private static final int TYPE_BASELINE = 2; private final String linkCtx; private final int span; private final int linkType; private final boolean isHor, fromEnd; private final ArrayList _compWraps = new ArrayList(4); private int lStart = 0, lSize = 0; // Currently mostly for debug painting private LinkedDimGroup(String linkCtx, int span, int linkType, boolean isHor, boolean fromEnd) { this.linkCtx = linkCtx; this.span = span; this.linkType = linkType; this.isHor = isHor; this.fromEnd = fromEnd; } private void addCompWrap(CompWrap cw) { _compWraps.add(cw); } private void setCompWraps(ArrayList cws) { if (_compWraps != cws) { _compWraps.clear(); _compWraps.addAll(cws); } } private void layout(DimConstraint dc, int start, int size, int spanCount) { lStart = start; lSize = size; if (_compWraps.isEmpty()) return; ContainerWrapper parent = _compWraps.get(0).comp.getParent(); if (linkType == TYPE_PARALLEL) { layoutParallel(parent, _compWraps, dc, start, size, isHor, fromEnd); } else if (linkType == TYPE_BASELINE) { layoutBaseline(parent, _compWraps, dc, start, size, LayoutUtil.PREF, spanCount); } else { layoutSerial(parent, _compWraps, dc, start, size, isHor, spanCount, fromEnd); } } /** Returns the min/pref/max sizes for this cell. Returned array must not be altered * @return A shared min/pref/max array of sizes. Always of length 3 and never null. Will always be of type STATIC and PIXEL. */ private int[] getMinPrefMax() { int[] sizes = new int[3]; if (!_compWraps.isEmpty()) { for (int sType = LayoutUtil.MIN; sType <= LayoutUtil.PREF; sType++) { if (linkType == TYPE_PARALLEL) { sizes[sType] = getTotalSizeParallel(_compWraps, sType, isHor); } else if (linkType == TYPE_BASELINE) { int[] aboveBelow = getBaselineAboveBelow(_compWraps, sType, false); sizes[sType] = aboveBelow[0] + aboveBelow[1]; } else { sizes[sType] = getTotalSizeSerial(_compWraps, sType, isHor); } } sizes[LayoutUtil.MAX] = LayoutUtil.INF; } return sizes; } } /** Wraps a {@link java.awt.Component} together with its constraint. Caches a lot of information about the component so * for instance not the preferred size has to be calculated more than once. * * Note! Does not ask the min/pref/max sizes again after the constructor. This means that */ private final class CompWrap { private final ComponentWrapper comp; private final CC cc; private final int eHideMode; private final boolean useVisualPadding; private boolean sizesOk = false; private boolean isAbsolute; private int[][] gaps; // [top,left(actually before),bottom,right(actually after)][min,pref,max] private final int[] horSizes = new int[3]; private final int[] verSizes = new int[3]; private int x = LayoutUtil.NOT_SET, y = LayoutUtil.NOT_SET, w = LayoutUtil.NOT_SET, h = LayoutUtil.NOT_SET; private int forcedPushGaps = 0; // 1 == before, 2 = after. Bitwise. /** * @param c * @param cc * @param eHideMode Effective hide mode. <= 0 means visible. * @param useVisualPadding */ private CompWrap(ComponentWrapper c, CC cc, int eHideMode, boolean useVisualPadding) { this.comp = c; this.cc = cc; this.eHideMode = eHideMode; this.useVisualPadding = useVisualPadding; this.isAbsolute = cc.getHorizontal().getSize().isAbsolute() && cc.getVertical().getSize().isAbsolute(); if (eHideMode > 1) { gaps = new int[4][]; for (int i = 0; i < gaps.length; i++) gaps[i] = new int[3]; } } private int[] getSizes(boolean isHor) { validateSize(); return isHor ? horSizes : verSizes; } private void validateSize() { BoundSize[] callbackSz = getCallbackSize(comp); if (isAbsolute && sizesOk && callbackSz == null) return; if (eHideMode <= 0) { int contentBias = comp.getContentBias(); int sizeHint = contentBias == -1 ? -1 : (contentBias == 0 ? (w != LayoutUtil.NOT_SET ? w : comp.getWidth()) : (h != LayoutUtil.NOT_SET ? h : comp.getHeight())); BoundSize hBS = (callbackSz != null && callbackSz[0] != null) ? callbackSz[0] : cc.getHorizontal().getSize(); BoundSize vBS = (callbackSz != null && callbackSz[1] != null) ? callbackSz[1] : cc.getVertical().getSize(); for (int i = LayoutUtil.MIN; i <= LayoutUtil.MAX; i++) { switch (contentBias) { case -1: // None default: horSizes[i] = getSize(hBS, i, true, useVisualPadding, -1); verSizes[i] = getSize(vBS, i, false, useVisualPadding, -1); break; case 0: // Hor horSizes[i] = getSize(hBS, i, true, useVisualPadding, -1); verSizes[i] = getSize(vBS, i, false, useVisualPadding, sizeHint > 0 ? sizeHint : horSizes[i]); break; case 1: // Ver verSizes[i] = getSize(vBS, i, false, useVisualPadding, -1); horSizes[i] = getSize(hBS, i, true, useVisualPadding, sizeHint > 0 ? sizeHint : verSizes[i]); break; } } correctMinMax(horSizes); correctMinMax(verSizes); } else { Arrays.fill(horSizes, 0); // Needed if component goes from visible -> invisible without recreating the grid. Arrays.fill(verSizes, 0); } sizesOk = true; } private int getSize(BoundSize uvs, int sizeType, boolean isHor, boolean useVP, int sizeHint) { int size; if (uvs == null || uvs.getSize(sizeType) == null) { switch(sizeType) { case LayoutUtil.MIN: size = isHor ? comp.getMinimumWidth(sizeHint) : comp.getMinimumHeight(sizeHint); break; case LayoutUtil.PREF: size = isHor ? comp.getPreferredWidth(sizeHint) : comp.getPreferredHeight(sizeHint); break; default: size = isHor ? comp.getMaximumWidth(sizeHint) : comp.getMaximumHeight(sizeHint); break; } if (useVP) { //Do not include visual padding when calculating layout int[] visualPadding = comp.getVisualPadding(); // Assume visualPadding is of length 4: top, left, bottom, right if (visualPadding != null && visualPadding.length > 0) size -= isHor ? (visualPadding[1] + visualPadding[3]) : (visualPadding[0] + visualPadding[2]); } } else { ContainerWrapper par = comp.getParent(); float refValue = isHor ? par.getWidth() : par.getHeight(); size = uvs.getSize(sizeType).getPixels(refValue, par, comp); } return size; } private void calcGaps(ComponentWrapper before, CC befCC, ComponentWrapper after, CC aftCC, String tag, boolean flowX, boolean isLTR) { ContainerWrapper par = comp.getParent(); int parW = par.getWidth(); int parH = par.getHeight(); BoundSize befGap = before != null ? (flowX ? befCC.getHorizontal() : befCC.getVertical()).getGapAfter() : null; BoundSize aftGap = after != null ? (flowX ? aftCC.getHorizontal() : aftCC.getVertical()).getGapBefore() : null; mergeGapSizes(cc.getVertical().getComponentGaps(par, comp, befGap, (flowX ? null : before), tag, parH, 0, isLTR), false, true); mergeGapSizes(cc.getHorizontal().getComponentGaps(par, comp, befGap, (flowX ? before : null), tag, parW, 1, isLTR), true, true); mergeGapSizes(cc.getVertical().getComponentGaps(par, comp, aftGap, (flowX ? null : after), tag, parH, 2, isLTR), false, false); mergeGapSizes(cc.getHorizontal().getComponentGaps(par, comp, aftGap, (flowX ? after : null), tag, parW, 3, isLTR), true, false); } private void setDimBounds(int start, int size, boolean isHor) { if (isHor) { if (start != x || w != size) { x = start; w = size; if (comp.getContentBias() == LayoutUtil.HORIZONTAL) invalidateSizes(); // Only for components that have a bias the sizes will have changed. } } else { if (start != y || h != size) { y = start; h = size; if (comp.getContentBias() == LayoutUtil.VERTICAL) invalidateSizes(); // Only for components that have a bias the sizes will have changed. } } } void invalidateSizes() { sizesOk = false; } private boolean isPushGap(boolean isHor, boolean isBefore) { if (isHor && ((isBefore ? 1 : 2) & forcedPushGaps) != 0) return true; // Forced DimConstraint dc = cc.getDimConstraint(isHor); BoundSize s = isBefore ? dc.getGapBefore() : dc.getGapAfter(); return s != null && s.getGapPush(); } /** Transfers the bounds to the component */ private void transferBounds(boolean addVisualPadding) { if (cc.isExternal()) return; int compX = x; int compY = y; int compW = w; int compH = h; if (addVisualPadding) { //Add the visual padding back to the component when changing its size int[] visualPadding = comp.getVisualPadding(); if (visualPadding != null) { //assume visualPadding is of length 4: top, left, bottom, right compX -= visualPadding[1]; compY -= visualPadding[0]; compW += (visualPadding[1] + visualPadding[3]); compH += (visualPadding[0] + visualPadding[2]); } } comp.setBounds(compX, compY, compW, compH); } private void setForcedSizes(int[] sizes, boolean isHor) { if (sizes == null) return; System.arraycopy(sizes, 0, getSizes(isHor), 0, 3); sizesOk = true; } private void setGaps(int[] minPrefMax, int ix) { if (gaps == null) gaps = new int[][] {null, null, null, null}; gaps[ix] = minPrefMax; } private void mergeGapSizes(int[] sizes, boolean isHor, boolean isTL) { if (gaps == null) gaps = new int[][] {null, null, null, null}; if (sizes == null) return; int gapIX = getGapIx(isHor, isTL); int[] oldGaps = gaps[gapIX]; if (oldGaps == null) { oldGaps = new int[] {0, 0, LayoutUtil.INF}; gaps[gapIX] = oldGaps; } oldGaps[LayoutUtil.MIN] = Math.max(sizes[LayoutUtil.MIN], oldGaps[LayoutUtil.MIN]); oldGaps[LayoutUtil.PREF] = Math.max(sizes[LayoutUtil.PREF], oldGaps[LayoutUtil.PREF]); oldGaps[LayoutUtil.MAX] = Math.min(sizes[LayoutUtil.MAX], oldGaps[LayoutUtil.MAX]); } private int getGapIx(boolean isHor, boolean isTL) { return isHor ? (isTL ? 1 : 3) : (isTL ? 0 : 2); } private int getSizeInclGaps(int sizeType, boolean isHor) { return filter(sizeType, getGapBefore(sizeType, isHor) + getSize(sizeType, isHor) + getGapAfter(sizeType, isHor)); } private int getSize(int sizeType, boolean isHor) { return filter(sizeType, getSizes(isHor)[sizeType]); } private int getGapBefore(int sizeType, boolean isHor) { int[] gaps = getGaps(isHor, true); return gaps != null ? filter(sizeType, gaps[sizeType]) : 0; } private int getGapAfter(int sizeType, boolean isHor) { int[] gaps = getGaps(isHor, false); return gaps != null ? filter(sizeType, gaps[sizeType]) : 0; } private int[] getGaps(boolean isHor, boolean isTL) { return gaps[getGapIx(isHor, isTL)]; } private int filter(int sizeType, int size) { if (size == LayoutUtil.NOT_SET) return sizeType != LayoutUtil.MAX ? 0 : LayoutUtil.INF; return constrainSize(size); } private boolean isBaselineAlign(boolean defValue) { Float g = cc.getVertical().getGrow(); if (g != null && g.intValue() != 0) return false; UnitValue al = cc.getVertical().getAlign(); return (al != null ? al == UnitValue.BASELINE_IDENTITY : defValue) && comp.hasBaseline(); } private int getBaseline(int sizeType) { return comp.getBaseline(getSize(sizeType, true), getSize(sizeType, false)); } public void adjustMinHorSizeUp(int minSize) { int[] sz = getSizes(true); if (sz[LayoutUtil.MIN] < minSize) sz[LayoutUtil.MIN] = minSize; correctMinMax(sz); } } //*************************************************************************************** //* Helper Methods //*************************************************************************************** private static void layoutBaseline(ContainerWrapper parent, ArrayList compWraps, DimConstraint dc, int start, int size, int sizeType, int spanCount) { int[] aboveBelow = getBaselineAboveBelow(compWraps, sizeType, true); int blRowSize = aboveBelow[0] + aboveBelow[1]; CC cc = compWraps.get(0).cc; // Align for the whole baseline component array UnitValue align = cc.getVertical().getAlign(); if (spanCount == 1 && align == null) align = dc.getAlignOrDefault(false); if (align == UnitValue.BASELINE_IDENTITY) align = UnitValue.CENTER; int offset = start + aboveBelow[0] + (align != null ? Math.max(0, align.getPixels(size - blRowSize, parent, null)) : 0); for (CompWrap cw : compWraps) { cw.y += offset; if (cw.y + cw.h > start + size) cw.h = start + size - cw.y; } } private static void layoutSerial(ContainerWrapper parent, ArrayList compWraps, DimConstraint dc, int start, int size, boolean isHor, int spanCount, boolean fromEnd) { FlowSizeSpec fss = mergeSizesGapsAndResConstrs( getComponentResizeConstraints(compWraps, isHor), getComponentGapPush(compWraps, isHor), getComponentSizes(compWraps, isHor), getGaps(compWraps, isHor)); Float[] pushW = dc.isFill() ? GROW_100 : null; int[] sizes = LayoutUtil.calculateSerial(fss.sizes, fss.resConstsInclGaps, pushW, LayoutUtil.PREF, size); setCompWrapBounds(parent, sizes, compWraps, dc.getAlignOrDefault(isHor), start, size, isHor, fromEnd); } private static void setCompWrapBounds(ContainerWrapper parent, int[] allSizes, ArrayList compWraps, UnitValue rowAlign, int start, int size, boolean isHor, boolean fromEnd) { int totSize = LayoutUtil.sum(allSizes); CC cc = compWraps.get(0).cc; UnitValue align = correctAlign(cc, rowAlign, isHor, fromEnd); int cSt = start; int slack = size - totSize; if (slack > 0 && align != null) { int al = Math.min(slack, Math.max(0, align.getPixels(slack, parent, null))); cSt += (fromEnd ? -al : al); } for (int i = 0, bIx = 0, iSz = compWraps.size(); i < iSz; i++) { CompWrap cw = compWraps.get(i); if (fromEnd ) { cSt -= allSizes[bIx++]; cw.setDimBounds(cSt - allSizes[bIx], allSizes[bIx], isHor); cSt -= allSizes[bIx++]; } else { cSt += allSizes[bIx++]; cw.setDimBounds(cSt, allSizes[bIx], isHor); cSt += allSizes[bIx++]; } } } private static void layoutParallel(ContainerWrapper parent, ArrayList compWraps, DimConstraint dc, int start, int size, boolean isHor, boolean fromEnd) { int[][] sizes = new int[compWraps.size()][]; // [compIx][gapBef,compSize,gapAft] for (int i = 0; i < sizes.length; i++) { CompWrap cw = compWraps.get(i); DimConstraint cDc = cw.cc.getDimConstraint(isHor); ResizeConstraint[] resConstr = new ResizeConstraint[] { cw.isPushGap(isHor, true) ? GAP_RC_CONST_PUSH : GAP_RC_CONST, cDc.resize, cw.isPushGap(isHor, false) ? GAP_RC_CONST_PUSH : GAP_RC_CONST, }; int[][] sz = new int[][] { cw.getGaps(isHor, true), cw.getSizes(isHor), cw.getGaps(isHor, false) }; Float[] pushW = dc.isFill() ? GROW_100 : null; sizes[i] = LayoutUtil.calculateSerial(sz, resConstr, pushW, LayoutUtil.PREF, size); } UnitValue rowAlign = dc.getAlignOrDefault(isHor); setCompWrapBounds(parent, sizes, compWraps, rowAlign, start, size, isHor, fromEnd); } private static void setCompWrapBounds(ContainerWrapper parent, int[][] sizes, ArrayList compWraps, UnitValue rowAlign, int start, int size, boolean isHor, boolean fromEnd) { for (int i = 0; i < sizes.length; i++) { CompWrap cw = compWraps.get(i); UnitValue align = correctAlign(cw.cc, rowAlign, isHor, fromEnd); int[] cSizes = sizes[i]; int gapBef = cSizes[0]; int cSize = cSizes[1]; // No Math.min(size, cSizes[1]) here! int gapAft = cSizes[2]; int cSt = fromEnd ? start - gapBef : start + gapBef; int slack = size - cSize - gapBef - gapAft; if (slack > 0 && align != null) { int al = Math.min(slack, Math.max(0, align.getPixels(slack, parent, null))); cSt += (fromEnd ? -al : al); } cw.setDimBounds(fromEnd ? cSt - cSize : cSt, cSize, isHor); } } private static UnitValue correctAlign(CC cc, UnitValue rowAlign, boolean isHor, boolean fromEnd) { UnitValue align = (isHor ? cc.getHorizontal() : cc.getVertical()).getAlign(); if (align == null) align = rowAlign; if (align == UnitValue.BASELINE_IDENTITY) align = UnitValue.CENTER; if (fromEnd) { if (align == UnitValue.LEFT) align = UnitValue.RIGHT; else if (align == UnitValue.RIGHT) align = UnitValue.LEFT; } return align; } private static int[] getBaselineAboveBelow(ArrayList compWraps, int sType, boolean centerBaseline) { int maxAbove = Integer.MIN_VALUE; int maxBelow = Integer.MIN_VALUE; for (CompWrap cw : compWraps) { int height = cw.getSize(sType, false); if (height >= LayoutUtil.INF) return new int[]{LayoutUtil.INF / 2, LayoutUtil.INF / 2}; int baseline = cw.getBaseline(sType); int above = baseline + cw.getGapBefore(sType, false); maxAbove = Math.max(above, maxAbove); maxBelow = Math.max(height - baseline + cw.getGapAfter(sType, false), maxBelow); if (centerBaseline) cw.setDimBounds(-baseline, height, false); } return new int[] {maxAbove, maxBelow}; } private static int getTotalSizeParallel(ArrayList compWraps, int sType, boolean isHor) { int size = sType == LayoutUtil.MAX ? LayoutUtil.INF : 0; for (CompWrap cw : compWraps) { int cwSize = cw.getSizeInclGaps(sType, isHor); if (cwSize >= LayoutUtil.INF) return LayoutUtil.INF; if (sType == LayoutUtil.MAX ? cwSize < size : cwSize > size) size = cwSize; } return constrainSize(size); } private static int getTotalSizeSerial(ArrayList compWraps, int sType, boolean isHor) { int totSize = 0; for (int i = 0, iSz = compWraps.size(), lastGapAfter = 0; i < iSz; i++) { CompWrap wrap = compWraps.get(i); int gapBef = wrap.getGapBefore(sType, isHor); if (gapBef > lastGapAfter) totSize += gapBef - lastGapAfter; totSize += wrap.getSize(sType, isHor); totSize += (lastGapAfter = wrap.getGapAfter(sType, isHor)); if (totSize >= LayoutUtil.INF) return LayoutUtil.INF; } return constrainSize(totSize); } private static int getTotalGroupsSizeParallel(ArrayList groups, int sType, boolean countSpanning) { int size = sType == LayoutUtil.MAX ? LayoutUtil.INF : 0; for (LinkedDimGroup group : groups) { if (countSpanning || group.span == 1) { int grpSize = group.getMinPrefMax()[sType]; if (grpSize >= LayoutUtil.INF) return LayoutUtil.INF; if (sType == LayoutUtil.MAX ? grpSize < size : grpSize > size) size = grpSize; } } return constrainSize(size); } /** * @param compWraps * @param isHor * @return Might contain LayoutUtil.NOT_SET */ private static int[][] getComponentSizes(ArrayList compWraps, boolean isHor) { int[][] compSizes = new int[compWraps.size()][]; for (int i = 0; i < compSizes.length; i++) compSizes[i] = compWraps.get(i).getSizes(isHor); return compSizes; } /** Merges sizes and gaps together with Resize Constraints. For gaps {@link #GAP_RC_CONST} is used. * @param resConstr One resize constraint for every row/component. Can be lesser in length and the last element should be used for missing elements. * @param gapPush If the corresponding gap should be considered pushing and thus want to take free space if left over. Should be one more than resConstrs! * @param minPrefMaxSizes The sizes (min/pref/max) for every row/component. * @param gapSizes The gaps before and after each row/component packed in one double sized array. * @return A holder for the merged values. */ private static FlowSizeSpec mergeSizesGapsAndResConstrs(ResizeConstraint[] resConstr, boolean[] gapPush, int[][] minPrefMaxSizes, int[][] gapSizes) { int[][] sizes = new int[(minPrefMaxSizes.length << 1) + 1][]; // Make room for gaps around. ResizeConstraint[] resConstsInclGaps = new ResizeConstraint[sizes.length]; sizes[0] = gapSizes[0]; for (int i = 0, crIx = 1; i < minPrefMaxSizes.length; i++, crIx += 2) { // Component bounds and constraints resConstsInclGaps[crIx] = resConstr[i]; sizes[crIx] = minPrefMaxSizes[i]; sizes[crIx + 1] = gapSizes[i + 1]; if (sizes[crIx - 1] != null) resConstsInclGaps[crIx - 1] = gapPush[i < gapPush.length ? i : gapPush.length - 1] ? GAP_RC_CONST_PUSH : GAP_RC_CONST; if (i == (minPrefMaxSizes.length - 1) && sizes[crIx + 1] != null) resConstsInclGaps[crIx + 1] = gapPush[(i + 1) < gapPush.length ? (i + 1) : gapPush.length - 1] ? GAP_RC_CONST_PUSH : GAP_RC_CONST; } // Check for null and set it to 0, 0, 0. for (int i = 0; i < sizes.length; i++) { if (sizes[i] == null) sizes[i] = new int[3]; } return new FlowSizeSpec(sizes, resConstsInclGaps); } private static int[] mergeSizes(int[] oldValues, int[] newValues) { if (oldValues == null) return newValues; if (newValues == null) return oldValues; int[] ret = new int[oldValues.length]; for (int i = 0; i < ret.length; i++) ret[i] = mergeSizes(oldValues[i], newValues[i], true); return ret; } private static int mergeSizes(int oldValue, int newValue, boolean toMax) { if (oldValue == LayoutUtil.NOT_SET || oldValue == newValue) return newValue; if (newValue == LayoutUtil.NOT_SET) return oldValue; return toMax != oldValue > newValue ? newValue : oldValue; } private static int constrainSize(int s) { return s > 0 ? (s < LayoutUtil.INF ? s : LayoutUtil.INF) : 0; } private static void correctMinMax(int s[]) { if (s[LayoutUtil.MIN] > s[LayoutUtil.MAX]) s[LayoutUtil.MIN] = s[LayoutUtil.MAX]; // Since MAX is almost always explicitly set use that if (s[LayoutUtil.PREF] < s[LayoutUtil.MIN]) s[LayoutUtil.PREF] = s[LayoutUtil.MIN]; if (s[LayoutUtil.PREF] > s[LayoutUtil.MAX]) s[LayoutUtil.PREF] = s[LayoutUtil.MAX]; } private static final class FlowSizeSpec { private final int[][] sizes; // [row/col index][min, pref, max] private final ResizeConstraint[] resConstsInclGaps; // [row/col index] private FlowSizeSpec(int[][] sizes, ResizeConstraint[] resConstsInclGaps) { this.sizes = sizes; this.resConstsInclGaps = resConstsInclGaps; } /** * @param specs The specs for the columns or rows. Last index will be used of fromIx + len is greater than this array's length. * @param targetSize The size to try to meet. * @param defGrow The default grow weight if the specs does not have anyone that will grow. Comes from "push" in the CC. * @param fromIx * @param len * @param sizeType * @param eagerness How eager the algorithm should be to try to expand the sizes. *

* @return The new size. */ private int expandSizes(DimConstraint[] specs, Float[] defGrow, int targetSize, int fromIx, int len, int sizeType, int eagerness) { ResizeConstraint[] resConstr = new ResizeConstraint[len]; int[][] sizesToExpand = new int[len][]; for (int i = 0; i < len; i++) { int[] minPrefMax = sizes[i + fromIx]; sizesToExpand[i] = new int[] {minPrefMax[sizeType], minPrefMax[LayoutUtil.PREF], minPrefMax[LayoutUtil.MAX]}; if (eagerness <= 1 && i % 2 == 0) { // (i % 2 == 0) means only odd indexes, which is only rows/col indexes and not gaps. int cIx = (i + fromIx - 1) >> 1; DimConstraint spec = (DimConstraint) LayoutUtil.getIndexSafe(specs, cIx); BoundSize sz = spec.getSize(); if ( (sizeType == LayoutUtil.MIN && sz.getMin() != null && sz.getMin().getUnit() != UnitValue.MIN_SIZE) || (sizeType == LayoutUtil.PREF && sz.getPreferred() != null && sz.getPreferred().getUnit() != UnitValue.PREF_SIZE)) { continue; } } resConstr[i] = (ResizeConstraint) LayoutUtil.getIndexSafe(resConstsInclGaps, i + fromIx); } Float[] growW = (eagerness == 1 || eagerness == 3) ? extractSubArray(specs, defGrow, fromIx, len): null; int[] newSizes = LayoutUtil.calculateSerial(sizesToExpand, resConstr, growW, LayoutUtil.PREF, targetSize); int newSize = 0; for (int i = 0; i < len; i++) { int s = newSizes[i]; sizes[i + fromIx][sizeType] = s; newSize += s; } return newSize; } } private static Float[] extractSubArray(DimConstraint[] specs, Float[] arr, int ix, int len) { if (arr == null || arr.length < ix + len) { Float[] growLastArr = new Float[len]; // Handle a group where some rows (first one/few and/or last one/few) are docks. for (int i = ix + len - 1; i >= 0; i -= 2) { int specIx = (i >> 1); if (specs[specIx] != DOCK_DIM_CONSTRAINT) { growLastArr[i - ix] = ResizeConstraint.WEIGHT_100; return growLastArr; } } return growLastArr; } Float[] newArr = new Float[len]; for (int i = 0; i < len; i++) newArr[i] = arr[ix + i]; return newArr; } private static WeakHashMap[] PARENT_ROWCOL_SIZES_MAP = null; @SuppressWarnings( "unchecked" ) private static synchronized void putSizesAndIndexes(Object parComp, int[] sizes, int[] ixArr, boolean isRows) { if (PARENT_ROWCOL_SIZES_MAP == null) // Lazy since only if designing in IDEs PARENT_ROWCOL_SIZES_MAP = new WeakHashMap[] {new WeakHashMap(4), new WeakHashMap(4)}; PARENT_ROWCOL_SIZES_MAP[isRows ? 0 : 1].put(parComp, new int[][]{ixArr, sizes}); } static synchronized int[][] getSizesAndIndexes(Object parComp, boolean isRows) { if (PARENT_ROWCOL_SIZES_MAP == null) return null; return PARENT_ROWCOL_SIZES_MAP[isRows ? 0 : 1].get(parComp); } private static WeakHashMap> PARENT_GRIDPOS_MAP = null; private static synchronized void saveGrid(ComponentWrapper parComp, LinkedHashMap grid) { if (PARENT_GRIDPOS_MAP == null) // Lazy since only if designing in IDEs PARENT_GRIDPOS_MAP = new WeakHashMap>(4); ArrayList weakCells = new ArrayList(grid.size()); for (Map.Entry e : grid.entrySet()) { Cell cell = e.getValue(); Integer xyInt = e.getKey(); if (xyInt != null) { int x = (xyInt << 16) >> 16; int y = xyInt >> 16; for (CompWrap cw : cell.compWraps) weakCells.add(new WeakCell(cw.comp.getComponent(), x, y, cell.spanx, cell.spany)); } } PARENT_GRIDPOS_MAP.put(parComp.getComponent(), weakCells); } static synchronized HashMap getGridPositions(Object parComp) { ArrayList weakCells = PARENT_GRIDPOS_MAP != null ? PARENT_GRIDPOS_MAP.get(parComp) : null; if (weakCells == null) return null; HashMap retMap = new HashMap(); for (WeakCell wc : weakCells) { Object component = wc.componentRef.get(); if (component != null) retMap.put(component, new int[] {wc.x, wc.y, wc.spanX, wc.spanY}); } return retMap; } private static class WeakCell { private final WeakReference componentRef; private final int x, y, spanX, spanY; private WeakCell(Object component, int x, int y, int spanX, int spanY) { this.componentRef = new WeakReference(component); this.x = x; this.y = y; this.spanX = spanX; this.spanY = spanY; } } } miglayout-5.1/core/src/main/java/net/miginfocom/layout/InCellGapProvider.java000077500000000000000000000066221324101563200273710ustar00rootroot00000000000000package net.miginfocom.layout; /* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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 */ /** An interface to implement if you want to decide the gaps between two types of components within the same cell. *

* E.g.: * *

 * {@code
 * if (adjacentComp == null || adjacentSide == SwingConstants.LEFT || adjacentSide == SwingConstants.TOP)
 *	  return null;
 *
 * boolean isHor = (adjacentSide == SwingConstants.LEFT || adjacentSide == SwingConstants.RIGHT);
 *
 * if (adjacentComp.getComponentType(false) == ComponentWrapper.TYPE_LABEL && comp.getComponentType(false) == ComponentWrapper.TYPE_TEXT_FIELD)
 *    return isHor ? UNRELATED_Y : UNRELATED_Y;
 *
 * return (adjacentSide == SwingConstants.LEFT || adjacentSide == SwingConstants.RIGHT) ? RELATED_X : RELATED_Y;
 * }
 * 
*/ public interface InCellGapProvider { /** Returns the default gap between two components that are in the same cell. * @param comp The component that the gap is for. Never null. * @param adjacentComp The adjacent component if any. May be null. * @param adjacentSide What side the adjacentComp is on. {@link javax.swing.SwingUtilities#TOP} or * {@link javax.swing.SwingUtilities#LEFT} or {@link javax.swing.SwingUtilities#BOTTOM} or {@link javax.swing.SwingUtilities#RIGHT}. * @param tag The tag string that the component might be tagged with in the component constraints. May be null. * @param isLTR If it is left-to-right. * @return The default gap between two components or null if there should be no gap. */ public abstract BoundSize getDefaultGap(ComponentWrapper comp, ComponentWrapper adjacentComp, int adjacentSide, String tag, boolean isLTR); } miglayout-5.1/core/src/main/java/net/miginfocom/layout/LC.java000077500000000000000000001360021324101563200243520ustar00rootroot00000000000000package net.miginfocom.layout; import java.io.*; /* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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 */ /** Contains the constraints for an instance of the {@link LC} layout manager. */ public final class LC implements Externalizable { // See the corresponding set/get method for documentation of the property! private int wrapAfter = LayoutUtil.INF; private Boolean leftToRight = null; private UnitValue[] insets = null; // Never null elements but if unset array is null private UnitValue alignX = null, alignY = null; private BoundSize gridGapX = null, gridGapY = null; private BoundSize width = BoundSize.NULL_SIZE, height = BoundSize.NULL_SIZE; private BoundSize packW = BoundSize.NULL_SIZE, packH = BoundSize.NULL_SIZE; private float pwAlign = 0.5f, phAlign = 1.0f; private int debugMillis = 0; private int hideMode = 0; private boolean noCache = false; private boolean flowX = true; private boolean fillX = false, fillY = false; private boolean topToBottom = true; private boolean noGrid = false; private boolean visualPadding = true; /** Empty constructor. */ public LC() { } // ************************************************************************ // * JavaBean get/set methods. // ************************************************************************ /** If components have sizes or positions linked to the bounds of the parent in some way (as for instance the "%" unit has) the cache * must be turned off for the panel. If components does not get the correct or expected size or position try to set this property to true. * @return true means no cache and slightly slower layout. */ public boolean isNoCache() { return noCache; } /** If components have sizes or positions linked to the bounds of the parent in some way (as for instance the "%" unit has) the cache * must be turned off for the panel. If components does not get the correct or expected size or position try to set this property to true. * @param b true means no cache and slightly slower layout. */ public void setNoCache(boolean b) { this.noCache = b; } /** If the laid out components' bounds in total is less than the final size of the container these align values will be used to align the components * in the parent. null is default and that means top/left alignment. The relative distances between the components will not be affected * by this property. * @return The current alignment. */ public final UnitValue getAlignX() { return alignX; } /** If the laid out components' bounds in total is less than the final size of the container these align values will be used to align the components * in the parent. null is default and that means top/left alignment. The relative distances between the components will not be affected * by this property. * @param uv The new alignment. Use {@link ConstraintParser#parseAlignKeywords(String, boolean)} to create the {@link UnitValue}. May be null. */ public final void setAlignX(UnitValue uv) { this.alignX = uv; } /** If the laid out components' bounds in total is less than the final size of the container these align values will be used to align the components * in the parent. null is default and that means top/left alignment. The relative distances between the components will not be affected * by this property. * @return The current alignment. */ public final UnitValue getAlignY() { return alignY; } /** If the laid out components' bounds in total is less than the final size of the container these align values will be used to align the components * in the parent. null is default and that means top/left alignment. The relative distances between the components will not be affected * by this property. * @param uv The new alignment. Use {@link ConstraintParser#parseAlignKeywords(String, boolean)} to create the {@link UnitValue}. May be null. */ public final void setAlignY(UnitValue uv) { this.alignY = uv; } /** If > 0 the debug decorations will be repainted every millis. No debug information if <= 0 (default). * @return The current debug repaint interval. */ public final int getDebugMillis() { return debugMillis; } /** If > 0 the debug decorations will be repainted every millis. No debug information if <= 0 (default). * @param millis The new debug repaint interval. */ public final void setDebugMillis(int millis) { this.debugMillis = millis; } /** If the layout should always claim the whole bounds of the laid out container even if the preferred size is smaller. * @return true means fill. false is default. */ public final boolean isFillX() { return fillX; } /** If the layout should always claim the whole bounds of the laid out container even if the preferred size is smaller. * @param b true means fill. false is default. */ public final void setFillX(boolean b) { this.fillX = b; } /** If the layout should always claim the whole bounds of the laid out container even if the preferred size is smaller. * @return true means fill. false is default. */ public final boolean isFillY() { return fillY; } /** If the layout should always claim the whole bounds of the laid out container even if the preferred size is smaller. * @param b true means fill. false is default. */ public final void setFillY(boolean b) { this.fillY = b; } /** The default flow direction. Normally (which is true) this is horizontal and that means that the "next" component * will be put in the cell to the right (or to the left if left-to-right is false). * @return true is the default flow horizontally. * @see #setLeftToRight(Boolean) */ public final boolean isFlowX() { return flowX; } /** The default flow direction. Normally (which is true) this is horizontal and that means that the "next" component * will be put in the cell to the right (or to the left if left-to-right is false). * @param b true is the default flow horizontally. * @see #setLeftToRight(Boolean) */ public final void setFlowX(boolean b) { this.flowX = b; } /** If non-null (null is default) these value will be used as the default gaps between the columns in the grid. * @return The default grid gap between columns in the grid. null if the platform default is used. */ public final BoundSize getGridGapX() { return gridGapX; } /** If non-null (null is default) these value will be used as the default gaps between the columns in the grid. * @param x The default grid gap between columns in the grid. If null the platform default is used. */ public final void setGridGapX(BoundSize x) { this.gridGapX = x; } /** If non-null (null is default) these value will be used as the default gaps between the rows in the grid. * @return The default grid gap between rows in the grid. null if the platform default is used. */ public final BoundSize getGridGapY() { return gridGapY; } /** If non-null (null is default) these value will be used as the default gaps between the rows in the grid. * @param y The default grid gap between rows in the grid. If null the platform default is used. */ public final void setGridGapY(BoundSize y) { this.gridGapY = y; } /** How a component that is hidden (not visible) should be treated by default. * @return The mode:
* 0 == Normal. Bounds will be calculated as if the component was visible.
* 1 == If hidden the size will be 0, 0 but the gaps remain.
* 2 == If hidden the size will be 0, 0 and gaps set to zero.
* 3 == If hidden the component will be disregarded completely and not take up a cell in the grid.. */ public final int getHideMode() { return hideMode; } /** How a component that is hidden (not visible) should be treated. * @param mode The mode:
* 0 == Normal. Bounds will be calculated as if the component was visible.
* 1 == If hidden the size will be 0, 0 but the gaps remain.
* 2 == If hidden the size will be 0, 0 and gaps set to zero.
* 3 == If hidden the component will be disregarded completely and not take up a cell in the grid.. */ public final void setHideMode(int mode) { if (mode < 0 || mode > 3) throw new IllegalArgumentException("Wrong hideMode: " + mode); this.hideMode = mode; } /** The insets for the layed out panel. The insets will be an empty space around the components in the panel. null values * means that the default panel insets for the platform is used. See {@link PlatformDefaults#setDialogInsets(net.miginfocom.layout.UnitValue, net.miginfocom.layout.UnitValue, net.miginfocom.layout.UnitValue, net.miginfocom.layout.UnitValue)}. * @return The insets. Of length 4 (top, left, bottom, right) or null. The elements (1 to 4) may be null. The array is a copy and can be used freely. * @see net.miginfocom.layout.ConstraintParser#parseInsets(String, boolean) */ public final UnitValue[] getInsets() { return insets != null ? new UnitValue[] {insets[0], insets[1], insets[2], insets[3]} : null; } /** The insets for the layed out panel. The insets will be an empty space around the components in the panel. null values * means that the default panel insets for the platform is used. See {@link PlatformDefaults#setDialogInsets(net.miginfocom.layout.UnitValue, net.miginfocom.layout.UnitValue, net.miginfocom.layout.UnitValue, net.miginfocom.layout.UnitValue)}. * @param ins The new insets. Must be of length 4 (top, left, bottom, right) or null. The elements (1 to 4) may be null to use * the platform default for that side. The array is copied for storage. * @see net.miginfocom.layout.ConstraintParser#parseInsets(String, boolean) */ public final void setInsets(UnitValue[] ins) { this.insets = ins != null ? new UnitValue[] {ins[0], ins[1], ins[2], ins[3]} : null; } /** If the layout should be forced to be left-to-right or right-to-left. A value of null is default and * means that this will be picked up from the {@link java.util.Locale} that the container being layed out is reporting. * @return Boolean.TRUE if force left-to-right. Boolean.FALSE if force tight-to-left. null * for the default "let the current Locale decide". */ public final Boolean getLeftToRight() { return leftToRight; } /** If the layout should be forced to be left-to-right or right-to-left. A value of null is default and * means that this will be picked up from the {@link java.util.Locale} that the container being layed out is reporting. * @param b Boolean.TRUE to force left-to-right. Boolean.FALSE to force tight-to-left. null * for the default "let the current Locale decide". */ public final void setLeftToRight(Boolean b) { this.leftToRight = b; } /** If the whole layout should be non grid based. It is the same as setting the "nogrid" property on every row/column in the grid. * @return true means not grid based. false is default. */ public final boolean isNoGrid() { return noGrid; } /** If the whole layout should be non grid based. It is the same as setting the "nogrid" property on every row/column in the grid. * @param b true means no grid. false is default. */ public final void setNoGrid(boolean b) { this.noGrid = b; } /** If the layout should go from the default top-to-bottom in the grid instead of the optional bottom-to-top. * @return true for the default top-to-bottom. */ public final boolean isTopToBottom() { return topToBottom; } /** If the layout should go from the default top-to-bottom in the grid instead of the optional bottom-to-top. * @param b true for the default top-to-bottom. */ public final void setTopToBottom(boolean b) { this.topToBottom = b; } /** If visual padding should be automatically used and compensated for by this layout instance. * @return true if visual padding. */ public final boolean isVisualPadding() { return visualPadding; } /** If visual padding should be automatically used and compensated for by this layout instance. * @param b true turns on visual padding. */ public final void setVisualPadding(boolean b) { this.visualPadding = b; } /** Returns after what cell the grid should always auto wrap. * @return After what cell the grid should always auto wrap. If 0 the number of columns/rows in the * {@link net.miginfocom.layout.AC} is used. LayoutUtil.INF is used for no auto wrap. */ public final int getWrapAfter() { return wrapAfter; } /** Sets after what cell the grid should always auto wrap. * @param count After what cell the grid should always auto wrap. If 0 the number of columns/rows in the * {@link net.miginfocom.layout.AC} is used. LayoutUtil.INF is used for no auto wrap. */ public final void setWrapAfter(int count) { this.wrapAfter = count; } /** Returns the "pack width" for the window that this container is located in. When the size of this container changes * the size of the window will be corrected to be within this BoundsSize. It can be used to set the minimum and/or maximum size of the window * as well as the size window should optimally get. This optimal size is normally its "preferred" size which is why "preferred" * is the normal value to set here. *

* ":push" can be appended to the bound size to only push the size bigger and never shrink it if the preferred size gets smaller. *

* E.g. "pref", "100:pref", "pref:700", "300::700", "pref:push" * @return The current value. Never null. Check if not set with .isUnset(). * @since 3.5 */ public final BoundSize getPackWidth() { return packW; } /** Sets the "pack width" for the window that this container is located in. When the size of this container changes * the size of the window will be corrected to be within this BoundsSize. It can be used to set the minimum and/or maximum size of the window * as well as the size window should optimally get. This optimal size is normally its "preferred" size which is why "preferred" * is the normal value to set here. *

* ":push" can be appended to the bound size to only push the size bigger and never shrink it if the preferred size gets smaller. *

* E.g. "pref", "100:pref", "pref:700", "300::700", "pref:push" * @param size The new pack size. If null it will be corrected to an "unset" BoundSize. * @since 3.5 */ public final void setPackWidth(BoundSize size) { packW = size != null ? size : BoundSize.NULL_SIZE; } /** Returns the "pack height" for the window that this container is located in. When the size of this container changes * the size of the window will be corrected to be within this BoundsSize. It can be used to set the minimum and/or maximum size of the window * as well as the size window should optimally get. This optimal size is normally its "preferred" size which is why "preferred" * is the normal value to set here. *

* ":push" can be appended to the bound size to only push the size bigger and never shrink it if the preferred size gets smaller. *

* E.g. "pref", "100:pref", "pref:700", "300::700", "pref:push" * @return The current value. Never null. Check if not set with .isUnset(). * @since 3.5 */ public final BoundSize getPackHeight() { return packH; } /** Sets the "pack height" for the window that this container is located in. When the size of this container changes * the size of the window will be corrected to be within this BoundsSize. It can be used to set the minimum and/or maximum size of the window * as well as the size window should optimally get. This optimal size is normally its "preferred" size which is why "preferred" * is the normal value to set here. *

* ":push" can be appended to the bound size to only push the size bigger and never shrink it if the preferred size gets smaller. *

* E.g. "pref", "100:pref", "pref:700", "300::700", "pref:push" * @param size The new pack size. If null it will be corrected to an "unset" BoundSize. * @since 3.5 */ public final void setPackHeight(BoundSize size) { packH = size != null ? size : BoundSize.NULL_SIZE; } /** If there is a resize of the window due to packing (see {@link #setPackHeight(BoundSize)} this value, which is between 0f and 1f, * decides where the extra/superfluous size is placed. 0f means that the window will resize so that the upper part moves up and the * lower side stays in the same place. 0.5f will expand/reduce the window equally upwards and downwards. 1f will do the opposite of 0f * of course. * @return The pack alignment. Always between 0f and 1f, inclusive. * @since 3.5 */ public final float getPackHeightAlign() { return phAlign; } /** If there is a resize of the window due to packing (see {@link #setPackHeight(BoundSize)} this value, which is between 0f and 1f, * decides where the extra/superfluous size is placed. 0f means that the window will resize so that the upper part moves up and the * lower side stays in the same place. 0.5f will expand/reduce the window equally upwards and downwards. 1f will do the opposite of 0f * of course. * @param align The pack alignment. Always between 0f and 1f, inclusive. Values outside this will be truncated. * @since 3.5 */ public final void setPackHeightAlign(float align) { phAlign = Math.max(0f, Math.min(1f, align)); } /** If there is a resize of the window due to packing (see {@link #setPackHeight(BoundSize)} this value, which is between 0f and 1f, * decides where the extra/superfluous size is placed. 0f means that the window will resize so that the left part moves left and the * right side stays in the same place. 0.5f will expand/reduce the window equally to the right and lefts. 1f will do the opposite of 0f * of course. * @return The pack alignment. Always between 0f and 1f, inclusive. * @since 3.5 */ public final float getPackWidthAlign() { return pwAlign; } /** If there is a resize of the window due to packing (see {@link #setPackHeight(BoundSize)} this value, which is between 0f and 1f, * decides where the extra/superfluous size is placed. 0f means that the window will resize so that the left part moves left and the * right side stays in the same place. 0.5f will expand/reduce the window equally to the right and lefts. 1f will do the opposite of 0f * of course. * @param align The pack alignment. Always between 0f and 1f, inclusive. Values outside this will be truncated. * @since 3.5 */ public final void setPackWidthAlign(float align) { pwAlign = Math.max(0f, Math.min(1f, align)); } /** Returns the minimum/preferred/maximum size for the container that this layout constraint is set for. Any of these * sizes that is not null will be returned directly instead of determining the corresponding size through * asking the components in this container. * @return The width for the container that this layout constraint is set for. Not null but * all sizes can be null. * @since 3.5 */ public final BoundSize getWidth() { return width; } /** Sets the minimum/preferred/maximum size for the container that this layout constraint is set for. Any of these * sizes that is not null will be returned directly instead of determining the corresponding size through * asking the components in this container. * @param size The width for the container that this layout constraint is set for. null is translated to * a bound size containing only null sizes. * @since 3.5 */ public final void setWidth(BoundSize size) { this.width = size != null ? size : BoundSize.NULL_SIZE; } /** Returns the minimum/preferred/maximum size for the container that this layout constraint is set for. Any of these * sizes that is not null will be returned directly instead of determining the corresponding size through * asking the components in this container. * @return The height for the container that this layout constraint is set for. Not null but * all sizes can be null. * @since 3.5 */ public final BoundSize getHeight() { return height; } /** Sets the minimum/preferred/maximum size for the container that this layout constraint is set for. Any of these * sizes that is not null will be returned directly instead of determining the corresponding size through * asking the components in this container. * @param size The height for the container that this layout constraint is set for. null is translated to * a bound size containing only null sizes. * @since 3.5 */ public final void setHeight(BoundSize size) { this.height = size != null ? size : BoundSize.NULL_SIZE; } // ************************************************************************ // * Builder methods. // ************************************************************************ /** Short for, and thus same as, .pack("pref", "pref"). *

* Same functionality as {@link #setPackHeight(BoundSize)} and {@link #setPackWidth(net.miginfocom.layout.BoundSize)} * only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @since 3.5 */ public final LC pack() { return pack("pref", "pref"); } /** Sets the pack width and height. *

* Same functionality as {@link #setPackHeight(BoundSize)} and {@link #setPackWidth(net.miginfocom.layout.BoundSize)} * only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param width The pack width. May be null. * @param height The pack height. May be null. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @since 3.5 */ public final LC pack(String width, String height) { setPackWidth(width != null ? ConstraintParser.parseBoundSize(width, false, true) : BoundSize.NULL_SIZE); setPackHeight(height != null ? ConstraintParser.parseBoundSize(height, false, false) : BoundSize.NULL_SIZE); return this; } /** Sets the pack width and height alignment. *

* Same functionality as {@link #setPackHeightAlign(float)} and {@link #setPackWidthAlign(float)} * only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param alignX The pack width alignment. 0.5f is default. * @param alignY The pack height alignment. 0.5f is default. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @since 3.5 */ public final LC packAlign(float alignX, float alignY) { setPackWidthAlign(alignX); setPackHeightAlign(alignY); return this; } /** Sets a wrap after the number of columns/rows that is defined in the {@link net.miginfocom.layout.AC}. *

* Same functionality as calling {@link #setWrapAfter(int)} with 0 only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). */ public final LC wrap() { setWrapAfter(0); return this; } /** Same functionality as {@link #setWrapAfter(int)} only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param count After what cell the grid should always auto wrap. If 0 the number of columns/rows in the * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). */ public final LC wrapAfter(int count) { setWrapAfter(count); return this; } /** Same functionality as calling {@link #setNoCache(boolean)} with true only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). */ public final LC noCache() { setNoCache(true); return this; } /** Same functionality as calling {@link #setFlowX(boolean)} with false only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). */ public final LC flowY() { setFlowX(false); return this; } /** Same functionality as calling {@link #setFlowX(boolean)} with true only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). */ public final LC flowX() { setFlowX(true); return this; } /** Same functionality as calling {@link #setFillX(boolean)} with true and {@link #setFillY(boolean)} with true conmbined.T his method returns * this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). */ public final LC fill() { setFillX(true); setFillY(true); return this; } /** Same functionality as calling {@link #setFillX(boolean)} with true only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). */ public final LC fillX() { setFillX(true); return this; } /** Same functionality as calling {@link #setFillY(boolean)} with true only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). */ public final LC fillY() { setFillY(true); return this; } /** Same functionality as {@link #setLeftToRight(Boolean)} only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param b true for forcing left-to-right. false for forcing right-to-left. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). */ public final LC leftToRight(boolean b) { setLeftToRight(b ? Boolean.TRUE : Boolean.FALSE); return this; } /** Same functionality as setLeftToRight(false) only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @since 3.7.2 */ public final LC rightToLeft() { setLeftToRight(Boolean.FALSE); return this; } /** Same functionality as calling {@link #setTopToBottom(boolean)} with false only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). */ public final LC bottomToTop() { setTopToBottom(false); return this; } /** Same functionality as calling {@link #setTopToBottom(boolean)} with true only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @since 3.7.2 */ public final LC topToBottom() { setTopToBottom(true); return this; } /** Same functionality as calling {@link #setNoGrid(boolean)} with true only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). */ public final LC noGrid() { setNoGrid(true); return this; } /** Same functionality as calling {@link #setVisualPadding(boolean)} with false only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). */ public final LC noVisualPadding() { setVisualPadding(false); return this; } /** Sets the same inset (expressed as a UnitValue, e.g. "10px" or "20mm") all around. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param allSides The unit value to set for all sides. May be null which means that the default panel insets * for the platform is used. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @see #setInsets(UnitValue[]) */ public final LC insetsAll(String allSides) { UnitValue insH = ConstraintParser.parseUnitValue(allSides, true); UnitValue insV = ConstraintParser.parseUnitValue(allSides, false); insets = new UnitValue[] {insV, insH, insV, insH}; // No setter to avoid copy again return this; } /** Same functionality as setInsets(ConstraintParser.parseInsets(s, true)). This method returns this * for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param s The string to parse. E.g. "10 10 10 10" or "20". If less than 4 groups the last will be used for the missing. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @see #setInsets(UnitValue[]) */ public final LC insets(String s) { insets = ConstraintParser.parseInsets(s, true); return this; } /** Sets the different insets (expressed as a UnitValues, e.g. "10px" or "20mm") for the corresponding sides. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param top The top inset. E.g. "10px" or "10mm" or "related". May be null in which case the default inset for this * side for the platform will be used. * @param left The left inset. E.g. "10px" or "10mm" or "related". May be null in which case the default inset for this * side for the platform will be used. * @param bottom The bottom inset. E.g. "10px" or "10mm" or "related". May be null in which case the default inset for this * side for the platform will be used. * @param right The right inset. E.g. "10px" or "10mm" or "related". May be null in which case the default inset for this * side for the platform will be used. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @see #setInsets(UnitValue[]) */ public final LC insets(String top, String left, String bottom, String right) { insets = new UnitValue[] { // No setter to avoid copy again ConstraintParser.parseUnitValue(top, false), ConstraintParser.parseUnitValue(left, true), ConstraintParser.parseUnitValue(bottom, false), ConstraintParser.parseUnitValue(right, true)}; return this; } /** Same functionality as setAlignX(ConstraintParser.parseUnitValueOrAlign(unitValue, true)) only this method returns this * for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param align The align keyword or for instance "100px". E.g "left", "right", "leading" or "trailing". * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @see #setAlignX(UnitValue) */ public final LC alignX(String align) { setAlignX(ConstraintParser.parseUnitValueOrAlign(align, true, null)); return this; } /** Same functionality as setAlignY(ConstraintParser.parseUnitValueOrAlign(align, false)) only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param align The align keyword or for instance "100px". E.g "top" or "bottom". * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @see #setAlignY(UnitValue) */ public final LC alignY(String align) { setAlignY(ConstraintParser.parseUnitValueOrAlign(align, false, null)); return this; } /** Sets both the alignX and alignY as the same time. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param ax The align keyword or for instance "100px". E.g "left", "right", "leading" or "trailing". * @param ay The align keyword or for instance "100px". E.g "top" or "bottom". * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @see #alignX(String) * @see #alignY(String) */ public final LC align(String ax, String ay) { if (ax != null) alignX(ax); if (ay != null) alignY(ay); return this; } /** Same functionality as setGridGapX(ConstraintParser.parseBoundSize(boundsSize, true, true)) only this method * returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param boundsSize The BoundSize of the gap. This is a minimum and/or preferred and/or maximum size. E.g. * "50:100:200" or "100px". * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @see #setGridGapX(BoundSize) */ public final LC gridGapX(String boundsSize) { setGridGapX(ConstraintParser.parseBoundSize(boundsSize, true, true)); return this; } /** Same functionality as setGridGapY(ConstraintParser.parseBoundSize(boundsSize, true, false)) only this method * returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param boundsSize The BoundSize of the gap. This is a minimum and/or preferred and/or maximum size. E.g. * "50:100:200" or "100px". * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @see #setGridGapY(BoundSize) */ public final LC gridGapY(String boundsSize) { setGridGapY(ConstraintParser.parseBoundSize(boundsSize, true, false)); return this; } /** Sets both grid gaps at the same time. see {@link #gridGapX(String)} and {@link #gridGapY(String)}. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param gapx The BoundSize of the gap. This is a minimum and/or preferred and/or maximum size. E.g. * "50:100:200" or "100px". * @param gapy The BoundSize of the gap. This is a minimum and/or preferred and/or maximum size. E.g. * "50:100:200" or "100px". * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @see #gridGapX(String) * @see #gridGapY(String) */ public final LC gridGap(String gapx, String gapy) { if (gapx != null) gridGapX(gapx); if (gapy != null) gridGapY(gapy); return this; } /** Calls {@link #debug(int)} with 300 as an argument. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @see #setDebugMillis(int) */ public final LC debug() { setDebugMillis(300); return this; } /** Same functionality as {@link #setDebugMillis(int repaintMillis)} only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param repaintMillis The new debug repaint interval. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @see #setDebugMillis(int) */ public final LC debug(int repaintMillis) { setDebugMillis(repaintMillis); return this; } /** Same functionality as {@link #setHideMode(int mode)} only this method returns this for chaining multiple calls. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcomponents.com. * @param mode The mode:
* 0 == Normal. Bounds will be calculated as if the component was visible.
* 1 == If hidden the size will be 0, 0 but the gaps remain.
* 2 == If hidden the size will be 0, 0 and gaps set to zero.
* 3 == If hidden the component will be disregarded completely and not take up a cell in the grid.. * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). * @see #setHideMode(int) */ public final LC hideMode(int mode) { setHideMode(mode); return this; } /** The minimum width for the container. The value will override any value that is set on the container itself. *

* For a more thorough explanation of what this constraint does see the white paper or Cheat Sheet at www.migcontainers.com. * @param width The width expressed as a UnitValue. E.g. "100px" or "200mm". * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). */ public final LC minWidth(String width) { setWidth(LayoutUtil.derive(getWidth(), ConstraintParser.parseUnitValue(width, true), null, null)); return this; } /** The width for the container as a min and/or preferred and/or maximum width. The value will override any value that is set on * the container itself. *

* For a more thorough explanation of what this constraint does see the white paper or Cheat Sheet at www.migcontainers.com. * @param width The width expressed as a BoundSize. E.g. "50:100px:200mm" or "100px". * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). */ public final LC width(String width) { setWidth(ConstraintParser.parseBoundSize(width, false, true)); return this; } /** The maximum width for the container. The value will override any value that is set on the container itself. *

* For a more thorough explanation of what this constraint does see the white paper or Cheat Sheet at www.migcontainers.com. * @param width The width expressed as a UnitValue. E.g. "100px" or "200mm". * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). */ public final LC maxWidth(String width) { setWidth(LayoutUtil.derive(getWidth(), null, null, ConstraintParser.parseUnitValue(width, true))); return this; } /** The minimum height for the container. The value will override any value that is set on the container itself. *

* For a more thorough explanation of what this constraint does see the white paper or Cheat Sheet at www.migcontainers.com. * @param height The height expressed as a UnitValue. E.g. "100px" or "200mm". * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). */ public final LC minHeight(String height) { setHeight(LayoutUtil.derive(getHeight(), ConstraintParser.parseUnitValue(height, false), null, null)); return this; } /** The height for the container as a min and/or preferred and/or maximum height. The value will override any value that is set on * the container itself. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcontainers.com. * @param height The height expressed as a BoundSize. E.g. "50:100px:200mm" or "100px". * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). */ public final LC height(String height) { setHeight(ConstraintParser.parseBoundSize(height, false, false)); return this; } /** The maximum height for the container. The value will override any value that is set on the container itself. *

* For a more thorough explanation of what this constraint does see the white paper or cheat Sheet at www.migcontainers.com. * @param height The height expressed as a UnitValue. E.g. "100px" or "200mm". * @return this so it is possible to chain calls. E.g. new LayoutConstraint().noGrid().gap().fill(). */ public final LC maxHeight(String height) { setHeight(LayoutUtil.derive(getHeight(), null, null, ConstraintParser.parseUnitValue(height, false))); return this; } // ************************************************ // Persistence Delegate and Serializable combined. // ************************************************ private Object readResolve() throws ObjectStreamException { return LayoutUtil.getSerializedObject(this); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { LayoutUtil.setSerializedObject(this, LayoutUtil.readAsXML(in)); } @Override public void writeExternal(ObjectOutput out) throws IOException { if (getClass() == LC.class) LayoutUtil.writeAsXML(out, this); } } miglayout-5.1/core/src/main/java/net/miginfocom/layout/LayoutCallback.java000077500000000000000000000070241324101563200267470ustar00rootroot00000000000000package net.miginfocom.layout; /* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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 */ /** A class to extend if you want to provide more control over where a component is placed or the size of it. *

* Note! Returned arrays from this class will never be altered. This means that caching of arrays in these methods * is OK. */ public abstract class LayoutCallback { /** Returns a position similar to the "pos" the component constraint. * @param comp The component wrapper that holds the actual component (JComponent is Swing and Control in SWT). * Should not be altered. * @return The [x, y, x2, y2] as explained in the documentation for "pos". If null * is returned nothing is done and this is the default. * @see UnitValue * @see net.miginfocom.layout.ConstraintParser#parseUnitValue(String, boolean) */ public UnitValue[] getPosition(ComponentWrapper comp) { return null; } /** Returns a size similar to the "width" and "height" in the component constraint. * @param comp The component wrapper that holds the actual component (JComponent is Swing and Control in SWT). * Should not be altered. * @return The [width, height] as explained in the documentation for "width" and "height". If null * is returned nothing is done and this is the default. * @see net.miginfocom.layout.BoundSize * @see net.miginfocom.layout.ConstraintParser#parseBoundSize(String, boolean, boolean) */ public BoundSize[] getSize(ComponentWrapper comp) { return null; } /** A last minute change of the bounds. The bound for the layout cycle has been set and you can correct there * after any set of rules you like. * @param comp The component wrapper that holds the actual component (JComponent is Swing and Control in SWT). */ public void correctBounds(ComponentWrapper comp) { } } miglayout-5.1/core/src/main/java/net/miginfocom/layout/LayoutUtil.java000077500000000000000000000513011324101563200261650ustar00rootroot00000000000000package net.miginfocom.layout; import java.beans.*; import java.io.*; import java.util.IdentityHashMap; import java.util.TreeSet; import java.util.WeakHashMap; /* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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 */ /** A utility class that has only static helper methods. */ public final class LayoutUtil { /** A substitute value for a really large value. Integer.MAX_VALUE is not used since that means a lot of defensive code * for potential overflow must exist in many places. This value is large enough for being unreasonable yet it is hard to * overflow. */ public static final int INF = (Integer.MAX_VALUE >> 10) - 100; // To reduce likelihood of overflow errors when calculating. /** Tag int for a value that in considered "not set". Used as "null" element in int arrays. */ static final int NOT_SET = Integer.MIN_VALUE + 12346; // Magic value... // Index for the different sizes public static final int MIN = 0; public static final int PREF = 1; public static final int MAX = 2; public static final int HORIZONTAL = 0; public static final int VERTICAL = 1; private static volatile WeakHashMap CR_MAP = null; private static volatile WeakHashMap DT_MAP = null; // The Containers that have design time. Value not used. private static int eSz = 0; private static int globalDebugMillis = 0; public static final boolean HAS_BEANS = hasBeans(); private static boolean hasBeans() { try { LayoutUtil.class.getClassLoader().loadClass("java.beans.Beans"); return true; } catch (Throwable e) { return false; } } private LayoutUtil() { } /** Returns the current version of MiG Layout. * @return The current version of MiG Layout. E.g. "3.6.3" or "4.0" */ public static String getVersion() { return "5.0"; } /** If global debug should be on or off. If > 0 then debug is turned on for all MigLayout * instances. * @return The current debug milliseconds. * @see LC#setDebugMillis(int) */ public static int getGlobalDebugMillis() { return globalDebugMillis; } /** If global debug should be on or off. If > 0 then debug is turned on for all MigLayout * instances. *

* Note! This is a passive value and will be read by panels when the needed, which is normally * when they repaint/layout. * @param millis The new debug milliseconds. 0 turns of global debug and leaves debug up to every * individual panel. * @see LC#setDebugMillis(int) */ public static void setGlobalDebugMillis(int millis) { globalDebugMillis = millis; } /** Sets if design time is turned on for a Container in {@link ContainerWrapper}. * @param cw The container to set design time for. null is legal and can be used as * a key to turn on/off design time "in general". Note though that design time "in general" is * always on as long as there is at least one ContainerWrapper with design time. *

* If this method has not ever been called it will default to what * Beans.isDesignTime() returns. This means that if you call * this method you indicate that you will take responsibility for the design time value. * @param b true means design time on. */ public static void setDesignTime(ContainerWrapper cw, boolean b) { if (DT_MAP == null) DT_MAP = new WeakHashMap(); DT_MAP.put((cw != null ? cw.getComponent() : null), b); } /** Returns if design time is turned on for a Container in {@link ContainerWrapper}. * @param cw The container to set design time for. null is legal will return true * if there is at least one ContainerWrapper (or null) that have design time * turned on. * @return If design time is set for cw. */ public static boolean isDesignTime(ContainerWrapper cw) { if (DT_MAP == null) return HAS_BEANS && Beans.isDesignTime(); // assume design time "in general" (cw is null) if there is at least one container with design time // (for storing constraints creation strings in method putCCString()) if (cw == null && DT_MAP != null && !DT_MAP.isEmpty() ) return true; if (cw != null && DT_MAP.containsKey(cw.getComponent()) == false) cw = null; Boolean b = DT_MAP.get(cw != null ? cw.getComponent() : null); return b != null && b; } /** The size of an empty row or columns in a grid during design time. * @return The number of pixels. Default is 15. */ public static int getDesignTimeEmptySize() { return eSz; } /** The size of an empty row or columns in a grid during design time. * @param pixels The number of pixels. Default is 0 (it was 15 prior to v3.7.2, but since that meant different behaviour * under design time by default it was changed to be 0, same as non-design time). IDE vendors can still set it to 15 to * get the old behaviour. */ public static void setDesignTimeEmptySize(int pixels) { eSz = pixels; } /** Associates con with the creation string s. The con object should * probably have an equals method that compares identities or con objects that .equals() will only * be able to have one creation string. *

* If {@link LayoutUtil#isDesignTime(ContainerWrapper)} returns false the method does nothing. * @param con The object. if null the method does nothing. * @param s The creation string. if null the method does nothing. */ static void putCCString(Object con, String s) { if (s != null && con != null && isDesignTime(null)) { if (CR_MAP == null) CR_MAP = new WeakHashMap(64); CR_MAP.put(con, s); } } /** Sets/add the persistence delegates to be used for a class. * @param c The class to set the registered delegate for. * @param del The new delegate or null to erase to old one. */ static synchronized void setDelegate(Class c, PersistenceDelegate del) { try { Introspector.getBeanInfo(c, Introspector.IGNORE_ALL_BEANINFO).getBeanDescriptor().setValue("persistenceDelegate", del); } catch (Exception ignored) { } } /** Returns strings set with {@link #putCCString(Object, String)} or null if nothing is associated or * {@link LayoutUtil#isDesignTime(ContainerWrapper)} returns false. * @param con The constrain object. * @return The creation string or null if nothing is registered with the con object. */ static String getCCString(Object con) { return CR_MAP != null ? CR_MAP.get(con) : null; } static void throwCC() { throw new IllegalStateException("setStoreConstraintData(true) must be set for strings to be saved."); } /** Takes a number on min/preferred/max sizes and resize constraints and returns the calculated sizes which sum should add up to bounds. Whether the sum * will actually equal bounds is dependent on the pref/max sizes and resize constraints. * @param sizes [ix],[MIN][PREF][MAX]. Grid.CompWrap.NOT_SET will be treated as N/A or 0. A "[MIN][PREF][MAX]" array with null elements will be interpreted as very flexible (no bounds) * but if the array itself is null it will not get any size. * @param resConstr Elements can be null and the whole array can be null. null means that the size will not be flexible at all. * Can have length less than sizes in which case the last element should be used for the elements missing. * @param defPushWeights If there is no grow weight for a resConstr the corresponding value of this array is used. * These forced resConstr will be grown last though and only if needed to fill to the bounds. * @param startSizeType The initial size to use. E.g. {@link net.miginfocom.layout.LayoutUtil#MIN}. * @param bounds To use for relative sizes. * @return The sizes. Array length will match sizes. */ static int[] calculateSerial(int[][] sizes, ResizeConstraint[] resConstr, Float[] defPushWeights, int startSizeType, int bounds) { float[] lengths = new float[sizes.length]; // heights/widths that are set float usedLength = 0.0f; // Give all preferred size to start with for (int i = 0; i < sizes.length; i++) { if (sizes[i] != null) { float len = sizes[i][startSizeType] != NOT_SET ? sizes[i][startSizeType] : 0; int newSizeBounded = getBrokenBoundary(len, sizes[i][MIN], sizes[i][MAX]); if (newSizeBounded != NOT_SET) len = newSizeBounded; usedLength += len; lengths[i] = len; } } int useLengthI = Math.round(usedLength); if (useLengthI != bounds && resConstr != null) { boolean isGrow = useLengthI < bounds; // Create a Set with the available priorities TreeSet prioList = new TreeSet(); for (int i = 0; i < sizes.length; i++) { ResizeConstraint resC = (ResizeConstraint) getIndexSafe(resConstr, i); if (resC != null) prioList.add(isGrow ? resC.growPrio : resC.shrinkPrio); } Integer[] prioIntegers = prioList.toArray(new Integer[prioList.size()]); for (int force = 0; force <= ((isGrow && defPushWeights != null) ? 1 : 0); force++) { // Run twice if defGrow and the need for growing. for (int pr = prioIntegers.length - 1; pr >= 0; pr--) { int curPrio = prioIntegers[pr]; float totWeight = 0f; Float[] resizeWeight = new Float[sizes.length]; for (int i = 0; i < sizes.length; i++) { if (sizes[i] == null) // if no min/pref/max size at all do not grow or shrink. continue; ResizeConstraint resC = (ResizeConstraint) getIndexSafe(resConstr, i); if (resC != null) { int prio = isGrow ? resC.growPrio : resC.shrinkPrio; if (curPrio == prio) { if (isGrow) { resizeWeight[i] = (force == 0 || resC.grow != null) ? resC.grow : (defPushWeights[i < defPushWeights.length ? i : defPushWeights.length - 1]); } else { resizeWeight[i] = resC.shrink; } if (resizeWeight[i] != null) totWeight += resizeWeight[i]; } } } if (totWeight > 0f) { boolean hit; do { float toChange = bounds - usedLength; hit = false; float changedWeight = 0f; for (int i = 0; i < sizes.length && totWeight > 0.0001f; i++) { Float weight = resizeWeight[i]; if (weight != null) { float sizeDelta = toChange * weight / totWeight; float newSize = lengths[i] + sizeDelta; if (sizes[i] != null) { int newSizeBounded = getBrokenBoundary(newSize, sizes[i][MIN], sizes[i][MAX]); if (newSizeBounded != NOT_SET) { resizeWeight[i] = null; hit = true; changedWeight += weight; newSize = newSizeBounded; sizeDelta = newSize - lengths[i]; } } lengths[i] = newSize; usedLength += sizeDelta; } } totWeight -= changedWeight; } while (hit); } } } } return roundSizes(lengths); } static Object getIndexSafe(Object[] arr, int ix) { return arr != null ? arr[ix < arr.length ? ix : arr.length - 1] : null; } /** Returns the broken boundary if sz is outside the boundaries lower or upper. If both boundaries * are broken, the lower one is returned. If sz is < 0 then new Float(0f) is returned so that no sizes can be * negative. * @param sz The size to check * @param lower The lower boundary (or null for no boundary). * @param upper The upper boundary (or null for no boundary). * @return The broken boundary. */ private static int getBrokenBoundary(float sz, int lower, int upper) { if (lower != NOT_SET) { if (sz < lower) return lower; } else if (sz < 0f) { return 0; } if (upper != NOT_SET && sz > upper) return upper; return NOT_SET; } static int sum(int[] terms, int start, int len) { int s = 0; for (int i = start, iSz = start + len; i < iSz; i++) s += terms[i]; return s; } static int sum(int[] terms) { return sum(terms, 0, terms.length); } /** Keeps f within min and max. Min is of higher priority if min is larger than max. * @param f The value to clamp * @param min * @param max * @return The clamped value, between min and max. */ static float clamp(float f, float min, float max) { return Math.max(min, Math.min(f, max)); } /** Keeps i within min and max. Min is of higher priority if min is larger than max. * @param i The value to clamp * @param min * @param max * @return The clamped value, between min and max. */ static int clamp(int i, int min, int max) { return Math.max(min, Math.min(i, max)); } public static int getSizeSafe(int[] sizes, int sizeType) { if (sizes == null || sizes[sizeType] == NOT_SET) return sizeType == MAX ? LayoutUtil.INF : 0; return sizes[sizeType]; } static BoundSize derive(BoundSize bs, UnitValue min, UnitValue pref, UnitValue max) { if (bs == null || bs.isUnset()) return new BoundSize(min, pref, max, null); return new BoundSize( min != null ? min : bs.getMin(), pref != null ? pref : bs.getPreferred(), max != null ? max : bs.getMax(), bs.getGapPush(), null); } /** Returns if left-to-right orientation is used. If not set explicitly in the layout constraints the Locale * of the parent is used. * @param lc The constraint if there is one. Can be null. * @param container The parent that may be used to get the left-to-right if lc does not specify this. * @return If left-to-right orientation is currently used. */ public static boolean isLeftToRight(LC lc, ContainerWrapper container) { if (lc != null && lc.getLeftToRight() != null) return lc.getLeftToRight(); return container == null || container.isLeftToRight(); } /** Round a number of float sizes into int sizes so that the total length match up * @param sizes The sizes to round * @return An array of equal length as sizes. */ static int[] roundSizes(float[] sizes) { int[] retInts = new int[sizes.length]; float posD = 0; for (int i = 0; i < retInts.length; i++) { int posI = (int) (posD + 0.5f); posD += sizes[i]; retInts[i] = (int) (posD + 0.5f) - posI; } return retInts; } /** Safe equals. null == null, but null never equals anything else. * @param o1 The first object. May be null. * @param o2 The second object. May be null. * @return Returns true if o1 and o2 are equal (using .equals()) or both are null. */ static boolean equals(Object o1, Object o2) { return o1 == o2 || (o1 != null && o2 != null && o1.equals(o2)); } // static int getBaselineCorrect(Component comp) // { // Dimension pSize = comp.getPreferredSize(); // int baseline = comp.getBaseline(pSize.width, pSize.height); // int nextBaseline = comp.getBaseline(pSize.width, pSize.height + 1); // // // Amount to add to height when calculating where baseline // // lands for a particular height: // int padding = 0; // // // Where the baseline is relative to the mid point // int baselineOffset = baseline - pSize.height / 2; // if (pSize.height % 2 == 0 && baseline != nextBaseline) { // padding = 1; // } else if (pSize.height % 2 == 1 && baseline == nextBaseline) { // baselineOffset--; // padding = 1; // } // // // The following calculates where the baseline lands for // // the height z: // return (pSize.height + padding) / 2 + baselineOffset; // } /** Returns the insets for the side. * @param side top == 0, left == 1, bottom = 2, right = 3. * @param getDefault If true the default insets will get retrieved if lc has none set. * @return The insets for the side. Never null. */ static UnitValue getInsets(LC lc, int side, boolean getDefault) { UnitValue[] i = lc.getInsets(); return (i != null && i[side] != null) ? i[side] : (getDefault ? PlatformDefaults.getPanelInsets(side) : UnitValue.ZERO); } /** Writes the object and CLOSES the stream. Uses the persistence delegate registered in this class. * @param os The stream to write to. Will be closed. * @param o The object to be serialized. * @param listener The listener to receive the exceptions if there are any. If null not used. */ static void writeXMLObject(OutputStream os, Object o, ExceptionListener listener) { ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(LayoutUtil.class.getClassLoader()); XMLEncoder encoder = new XMLEncoder(os); if (listener != null) encoder.setExceptionListener(listener); encoder.writeObject(o); encoder.close(); // Must be closed to write. Thread.currentThread().setContextClassLoader(oldClassLoader); } private static ByteArrayOutputStream writeOutputStream = null; /** Writes an object to XML. * @param out The object out to write to. Will not be closed. * @param o The object to write. */ public static synchronized void writeAsXML(ObjectOutput out, Object o) throws IOException { if (writeOutputStream == null) writeOutputStream = new ByteArrayOutputStream(16384); writeOutputStream.reset(); writeXMLObject(writeOutputStream, o, new ExceptionListener() { @Override public void exceptionThrown(Exception e) { e.printStackTrace(); }}); byte[] buf = writeOutputStream.toByteArray(); out.writeInt(buf.length); out.write(buf); } private static byte[] readBuf = null; /** Reads an object from in using the * @param in The object input to read from. * @return The object. Never null. * @throws IOException If there was a problem saving as XML */ public static synchronized Object readAsXML(ObjectInput in) throws IOException { if (readBuf == null) readBuf = new byte[16384]; Thread cThread = Thread.currentThread(); ClassLoader oldCL = null; try { oldCL = cThread.getContextClassLoader(); cThread.setContextClassLoader(LayoutUtil.class.getClassLoader()); } catch(SecurityException ignored) { } Object o = null; try { int length = in.readInt(); if (length > readBuf.length) readBuf = new byte[length]; in.readFully(readBuf, 0, length); o = new XMLDecoder(new ByteArrayInputStream(readBuf, 0, length)).readObject(); } catch(EOFException ignored) { } if (oldCL != null) cThread.setContextClassLoader(oldCL); return o; } private static final IdentityHashMap SER_MAP = new IdentityHashMap(2); /** Sets the serialized object and associates it with caller. * @param caller The object created o * @param o The just serialized object. */ public static void setSerializedObject(Object caller, Object o) { synchronized(SER_MAP) { SER_MAP.put(caller, o); } } /** Returns the serialized object that are associated with caller. It also removes it from the list. * @param caller The original creator of the object. * @return The object. */ public static Object getSerializedObject(Object caller) { synchronized(SER_MAP) { return SER_MAP.remove(caller); } } } miglayout-5.1/core/src/main/java/net/miginfocom/layout/LinkHandler.java000077500000000000000000000140071324101563200262470ustar00rootroot00000000000000package net.miginfocom.layout; import java.util.HashMap; import java.util.WeakHashMap; /* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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 */ /** */ public final class LinkHandler { public static final int X = 0; public static final int Y = 1; public static final int WIDTH = 2; public static final int HEIGHT = 3; public static final int X2 = 4; public static final int Y2 = 5; // indices for values of LAYOUTS private static final int VALUES = 0; private static final int VALUES_TEMP = 1; private static final WeakHashMap[]> LAYOUTS = new WeakHashMap[]>(); private LinkHandler() { } public synchronized static Integer getValue(Object layout, String key, int type) { Integer ret = null; HashMap[] layoutValues = LAYOUTS.get(layout); if (layoutValues != null) { int[] rect = layoutValues[VALUES_TEMP].get(key); if (rect != null && rect[type] != LayoutUtil.NOT_SET) { ret = rect[type]; } else { rect = layoutValues[VALUES].get(key); ret = (rect != null && rect[type] != LayoutUtil.NOT_SET) ? rect[type] : null; } } return ret; } /** Sets a key that can be linked to from any component. * @param layout The MigLayout instance * @param key The key to link to. This is the same as the ID in a component constraint. * @param x x * @param y y * @param width Width * @param height Height * @return If the value was changed */ public synchronized static boolean setBounds(Object layout, String key, int x, int y, int width, int height) { return setBounds(layout, key, x, y, width, height, false, false); } synchronized static boolean setBounds(Object layout, String key, int x, int y, int width, int height, boolean temporary, boolean incCur) { HashMap[] layoutValues = LAYOUTS.get(layout); if (layoutValues != null) { HashMap map = layoutValues[temporary ? VALUES_TEMP : VALUES]; int[] old = map.get(key); if (old == null || old[X] != x || old[Y] != y || old[WIDTH] != width || old[HEIGHT] != height) { if (old == null || incCur == false) { map.put(key, new int[] {x, y, width, height, x + width, y + height}); return true; } else { boolean changed = false; if (x != LayoutUtil.NOT_SET) { if (old[X] == LayoutUtil.NOT_SET || x < old[X]) { old[X] = x; old[WIDTH] = old[X2] - x; changed = true; } if (width != LayoutUtil.NOT_SET) { int x2 = x + width; if (old[X2] == LayoutUtil.NOT_SET || x2 > old[X2]) { old[X2] = x2; old[WIDTH] = x2 - old[X]; changed = true; } } } if (y != LayoutUtil.NOT_SET) { if (old[Y] == LayoutUtil.NOT_SET || y < old[Y]) { old[Y] = y; old[HEIGHT] = old[Y2] - y; changed = true; } if (height != LayoutUtil.NOT_SET) { int y2 = y + height; if (old[Y2] == LayoutUtil.NOT_SET || y2 > old[Y2]) { old[Y2] = y2; old[HEIGHT] = y2 - old[Y]; changed = true; } } } return changed; } } return false; } int[] bounds = new int[] {x, y, width, height, x + width, y + height}; HashMap values_temp = new HashMap(4); if (temporary) values_temp.put(key, bounds); HashMap values = new HashMap(4); if (temporary == false) values.put(key, bounds); LAYOUTS.put(layout, new HashMap[] {values, values_temp}); return true; } /** This method clear any weak references right away instead of waiting for the GC. This might be advantageous * if lots of layout are created and disposed of quickly to keep memory consumption down. * @since 3.7.4 */ public synchronized static void clearWeakReferencesNow() { LAYOUTS.clear(); } public synchronized static boolean clearBounds(Object layout, String key) { HashMap[] layoutValues = LAYOUTS.get(layout); if (layoutValues != null) return layoutValues[VALUES].remove(key) != null; return false; } synchronized static void clearTemporaryBounds(Object layout) { HashMap[] layoutValues = LAYOUTS.get(layout); if (layoutValues != null) layoutValues[VALUES_TEMP].clear(); } } miglayout-5.1/core/src/main/java/net/miginfocom/layout/PlatformDefaults.java000077500000000000000000001031201324101563200273230ustar00rootroot00000000000000package net.miginfocom.layout; import java.util.HashMap; /* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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 * @author Xxxx Xxxx, Xxxx - Gnome support * Date: 2008-jan-16 */ /** Currently handles Windows, Mac OS X, and GNOME spacing. */ public final class PlatformDefaults { /** Property to use in LAF settings and as JComponent client property * to specify the visual padding. *

*/ public static String VISUAL_PADDING_PROPERTY = "visualPadding"; private static int DEF_H_UNIT = UnitValue.LPX; private static int DEF_V_UNIT = UnitValue.LPY; private static InCellGapProvider GAP_PROVIDER = null; private static volatile int MOD_COUNT = 0; // private static final UnitValue LPX1 = new UnitValue(1, UnitValue.LPX, null); // private static final UnitValue LPX4 = new UnitValue(4, UnitValue.LPX, null); private static final UnitValue LPX6 = new UnitValue(6, UnitValue.LPX, null); private static final UnitValue LPX7 = new UnitValue(7, UnitValue.LPX, null); // private static final UnitValue LPX8 = new UnitValue(8, UnitValue.LPX, null); // private static final UnitValue LPX9 = new UnitValue(9, UnitValue.LPX, null); // private static final UnitValue LPX10 = new UnitValue(10, UnitValue.LPX, null); private static final UnitValue LPX11 = new UnitValue(11, UnitValue.LPX, null); private static final UnitValue LPX12 = new UnitValue(12, UnitValue.LPX, null); // private static final UnitValue LPX14 = new UnitValue(14, UnitValue.LPX, null); private static final UnitValue LPX16 = new UnitValue(16, UnitValue.LPX, null); private static final UnitValue LPX18 = new UnitValue(18, UnitValue.LPX, null); private static final UnitValue LPX20 = new UnitValue(20, UnitValue.LPX, null); // private static final UnitValue LPY1 = new UnitValue(1, UnitValue.LPY, null); // private static final UnitValue LPY4 = new UnitValue(4, UnitValue.LPY, null); private static final UnitValue LPY6 = new UnitValue(6, UnitValue.LPY, null); private static final UnitValue LPY7 = new UnitValue(7, UnitValue.LPY, null); // private static final UnitValue LPY8 = new UnitValue(8, UnitValue.LPY, null); // private static final UnitValue LPY9 = new UnitValue(9, UnitValue.LPY, null); // private static final UnitValue LPY10 = new UnitValue(10, UnitValue.LPY, null); private static final UnitValue LPY11 = new UnitValue(11, UnitValue.LPY, null); private static final UnitValue LPY12 = new UnitValue(12, UnitValue.LPY, null); // private static final UnitValue LPY14 = new UnitValue(14, UnitValue.LPY, null); private static final UnitValue LPY16 = new UnitValue(16, UnitValue.LPY, null); private static final UnitValue LPY18 = new UnitValue(18, UnitValue.LPY, null); private static final UnitValue LPY20 = new UnitValue(20, UnitValue.LPY, null); public static final int WINDOWS_XP = 0; public static final int MAC_OSX = 1; public static final int GNOME = 2; // private static final int KDE = 3; private static int CUR_PLAF = WINDOWS_XP; // Used for holding values. private final static UnitValue[] PANEL_INS = new UnitValue[4]; private final static UnitValue[] DIALOG_INS = new UnitValue[4]; private static String BUTTON_FORMAT = null; private static final HashMap HOR_DEFS = new HashMap(32); private static final HashMap VER_DEFS = new HashMap(32); private static BoundSize DEF_VGAP = null, DEF_HGAP = null; static BoundSize RELATED_X = null, RELATED_Y = null, UNRELATED_X = null, UNRELATED_Y = null; private static UnitValue BUTT_WIDTH = null; private static UnitValue BUTT_PADDING = null; private static Float horScale = null, verScale = null; /** I value indicating that the size of the font for the container of the component * will be used as a base for calculating the logical pixel size. This is much as how * Windows calculated DLU (dialog units). * @see net.miginfocom.layout.UnitValue#LPX * @see net.miginfocom.layout.UnitValue#LPY * @see #setLogicalPixelBase(int) */ public static final int BASE_FONT_SIZE = 100; /** I value indicating that the screen DPI will be used as a base for calculating the * logical pixel size. *

* This is the default value. * @see net.miginfocom.layout.UnitValue#LPX * @see net.miginfocom.layout.UnitValue#LPY * @see #setLogicalPixelBase(int) * @see #setVerticalScaleFactor(Float) * @see #setHorizontalScaleFactor(Float) */ public static final int BASE_SCALE_FACTOR = 101; /** I value indicating that the size of a logical pixel should always be a real pixel * and thus no compensation will be made. * @see net.miginfocom.layout.UnitValue#LPX * @see net.miginfocom.layout.UnitValue#LPY * @see #setLogicalPixelBase(int) */ public static final int BASE_REAL_PIXEL = 102; private static int LP_BASE = BASE_SCALE_FACTOR; private static Integer BASE_DPI_FORCED = null; private static int BASE_DPI = 96; private static boolean dra = true; private static final HashMap VISUAL_BOUNDS = new HashMap(64); static { setPlatform(getCurrentPlatform()); MOD_COUNT = 0; } /** Returns the platform that the JRE is running on currently. * @return The platform that the JRE is running on currently. E.g. {@link #MAC_OSX}, {@link #WINDOWS_XP}, or {@link #GNOME}. */ public static int getCurrentPlatform() { final String os = System.getProperty("os.name"); if (os.startsWith("Mac OS")) { return MAC_OSX; } else if (os.startsWith("Linux")) { return GNOME; } else { return WINDOWS_XP; } } private PlatformDefaults() { } /** Set the defaults to the default for the platform * @param plaf The platform. PlatformDefaults.WINDOWS_XP, * PlatformDefaults.MAC_OSX, or * PlatformDefaults.GNOME. */ public static void setPlatform(int plaf) { switch (plaf) { case WINDOWS_XP: setDefaultVisualPadding("TabbedPane." + VISUAL_PADDING_PROPERTY, new int[]{1, 0, 1, 2}); setRelatedGap(LPX7, LPY7); setUnrelatedGap(LPX11, LPY11); setParagraphGap(LPX20, LPY20); setIndentGap(LPX11, LPY11); setGridCellGap(LPX7, LPY7); setMinimumButtonWidth(new UnitValue(75, UnitValue.LPX, null)); setButtonOrder("L_E+U+YNBXOCAH_I_R"); setDialogInsets(LPY11, LPX11, LPY11, LPX11); setPanelInsets(LPY7, LPX7, LPY7, LPX7); break; case MAC_OSX: setDefaultVisualPadding("Button." + VISUAL_PADDING_PROPERTY, new int[]{3, 6, 5, 6}); setDefaultVisualPadding("Button.icon." + VISUAL_PADDING_PROPERTY, new int[]{3, 2, 3, 2}); setDefaultVisualPadding("Button.square." + VISUAL_PADDING_PROPERTY, new int[]{4, 4, 4, 4}); setDefaultVisualPadding("Button.square.icon." + VISUAL_PADDING_PROPERTY, new int[]{4, 4, 4, 4}); setDefaultVisualPadding("Button.gradient." + VISUAL_PADDING_PROPERTY, new int[]{5, 4, 5, 4}); setDefaultVisualPadding("Button.gradient.icon." + VISUAL_PADDING_PROPERTY, new int[]{5, 4, 5, 4}); setDefaultVisualPadding("Button.bevel." + VISUAL_PADDING_PROPERTY, new int[]{2, 2, 3, 2}); setDefaultVisualPadding("Button.bevel.icon." + VISUAL_PADDING_PROPERTY, new int[]{2, 2, 3, 2}); setDefaultVisualPadding("Button.textured." + VISUAL_PADDING_PROPERTY, new int[]{3, 2, 3, 2}); setDefaultVisualPadding("Button.textured.icon." + VISUAL_PADDING_PROPERTY, new int[]{3, 2, 3, 2}); setDefaultVisualPadding("Button.roundRect." + VISUAL_PADDING_PROPERTY, new int[]{5, 4, 5, 4}); setDefaultVisualPadding("Button.roundRect.icon." + VISUAL_PADDING_PROPERTY, new int[]{5, 4, 5, 4}); setDefaultVisualPadding("Button.recessed." + VISUAL_PADDING_PROPERTY, new int[]{5, 4, 5, 4}); setDefaultVisualPadding("Button.recessed.icon." + VISUAL_PADDING_PROPERTY, new int[]{5, 4, 5, 4}); setDefaultVisualPadding("Button.help." + VISUAL_PADDING_PROPERTY, new int[]{4, 3, 3, 4}); setDefaultVisualPadding("Button.help.icon." + VISUAL_PADDING_PROPERTY, new int[]{4, 3, 3, 4}); setDefaultVisualPadding("ComboBox." + VISUAL_PADDING_PROPERTY, new int[]{2, 4, 4, 5}); setDefaultVisualPadding("ComboBox.isPopDown." + VISUAL_PADDING_PROPERTY, new int[]{2, 5, 4, 5}); setDefaultVisualPadding("ComboBox.isSquare." + VISUAL_PADDING_PROPERTY, new int[]{1, 6, 5, 7}); setDefaultVisualPadding("ComboBox.editable." + VISUAL_PADDING_PROPERTY, new int[]{3, 3, 3, 2}); setDefaultVisualPadding("ComboBox.editable.isSquare." + VISUAL_PADDING_PROPERTY, new int[]{3, 3, 3, 1}); setDefaultVisualPadding("TextField." + VISUAL_PADDING_PROPERTY, new int[]{3, 3, 3, 3}); setDefaultVisualPadding("TabbedPane." + VISUAL_PADDING_PROPERTY, new int[]{4, 8, 11, 8}); setDefaultVisualPadding("Spinner." + VISUAL_PADDING_PROPERTY, new int[]{3, 3, 3, 1}); setDefaultVisualPadding("RadioButton." + VISUAL_PADDING_PROPERTY, new int[]{4, 6, 3, 5}); setDefaultVisualPadding("RadioButton.small." + VISUAL_PADDING_PROPERTY, new int[]{4, 6, 3, 5}); setDefaultVisualPadding("RadioButton.mini." + VISUAL_PADDING_PROPERTY, new int[]{5, 7, 4, 5}); setDefaultVisualPadding("CheckBox." + VISUAL_PADDING_PROPERTY, new int[]{5, 7, 4, 5}); setDefaultVisualPadding("CheckBox.small." + VISUAL_PADDING_PROPERTY, new int[]{5, 7, 4, 5}); setDefaultVisualPadding("CheckBox.mini." + VISUAL_PADDING_PROPERTY, new int[]{6, 7, 3, 5}); setRelatedGap(LPX7, LPY7); setUnrelatedGap(LPX11, LPY11); setParagraphGap(LPX20, LPY20); setIndentGap(LPX11, LPY11); setGridCellGap(LPX7, LPY7); setMinimumButtonWidth(new UnitValue(70, UnitValue.LPX, null)); setMinimumButtonPadding(new UnitValue(8, UnitValue.LPX, null)); setButtonOrder("L_HE+U+NYBXCOA_I_R"); setDialogInsets(LPY20, LPX20, LPY20, LPX20); setPanelInsets(LPY16, LPX16, LPY16, LPX16); break; case GNOME: setRelatedGap(LPX6, LPY6); // GNOME HIG 8.2.3 setUnrelatedGap(LPX12, LPY12); // GNOME HIG 8.2.3 setParagraphGap(LPX18, LPY18); // GNOME HIG 8.2.3 setIndentGap(LPX12, LPY12); // GNOME HIG 8.2.3 setGridCellGap(LPX6, LPY6); // GNOME HIG 8.2.3 // GtkButtonBox, child-min-width property default value setMinimumButtonWidth(new UnitValue(85, UnitValue.LPX, null)); setButtonOrder("L_HE+UNYACBXO_I_R"); // GNOME HIG 3.4.2, 3.7.1 setDialogInsets(LPY12, LPX12, LPY12, LPX12); // GNOME HIG 3.4.3 setPanelInsets(LPY6, LPX6, LPY6, LPX6); // ??? break; default: throw new IllegalArgumentException("Unknown platform: " + plaf); } CUR_PLAF = plaf; BASE_DPI = BASE_DPI_FORCED != null ? BASE_DPI_FORCED : getPlatformDPI(plaf); } /** Sets the visual bounds for a component type. * @param key The component type. E.g. "TabbedPane.visualPadding" or "ComboBox.editable.isSquare.visualPadding". See source code for list. * @param insets Top, left, bottom, right. Always length 4 or null. * @see net.miginfocom.layout.ComponentWrapper#getVisualPadding() */ public static void setDefaultVisualPadding(String key, int[] insets) { VISUAL_BOUNDS.put(key, insets); } /** Returns the visual bounds for a component type. * @param key The component type. E.g. "TabbedPane.visualPadding" or "ComboBox.editable.isSquare.visualPadding". See source code for list. * @return insets Top, left, bottom, right. Always length 4 or null. Live object, MUST NOT BE CHANGED!. * @see net.miginfocom.layout.ComponentWrapper#getVisualPadding() */ public static int[] getDefaultVisualPadding(String key) { return VISUAL_BOUNDS.get(key); } public static int getPlatformDPI(int plaf) { switch (plaf) { case WINDOWS_XP: case GNOME: return 96; case MAC_OSX: try { return java.awt.Toolkit.getDefaultToolkit().getScreenResolution(); } catch (Throwable t) { return 72; } default: throw new IllegalArgumentException("Unknown platform: " + plaf); } } /** Returns the current platform * @return PlatformDefaults.WINDOWS or PlatformDefaults.MAC_OSX */ public static int getPlatform() { return CUR_PLAF; } public static int getDefaultDPI() { return BASE_DPI; } /** Sets the default platform DPI. Normally this is set in the {@link #setPlatform(int)} for the different platforms * but it can be tweaked here. For instance SWT on Mac does this. *

* Note that this is not the actual current DPI, but the base DPI for the toolkit. * @param dpi The base DPI. If null the default DPI is reset to the platform base DPI. */ public static void setDefaultDPI(Integer dpi) { BASE_DPI = dpi != null ? dpi : getPlatformDPI(CUR_PLAF); BASE_DPI_FORCED = dpi; } /** The forced scale factor that all screen relative units (e.g. millimeters, inches and logical pixels) will be multiplied * with. If null this will default to a scale that will scale the current screen to the default screen resolution * (72 DPI for Mac and 92 DPI for Windows). * @return The forced scale or null for default scaling. * @see #getHorizontalScaleFactor() * @see ComponentWrapper#getHorizontalScreenDPI() */ public static Float getHorizontalScaleFactor() { return horScale; } /** The forced scale factor that all screen relative units (e.g. millimeters, inches and logical pixels) will be multiplied * with. If null this will default to a scale that will scale the current screen to the default screen resolution * (72 DPI for Mac and 92 DPI for Windows). * @param f The forced scale or null for default scaling. * @see #getHorizontalScaleFactor() * @see ComponentWrapper#getHorizontalScreenDPI() */ public static void setHorizontalScaleFactor(Float f) { if (!LayoutUtil.equals(horScale, f)) { horScale = f; MOD_COUNT++; } } /** The forced scale factor that all screen relative units (e.g. millimeters, inches and logical pixels) will be multiplied * with. If null this will default to a scale that will scale the current screen to the default screen resolution * (72 DPI for Mac and 92 DPI for Windows). * @return The forced scale or null for default scaling. * @see #getHorizontalScaleFactor() * @see ComponentWrapper#getVerticalScreenDPI() */ public static Float getVerticalScaleFactor() { return verScale; } /** The forced scale factor that all screen relative units (e.g. millimeters, inches and logical pixels) will be multiplied * with. If null this will default to a scale that will scale the current screen to the default screen resolution * (72 DPI for Mac and 92 DPI for Windows). * @param f The forced scale or null for default scaling. * @see #getHorizontalScaleFactor() * @see ComponentWrapper#getVerticalScreenDPI() */ public static void setVerticalScaleFactor(Float f) { if (!LayoutUtil.equals(verScale, f)) { verScale = f; MOD_COUNT++; } } /** What base value should be used to calculate logical pixel sizes. * @return The current base. Default is {@link #BASE_SCALE_FACTOR} * @see #BASE_FONT_SIZE * @see #BASE_SCALE_FACTOR * @see #BASE_REAL_PIXEL */ public static int getLogicalPixelBase() { return LP_BASE; } /** What base value should be used to calculate logical pixel sizes. * @param base The new base. Default is {@link #BASE_SCALE_FACTOR} * @see #BASE_FONT_SIZE * @see #BASE_SCALE_FACTOR * @see #BASE_REAL_PIXEL */ public static void setLogicalPixelBase(int base) { if (LP_BASE != base) { if (base < BASE_FONT_SIZE || base > BASE_REAL_PIXEL) throw new IllegalArgumentException("Unrecognized base: " + base); LP_BASE = base; MOD_COUNT++; } } /** Sets gap value for components that are "related". * @param x The value that will be transformed to pixels. If null the current value will not change. * @param y The value that will be transformed to pixels. If null the current value will not change. */ public static void setRelatedGap(UnitValue x, UnitValue y) { setUnitValue(new String[] {"r", "rel", "related"}, x, y); RELATED_X = new BoundSize(x, x, null, "rel:rel"); RELATED_Y = new BoundSize(y, y, null, "rel:rel"); } /** Sets gap value for components that are "unrelated". * @param x The value that will be transformed to pixels. If null the current value will not change. * @param y The value that will be transformed to pixels. If null the current value will not change. */ public static void setUnrelatedGap(UnitValue x, UnitValue y) { setUnitValue(new String[] {"u", "unrel", "unrelated"}, x, y); UNRELATED_X = new BoundSize(x, x, null, "unrel:unrel"); UNRELATED_Y = new BoundSize(y, y, null, "unrel:unrel"); } /** Sets paragraph gap value for components. * @param x The value that will be transformed to pixels. If null the current value will not change. * @param y The value that will be transformed to pixels. If null the current value will not change. */ public static void setParagraphGap(UnitValue x, UnitValue y) { setUnitValue(new String[] {"p", "para", "paragraph"}, x, y); } /** Sets gap value for components that are "intended". * @param x The value that will be transformed to pixels. If null the current value will not change. * @param y The value that will be transformed to pixels. If null the current value will not change. */ public static void setIndentGap(UnitValue x, UnitValue y) { setUnitValue(new String[] {"i", "ind", "indent"}, x, y); } /** Sets gap between two cells in the grid. Note that this is not a gap between component IN a cell, that has to be set * on the component constraints. The value will be the min and preferred size of the gap. * @param x The value that will be transformed to pixels. If null the current value will not change. * @param y The value that will be transformed to pixels. If null the current value will not change. */ public static void setGridCellGap(UnitValue x, UnitValue y) { if (x != null) DEF_HGAP = new BoundSize(x, x, null, null); if (y != null) DEF_VGAP = new BoundSize(y, y, null, null); MOD_COUNT++; } /** Sets the recommended minimum button width. * @param width The recommended minimum button width. */ public static void setMinimumButtonWidth(UnitValue width) { BUTT_WIDTH = width; MOD_COUNT++; } /** Returns the recommended minimum button width depending on the current set platform. * @return The recommended minimum button width depending on the current set platform. */ public static UnitValue getMinimumButtonWidth() { return BUTT_WIDTH; } public static void setMinimumButtonPadding(UnitValue padding) { BUTT_PADDING = padding; MOD_COUNT++; } public static UnitValue getMinimumButtonPadding() { return BUTT_PADDING; } public static float getMinimumButtonWidthIncludingPadding(float refValue, ContainerWrapper parent, ComponentWrapper comp) { final int buttonMinWidth = getMinimumButtonWidth().getPixels(refValue, parent, comp); if (comp != null && getMinimumButtonPadding() != null) { return Math.max(comp.getMinimumWidth(comp.getWidth()) + getMinimumButtonPadding().getPixels(refValue, parent, comp) * 2, buttonMinWidth); } else { return buttonMinWidth; } } /** Returns the unit value associated with the unit. (E.i. "related" or "indent"). Must be lower case. * @param unit The unit string. * @return The unit value associated with the unit. null for unrecognized units. */ public static UnitValue getUnitValueX(String unit) { return HOR_DEFS.get(unit); } /** Returns the unit value associated with the unit. (E.i. "related" or "indent"). Must be lower case. * @param unit The unit string. * @return The unit value associated with the unit. null for unrecognized units. */ public static UnitValue getUnitValueY(String unit) { return VER_DEFS.get(unit); } /** Sets the unit value associated with a unit string. This may be used to store values for new unit strings * or modify old. Note that if a built in unit (such as "related") is modified all versions of it must be * set (I.e. "r", "rel" and "related"). The build in values will be reset to the default ones if the platform * is re-set. * @param unitStrings The unit strings. E.g. "mu", "myunit". Will be converted to lower case and trimmed. Not null. * @param x The value for the horizontal dimension. If null the value is not changed. * @param y The value for the vertical dimension. Might be same object as for x. If null the value is not changed. */ public static void setUnitValue(String[] unitStrings, UnitValue x, UnitValue y) { for (String unitString : unitStrings) { String s = unitString.toLowerCase().trim(); if (x != null) HOR_DEFS.put(s, x); if (y != null) VER_DEFS.put(s, y); } MOD_COUNT++; } /** Understands ("r", "rel", "related") OR ("u", "unrel", "unrelated") OR ("i", "ind", "indent") OR ("p", "para", "paragraph"). */ static int convertToPixels(float value, String unit, boolean isHor, float ref, ContainerWrapper parent, ComponentWrapper comp) { UnitValue uv = (isHor ? HOR_DEFS : VER_DEFS).get(unit); return uv != null ? Math.round(value * uv.getPixels(ref, parent, comp)) : UnitConverter.UNABLE; } /** Returns the order for the typical buttons in a standard button bar. It is one letter per button type. * @return The button order. * @see #setButtonOrder(String) */ public static String getButtonOrder() { return BUTTON_FORMAT; } /** Sets the order for the typical buttons in a standard button bar. It is one letter per button type. *

* Letter in upper case will get the minimum button width that the {@link #getMinimumButtonWidth()} specifies * and letters in lower case will get the width the current look&feel specifies. *

* Gaps will never be added to before the first component or after the last component. However, '+' (push) will be * applied before and after as well, but with a minimum size of 0 if first/last so there will not be a gap * before or after. *

* If gaps are explicitly set on buttons they will never be reduced, but they may be increased. *

* These are the characters that can be used: *

    *
  • 'L' - Buttons with this style tag will statically end up on the left end of the bar. *
  • 'R' - Buttons with this style tag will statically end up on the right end of the bar. *
  • 'H' - A tag for the "help" button that normally is supposed to be on the right. *
  • 'E' - A tag for the "help2" button that normally is supposed to be on the left. *
  • 'Y' - A tag for the "yes" button. *
  • 'N' - A tag for the "no" button. *
  • 'X' - A tag for the "next >" or "forward >" button. *
  • 'B' - A tag for the "< back" or "< previous" button. *
  • 'I' - A tag for the "finish" button. *
  • 'A' - A tag for the "apply" button. *
  • 'C' - A tag for the "cancel" or "close" button. *
  • 'O' - A tag for the "ok" or "done" button. *
  • 'U' - All Uncategorized, Other, or "Unknown" buttons. Tag will be "other". *
  • '+' - A glue push gap that will take as much space as it can and at least an "unrelated" gap. (Platform dependent) *
  • '_' - (underscore) An "unrelated" gap. (Platform dependent) *
*

* Even though the style tags are normally applied to buttons this works with all components. *

* The normal style for MAC OS X is "L_HE+U+NYBXCOA_I_R", * for Windows is "L_E+U+YNBXOCAH_I_R", and for GNOME is * "L_HE+UNYACBXO_I_R". * * @param order The new button order for the current platform. */ public static void setButtonOrder(String order) { BUTTON_FORMAT = order; MOD_COUNT++; } /** Returns the tag (used in the {@link CC}) for a char. The char is same as used in {@link #getButtonOrder()}. * @param c The char. Must be lower case! * @return The tag that corresponds to the char or null if the char is unrecognized. */ static String getTagForChar(char c) { switch (c) { case 'o': return "ok"; case 'c': return "cancel"; case 'h': return "help"; case 'e': return "help2"; case 'y': return "yes"; case 'n': return "no"; case 'a': return "apply"; case 'x': return "next"; // a.k.a forward case 'b': return "back"; // a.k.a. previous case 'i': return "finish"; case 'l': return "left"; case 'r': return "right"; case 'u': return "other"; default: return null; } } /** Returns the platform recommended inter-cell gap in the horizontal (x) dimension.. * @return The platform recommended inter-cell gap in the horizontal (x) dimension.. */ public static BoundSize getGridGapX() { return DEF_HGAP; } /** Returns the platform recommended inter-cell gap in the vertical (x) dimension.. * @return The platform recommended inter-cell gap in the vertical (x) dimension.. */ public static BoundSize getGridGapY() { return DEF_VGAP; } /** Returns the default dialog insets depending of the current platform. * @param side top == 0, left == 1, bottom = 2, right = 3. * @return The insets. Never null. */ public static UnitValue getDialogInsets(int side) { return DIALOG_INS[side]; } /** Sets the default insets for a dialog. Values that are null will not be changed. * @param top The top inset. May be null. * @param left The left inset. May be null. * @param bottom The bottom inset. May be null. * @param right The right inset. May be null. */ public static void setDialogInsets(UnitValue top, UnitValue left, UnitValue bottom, UnitValue right) { if (top != null) DIALOG_INS[0] = top; if (left != null) DIALOG_INS[1] = left; if (bottom != null) DIALOG_INS[2] = bottom; if (right != null) DIALOG_INS[3] = right; MOD_COUNT++; } /** Returns the default panel insets depending of the current platform. * @param side top == 0, left == 1, bottom = 2, right = 3. * @return The insets. Never null. */ public static UnitValue getPanelInsets(int side) { return PANEL_INS[side]; } /** Sets the default insets for a dialog. Values that are null will not be changed. * @param top The top inset. May be null. * @param left The left inset. May be null. * @param bottom The bottom inset. May be null. * @param right The right inset. May be null. */ public static void setPanelInsets(UnitValue top, UnitValue left, UnitValue bottom, UnitValue right) { if (top != null) PANEL_INS[0] = top; if (left != null) PANEL_INS[1] = left; if (bottom != null) PANEL_INS[2] = bottom; if (right != null) PANEL_INS[3] = right; MOD_COUNT++; } /** Returns the percentage used for alignment for labels (0 is left, 50 is center and 100 is right). * @return The percentage used for alignment for labels */ public static float getLabelAlignPercentage() { return CUR_PLAF == MAC_OSX ? 1f : 0f; } /** Returns the default gap between two components that are in the same cell. * @param comp The component that the gap is for. Never null. * @param adjacentComp The adjacent component if any. May be null. * @param adjacentSide What side the adjacentComp is on. {@link javax.swing.SwingUtilities#TOP} (1) or * {@link javax.swing.SwingUtilities#LEFT} (2) or {@link javax.swing.SwingUtilities#BOTTOM} (3) or {@link javax.swing.SwingUtilities#RIGHT} (4). * @param tag The tag string that the component might be tagged with in the component constraints. May be null. * @param isLTR If it is left-to-right. * @return The default gap between two components or null if there should be no gap. */ static BoundSize getDefaultComponentGap(ComponentWrapper comp, ComponentWrapper adjacentComp, int adjacentSide, String tag, boolean isLTR) { if (GAP_PROVIDER != null) return GAP_PROVIDER.getDefaultGap(comp, adjacentComp, adjacentSide, tag, isLTR); if (adjacentComp == null) return null; // if (adjacentComp == null || adjacentSide == SwingConstants.LEFT || adjacentSide == SwingConstants.TOP) // return null; // SwingConstants.RIGHT == 4, SwingConstants.LEFT == 2 return (adjacentSide == 2 || adjacentSide == 4) ? RELATED_X : RELATED_Y; } /** Returns the current gap provider or null if none is set and "related" should always be used. * @return The current gap provider or null if none is set and "related" should always be used. */ public static InCellGapProvider getGapProvider() { return GAP_PROVIDER; } /** Sets the current gap provider or null if none is set and "related" should always be used. * @param provider The current gap provider or null if none is set and "related" should always be used. */ public static void setGapProvider(InCellGapProvider provider) { GAP_PROVIDER = provider; } /** Returns how many times the defaults has been changed. This can be used as a light weight check to * see if layout caches needs to be refreshed. * @return How many times the defaults has been changed. */ public static int getModCount() { return MOD_COUNT; } /** Tells all layout manager instances to revalidate and recalculated everything. */ public void invalidate() { MOD_COUNT++; } /** Returns the current default unit. The default unit is the unit used if no unit is set. E.g. "width 10". * @return The current default unit. * @see UnitValue#PIXEL * @see UnitValue#LPX */ public static int getDefaultHorizontalUnit() { return DEF_H_UNIT; } /** Sets the default unit. The default unit is the unit used if no unit is set. E.g. "width 10". * @param unit The new default unit. * @see UnitValue#PIXEL * @see UnitValue#LPX */ public static void setDefaultHorizontalUnit(int unit) { if (unit < UnitValue.PIXEL || unit > UnitValue.LABEL_ALIGN) throw new IllegalArgumentException("Illegal Unit: " + unit); if (DEF_H_UNIT != unit) { DEF_H_UNIT = unit; MOD_COUNT++; } } /** Returns the current default unit. The default unit is the unit used if no unit is set. E.g. "width 10". * @return The current default unit. * @see UnitValue#PIXEL * @see UnitValue#LPY */ public static int getDefaultVerticalUnit() { return DEF_V_UNIT; } /** Sets the default unit. The default unit is the unit used if no unit is set. E.g. "width 10". * @param unit The new default unit. * @see UnitValue#PIXEL * @see UnitValue#LPY */ public static void setDefaultVerticalUnit(int unit) { if (unit < UnitValue.PIXEL || unit > UnitValue.LABEL_ALIGN) throw new IllegalArgumentException("Illegal Unit: " + unit); if (DEF_V_UNIT != unit) { DEF_V_UNIT = unit; MOD_COUNT++; } } /** The default alignment for rows. Pre v3.5 this was false but now it is * true. * @return The current value. Default is true. * @since 3.5 */ public static boolean getDefaultRowAlignmentBaseline() { return dra; } /** The default alignment for rows. Pre v3.5 this was false but now it is * true. * @param b The new value. Default is true from v3.5. * @since 3.5 */ public static void setDefaultRowAlignmentBaseline(boolean b) { dra = b; } } miglayout-5.1/core/src/main/java/net/miginfocom/layout/ResizeConstraint.java000077500000000000000000000066621324101563200273720ustar00rootroot00000000000000package net.miginfocom.layout; import java.io.*; /* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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 */ /** A parsed constraint that specifies how an entity (normally column/row or component) can shrink or * grow compared to other entities. */ final class ResizeConstraint implements Externalizable { static final Float WEIGHT_100 = 100f; /** How flexible the entity should be, relative to other entities, when it comes to growing. null or * zero mean it will never grow. An entity that has twice the growWeight compared to another entity will get twice * as much of available space. *

* "grow" are only compared within the same "growPrio". */ Float grow = null; /** The relative priority used for determining which entities gets the extra space first. */ int growPrio = 100; Float shrink = WEIGHT_100; int shrinkPrio = 100; public ResizeConstraint() // For Externalizable { } ResizeConstraint(int shrinkPrio, Float shrinkWeight, int growPrio, Float growWeight) { this.shrinkPrio = shrinkPrio; this.shrink = shrinkWeight; this.growPrio = growPrio; this.grow = growWeight; } // ************************************************ // Persistence Delegate and Serializable combined. // ************************************************ private Object readResolve() throws ObjectStreamException { return LayoutUtil.getSerializedObject(this); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { LayoutUtil.setSerializedObject(this, LayoutUtil.readAsXML(in)); } @Override public void writeExternal(ObjectOutput out) throws IOException { if (getClass() == ResizeConstraint.class) LayoutUtil.writeAsXML(out, this); } } miglayout-5.1/core/src/main/java/net/miginfocom/layout/UnitConverter.java000077500000000000000000000062051324101563200266640ustar00rootroot00000000000000package net.miginfocom.layout; /* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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 */ /** */ public abstract class UnitConverter { /** Value to return if this converter can not handle the unit sent in as an argument * to the convert method. */ public static final int UNABLE = -87654312; /** Converts value to pixels. * @param value The value to be converted. * @param unit The unit of value. Never null and at least one character. * @param refValue Some reference value that may of may not be used. If the unit is percent for instance this value * is the value to take the percent from. Usually the size of the parent component in the appropriate dimension. * @param isHor If the value is horizontal (true) or vertical (false). * @param parent The parent of the target component that value is to be applied to. * Might for instance be needed to get the screen that the component is on in a multi screen environment. *

* May be null in which case a "best guess" value should be returned. * @param comp The component, if applicable, or null if none. * @return The number of pixels if unit is handled by this converter, UnitConverter.UNABLE if not. */ public abstract int convertToPixels(float value, String unit, boolean isHor, float refValue, ContainerWrapper parent, ComponentWrapper comp); } miglayout-5.1/core/src/main/java/net/miginfocom/layout/UnitValue.java000077500000000000000000000520111324101563200257650ustar00rootroot00000000000000package net.miginfocom.layout; /* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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 */ import java.beans.Encoder; import java.beans.Expression; import java.beans.PersistenceDelegate; import java.io.*; import java.util.ArrayList; import java.util.HashMap; public final class UnitValue implements Serializable { private static final HashMap UNIT_MAP = new HashMap(32); private static final ArrayList CONVERTERS = new ArrayList(); /** An operation indicating a static value. */ public static final int STATIC = 100; /** An operation indicating a addition of two sub units. */ public static final int ADD = 101; // Must have "sub-unit values" /** An operation indicating a subtraction of two sub units */ public static final int SUB = 102; // Must have "sub-unit values" /** An operation indicating a multiplication of two sub units. */ public static final int MUL = 103; // Must have "sub-unit values" /** An operation indicating a division of two sub units. */ public static final int DIV = 104; // Must have "sub-unit values" /** An operation indicating the minimum of two sub units */ public static final int MIN = 105; // Must have "sub-unit values" /** An operation indicating the maximum of two sub units */ public static final int MAX = 106; // Must have "sub-unit values" /** An operation indicating the middle value of two sub units */ public static final int MID = 107; // Must have "sub-unit values" /** A unit indicating pixels. */ public static final int PIXEL = 0; /** A unit indicating logical horizontal pixels. */ public static final int LPX = 1; /** A unit indicating logical vertical pixels. */ public static final int LPY = 2; /** A unit indicating millimeters. */ public static final int MM = 3; /** A unit indicating centimeters. */ public static final int CM = 4; /** A unit indicating inches. */ public static final int INCH = 5; /** A unit indicating percent. */ public static final int PERCENT = 6; /** A unit indicating points. */ public static final int PT = 7; /** A unit indicating screen percentage width. */ public static final int SPX = 8; /** A unit indicating screen percentage height. */ public static final int SPY = 9; /** A unit indicating alignment. */ public static final int ALIGN = 12; /** A unit indicating minimum size. */ public static final int MIN_SIZE = 13; /** A unit indicating preferred size. */ public static final int PREF_SIZE = 14; /** A unit indicating maximum size. */ public static final int MAX_SIZE = 15; /** A unit indicating button size. */ public static final int BUTTON = 16; /** A unit indicating linking to x. */ public static final int LINK_X = 18; // First link /** A unit indicating linking to y. */ public static final int LINK_Y = 19; /** A unit indicating linking to width. */ public static final int LINK_W = 20; /** A unit indicating linking to height. */ public static final int LINK_H = 21; /** A unit indicating linking to x2. */ public static final int LINK_X2 = 22; /** A unit indicating linking to y2. */ public static final int LINK_Y2 = 23; /** A unit indicating linking to x position on screen. */ public static final int LINK_XPOS = 24; /** A unit indicating linking to y position on screen. */ public static final int LINK_YPOS = 25; // Last link /** A unit indicating a lookup. */ public static final int LOOKUP = 26; /** A unit indicating label alignment. */ public static final int LABEL_ALIGN = 27; private static final int IDENTITY = -1; static { UNIT_MAP.put("px", PIXEL); UNIT_MAP.put("lpx", LPX); UNIT_MAP.put("lpy", LPY); UNIT_MAP.put("%", PERCENT); UNIT_MAP.put("cm", CM); UNIT_MAP.put("in", INCH); UNIT_MAP.put("spx", SPX); UNIT_MAP.put("spy", SPY); UNIT_MAP.put("al", ALIGN); UNIT_MAP.put("mm", MM); UNIT_MAP.put("pt", PT); UNIT_MAP.put("min", MIN_SIZE); UNIT_MAP.put("minimum", MIN_SIZE); UNIT_MAP.put("p", PREF_SIZE); UNIT_MAP.put("pref", PREF_SIZE); UNIT_MAP.put("max", MAX_SIZE); UNIT_MAP.put("maximum", MAX_SIZE); UNIT_MAP.put("button", BUTTON); UNIT_MAP.put("label", LABEL_ALIGN); } static final UnitValue ZERO = new UnitValue(0, null, PIXEL, true, STATIC, null, null, "0px"); static final UnitValue TOP = new UnitValue(0, null, PERCENT, false, STATIC, null, null, "top"); static final UnitValue LEADING = new UnitValue(0, null, PERCENT, true, STATIC, null, null, "leading"); static final UnitValue LEFT = new UnitValue(0, null, PERCENT, true, STATIC, null, null, "left"); static final UnitValue CENTER = new UnitValue(50, null, PERCENT, true, STATIC, null, null, "center"); static final UnitValue TRAILING = new UnitValue(100, null, PERCENT, true, STATIC, null, null, "trailing"); static final UnitValue RIGHT = new UnitValue(100, null, PERCENT, true, STATIC, null, null, "right"); static final UnitValue BOTTOM = new UnitValue(100, null, PERCENT, false, STATIC, null, null, "bottom"); static final UnitValue LABEL = new UnitValue(0, null, LABEL_ALIGN, false, STATIC, null, null, "label"); static final UnitValue INF = new UnitValue(LayoutUtil.INF, null, PIXEL, true, STATIC, null, null, "inf"); static final UnitValue BASELINE_IDENTITY = new UnitValue(0, null, IDENTITY, false, STATIC, null, null, "baseline"); private final transient float value; private final transient int unit; private final transient int oper; private final transient String unitStr; private transient String linkId = null; // Should be final, but initializes in a sub method. private final transient boolean isHor; private final transient UnitValue[] subUnits; // Pixel public UnitValue(float value) // If hor/ver does not matter. { this(value, null, PIXEL, true, STATIC, null, null, value + "px"); } public UnitValue(float value, int unit, String createString) // If hor/ver does not matter. { this(value, null, unit, true, STATIC, null, null, createString); } public UnitValue(float value, String unitStr, boolean isHor, int oper, String createString) { this(value, unitStr, -1, isHor, oper, null, null, createString); } UnitValue(boolean isHor, int oper, UnitValue sub1, UnitValue sub2, String createString) { this(0, "", -1, isHor, oper, sub1, sub2, createString); if (sub1 == null || sub2 == null) throw new IllegalArgumentException("Sub units is null!"); } private UnitValue(float value, String unitStr, int unit, boolean isHor, int oper, UnitValue sub1, UnitValue sub2, String createString) { if (oper < STATIC || oper > MID) throw new IllegalArgumentException("Unknown Operation: " + oper); if (oper >= ADD && oper <= MID && (sub1 == null || sub2 == null)) throw new IllegalArgumentException(oper + " Operation may not have null sub-UnitValues."); this.value = value; this.oper = oper; this.isHor = isHor; this.unitStr = unitStr; this.unit = unitStr != null ? parseUnitString() : unit; this.subUnits = sub1 != null && sub2 != null ? new UnitValue[] {sub1, sub2} : null; LayoutUtil.putCCString(this, createString); // "this" escapes!! Safe though. } /** Returns the size in pixels rounded. * @param refValue The reference value. Normally the size of the parent. For unit {@link #ALIGN} the current size of the component should be sent in. * @param parent The parent. May be null for testing the validity of the value, but should normally not and are not * required to return any usable value if null. * @param comp The component, if any, that the value is for. Might be null if the value is not * connected to any component. * @return The size in pixels. */ public final int getPixels(float refValue, ContainerWrapper parent, ComponentWrapper comp) { return Math.round(getPixelsExact(refValue, parent, comp)); } private static final float[] SCALE = new float[] {25.4f, 2.54f, 1f, 0f, 72f}; /** Returns the size in pixels. * @param refValue The reference value. Normally the size of the parent. For unit {@link #ALIGN} the current size of the component should be sent in. * @param parent The parent. May be null for testing the validity of the value, but should normally not and are not * required to return any usable value if null. * @param comp The component, if any, that the value is for. Might be null if the value is not * connected to any component. * @return The size in pixels. */ public final float getPixelsExact(float refValue, ContainerWrapper parent, ComponentWrapper comp) { if (parent == null) return 1; if (oper == STATIC) { switch (unit) { case PIXEL: return value; case LPX: case LPY: return parent.getPixelUnitFactor(unit == LPX) * value; case MM: case CM: case INCH: case PT: float f = SCALE[unit - MM]; Float s = isHor ? PlatformDefaults.getHorizontalScaleFactor() : PlatformDefaults.getVerticalScaleFactor(); if (s != null) f *= s; return (isHor ? parent.getHorizontalScreenDPI() : parent.getVerticalScreenDPI()) * value / f; case PERCENT: return value * refValue * 0.01f; case SPX: case SPY: return (unit == SPX ? parent.getScreenWidth() : parent.getScreenHeight()) * value * 0.01f; case ALIGN: Integer st = LinkHandler.getValue(parent.getLayout(), "visual", isHor ? LinkHandler.X : LinkHandler.Y); Integer sz = LinkHandler.getValue(parent.getLayout(), "visual", isHor ? LinkHandler.WIDTH : LinkHandler.HEIGHT); if (st == null || sz == null) return 0; return value * (Math.max(0, sz.intValue()) - refValue) + st; case MIN_SIZE: if (comp == null) return 0; return isHor ? comp.getMinimumWidth(comp.getHeight()) : comp.getMinimumHeight(comp.getWidth()); case PREF_SIZE: if (comp == null) return 0; return isHor ? comp.getPreferredWidth(comp.getHeight()) : comp.getPreferredHeight(comp.getWidth()); case MAX_SIZE: if (comp == null) return 0; return isHor ? comp.getMaximumWidth(comp.getHeight()) : comp.getMaximumHeight(comp.getWidth()); case BUTTON: return PlatformDefaults.getMinimumButtonWidthIncludingPadding(refValue, parent, comp); case LINK_X: case LINK_Y: case LINK_W: case LINK_H: case LINK_X2: case LINK_Y2: case LINK_XPOS: case LINK_YPOS: Integer v = LinkHandler.getValue(parent.getLayout(), getLinkTargetId(), unit - (unit >= LINK_XPOS ? LINK_XPOS : LINK_X)); if (v == null) return 0; if (unit == LINK_XPOS) return parent.getScreenLocationX() + v; if (unit == LINK_YPOS) return parent.getScreenLocationY() + v; return v; case LOOKUP: float res = lookup(refValue, parent, comp); if (res != UnitConverter.UNABLE) return res; case LABEL_ALIGN: return PlatformDefaults.getLabelAlignPercentage() * refValue; case IDENTITY: } throw new IllegalArgumentException("Unknown/illegal unit: " + unit + ", unitStr: " + unitStr); } if (subUnits != null && subUnits.length == 2) { float r1 = subUnits[0].getPixelsExact(refValue, parent, comp); float r2 = subUnits[1].getPixelsExact(refValue, parent, comp); switch (oper) { case ADD: return r1 + r2; case SUB: return r1 - r2; case MUL: return r1 * r2; case DIV: return r1 / r2; case MIN: return r1 < r2 ? r1 : r2; case MAX: return r1 > r2 ? r1 : r2; case MID: return (r1 + r2) * 0.5f; } } throw new IllegalArgumentException("Internal: Unknown Oper: " + oper); } private float lookup(float refValue, ContainerWrapper parent, ComponentWrapper comp) { float res = UnitConverter.UNABLE; for (int i = CONVERTERS.size() - 1; i >= 0; i--) { res = CONVERTERS.get(i).convertToPixels(value, unitStr, isHor, refValue, parent, comp); if (res != UnitConverter.UNABLE) return res; } return PlatformDefaults.convertToPixels(value, unitStr, isHor, refValue, parent, comp); } private int parseUnitString() { int len = unitStr.length(); if (len == 0) return isHor ? PlatformDefaults.getDefaultHorizontalUnit() : PlatformDefaults.getDefaultVerticalUnit(); Integer u = UNIT_MAP.get(unitStr); if (u != null) { if (!isHor && (u == BUTTON || u == LABEL_ALIGN)) throw new IllegalArgumentException("Not valid in vertical contexts: '" + unitStr + "'"); return u; } if (unitStr.equals("lp")) return isHor ? LPX : LPY; if (unitStr.equals("sp")) return isHor ? SPX : SPY; if (lookup(0, null, null) != UnitConverter.UNABLE) // To test so we can fail fast return LOOKUP; // Only link left. E.g. "otherID.width" int pIx = unitStr.indexOf('.'); if (pIx != -1) { linkId = unitStr.substring(0, pIx); String e = unitStr.substring(pIx + 1); if (e.equals("x")) return LINK_X; if (e.equals("y")) return LINK_Y; if (e.equals("w") || e.equals("width")) return LINK_W; if (e.equals("h") || e.equals("height")) return LINK_H; if (e.equals("x2")) return LINK_X2; if (e.equals("y2")) return LINK_Y2; if (e.equals("xpos")) return LINK_XPOS; if (e.equals("ypos")) return LINK_YPOS; } throw new IllegalArgumentException("Unknown keyword: " + unitStr); } final boolean isAbsolute() { switch (unit) { case PIXEL: case LPX: case LPY: case MM: case CM: case INCH: case PT: return true; case SPX: case SPY: case PERCENT: case ALIGN: case MIN_SIZE: case PREF_SIZE: case MAX_SIZE: case BUTTON: case LINK_X: case LINK_Y: case LINK_W: case LINK_H: case LINK_X2: case LINK_Y2: case LINK_XPOS: case LINK_YPOS: case LOOKUP: case LABEL_ALIGN: return false; case IDENTITY: } throw new IllegalArgumentException("Unknown/illegal unit: " + unit + ", unitStr: " + unitStr); } final boolean isAbsoluteDeep() { if (subUnits != null) { for (UnitValue subUnit : subUnits) { if (subUnit.isAbsoluteDeep()) return true; } } return isAbsolute(); } final boolean isLinked() { return linkId != null; } final boolean isLinkedDeep() { if (subUnits != null) { for (UnitValue subUnit : subUnits) { if (subUnit.isLinkedDeep()) return true; } } return isLinked(); } final String getLinkTargetId() { return linkId; } final UnitValue getSubUnitValue(int i) { return subUnits[i]; } final int getSubUnitCount() { return subUnits != null ? subUnits.length : 0; } public final UnitValue[] getSubUnits() { return subUnits != null ? subUnits.clone() : null; } public final int getUnit() { return unit; } public final String getUnitString() { return unitStr; } public final int getOperation() { return oper; } public final float getValue() { return value; } public final boolean isHorizontal() { return isHor; } @Override final public String toString() { return getClass().getName() + ". Value=" + value + ", unit=" + unit + ", unitString: " + unitStr + ", oper=" + oper + ", isHor: " + isHor; } /** Returns the creation string for this object. Note that {@link LayoutUtil#setDesignTime(ContainerWrapper, boolean)} must be * set to true for the creation strings to be stored. * @return The constraint string or null if none is registered. */ public final String getConstraintString() { return LayoutUtil.getCCString(this); } @Override public final int hashCode() { return (int) (value * 12345) + (oper >>> 5) + unit >>> 17; } /** Adds a global unit converter that can convert from some unit to pixels. *

* This converter will be asked before the platform converter so the values for it (e.g. "related" and "unrelated") * can be overridden. It is however not possible to override the built in ones (e.g. "mm", "pixel" or "lp"). * @param conv The converter. Not null. */ public synchronized static void addGlobalUnitConverter(UnitConverter conv) { if (conv == null) throw new NullPointerException(); CONVERTERS.add(conv); } /** Removed the converter. * @param unit The converter. * @return If there was a converter found and thus removed. */ public synchronized static boolean removeGlobalUnitConverter(UnitConverter unit) { return CONVERTERS.remove(unit); } /** Returns the global converters currently registered. The platform converter will not be in this list. * @return The converters. Never null. */ public synchronized static UnitConverter[] getGlobalUnitConverters() { return CONVERTERS.toArray(new UnitConverter[CONVERTERS.size()]); } /** Returns the current default unit. The default unit is the unit used if no unit is set. E.g. "width 10". * @return The current default unit. * @see #PIXEL * @see #LPX * @deprecated Use {@link PlatformDefaults#getDefaultHorizontalUnit()} and {@link PlatformDefaults#getDefaultVerticalUnit()} instead. */ public static int getDefaultUnit() { return PlatformDefaults.getDefaultHorizontalUnit(); } /** Sets the default unit. The default unit is the unit used if no unit is set. E.g. "width 10". * @param unit The new default unit. * @see #PIXEL * @see #LPX * @deprecated Use {@link PlatformDefaults#setDefaultHorizontalUnit(int)} and {@link PlatformDefaults#setDefaultVerticalUnit(int)} instead. */ public static void setDefaultUnit(int unit) { PlatformDefaults.setDefaultHorizontalUnit(unit); PlatformDefaults.setDefaultVerticalUnit(unit); } static { if(LayoutUtil.HAS_BEANS){ LayoutUtil.setDelegate(UnitValue.class, new PersistenceDelegate() { @Override protected Expression instantiate(Object oldInstance, Encoder out) { UnitValue uv = (UnitValue) oldInstance; String cs = uv.getConstraintString(); if (cs == null) throw new IllegalStateException("Design time must be on to use XML persistence. See LayoutUtil."); return new Expression(oldInstance, ConstraintParser.class, "parseUnitValueOrAlign", new Object[] { uv.getConstraintString(), (uv.isHorizontal() ? Boolean.TRUE : Boolean.FALSE), null }); } }); } } // ************************************************ // Persistence Delegate and Serializable combined. // ************************************************ private static final long serialVersionUID = 1L; private Object readResolve() throws ObjectStreamException { return LayoutUtil.getSerializedObject(this); } private void writeObject(ObjectOutputStream out) throws IOException { if (getClass() == UnitValue.class) LayoutUtil.writeAsXML(out, this); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { LayoutUtil.setSerializedObject(this, LayoutUtil.readAsXML(in)); } } miglayout-5.1/demo/000077500000000000000000000000001324101563200143125ustar00rootroot00000000000000miglayout-5.1/demo/pom.xml000077500000000000000000000044271324101563200156410ustar00rootroot00000000000000 4.0.0 com.miglayout miglayout-parent 5.1-SNAPSHOT ../pom.xml miglayout-demo jar MiGLayout Demo MiGLayout - Demo's for Swing and SWT org.apache.maven.plugins maven-compiler-plugin 3.7.0 1.8 1.8 true none -g:none ${project.groupId} miglayout-swing ${project.version} ${project.groupId} miglayout-swt ${project.version} ${project.groupId} miglayout-javafx ${project.version} ${project.groupId} miglayout-ideutil ${project.version} org.java.net.substance substance 5.3 true miglayout-5.1/demo/src/000077500000000000000000000000001324101563200151015ustar00rootroot00000000000000miglayout-5.1/demo/src/main/000077500000000000000000000000001324101563200160255ustar00rootroot00000000000000miglayout-5.1/demo/src/main/java/000077500000000000000000000000001324101563200167465ustar00rootroot00000000000000miglayout-5.1/demo/src/main/java/net/000077500000000000000000000000001324101563200175345ustar00rootroot00000000000000miglayout-5.1/demo/src/main/java/net/miginfocom/000077500000000000000000000000001324101563200216635ustar00rootroot00000000000000miglayout-5.1/demo/src/main/java/net/miginfocom/demo/000077500000000000000000000000001324101563200226075ustar00rootroot00000000000000miglayout-5.1/demo/src/main/java/net/miginfocom/demo/CallbackDemo.java000077500000000000000000000146541324101563200257700ustar00rootroot00000000000000package net.miginfocom.demo; import net.miginfocom.layout.BoundSize; import net.miginfocom.layout.ComponentWrapper; import net.miginfocom.layout.LayoutCallback; import net.miginfocom.layout.UnitValue; import net.miginfocom.swing.MigLayout; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.IdentityHashMap; /* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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 */ public class CallbackDemo extends JFrame implements ActionListener, MouseMotionListener, MouseListener { private final Timer repaintTimer = new Timer(20, new ActionListener() { public void actionPerformed(ActionEvent e) { ((JPanel) getContentPane()).revalidate(); } }); private final IdentityHashMap pressMap = new IdentityHashMap(); private Point mousePos = null; public CallbackDemo() { super("MiG Layout Callback Demo"); MigLayout migLayout = new MigLayout("align center bottom, insets 30"); final JPanel panel = new JPanel(migLayout) { protected void paintComponent(Graphics g) { ((Graphics2D) g).setPaint(new GradientPaint(0, getHeight() / 2, Color.WHITE, 0, getHeight(), new Color(240, 238, 235))); g.fillRect(0, 0, getWidth(), getHeight()); } }; setContentPane(panel); // This callback methods will be called for every layout cycle and let you make correction before and after the calculations. migLayout.addLayoutCallback(new LayoutCallback() { // This is the size change part public BoundSize[] getSize(ComponentWrapper comp) { if (comp.getComponent() instanceof JButton) { Component c = (Component) comp.getComponent(); Point p = mousePos != null ? SwingUtilities.convertPoint(panel, mousePos, c) : new Point(-1000, -1000); float fact = (float) Math.sqrt(Math.pow(Math.abs(p.x - c.getWidth() / 2f), 2) + Math.pow(Math.abs(p.y - c.getHeight() / 2f), 2)); fact = Math.max(2 - (fact / 200), 1); return new BoundSize[] {new BoundSize(new UnitValue(70 * fact), ""), new BoundSize(new UnitValue(70 * fact), "")}; } return null; } // This is the jumping part public void correctBounds(ComponentWrapper c) { Long pressedNanos = pressMap.get(c.getComponent()); if (pressedNanos != null) { long duration = System.nanoTime() - pressedNanos; double maxHeight = 100.0 - (duration / 100000000.0); int deltaY = (int) Math.round(Math.abs(Math.sin((duration) / 300000000.0) * maxHeight)); c.setBounds(c.getX(), c.getY() - deltaY, c.getWidth(), c.getHeight()); if (maxHeight < 0.5) { pressMap.remove(c.getComponent()); if (pressMap.size() == 0) repaintTimer.stop(); } } } }); for (int j = 0; j < 10; j++) panel.add(createButton(j), "aligny 0.8al"); JLabel label = new JLabel("Press one of those Swing JButtons!"); label.setFont(new Font("verdana", Font.PLAIN, 24)); label.setForeground(new Color(150, 150, 150)); panel.add(label, "pos 0.5al 0.2al"); panel.addMouseMotionListener(this); panel.addMouseListener(this); } private static Font[] FONTS = new Font[120]; private JButton createButton(int i) { JButton button = new JButton(String.valueOf("MIG LAYOUT".charAt(i))) { public Font getFont() { if (FONTS[0] == null) { for (int i = 0; i < FONTS.length; i++) FONTS[i] = new Font("tahoma", Font.PLAIN, i); } return FONTS[getWidth() >> 1]; } }; button.setForeground(new Color(100, 100, 100)); button.setFocusPainted(false); button.addMouseMotionListener(this); button.addActionListener(this); button.setMargin(new Insets(0, 0, 0, 0)); return button; } public void mouseDragged(MouseEvent e) {} public void mouseMoved(MouseEvent e) { if (e.getSource() instanceof JButton) { mousePos = SwingUtilities.convertPoint((Component) e.getSource(), e.getPoint(), getContentPane()); } else { mousePos = e.getPoint(); } ((JPanel) getContentPane()).revalidate(); } public void mousePressed(MouseEvent e) {} public void mouseReleased(MouseEvent e) {} public void mouseClicked(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) { mousePos = null; ((JPanel) getContentPane()).revalidate(); } public void actionPerformed(ActionEvent e) { pressMap.put(e.getSource(), System.nanoTime()); repaintTimer.start(); } public static void main(String args[]) { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception ex) {} CallbackDemo demoFrame = new CallbackDemo(); demoFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); demoFrame.setSize(970, 500); demoFrame.setLocationRelativeTo(null); demoFrame.setVisible(true); } }miglayout-5.1/demo/src/main/java/net/miginfocom/demo/HiDPISimulator.java000077500000000000000000000437671324101563200262730ustar00rootroot00000000000000package net.miginfocom.demo; //import org.jvnet.substance.SubstanceLookAndFeel; //import org.jvnet.substance.fonts.SubstanceFontUtilities; //import org.jvnet.substance.skin.SubstanceBusinessBlackSteelLookAndFeel; /* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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 */ // Since Substance Look & Fell is discontinued, so is this HiDPI Simulator. /** A demo application that shows some components in a GUI and how they will look on a HiDPI screen. */ public class HiDPISimulator { // static final String SYSTEM_LAF_NAME = "System"; // static final String SUBSTANCE_LAF_NAME = "Substance"; // static final String OCEAN_LAF_NAME = "Ocean"; // static final String NUMBUS_LAF_NAME = "Nimbus (Soon..)"; // // static JFrame APP_GUI_FRAME; // static HiDPIDemoPanel HiDPIDEMO_PANEL; // static JPanel SIM_PANEL; // static JPanel MIRROR_PANEL; // static JScrollPane MAIN_SCROLL; // static JTextArea TEXT_AREA; // // static boolean SCALE_LAF = false; // static boolean SCALE_FONTS = true; // static boolean SCALE_LAYOUT = true; // // static boolean PAINT_GHOSTED = false; // // static BufferedImage GUI_BUF = null; // static BufferedImage ORIG_GUI_BUF = null; // // static int CUR_DPI = PlatformDefaults.getDefaultDPI(); // static HashMap ORIG_DEFAULTS; // // private static JPanel createScaleMirror() // { // return new JPanel(new MigLayout()) { // protected void paintComponent(Graphics g) // { // super.paintComponent(g); // // if (GUI_BUF != null) { // Graphics2D g2 = (Graphics2D) g.create(); // // double dpi = getToolkit().getScreenResolution(); // // AffineTransform oldTrans = g2.getTransform(); // g2.scale(dpi / CUR_DPI, dpi / CUR_DPI); // // g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); // // g2.drawImage(GUI_BUF, 0, 0, null); // // g2.setTransform(oldTrans); // // if (ORIG_GUI_BUF != null && PAINT_GHOSTED) { // g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2f)); // g2.drawImage(ORIG_GUI_BUF, 0, 0, null); // } // // g2.dispose(); // } // } // // public Dimension getPreferredSize() // { // return ORIG_GUI_BUF != null ? new Dimension(ORIG_GUI_BUF.getWidth(), ORIG_GUI_BUF.getHeight()) : new Dimension(100, 100); // } // // public Dimension getMinimumSize() // { // return getPreferredSize(); // } // }; // } // // private static JPanel createSimulator() // { // final JRadioButton scaleCompsFonts = new JRadioButton("UIManager Font Substitution", true); // final JRadioButton scaleCompsLaf = new JRadioButton("Native Look&Feel Scaling", false); // final JRadioButton scaleCompsNone = new JRadioButton("No Scaling", false); // final JRadioButton scaleLayoutMig = new JRadioButton("Native MigLayout Gap Scaling", true); // final JRadioButton scaleLayoutNone = new JRadioButton("No Gap Scaling", false); // final JComboBox lafCombo = new JComboBox(new String[] {SYSTEM_LAF_NAME, SUBSTANCE_LAF_NAME, OCEAN_LAF_NAME, NUMBUS_LAF_NAME}); // // final ButtonGroup bg1 = new ButtonGroup(); // final ButtonGroup bg2 = new ButtonGroup(); // final JCheckBox ghostCheck = new JCheckBox("Overlay \"Optimal\" HiDPI Result"); // // scaleCompsLaf.setEnabled(false); // // bg1.add(scaleCompsFonts); // bg1.add(scaleCompsLaf); // bg1.add(scaleCompsNone); // // bg2.add(scaleLayoutMig); // bg2.add(scaleLayoutNone); // // Vector dpiStrings = new Vector(); // // for (float f = 0.5f; f < 2.01f; f += 0.1f) // dpiStrings.add(Math.round(PlatformDefaults.getDefaultDPI() * f) + " DPI (" + Math.round(f * 100f + 0.499f) + "%)"); // // final JComboBox dpiCombo = new JComboBox(dpiStrings); // dpiCombo.setSelectedIndex(5); // // JPanel panel = new JPanel(new MigLayout("alignx center, insets 10px, flowy", "[]", "[]3px[]0px[]")); // // JLabel lafLabel = new JLabel("Look & Feel:"); // JLabel sliderLabel = new JLabel("Simulated DPI:"); // JLabel scaleLabel = new JLabel("Component/Text Scaling:"); // JLabel layoutLabel = new JLabel("LayoutManager Scaling:"); // JLabel visualsLabel = new JLabel("Visual Aids:"); // // panel.add(lafLabel, ""); // panel.add(lafCombo, "wrap"); // // panel.add(sliderLabel, ""); // panel.add(dpiCombo, "wrap"); // // panel.add(scaleLabel, ""); // panel.add(scaleCompsFonts, ""); // panel.add(scaleCompsLaf, ""); // panel.add(scaleCompsNone, "wrap"); // // panel.add(layoutLabel, ""); // panel.add(scaleLayoutMig, ""); // panel.add(scaleLayoutNone, "wrap"); // // panel.add(visualsLabel, ""); // panel.add(ghostCheck, ""); // // lockFont(dpiCombo, scaleCompsFonts, scaleCompsLaf, scaleLayoutMig, scaleCompsNone, lafCombo, ghostCheck, panel, lafLabel, sliderLabel, scaleLayoutNone, scaleLabel, layoutLabel, visualsLabel); // // lafCombo.addActionListener(new ActionListener() { // public void actionPerformed(ActionEvent e) // { // GUI_BUF = null; // try { // Object s = lafCombo.getSelectedItem(); // // dpiCombo.setSelectedIndex(5); // // if (s.equals(SYSTEM_LAF_NAME)) { // UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); // } else if (s.equals(SUBSTANCE_LAF_NAME)) { // UIManager.setLookAndFeel(new SubstanceBusinessBlackSteelLookAndFeel()); // } else if (s.equals(OCEAN_LAF_NAME)) { // UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); // } else { // JOptionPane.showMessageDialog(APP_GUI_FRAME, "Nimbus will be included as soon as it is ready!"); // } // // if (ORIG_DEFAULTS != null) { // for (String key : ORIG_DEFAULTS.keySet()) // UIManager.put(key, null); // } // ORIG_DEFAULTS = null; // // if (UIManager.getLookAndFeel().getName().toLowerCase().contains("windows")) { // UIManager.put("TextArea.font", UIManager.getFont("TextField.font")); // } else { // UIManager.put("TextArea.font", null); // } // // SwingUtilities.updateComponentTreeUI(APP_GUI_FRAME); // MAIN_SCROLL.setBorder(null); // // if (s.equals(SYSTEM_LAF_NAME)) { // if (scaleCompsLaf.isSelected()) // scaleCompsFonts.setSelected(true); // // scaleCompsLaf.setEnabled(false); // // } else if (s.equals(SUBSTANCE_LAF_NAME)) { // scaleCompsLaf.setEnabled(true); // // } else if (s.equals(OCEAN_LAF_NAME)) { // if (scaleCompsLaf.isSelected()) // scaleCompsFonts.setSelected(true); // scaleCompsLaf.setEnabled(false); // } // // setDPI(CUR_DPI); // // } catch (Exception ex) { // ex.printStackTrace(); // } // } // }); // // ghostCheck.addActionListener(new ActionListener() { // public void actionPerformed(ActionEvent actionEvent) // { // GUI_BUF = null; // PAINT_GHOSTED = ghostCheck.isSelected(); // APP_GUI_FRAME.repaint(); // } // }); // // scaleLayoutMig.addItemListener(new ItemListener() { // public void itemStateChanged(ItemEvent e) // { // GUI_BUF = null; // SCALE_LAYOUT = scaleLayoutMig.isSelected(); // setDPI(CUR_DPI); // } // }); // // ItemListener il = new ItemListener() { // public void itemStateChanged(ItemEvent e) // { // if (e.getStateChange() == ItemEvent.SELECTED) { // GUI_BUF = null; // SCALE_LAF = scaleCompsLaf.isSelected(); // SCALE_FONTS = scaleCompsFonts.isSelected(); // setDPI(CUR_DPI); // } // } // }; // // scaleCompsLaf.addItemListener(il); // scaleCompsFonts.addItemListener(il); // scaleCompsNone.addItemListener(il); // // dpiCombo.addItemListener(new ItemListener() { // public void itemStateChanged(ItemEvent e) // { // if (e.getStateChange() == ItemEvent.SELECTED) { // GUI_BUF = null; // CUR_DPI = Integer.parseInt(dpiCombo.getSelectedItem().toString().substring(0, 3).trim()); // setDPI(CUR_DPI); // } // } // }); // // return panel; // } // // private static void lockFont(Component ... comps) // { // for (Component c : comps) { // Font f = c.getFont(); // c.setFont(f.deriveFont((float) f.getSize())); // } // } // // private static void revalidateGUI() // { // APP_GUI_FRAME.getContentPane().invalidate(); // APP_GUI_FRAME.repaint(); // } // // private synchronized static void setDPI(int dpi) // { // float scaleFactor = dpi / (float) Toolkit.getDefaultToolkit().getScreenResolution(); // TEXT_AREA.setSize(0, 0); // To reset for Swing TextArea horizontal size bug... // PlatformDefaults.setHorizontalScaleFactor(.1f);// Only so that the cache will be invalidated for sure // PlatformDefaults.setHorizontalScaleFactor(SCALE_LAYOUT ? scaleFactor : null); // PlatformDefaults.setVerticalScaleFactor(SCALE_LAYOUT ? scaleFactor : null); // // float fontScale = SCALE_FONTS ? dpi / (float) Toolkit.getDefaultToolkit().getScreenResolution() : 1f; // // if (ORIG_DEFAULTS == null) { // ORIG_DEFAULTS = new HashMap(); // // Set entries = new HashSet(UIManager.getLookAndFeelDefaults().keySet()); // for (Iterator it = entries.iterator(); it.hasNext();) { // String key = it.next().toString(); // Object value = UIManager.get(key); // // if (value instanceof Font) // ORIG_DEFAULTS.put(key, (Font) value); // } // } // // Set entries = ORIG_DEFAULTS.entrySet(); // for (Iterator> it = entries.iterator(); it.hasNext();) { // Map.Entry e = it.next(); // Font origFont = e.getValue(); // // if (SCALE_LAF == false) { // UIManager.put(e.getKey(), new FontUIResource(origFont.deriveFont(origFont.getSize() * fontScale))); // } else { // UIManager.put(e.getKey(), null); // } // } // // if (SCALE_LAF) { // scaleSubstanceLAF(scaleFactor); // } else if (UIManager.getLookAndFeel().getName().toLowerCase().contains("substance")) { // scaleSubstanceLAF(1); // } // // SwingUtilities.updateComponentTreeUI(HiDPIDEMO_PANEL); // revalidateGUI(); // } // // private static void scaleSubstanceLAF(float factor) // { // SubstanceLookAndFeel.setFontPolicy(SubstanceFontUtilities.getScaledFontPolicy(factor)); // // try { // UIManager.setLookAndFeel(new SubstanceBusinessBlackSteelLookAndFeel()); // } catch (Exception exc) { // } // // SwingUtilities.updateComponentTreeUI(APP_GUI_FRAME); // MAIN_SCROLL.setBorder(null); // } // // public static void main(String[] args) // { // try { // System.setProperty("apple.laf.useScreenMenuBar", "true"); // System.setProperty("com.apple.mrj.application.apple.menu.about.name", "HiDPI Simulator"); // } catch(Exception ex) {} // // PlatformDefaults.setDefaultHorizontalUnit(UnitValue.LPX); // PlatformDefaults.setDefaultVerticalUnit(UnitValue.LPY); // // SwingUtilities.invokeLater(new Runnable() { // public void run() { // try { //// UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); // UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); // } catch (Exception ex) { // ex.printStackTrace(); // } // // if (UIManager.getLookAndFeel().getName().toLowerCase().contains("windows")) // UIManager.put("TextArea.font", UIManager.getFont("TextField.font")); // // APP_GUI_FRAME = new JFrame("Resolution Independence Simulator"); // //// RepaintManager.currentManager(APP_GUI_FRAME).setDoubleBufferingEnabled(false); // // JPanel uberPanel = new JPanel(new MigLayout("fill, insets 0px, nocache")); // // JPanel mainPanel = new JPanel(new MigLayout("fill, insets 0px, nocache")) { // public void paintComponent(Graphics g) // { // Graphics2D g2 = (Graphics2D) g.create(); // // g2.setPaint(new GradientPaint(0, 0, new Color(20, 20, 30), 0, getHeight(), new Color(90, 90, 110), false)); // g2.fillRect(0, 0, getWidth(), getHeight()); // // g2.setFont(g2.getFont().deriveFont(Font.BOLD, 13)); // g2.setPaint(Color.WHITE); // g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); // // g2.drawString("Left panel shows the scaled version. Right side shows how this would look on a HiDPI screen. It should look the same as the original panel!", 10, 19); // // g2.dispose(); // } // }; // // HiDPIDEMO_PANEL = new HiDPIDemoPanel(); // SIM_PANEL = createSimulator(); // MIRROR_PANEL = createScaleMirror(); // // MAIN_SCROLL = new JScrollPane(mainPanel); // MAIN_SCROLL.setBorder(null); // // mainPanel.add(HiDPIDEMO_PANEL, "align center center, split, span, width pref!"); // mainPanel.add(MIRROR_PANEL, "id mirror, gap 20px!, width pref!"); // // uberPanel.add(SIM_PANEL, "dock south"); // uberPanel.add(MAIN_SCROLL, "dock center"); // // Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); // APP_GUI_FRAME.setContentPane(uberPanel); // APP_GUI_FRAME.setSize(Math.min(1240, screenSize.width), Math.min(950, screenSize.height - 30)); // APP_GUI_FRAME.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); // APP_GUI_FRAME.setLocationRelativeTo(null); // APP_GUI_FRAME.setVisible(true); // } // }); // } //} // //class HiDPIDemoPanel extends JPanel { // public HiDPIDemoPanel() // { // super(new MigLayout()); // // JLabel jLabel1 = new JLabel("A Small Label:"); // JTextField jTextField1 = new JTextField(10); // JButton jButton1 = new JButton("Cancel"); // JButton jButton2 = new JButton("OK"); // JButton jButton4 = new JButton("Help"); // JList jList1 = new JList(); // JLabel jLabel2 = new JLabel("Label:"); // JTextField jTextField2 = new JTextField(10); // JLabel jLabel3 = new JLabel("This is another section"); // JSeparator jSeparator1 = new JSeparator(); // JTextArea jTextArea1 = new JTextArea("Some general text that takes place, doesn't offend anyone and fills some pixels.", 3, 30); // colums set always! // JLabel jLabel4 = new JLabel("Some Text Area"); // JLabel jLabel6 = new JLabel("Some List:"); // JComboBox jComboBox1 = new JComboBox(); // JCheckBox jCheckBox1 = new JCheckBox("Orange"); // // JScrollBar scroll1 = new JScrollBar(JScrollBar.VERTICAL); // JScrollBar scroll2 = new JScrollBar(JScrollBar.HORIZONTAL, 30, 40, 0, 100); // JRadioButton radio = new JRadioButton("Apple"); // JProgressBar prog = new JProgressBar(); // prog.setValue(50); // JSpinner spinner = new JSpinner(new SpinnerNumberModel(50, 0, 100, 1)); // JTree tree = new JTree(); // tree.setOpaque(false); // tree.setEnabled(false); // // jList1.setModel(new AbstractListModel() { // String[] strings = { "Donald Duck", "Mickey Mouse", "Pluto", "Cartman" }; // public int getSize() { return strings.length; } // public Object getElementAt(int i) { return strings[i]; } // }); // // jList1.setVisibleRowCount(4); // jList1.setBorder(new LineBorder(Color.GRAY)); // jTextArea1.setLineWrap(true); // jTextArea1.setWrapStyleWord(true); // jTextArea1.setBorder(new LineBorder(Color.GRAY)); // jComboBox1.setModel(new DefaultComboBoxModel(new String[] {"Text in ComboBox"})); // jCheckBox1.setMargin(new java.awt.Insets(0, 0, 0, 0)); // // add(jLabel1, "split, span"); // add(jTextField1, ""); // add(jLabel2, "gap unrelated"); // add(jTextField2, "wrap"); // add(jLabel3, "split, span"); // add(jSeparator1, "growx, span, gap 2, wrap unrelated"); // add(jLabel4, "wrap 2"); // add(jTextArea1, "span, wmin 150, wrap unrelated"); // add(jLabel6, "wrap 2"); // add(jList1, "split, span"); // add(scroll1, "growy"); // add(prog, "width 80!"); // add(tree, "wrap unrelated"); // // add(scroll2, "split, span, growx"); // add(spinner, "wrap unrelated"); // add(jComboBox1, "span, split"); // add(radio, ""); // add(jCheckBox1, "wrap unrelated"); // add(jButton4, "split, span, tag help2"); // add(jButton2, "tag ok"); // add(jButton1, "tag cancel"); // // HiDPISimulator.TEXT_AREA = jTextArea1; // } // // public void paint(Graphics g) // { // if (HiDPISimulator.GUI_BUF == null) { // BufferedImage bi = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); // // Graphics2D g2 = bi.createGraphics(); // // super.paint(g2); // // g2.dispose(); // // g.drawImage(bi, 0, 0, null); // // HiDPISimulator.GUI_BUF = bi; // // if (HiDPISimulator.CUR_DPI == PlatformDefaults.getDefaultDPI()) // HiDPISimulator.ORIG_GUI_BUF = bi; // // SwingUtilities.invokeLater(new Runnable() { // public void run() { // HiDPISimulator.MIRROR_PANEL.revalidate(); // HiDPISimulator.MIRROR_PANEL.repaint(); // } // }); // } else { // super.paint(g); // } // } } miglayout-5.1/demo/src/main/java/net/miginfocom/demo/JavaFXCallbackDemo.java000066400000000000000000000134751324101563200270250ustar00rootroot00000000000000package net.miginfocom.demo; import javafx.animation.AnimationTimer; import javafx.application.Application; import javafx.geometry.Point2D; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.input.MouseEvent; import javafx.scene.paint.Color; import javafx.scene.paint.CycleMethod; import javafx.scene.paint.LinearGradient; import javafx.scene.paint.Stop; import javafx.scene.text.Font; import javafx.stage.Stage; import net.miginfocom.layout.BoundSize; import net.miginfocom.layout.ComponentWrapper; import net.miginfocom.layout.LayoutCallback; import net.miginfocom.layout.UnitValue; import org.tbee.javafx.scene.layout.MigPane; import java.util.IdentityHashMap; /* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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 */ public class JavaFXCallbackDemo extends Application { private AnimationTimer layoutTimer; private final IdentityHashMap jumpingMap = new IdentityHashMap<>(); private Point2D mousePos = null; private MigPane migPane = null; private Button createButton(int i) { Button button = new Button(String.valueOf("MIG LAYOUT".charAt(i))); button.setOnAction(event -> { jumpingMap.put(button, System.nanoTime()); layoutTimer.start(); }); button.addEventHandler(MouseEvent.MOUSE_MOVED, (MouseEvent event) -> { mousePos = button.localToParent(event.getX(), event.getY()); migPane.requestLayout(); }); button.widthProperty().addListener((observable, oldValue, newValue) -> { button.setFont(new Font(newValue.doubleValue() / 4)); }); button.setTextFill(Color.rgb(100, 100, 100)); button.setFont(new Font(24)); return button; } public void start(Stage stage) { migPane = new MigPane("align center bottom, insets 80"); // This callback methods will be called for every layout cycle and let you make correction before and after the calculations. migPane.addLayoutCallback(new LayoutCallback() { // This is the size change part public BoundSize[] getSize(ComponentWrapper wrapper) { if (wrapper.getComponent() instanceof Button) { Button c = (Button) wrapper.getComponent(); Point2D p = mousePos != null ? c.parentToLocal(mousePos) : new Point2D(-1000, -1000); double fact = Math.sqrt(Math.pow(Math.abs(p.getX() - c.getWidth() / 2f), 2) + Math.pow(Math.abs(p.getY() - c.getHeight() / 2f), 2)); fact = Math.max(2 - (fact / 200), 1); return new BoundSize[] {new BoundSize(new UnitValue((float) (70 * fact)), ""), new BoundSize(new UnitValue((float) (70 * fact)), "")}; } return null; } // This is the jumping part public void correctBounds(ComponentWrapper wrapper) { Long pressedNanos = jumpingMap.get(wrapper.getComponent()); if (pressedNanos != null) { long duration = System.nanoTime() - pressedNanos; double maxHeight = 100.0 - (duration / 70000000.0); int deltaY = (int) Math.round(Math.abs(Math.sin((duration) / 300000000.0) * maxHeight)); wrapper.setBounds(wrapper.getX(), wrapper.getY() - deltaY, wrapper.getWidth(), wrapper.getHeight()); if (maxHeight < 0.5) { jumpingMap.remove(wrapper.getComponent()); if (jumpingMap.isEmpty()) layoutTimer.stop(); } } } }); for (int j = 0; j < 10; j++) migPane.add(createButton(j), "aligny 0.8al"); Label label = new Label("Press one of those Buttons!"); label.setFont(new Font(24)); label.setTextFill(Color.rgb(150, 150, 150)); migPane.add(label, "pos 0.5al 0al"); migPane.addEventHandler(MouseEvent.MOUSE_MOVED, (MouseEvent event) -> { mousePos = new Point2D(event.getX(), event.getY()); migPane.requestLayout(); }); migPane.addEventHandler(MouseEvent.MOUSE_EXITED, event -> { mousePos = null; migPane.requestLayout(); }); // create scene Scene scene = new Scene(migPane, -1, 450); scene.setFill(new LinearGradient(0, 0, 0, 500, true, CycleMethod.NO_CYCLE, new Stop(0, Color.WHITE), new Stop(1, Color.rgb(240, 238, 235)))); // create stage stage.setTitle("Callback Demo"); stage.setScene(scene); stage.sizeToScene(); stage.show(); layoutTimer = new AnimationTimer() { public void handle(long now) { migPane.requestLayout(); } }; } public static void main(String[] args) { launch(args); } }miglayout-5.1/demo/src/main/java/net/miginfocom/demo/SwingDemo.java000077500000000000000000005157331324101563200253670ustar00rootroot00000000000000package net.miginfocom.demo; import net.miginfocom.layout.*; import net.miginfocom.swing.MigLayout; import javax.swing.*; import javax.swing.border.EmptyBorder; import javax.swing.border.EtchedBorder; import javax.swing.border.LineBorder; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import java.awt.*; import java.awt.event.*; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.util.Random; /* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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 */ public class SwingDemo extends JFrame { public static final int INITIAL_INDEX = 0; private static final boolean DEBUG = false; private static final boolean OPAQUE = false; private static final String[][] panels = new String[][] { // {"Test", "BugTestApp, disregard"}, {"Welcome", "\n\n \"MigLayout makes complex layouts easy and normal layouts one-liners.\""}, {"Quick Start", "This is an example of how to build a common dialog type. Note that there are no special components, nested panels or absolute references to cell positions. If you look at the source code you will see that the layout code is very simple to understand."}, {"Plain", "A simple example on how simple it is to create normal forms. No builders needed since the whole layout manager works like a builder."}, {"Alignments", "Shows how the alignment of components are specified. At the top/left is the alignment for the column/row. The components have no alignments specified.\n\nNote that baseline alignment will be interpreted as 'center' before JDK 6."}, {"Cell Alignments", "Shows how components are aligned when both column/row alignments and component constraints are specified. At the top/left are the alignment for the column/row and the text on the buttons is the component constraint that will override the column/row alignment if it is an alignment.\n\nNote that baseline alignment will be interpreted as 'center' before JDK 6."}, {"Basic Sizes", "A simple example that shows how to use the column or row min/preferred/max size to set the sizes of the contained components and also an example that shows how to do this directly in the component constraints."}, {"Growing", "A simple example that shows how to use the growx and growy constraint to set the sizes and how they should grow to fit the available size. Both the column/row and the component grow/shrink constraints can be set, but the components will always be confined to the space given by its column/row."}, {"Grow Shrink", "Demonstrates the very flexible grow and shrink constraints that can be set on a component.\nComponents can be divided into grow/shrink groups and also have grow/shrink weight within each of those groups.\n\nBy default " + "components shrink to their inherent (or specified) minimum size, but they don't grow."}, {"Span", "This example shows the powerful spanning and splitting that can be specified in the component constraints. With spanning any number of cells can be merged with the additional option to split that space for more than one component. This makes layouts very flexible and reduces the number of times you will need nested panels to very few."}, {"Flow Direction", "Shows the different flow directions. Flow direction for the layout specifies if the next cell will be in the x or y dimension. Note that it can be a different flow direction in the slit cell (the middle cell is slit in two). Wrap is set to 3 for all panels."}, {"Grouping", "Sizes for both components and columns/rows can be grouped so they get the same size. For instance buttons in a button bar can be given a size-group so that they will all get " + "the same minimum and preferred size (the largest within the group). Size-groups can be set for the width, height or both."}, {"Units", "Demonstrates the basic units that are understood by MigLayout. These units can be extended by the user by adding one or more UnitConverter(s)."}, {"Component Sizes", "Minimum, preferred and maximum component sizes can be overridden in the component constraints using any unit type. The format to do this is short and simple to understand. You simply specify the " + "min, preferred and max sizes with a colon between.\n\nAbove are some examples of this. An exclamation mark means that the value will be used for all sizes."}, {"Bound Sizes", "Shows how to create columns that are stable between tabs using minimum sizes."}, {"Cell Position", "Even though MigLayout has automatic grid flow you can still specify the cell position explicitly. You can even combine absolute (x, y) and flow (skip, wrap and newline) constraints to build your layout."}, {"Orientation", "MigLayout supports not only right-to-left orientation, but also bottom-to-top. You can even set the flow direction so that the flow is vertical instead of horizontal. It will automatically " + "pick up if right-to-left is to be used depending on the ComponentWrapper, but it can also be manually set for every layout."}, {"Absolute Position", "Demonstrates the option to place any number of components using absolute coordinates. This can be just the position (if min/preferred size) using \"x y p p\" format or" + "the bounds using the \"x1 y1 x2 y2\" format. Any unit can be used and percent is relative to the parent.\nAbsolute components will not disturb the flow or occupy cells in the grid. " + "Absolute positioned components will be taken into account when calculating the container's preferred size."}, {"Component Links", "Components can be linked to any side of any other component. It can be a forward, backward or cyclic link references, as long as it is stable and won't continue to change value over many iterations." + "Links are referencing the ID of another component. The ID can be overridden by the component's constrains or is provided by the ComponentWrapper. For instance it will use the component's 'name' on Swing.\n" + "Since the links can be combined with any expression (such as 'butt1.x+10' or 'max(button.x, 200)' the links are very customizable."}, {"Docking", "Docking components can be added around the grid. The docked component will get the whole width/height on the docked side by default, however this can be overridden. When all docked components are laid out, whatever space " + "is left will be available for the normal grid laid out components. Docked components does not in any way affect the flow in the grid.\n\nSince the docking runs in the same code path " + "as the normal layout code the same properties can be specified for the docking components. You can for instance set the sizes and alignment or link other components to their docked component's bounds."}, {"Button Bars", "Button order is very customizable and are by default different on the supported platforms. E.g. Gaps, button order and minimum button size are properties that are 'per platform'. MigLayout picks up the current platform automatically and adjusts the button order and minimum button size accordingly, all without using a button builder or any other special code construct."}, {"Visual Bounds", "Human perceptible bounds may not be the same as the mathematical bounds for the component. This is for instance the case if there is a drop shadow painted by the component's border. MigLayout can compensate " + "for this in a simple way. Note the top middle tab-component, it is not aligned visually correct on Windows XP. For the second tab the bounds are corrected automatically on Windows XP."}, {"Debug", "Demonstrates the non-intrusive way to get visual debugging aid. There is no need to use a special DebugPanel or anything that will need code changes. The user can simply turn on debug on the layout manager by using the \"debug\" constraint and it will " + "continuously repaint the panel with debug information on top. This means you don't have to change your code to debug!"}, {"Layout Showdown", "This is an implementation of the Layout Showdown posted on java.net by John O'Conner. The first tab is a pure implementation of the showdown that follows all the rules. The second tab is a slightly fixed version that follows some improved layout guidelines." + "The source code is for both the first and for the fixed version. Note the simplification of the code for the fixed version. Writing better layouts with MiG Layout is easier that writing bad.\n\nReference: http://weblogs.java.net/blog/joconner/archive/2006/10/more_informatio.html"}, {"API Constraints1", "This dialog shows the constraint API added to v2.0. It works the same way as the string constraints but with chained method calls. See the source code for details."}, {"API Constraints2", "This dialog shows the constraint API added to v2.0. It works the same way as the string constraints but with chained method calls. See the source code for details."} }; private int lastIndex = -10; private JPanel contentPanel = DEBUG ? new JPanel(new BorderLayout()) : new JPanel(new MigLayout("wrap", "[]unrel[grow]", "[grow][pref]")); private JTabbedPane layoutPickerTabPane = new JTabbedPane(); private JList pickerList = new JList(new DefaultListModel()); private JTabbedPane southTabPane = new JTabbedPane(); private JScrollPane descrTextAreaScroll = createTextAreaScroll("", 5, 80, true); private JTextArea descrTextArea = (JTextArea) descrTextAreaScroll.getViewport().getView(); private JScrollPane sourceTextAreaScroll = null; private JTextArea sourceTextArea = null; private JPanel layoutDisplayPanel = new JPanel(new BorderLayout(0, 0)); private static boolean buttonOpaque = true; private static boolean contentAreaFilled = true; private JFrame sourceFrame = null; private JTextArea sourceFrameTextArea = null; private static int benchRuns = 0; private static long startupMillis = 0; private static long timeToShowMillis = 0; private static long benchRunTime = 0; private static String benchOutFileName = null; private static boolean append = false; private static long lastRunTimeStart = 0; private static StringBuffer runTimeSB = null; public static void main(String args[]) { try { System.setProperty("apple.laf.useScreenMenuBar", "true"); System.setProperty("com.apple.mrj.application.apple.menu.about.name", "MiGLayout Swing Demo"); } catch(Throwable ex) { // Beacuse we did not have permissions. } startupMillis = System.currentTimeMillis(); String laf = UIManager.getSystemLookAndFeelClassName(); if (args.length > 0) { for (int i = 0; i 0) // RepaintManager.currentManager(this).setDoubleBufferingEnabled(false); if (benchRuns == 0) { sourceTextAreaScroll = createTextAreaScroll("", 5, 80, true); sourceTextArea = (JTextArea) sourceTextAreaScroll.getViewport().getView(); } if (DEBUG) { contentPanel.add(layoutDisplayPanel, BorderLayout.CENTER); // contentPanel.add(layoutPickerTabPane, BorderLayout.WEST); // contentPanel.add(descriptionTabPane, BorderLayout.SOUTH); } else { contentPanel.add(layoutPickerTabPane, "spany,grow"); contentPanel.add(layoutDisplayPanel, "grow"); contentPanel.add(southTabPane, "growx"); } setContentPane(contentPanel); pickerList.setOpaque(OPAQUE); ((DefaultListCellRenderer) pickerList.getCellRenderer()).setOpaque(OPAQUE); pickerList.setSelectionForeground(new Color(0, 0, 220)); pickerList.setBackground(null); pickerList.setBorder(new EmptyBorder(2, 5, 0, 4)); pickerList.setFont(pickerList.getFont().deriveFont(Font.BOLD)); layoutPickerTabPane.addTab("Example Browser", pickerList); descrTextAreaScroll.setBorder(null); descrTextAreaScroll.setOpaque(OPAQUE); descrTextAreaScroll.getViewport().setOpaque(OPAQUE); descrTextArea.setOpaque(OPAQUE); descrTextArea.setEditable(false); descrTextArea.setBorder(new EmptyBorder(0, 4, 0, 4)); southTabPane.addTab("Description", descrTextAreaScroll); if (sourceTextArea != null) { sourceTextAreaScroll.setBorder(null); sourceTextAreaScroll.setOpaque(OPAQUE); sourceTextAreaScroll.getViewport().setOpaque(OPAQUE); sourceTextAreaScroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); sourceTextArea.setOpaque(OPAQUE); sourceTextArea.setLineWrap(false); sourceTextArea.setWrapStyleWord(false); sourceTextArea.setEditable(false); sourceTextArea.setBorder(new EmptyBorder(0, 4, 0, 4)); sourceTextArea.setFont(new Font("monospaced", Font.PLAIN, 11)); southTabPane.addTab("Source Code", sourceTextAreaScroll); southTabPane.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { if (e.getClickCount() == 2) showSourceInFrame(); } }); } for (int i = 0; i < panels.length; i++) ((DefaultListModel) pickerList.getModel()).addElement(panels[i][0]); try { if (UIManager.getLookAndFeel().getID().equals("Aqua")) { setSize(1000, 750); } else { setSize(900, 650); } setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); } catch(Throwable t) { t.printStackTrace(); System.exit(1); } pickerList.addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { int ix = pickerList.getSelectedIndex(); if (ix == -1 || lastIndex == ix) return; lastIndex = ix; String methodName = "create" + panels[ix][0].replace(' ', '_'); layoutDisplayPanel.removeAll(); try { pickerList.requestFocusInWindow(); final JComponent panel = (JComponent) SwingDemo.class.getMethod(methodName, new Class[0]).invoke(SwingDemo.this, new Object[0]); layoutDisplayPanel.add(panel); descrTextArea.setText(panels[ix][1]); descrTextArea.setCaretPosition(0); contentPanel.revalidate(); } catch (Exception e1) { e1.printStackTrace(); // Should never happen... } southTabPane.setSelectedIndex(0); } }); pickerList.requestFocusInWindow(); Toolkit.getDefaultToolkit().setDynamicLayout(true); if (benchRuns > 0) { doBenchmark(); } else { pickerList.setSelectedIndex(INITIAL_INDEX); KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new KeyEventDispatcher() { public boolean dispatchKeyEvent(KeyEvent e) { if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_B && (e.getModifiersEx() & KeyEvent.CTRL_DOWN_MASK) > 0) { startupMillis = System.currentTimeMillis(); timeToShowMillis = System.currentTimeMillis() - startupMillis; benchRuns = 1; doBenchmark(); return true; } return false; } }); } } private void doBenchmark() { Thread benchThread = new Thread() { public void run() { for (int j = 0; j < benchRuns; j++) { lastRunTimeStart = System.currentTimeMillis(); for (int i = 0, iCnt = pickerList.getModel().getSize(); i < iCnt; i++) { if (benchRuns > 0 && panels[i][0].equals("Visual Bounds")) continue; // the SWT version does not have Visual bounds... final int ii = i; try { SwingUtilities.invokeAndWait(new Runnable() { public void run() { pickerList.setSelectedIndex(ii); Toolkit.getDefaultToolkit().sync(); } }); } catch (Exception e) { e.printStackTrace(); } Component[] comps = layoutDisplayPanel.getComponents(); for (int cIx = 0; cIx < comps.length; cIx++) { if (comps[cIx] instanceof JTabbedPane) { final JTabbedPane tp = (JTabbedPane) comps[cIx]; for (int k = 0, kCnt = tp.getTabCount(); k < kCnt; k++) { final int kk = k; try { SwingUtilities.invokeAndWait(new Runnable() { public void run() { tp.setSelectedIndex(kk); Toolkit.getDefaultToolkit().sync(); if (timeToShowMillis == 0) timeToShowMillis = System.currentTimeMillis() - startupMillis; } }); } catch (Exception e) { e.printStackTrace(); } } } } } if (runTimeSB != null) { runTimeSB.append("Run ").append(j).append(": "); runTimeSB.append(System.currentTimeMillis() - lastRunTimeStart).append(" millis.\n"); } } benchRunTime = System.currentTimeMillis() - startupMillis - timeToShowMillis; final String message = "Java Version: " + System.getProperty("java.version") + "\n" + "Look & Feel: " + UIManager.getLookAndFeel().getDescription() + "\n" + "Time to Show: " + timeToShowMillis + " millis.\n" + (runTimeSB != null ? runTimeSB.toString() : "") + "Benchmark Run Time: " + benchRunTime + " millis.\n" + "Average Run Time: " + (benchRunTime / benchRuns) + " millis (" + benchRuns + " runs).\n\n"; if (benchOutFileName == null) { JOptionPane.showMessageDialog(SwingDemo.this, message, "Results", JOptionPane.INFORMATION_MESSAGE); } else { FileWriter fw = null; try { fw = new FileWriter(benchOutFileName, append); fw.write(message); } catch(IOException ex) { ex.printStackTrace(); } finally { if (fw != null) try {fw.close();} catch(IOException ex) {} } } System.out.println(message); } }; benchThread.start(); } private void setSource(String source) { if (benchRuns > 0 || sourceTextArea == null) return; if (source.length() > 0) { source = source.replaceAll("\t\t", ""); source = "DOUBLE CLICK TAB TO SHOW SOURCE IN SEPARATE WINDOW!\n===================================================\n\n" + source; } sourceTextArea.setText(source); sourceTextArea.setCaretPosition(0); if (sourceFrame != null && sourceFrame.isVisible()) { sourceFrameTextArea.setText(source.length() > 105 ? source.substring(105) : "No Source Code Available!"); sourceFrameTextArea.setCaretPosition(0); } } private void showSourceInFrame() { if (sourceTextArea == null) return; JScrollPane sourceFrameTextAreaScroll = createTextAreaScroll("", 5, 80, true); sourceFrameTextArea = (JTextArea) sourceFrameTextAreaScroll.getViewport().getView(); sourceFrameTextAreaScroll.setBorder(null); sourceFrameTextAreaScroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); sourceFrameTextArea.setLineWrap(false); sourceFrameTextArea.setWrapStyleWord(false); sourceFrameTextArea.setEditable(false); sourceFrameTextArea.setBorder(new EmptyBorder(10, 10, 10, 10)); sourceFrameTextArea.setFont(new Font("monospaced", Font.PLAIN, 12)); String source = this.sourceTextArea.getText(); sourceFrameTextArea.setText(source.length() > 105 ? source.substring(105) : "No Source Code Available!"); sourceFrameTextArea.setCaretPosition(0); sourceFrame = new JFrame("Source Code"); sourceFrame.getContentPane().add(sourceFrameTextAreaScroll, BorderLayout.CENTER); sourceFrame.setSize(700, 800); sourceFrame.setLocationRelativeTo(this); sourceFrame.setVisible(true); } public JComponent createTest() { JPanel thisp = new JPanel(); MigLayout layout = new MigLayout(); thisp.setLayout(layout); // thisp.add("wrap, span", new JButton()); // thisp.add("newline, span", new JButton()); // thisp.add("newline, span", new JButton()); // thisp.add("newline, span", new JButton()); // thisp.add("newline 100", new JButton("should have 40 pixels before")); // thisp.add("newline", new JButton()); // thisp.add("newline", new JButton()); // thisp.add("newline", new JButton()); return thisp; } public JComponent createAPI_Constraints1() { JTabbedPane tabbedPane = new JTabbedPane(); LC layC = new LC().fill().wrap(); AC colC = new AC().align("right", 1).fill(2, 4).grow(100, 2, 4).align("right", 3).gap("15", 2); AC rowC = new AC().align("top", 7).gap("15!", 6).grow(100, 8); JPanel panel = createTabPanel(new MigLayout(layC, colC, rowC)); // Makes the background gradient // References to text fields not stored to reduce code clutter. JScrollPane list2 = new JScrollPane(new JList(new String[] {"Mouse, Mickey"})); panel.add(list2, new CC().spanY().growY().minWidth("150").gapX(null, "10")); panel.add(new JLabel("Last Name")); panel.add(new JTextField()); panel.add(new JLabel("First Name")); panel.add(new JTextField(), new CC().wrap().alignX("right")); panel.add(new JLabel("Phone")); panel.add(new JTextField()); panel.add(new JLabel("Email")); panel.add(new JTextField()); panel.add(new JLabel("Address 1")); panel.add(new JTextField(), new CC().spanX().growX()); panel.add(new JLabel("Address 2")); panel.add(new JTextField(), new CC().spanX().growX()); panel.add(new JLabel("City")); panel.add(new JTextField(), new CC().wrap()); panel.add(new JLabel("State")); panel.add(new JTextField()); panel.add(new JLabel("Postal Code")); panel.add(new JTextField(10), new CC().spanX(2).growX(0)); panel.add(new JLabel("Country")); panel.add(new JTextField(), new CC().wrap()); panel.add(new JButton("New"), new CC().spanX(5).split(5).tag("other")); panel.add(new JButton("Delete"), new CC().tag("other")); panel.add(new JButton("Edit"), new CC().tag("other")); panel.add(new JButton("Save"), new CC().tag("other")); panel.add(new JButton("Cancel"), new CC().tag("cancel")); tabbedPane.addTab("Layout Showdown (improved)", panel); setSource("JTabbedPane tabbedPane = new JTabbedPane();\n" + "\n" + "LC layC = new LC().fill().wrap();\n" + "AC colC = new AC().align(\"right\", 1).fill(2, 4).grow(100, 2, 4).align(\"right\", 3).gap(\"15\", 2);\n" + "AC rowC = new AC().align(\"top\", 7).gap(\"15!\", 6).grow(100, 8);\n" + "\n" + "JPanel panel = createTabPanel(new MigLayout(layC, colC, rowC)); // Makes the background gradient\n" + "\n" + "// References to text fields not stored to reduce code clutter.\n" + "\n" + "JScrollPane list2 = new JScrollPane(new JList(new String[] {\"Mouse, Mickey\"}));\n" + "panel.add(list2, new CC().spanY().growY().minWidth(\"150\").gapX(null, \"10\"));\n" + "\n" + "panel.add(new JLabel(\"Last Name\"));\n" + "panel.add(new JTextField());\n" + "panel.add(new JLabel(\"First Name\"));\n" + "panel.add(new JTextField(), new CC().wrap().alignX(\"right\"));\n" + "panel.add(new JLabel(\"Phone\"));\n" + "panel.add(new JTextField());\n" + "panel.add(new JLabel(\"Email\"));\n" + "panel.add(new JTextField());\n" + "panel.add(new JLabel(\"Address 1\"));\n" + "panel.add(new JTextField(), new CC().spanX().growX());\n" + "panel.add(new JLabel(\"Address 2\"));\n" + "panel.add(new JTextField(), new CC().spanX().growX());\n" + "panel.add(new JLabel(\"City\"));\n" + "panel.add(new JTextField(), new CC().wrap());\n" + "panel.add(new JLabel(\"State\"));\n" + "panel.add(new JTextField());\n" + "panel.add(new JLabel(\"Postal Code\"));\n" + "panel.add(new JTextField(10), new CC().spanX(2).growX(0));\n" + "panel.add(new JLabel(\"Country\"));\n" + "panel.add(new JTextField(), new CC().wrap());\n" + "\n" + "panel.add(new JButton(\"New\"), new CC().spanX(5).split(5).tag(\"other\"));\n" + "panel.add(new JButton(\"Delete\"), new CC().tag(\"other\"));\n" + "panel.add(new JButton(\"Edit\"), new CC().tag(\"other\"));\n" + "panel.add(new JButton(\"Save\"), new CC().tag(\"other\"));\n" + "panel.add(new JButton(\"Cancel\"), new CC().tag(\"cancel\"));\n" + "\n" + "tabbedPane.addTab(\"Layout Showdown (improved)\", panel);"); return tabbedPane; } public JComponent createAPI_Constraints2() { JTabbedPane tabbedPane = new JTabbedPane(); LC layC = new LC().fill().wrap(); AC colC = new AC().align("right", 0).fill(1, 3).grow(100, 1, 3).align("right", 2).gap("15", 1); AC rowC = new AC().index(6).gap("15!").align("top").grow(100, 8); JPanel panel = createTabPanel(new MigLayout(layC, colC, rowC)); // Makes the background gradient // References to text fields not stored to reduce code clutter. panel.add(new JLabel("Last Name")); panel.add(new JTextField()); panel.add(new JLabel("First Name")); panel.add(new JTextField(), new CC().wrap()); panel.add(new JLabel("Phone")); panel.add(new JTextField()); panel.add(new JLabel("Email")); panel.add(new JTextField()); panel.add(new JLabel("Address 1")); panel.add(new JTextField(), new CC().spanX().growX()); panel.add(new JLabel("Address 2")); panel.add(new JTextField(), new CC().spanX().growX()); panel.add(new JLabel("City")); panel.add(new JTextField(), new CC().wrap()); panel.add(new JLabel("State")); panel.add(new JTextField()); panel.add(new JLabel("Postal Code")); panel.add(new JTextField(10), new CC().spanX(2).growX(0)); panel.add(new JLabel("Country")); panel.add(new JTextField(), new CC().wrap()); panel.add(createButton("New"), new CC().spanX(5).split(5).tag("other")); panel.add(createButton("Delete"), new CC().tag("other")); panel.add(createButton("Edit"), new CC().tag("other")); panel.add(createButton("Save"), new CC().tag("other")); panel.add(createButton("Cancel"), new CC().tag("cancel")); tabbedPane.addTab("Layout Showdown (improved)", panel); setSource("JTabbedPane tabbedPane = new JTabbedPane();\n" + "\n" + "LC layC = new LC().fill().wrap();\n" + "AC colC = new AC().align(\"right\", 0).fill(1, 3).grow(100, 1, 3).align(\"right\", 2).gap(\"15\", 1);\n" + "AC rowC = new AC().index(6).gap(\"15!\").align(\"top\").grow(100, 8);\n" + "\n" + "JPanel panel = createTabPanel(new MigLayout(layC, colC, rowC)); // Makes the background gradient\n" + "\n" + "// References to text fields not stored to reduce code clutter.\n" + "\n" + "panel.add(new JLabel(\"Last Name\"));\n" + "panel.add(new JTextField());\n" + "panel.add(new JLabel(\"First Name\"));\n" + "panel.add(new JTextField(), new CC().wrap());\n" + "panel.add(new JLabel(\"Phone\"));\n" + "panel.add(new JTextField());\n" + "panel.add(new JLabel(\"Email\"));\n" + "panel.add(new JTextField());\n" + "panel.add(new JLabel(\"Address 1\"));\n" + "panel.add(new JTextField(), new CC().spanX().growX());\n" + "panel.add(new JLabel(\"Address 2\"));\n" + "panel.add(new JTextField(), new CC().spanX().growX());\n" + "panel.add(new JLabel(\"City\"));\n" + "panel.add(new JTextField(), new CC().wrap());\n" + "panel.add(new JLabel(\"State\"));\n" + "panel.add(new JTextField());\n" + "panel.add(new JLabel(\"Postal Code\"));\n" + "panel.add(new JTextField(10), new CC().spanX(2).growX(0));\n" + "panel.add(new JLabel(\"Country\"));\n" + "panel.add(new JTextField(), new CC().wrap());\n" + "\n" + "panel.add(createButton(\"New\"), new CC().spanX(5).split(5).tag(\"other\"));\n" + "panel.add(createButton(\"Delete\"), new CC().tag(\"other\"));\n" + "panel.add(createButton(\"Edit\"), new CC().tag(\"other\"));\n" + "panel.add(createButton(\"Save\"), new CC().tag(\"other\"));\n" + "panel.add(createButton(\"Cancel\"), new CC().tag(\"cancel\"));\n" + "\n" + "tabbedPane.addTab(\"Layout Showdown (improved)\", panel);"); return tabbedPane; } public JComponent createLayout_Showdown() { JTabbedPane tabbedPane = new JTabbedPane(); JPanel p = createTabPanel(new MigLayout("", "[]15[][grow,fill]15[grow]")); JScrollPane list1 = new JScrollPane(new JList(new String[] {"Mouse, Mickey"})); p.add(list1, "spany, growy, wmin 150"); p.add(new JLabel("Last Name")); p.add(new JTextField()); p.add(new JLabel("First Name"), "split"); // split divides the cell p.add(new JTextField(), "growx, wrap"); p.add(new JLabel("Phone")); p.add(new JTextField()); p.add(new JLabel("Email"), "split"); p.add(new JTextField(), "growx, wrap"); p.add(new JLabel("Address 1")); p.add(new JTextField(), "span, growx"); // span merges cells p.add(new JLabel("Address 2")); p.add(new JTextField(), "span, growx"); p.add(new JLabel("City")); p.add(new JTextField(), "wrap"); // wrap continues on next line p.add(new JLabel("State")); p.add(new JTextField()); p.add(new JLabel("Postal Code"), "split"); p.add(new JTextField(), "growx, wrap"); p.add(new JLabel("Country")); p.add(new JTextField(), "wrap 15"); p.add(createButton("New"), "span, split, align left"); p.add(createButton("Delete"), ""); p.add(createButton("Edit"), ""); p.add(createButton("Save"), ""); p.add(createButton("Cancel"), "wrap push"); tabbedPane.addTab("Layout Showdown (pure)", p); // Fixed version ******************************************* JPanel p2 = createTabPanel(new MigLayout("", "[]15[][grow,fill]15[][grow,fill]")); // Makes the background gradient // References to text fields not stored to reduce code clutter. JScrollPane list2 = new JScrollPane(new JList(new String[] {"Mouse, Mickey"})); p2.add(list2, "spany, growy, wmin 150"); p2.add(new JLabel("Last Name")); p2.add(new JTextField()); p2.add(new JLabel("First Name")); p2.add(new JTextField(), "wrap"); p2.add(new JLabel("Phone")); p2.add(new JTextField()); p2.add(new JLabel("Email")); p2.add(new JTextField(), "wrap"); p2.add(new JLabel("Address 1")); p2.add(new JTextField(), "span"); p2.add(new JLabel("Address 2")); p2.add(new JTextField(), "span"); p2.add(new JLabel("City")); p2.add(new JTextField(), "wrap"); p2.add(new JLabel("State")); p2.add(new JTextField()); p2.add(new JLabel("Postal Code")); p2.add(new JTextField(10), "growx 0, wrap"); p2.add(new JLabel("Country")); p2.add(new JTextField(), "wrap 15"); p2.add(createButton("New"), "tag other, span, split"); p2.add(createButton("Delete"), "tag other"); p2.add(createButton("Edit"), "tag other"); p2.add(createButton("Save"), "tag other"); p2.add(createButton("Cancel"), "tag cancel, wrap push"); tabbedPane.addTab("Layout Showdown (improved)", p2); setSource("JTabbedPane tabbedPane = new JTabbedPane();\n" + "\n" + "JPanel p = createTabPanel(new MigLayout(\"\", \"[]15[][grow,fill]15[grow]\"));\n" + "\n" + "JScrollPane list1 = new JScrollPane(new JList(new String[] {\"Mouse, Mickey\"}));\n" + "\n" + "p.add(list1, \"spany, growy, wmin 150\");\n" + "p.add(new JLabel(\"Last Name\"));\n" + "p.add(new JTextField());\n" + "p.add(new JLabel(\"First Name\"), \"split\"); // split divides the cell\n" + "p.add(new JTextField(), \"growx, wrap\");\n" + "p.add(new JLabel(\"Phone\"));\n" + "p.add(new JTextField());\n" + "p.add(new JLabel(\"Email\"), \"split\");\n" + "p.add(new JTextField(), \"growx, wrap\");\n" + "p.add(new JLabel(\"Address 1\"));\n" + "p.add(new JTextField(), \"span, growx\"); // span merges cells\n" + "p.add(new JLabel(\"Address 2\"));\n" + "p.add(new JTextField(), \"span, growx\");\n" + "p.add(new JLabel(\"City\"));\n" + "p.add(new JTextField(), \"wrap\"); // wrap continues on next line\n" + "p.add(new JLabel(\"State\"));\n" + "p.add(new JTextField());\n" + "p.add(new JLabel(\"Postal Code\"), \"split\");\n" + "p.add(new JTextField(), \"growx, wrap\");\n" + "p.add(new JLabel(\"Country\"));\n" + "p.add(new JTextField(), \"wrap 15\");\n" + "\n" + "p.add(createButton(\"New\"), \"span, split, align left\");\n" + "p.add(createButton(\"Delete\"), \"\");\n" + "p.add(createButton(\"Edit\"), \"\");\n" + "p.add(createButton(\"Save\"), \"\");\n" + "p.add(createButton(\"Cancel\"), \"wrap push\");\n" + "\n" + "tabbedPane.addTab(\"Layout Showdown (pure)\", p);" + "\n" + "\t\t// Fixed version *******************************************\n" + "JPanel p2 = createTabPanel(new MigLayout(\"\", \"[]15[][grow,fill]15[][grow,fill]\")); // Makes the background gradient\n" + "\n" + "// References to text fields not stored to reduce code clutter.\n" + "\n" + "JScrollPane list2 = new JScrollPane(new JList(new String[] {\"Mouse, Mickey\"}));\n" + "p2.add(list2, \"spany, growy, wmin 150\");\n" + "p2.add(new JLabel(\"Last Name\"));\n" + "p2.add(new JTextField());\n" + "p2.add(new JLabel(\"First Name\"));\n" + "p2.add(new JTextField(), \"wrap\");\n" + "p2.add(new JLabel(\"Phone\"));\n" + "p2.add(new JTextField());\n" + "p2.add(new JLabel(\"Email\"));\n" + "p2.add(new JTextField(), \"wrap\");\n" + "p2.add(new JLabel(\"Address 1\"));\n" + "p2.add(new JTextField(), \"span\");\n" + "p2.add(new JLabel(\"Address 2\"));\n" + "p2.add(new JTextField(), \"span\");\n" + "p2.add(new JLabel(\"City\"));\n" + "p2.add(new JTextField(), \"wrap\");\n" + "p2.add(new JLabel(\"State\"));\n" + "p2.add(new JTextField());\n" + "p2.add(new JLabel(\"Postal Code\"));\n" + "p2.add(new JTextField(10), \"growx 0, wrap\");\n" + "p2.add(new JLabel(\"Country\"));\n" + "p2.add(new JTextField(), \"wrap 15\");\n" + "\n" + "p2.add(createButton(\"New\"), \"tag other, span, split\");\n" + "p2.add(createButton(\"Delete\"), \"tag other\");\n" + "p2.add(createButton(\"Edit\"), \"tag other\");\n" + "p2.add(createButton(\"Save\"), \"tag other\");\n" + "p2.add(createButton(\"Cancel\"), \"tag cancel, wrap push\");\n" + "\n" + "tabbedPane.addTab(\"Layout Showdown (improved)\", p2);"); return tabbedPane; } public JComponent createWelcome() { JTabbedPane tabbedPane = new JTabbedPane(); MigLayout lm = new MigLayout("ins 20, fill", "", "[grow]unrel[]"); JPanel mainPanel = createTabPanel(lm); String s = "MigLayout's main purpose is to make layouts for SWT and Swing, and possibly other frameworks, much more powerful and a lot easier to create, especially for manual coding.\n\n" + "The motto is: \"MigLayout makes complex layouts easy and normal layouts one-liners.\"\n\n" + "The layout engine is very flexible and advanced, something that is needed to make it simple to use yet handle almost all layout use-cases.\n\n" + "MigLayout can handle all layouts that the commonly used Swing Layout Managers can handle and this with a lot of extra features. " + "It also incorporates most, if not all, of the open source alternatives FormLayout's and TableLayout's functionality." + "\n\n\nThanks to Karsten Lentzsch of JGoodies.com for allowing the reuse of the main demo application layout and for his inspiring talks that led to this layout manager." + "\n\n\nMikael Grev\n" + "MiG InfoCom AB\n" + "miglayout@miginfocom.com"; JTextArea textArea = new JTextArea(s); textArea.setEditable(false); textArea.setSize(400, 400); if (PlatformDefaults.getCurrentPlatform() == PlatformDefaults.WINDOWS_XP) textArea.setFont(new Font("tahoma", Font.BOLD, 11)); textArea.setOpaque(OPAQUE); textArea.setWrapStyleWord(true); textArea.setLineWrap(true); JLabel label = new JLabel("You can Right Click any Component or Container to change the constraints for it!"); label.setForeground(new Color(200, 0, 0)); mainPanel.add(textArea, "wmin 500, ay top, grow, push, wrap"); mainPanel.add(label, "growx"); label.setFont(label.getFont().deriveFont(Font.BOLD)); tabbedPane.addTab("Welcome", mainPanel); setSource(""); return tabbedPane; } public JComponent createVisual_Bounds() { JTabbedPane tabbedPane = new JTabbedPane(); // "NON"-corrected bounds JPanel p1 = createTabPanel(new MigLayout("fill, ins 3, novisualpadding")); p1.setBorder(new LineBorder(Color.BLACK)); JTabbedPane demoPane2 = new JTabbedPane(); JPanel demoPanel2 = new JPanel(); demoPanel2.setBackground(Color.WHITE); demoPane2.addTab("Demo Tab", demoPanel2); p1.add(createTextArea("A JTextArea", 1, 100), "grow, aligny bottom, wmin 100"); p1.add(demoPane2, "grow, aligny bottom"); p1.add(createTextField("A JTextField", 100), "grow, aligny bottom, wmin 100"); p1.add(createTextArea("A JTextArea", 1, 100), "newline,grow, aligny bottom, wmin 100"); p1.add(createTextArea("A JTextArea", 1, 100), "grow, aligny bottom, wmin 100"); p1.add(createTextArea("A JTextArea", 1, 100), "grow, aligny bottom, wmin 100"); JPanel p2 = createTabPanel(new MigLayout("center,center,fill,ins 3")); p2.setBorder(new LineBorder(Color.BLACK)); JTabbedPane demoPane = new JTabbedPane(); JPanel demoPanel = new JPanel(); demoPanel.setBackground(Color.WHITE); demoPane.addTab("Demo Tab", demoPanel); p2.add(createTextArea("A JTextArea", 1, 100), "grow, aligny bottom, wmin 100"); p2.add(demoPane, "grow, aligny bottom"); p2.add(createTextField("A JTextField", 100), "grow, aligny bottom, wmin 100"); p2.add(createTextArea("A JTextArea", 1, 100), "newline,grow, aligny bottom, wmin 100"); p2.add(createTextArea("A JTextArea", 1, 100), "grow, aligny bottom, wmin 100"); p2.add(createTextArea("A JTextArea", 1, 100), "grow, aligny bottom, wmin 100"); tabbedPane.addTab("Visual Bounds (Not Corrected)", p1); tabbedPane.addTab("Visual Bounds (Corrected)", p2); // Disregard. Just forgetting the source code text close to the source code. setSource("JTabbedPane tabbedPane = new JTabbedPane();\n" + "\n" + "// \"NON\"-corrected bounds\n" + "JPanel p1 = createTabPanel(new MigLayout(\"fill, ins 3, novisualpadding\"));\n" + "p1.setBorder(new LineBorder(Color.BLACK));\n" + "\n" + "JTabbedPane demoPane2 = new JTabbedPane();\n" + "JPanel demoPanel2 = new JPanel();\n" + "demoPanel2.setBackground(Color.WHITE);\n" + "demoPane2.addTab(\"Demo Tab\", demoPanel2);\n" + "\n" + "p1.add(createTextArea(\"A JTextArea\", 1, 100), \"grow, aligny bottom, wmin 100\");\n" + "p1.add(demoPane2, \"grow, aligny bottom\");\n" + "p1.add(createTextField(\"A JTextField\", 100), \"grow, aligny bottom, wmin 100\");\n" + "p1.add(createTextArea(\"A JTextArea\", 1, 100), \"newline,grow, aligny bottom, wmin 100\");\n" + "p1.add(createTextArea(\"A JTextArea\", 1, 100), \"grow, aligny bottom, wmin 100\");\n" + "p1.add(createTextArea(\"A JTextArea\", 1, 100), \"grow, aligny bottom, wmin 100\");\n" + "\n" + "JPanel p2 = createTabPanel(new MigLayout(\"center,center,fill,ins 3\"));\n" + "p2.setBorder(new LineBorder(Color.BLACK));\n" + "\n" + "JTabbedPane demoPane = new JTabbedPane();\n" + "JPanel demoPanel = new JPanel();\n" + "demoPanel.setBackground(Color.WHITE);\n" + "demoPane.addTab(\"Demo Tab\", demoPanel);\n" + "\n" + "p2.add(createTextArea(\"A JTextArea\", 1, 100), \"grow, aligny bottom, wmin 100\");\n" + "p2.add(demoPane, \"grow, aligny bottom\");\n" + "p2.add(createTextField(\"A JTextField\", 100), \"grow, aligny bottom, wmin 100\");\n" + "p2.add(createTextArea(\"A JTextArea\", 1, 100), \"newline,grow, aligny bottom, wmin 100\");\n" + "p2.add(createTextArea(\"A JTextArea\", 1, 100), \"grow, aligny bottom, wmin 100\");\n" + "p2.add(createTextArea(\"A JTextArea\", 1, 100), \"grow, aligny bottom, wmin 100\");\n" + "\n" + "tabbedPane.addTab(\"Visual Bounds (Not Corrected)\", p1);\n" + "tabbedPane.addTab(\"Visual Bounds (Corrected)\", p2);"); return tabbedPane; } public JComponent createDocking() { JTabbedPane tabbedPane = new JTabbedPane(); JPanel p1 = createTabPanel(new MigLayout("fill")); p1.add(createPanel("1. North"), "north"); p1.add(createPanel("2. West"), "west"); p1.add(createPanel("3. East"), "east"); p1.add(createPanel("4. South"), "south"); String[][] data = new String[20][6]; for (int r = 0; r < data.length; r++) { data[r] = new String[6]; for (int c = 0; c < data[r].length; c++) data[r][c] = "Cell " + (r + 1) + ", " + (c + 1); } JTable table = new JTable(data, new String[] {"Column 1", "Column 2", "Column 3", "Column 4", "Column 5", "Column 6"}); p1.add(new JScrollPane(table), "grow"); JPanel p2 = createTabPanel(new MigLayout("fill", "[c]", "")); p2.add(createPanel("1. North"), "north"); p2.add(createPanel("2. North"), "north"); p2.add(createPanel("3. West"), "west"); p2.add(createPanel("4. West"), "west"); p2.add(createPanel("5. South"), "south"); p2.add(createPanel("6. East"), "east"); p2.add(createButton("7. Normal")); p2.add(createButton("8. Normal")); p2.add(createButton("9. Normal")); JPanel p3 = createTabPanel(new MigLayout()); p3.add(createPanel("1. North"), "north"); p3.add(createPanel("2. South"), "south"); p3.add(createPanel("3. West"), "west"); p3.add(createPanel("4. East"), "east"); p3.add(createButton("5. Normal")); JPanel p4 = createTabPanel(new MigLayout()); p4.add(createPanel("1. North"), "north"); p4.add(createPanel("2. North"), "north"); p4.add(createPanel("3. West"), "west"); p4.add(createPanel("4. West"), "west"); p4.add(createPanel("5. South"), "south"); p4.add(createPanel("6. East"), "east"); p4.add(createButton("7. Normal")); p4.add(createButton("8. Normal")); p4.add(createButton("9. Normal")); JPanel p5 = createTabPanel(new MigLayout("fillx", "[c]", "")); p5.add(createPanel("1. North"), "north"); p5.add(createPanel("2. North"), "north"); p5.add(createPanel("3. West"), "west"); p5.add(createPanel("4. West"), "west"); p5.add(createPanel("5. South"), "south"); p5.add(createPanel("6. East"), "east"); p5.add(createButton("7. Normal")); p5.add(createButton("8. Normal")); p5.add(createButton("9. Normal")); JPanel p6 = createTabPanel(new MigLayout("fill", "", "")); Random rand = new Random(); String[] sides = {"north", "east", "south", "west"}; for (int i = 0; i < 20; i++) { int side = rand.nextInt(4); p6.add(createPanel((i + 1) + " " + sides[side]), sides[side]); } p6.add(createPanel("I'm in the Center!"), "dock center"); tabbedPane.addTab("Docking 1 (fill)", p1); tabbedPane.addTab("Docking 2 (fill)", p2); tabbedPane.addTab("Docking 3", p3); tabbedPane.addTab("Docking 4", p4); tabbedPane.addTab("Docking 5 (fillx)", p5); tabbedPane.addTab("Random Docking", new JScrollPane(p6)); // Disregard. Just forgetting the source code text close to the source code. setSource("JTabbedPane tabbedPane = new JTabbedPane();\n" + "\n" + "JPanel p1 = createTabPanel(new MigLayout(\"fill\"));\n" + "\n" + "p1.add(createPanel(\"1. North\"), \"north\");\n" + "p1.add(createPanel(\"2. West\"), \"west\");\n" + "p1.add(createPanel(\"3. East\"), \"east\");\n" + "p1.add(createPanel(\"4. South\"), \"south\");\n" + "\n" + "String[][] data = new String[20][6];\n" + "for (int r = 0; r < data.length; r++) {\n" + "\tdata[r] = new String[6];\n" + "\tfor (int c = 0; c < data[r].length; c++)\n" + "\t\tdata[r][c] = \"Cell \" + (r + 1) + \", \" + (c + 1);\n" + "}\n" + "JTable table = new JTable(data, new String[] {\"Column 1\", \"Column 2\", \"Column 3\", \"Column 4\", \"Column 5\", \"Column 6\"});\n" + "p1.add(new JScrollPane(table), \"grow\");\n" + "\n" + "JPanel p2 = createTabPanel(new MigLayout(\"fill\", \"[c]\", \"\"));\n" + "\n" + "p2.add(createPanel(\"1. North\"), \"north\");\n" + "p2.add(createPanel(\"2. North\"), \"north\");\n" + "p2.add(createPanel(\"3. West\"), \"west\");\n" + "p2.add(createPanel(\"4. West\"), \"west\");\n" + "p2.add(createPanel(\"5. South\"), \"south\");\n" + "p2.add(createPanel(\"6. East\"), \"east\");\n" + "p2.add(createButton(\"7. Normal\"));\n" + "p2.add(createButton(\"8. Normal\"));\n" + "p2.add(createButton(\"9. Normal\"));\n" + "\n" + "JPanel p3 = createTabPanel(new MigLayout());\n" + "\n" + "p3.add(createPanel(\"1. North\"), \"north\");\n" + "p3.add(createPanel(\"2. South\"), \"south\");\n" + "p3.add(createPanel(\"3. West\"), \"west\");\n" + "p3.add(createPanel(\"4. East\"), \"east\");\n" + "p3.add(createButton(\"5. Normal\"));\n" + "\n" + "JPanel p4 = createTabPanel(new MigLayout());\n" + "\n" + "p4.add(createPanel(\"1. North\"), \"north\");\n" + "p4.add(createPanel(\"2. North\"), \"north\");\n" + "p4.add(createPanel(\"3. West\"), \"west\");\n" + "p4.add(createPanel(\"4. West\"), \"west\");\n" + "p4.add(createPanel(\"5. South\"), \"south\");\n" + "p4.add(createPanel(\"6. East\"), \"east\");\n" + "p4.add(createButton(\"7. Normal\"));\n" + "p4.add(createButton(\"8. Normal\"));\n" + "p4.add(createButton(\"9. Normal\"));\n" + "\n" + "JPanel p5 = createTabPanel(new MigLayout(\"fillx\", \"[c]\", \"\"));\n" + "\n" + "p5.add(createPanel(\"1. North\"), \"north\");\n" + "p5.add(createPanel(\"2. North\"), \"north\");\n" + "p5.add(createPanel(\"3. West\"), \"west\");\n" + "p5.add(createPanel(\"4. West\"), \"west\");\n" + "p5.add(createPanel(\"5. South\"), \"south\");\n" + "p5.add(createPanel(\"6. East\"), \"east\");\n" + "p5.add(createButton(\"7. Normal\"));\n" + "p5.add(createButton(\"8. Normal\"));\n" + "p5.add(createButton(\"9. Normal\"));\n" + "\n" + "JPanel p6 = createTabPanel(new MigLayout(\"fill\", \"\", \"\"));\n" + "\n" + "Random rand = new Random();\n" + "String[] sides = {\"north\", \"east\", \"south\", \"west\"};\n" + "for (int i = 0; i < 20; i++) {\n" + "\tint side = rand.nextInt(4);\n" + "\tp6.add(createPanel((i + 1) + \" \" + sides[side]), sides[side]);\n" + "}\n" + "p6.add(createButton(\"I'm in the middle!\"), \"grow\");\n" + "\n" + "tabbedPane.addTab(\"Docking 1 (fill)\", p1);\n" + "tabbedPane.addTab(\"Docking 2 (fill)\", p2);\n" + "tabbedPane.addTab(\"Docking 3\", p3);\n" + "tabbedPane.addTab(\"Docking 4\", p4);\n" + "tabbedPane.addTab(\"Docking 5 (fillx)\", p5);\n" + "tabbedPane.addTab(\"Docking Spiral\", new JScrollPane(p6));"); return tabbedPane; } public JComponent createAbsolute_Position() { JTabbedPane tabbedPane = new JTabbedPane(); // Pos tab final JPanel posPanel = createTabPanel(new MigLayout()); posPanel.add(createButton(), "pos 0.5al 0al"); posPanel.add(createButton(), "pos 1al 0al"); posPanel.add(createButton(), "pos 0.5al 0.5al"); posPanel.add(createButton(), "pos 5in 45lp"); posPanel.add(createButton(), "pos 0.5al 0.5al"); posPanel.add(createButton(), "pos 0.5al 1.0al"); posPanel.add(createButton(), "pos 1al .25al"); posPanel.add(createButton(), "pos visual.x2-pref visual.y2-pref"); posPanel.add(createButton(), "pos 1al -1in"); posPanel.add(createButton(), "pos 100 100"); posPanel.add(createButton(), "pos (10+(20*3lp)) 200"); posPanel.add(createButton("Drag Window! (pos 500-container.xpos 500-container.ypos)"), "pos 500-container.xpos 500-container.ypos"); // Bounds tab JPanel boundsPanel = createTabPanel(new MigLayout()); String constr = "pos (visual.x+visual.w*0.1) visual.y2-40 (visual.x2-visual.w*0.1) visual.y2"; JLabel southLabel = createLabel(constr, SwingConstants.CENTER); southLabel.setBorder(new LineBorder(Color.LIGHT_GRAY, 1)); southLabel.setBackground(new Color(200, 200, 255, benchRuns == 0 ? 70 : 255)); southLabel.setOpaque(true); southLabel.setFont(southLabel.getFont().deriveFont(Font.BOLD)); boundsPanel.add(southLabel, constr); boundsPanel.add(createButton(), "pos 0 0 container.x2 n"); boundsPanel.add(createButton(), "pos visual.x 40 visual.x2 70"); boundsPanel.add(createButton(), "pos visual.x 100 visual.x2 p"); boundsPanel.add(createButton(), "pos 0.1al 0.4al n (visual.y2 - 10)"); boundsPanel.add(createButton(), "pos 0.9al 0.4al n visual.y2-10"); boundsPanel.add(createButton(), "pos 0.5al 0.5al, pad 3 0 -3 0"); boundsPanel.add(createButton(), "pos n n 50% 50%"); boundsPanel.add(createButton(), "pos 50% 50% n n"); boundsPanel.add(createButton(), "pos 50% n n 50%"); boundsPanel.add(createButton(), "pos n 50% 50% n"); tabbedPane.addTab("X Y Positions", posPanel); tabbedPane.addTab("X1 Y1 X2 Y2 Bounds", boundsPanel); // Glass pane tab if (benchRuns == 0) { final JPanel glassPanel = createTabPanel(new MigLayout("align c c, ins 0")); final JButton butt = createButton("Press me!!"); glassPanel.add(butt); butt.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { butt.setEnabled(false); final JPanel bg = new JPanel(new MigLayout("align c c,fill")) { public void paint(Graphics g) { g.setColor(getBackground()); g.fillRect(0, 0, getWidth(), getHeight()); super.paint(g); } }; bg.setOpaque(OPAQUE); configureActiveComponet(bg); final JLabel label = createLabel("You don't need a GlassPane to be cool!"); label.setFont(label.getFont().deriveFont(30f)); label.setForeground(new Color(255, 255, 255, 0)); bg.add(label, "align 50% 30%"); glassPanel.add(bg, "pos visual.x visual.y visual.x2 visual.y2", 0); final long startTime = System.nanoTime(); final long endTime = startTime + 500000000L; glassPanel.revalidate(); final javax.swing.Timer timer = new Timer(25, null); timer.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { long now = System.nanoTime(); int alpha = (int) (((now - startTime) / (double) (endTime - startTime)) * 300); if (alpha < 150) bg.setBackground(new Color(100, 100, 100, alpha)); if (alpha > 150 && alpha < 405) { label.setForeground(new Color(255, 255, 255, (alpha - 150))); bg.repaint(); } if (alpha > 405) timer.stop(); } }); timer.start(); } }); tabbedPane.addTab("GlassPane Substitute", glassPanel); addComponentListener(new ComponentAdapter() { public void componentMoved(ComponentEvent e) { if (posPanel.isDisplayable()) { posPanel.revalidate(); } else { removeComponentListener(this); } } }); } // Disregard. Just forgetting the source code text close to the source code. setSource("JTabbedPane tabbedPane = new JTabbedPane();\n" + "\n" + "// Pos tab\n" + "final JPanel posPanel = createTabPanel(new MigLayout());\n" + "\n" + "posPanel.add(createButton(), \"pos 0.5al 0al\");\n" + "posPanel.add(createButton(), \"pos 1al 0al\");\n" + "posPanel.add(createButton(), \"pos 0.5al 0.5al\");\n" + "posPanel.add(createButton(), \"pos 5in 45lp\");\n" + "posPanel.add(createButton(), \"pos 0.5al 0.5al\");\n" + "posPanel.add(createButton(), \"pos 0.5al 1.0al\");\n" + "posPanel.add(createButton(), \"pos 1al .25al\");\n" + "posPanel.add(createButton(), \"pos visual.x2-pref visual.y2-pref\");\n" + "posPanel.add(createButton(), \"pos 1al -1in\");\n" + "posPanel.add(createButton(), \"pos 100 100\");\n" + "posPanel.add(createButton(), \"pos (10+(20*3lp)) 200\");\n" + "posPanel.add(createButton(\"Drag Window! (pos 500-container.xpos 500-container.ypos)\"),\n" + " \"pos 500-container.xpos 500-container.ypos\");\n" + "\n" + "// Bounds tab\n" + "JPanel boundsPanel = createTabPanel(new MigLayout());\n" + "\n" + "String constr = \"pos (visual.x+visual.w*0.1) visual.y2-40 (visual.x2-visual.w*0.1) visual.y2\";\n" + "JLabel southLabel = createLabel(constr, SwingConstants.CENTER);\n" + "southLabel.setBorder(new LineBorder(Color.LIGHT_GRAY, 1));\n" + "southLabel.setBackground(new Color(200, 200, 255, 70));\n" + "southLabel.setOpaque(true);\n" + "southLabel.setFont(southLabel.getFont().deriveFont(Font.BOLD));\n" + "boundsPanel.add(southLabel, constr);\n" + "\n" + "boundsPanel.add(createButton(), \"pos 0 0 container.x2 n\");\n" + "boundsPanel.add(createButton(), \"pos visual.x 40 visual.x2 70\");\n" + "boundsPanel.add(createButton(), \"pos visual.x 100 visual.x2 p\");\n" + "boundsPanel.add(createButton(), \"pos 0.1al 0.4al n visual.y2-10\");\n" + "boundsPanel.add(createButton(), \"pos 0.9al 0.4al n visual.y2-10\");\n" + "boundsPanel.add(createButton(), \"pos 0.5al 0.5al, pad 3 0 -3 0\");\n" + "boundsPanel.add(createButton(), \"pos n n 50% 50%\");\n" + "boundsPanel.add(createButton(), \"pos 50% 50% n n\");\n" + "boundsPanel.add(createButton(), \"pos 50% n n 50%\");\n" + "boundsPanel.add(createButton(), \"pos n 50% 50% n\");\n" + "\n" + "// Glass pane tab\n" + "final JPanel glassPanel = createTabPanel(new MigLayout(\"align c c, ins 0\"));\n" + "final JButton butt = createButton(\"Press me!!\");\n" + "glassPanel.add(butt);\n" + "\n" + "butt.addActionListener(new ActionListener()\t\t{\n" + "\tpublic void actionPerformed(ActionEvent e)\n" + "\t{\n" + "\t\tbutt.setEnabled(false);\n" + "\t\tfinal JPanel bg = new JPanel(new MigLayout(\"align c c,fill\")) {\n" + "\t\t\tpublic void paint(Graphics g)\n" + "\t\t\t{\n" + "\t\t\t\tg.setColor(getBackground());\n" + "\t\t\t\tg.fillRect(0, 0, getWidth(), getHeight());\n" + "\t\t\t\tsuper.paint(g);\n" + "\t\t\t}\n" + "\t\t};\n" + "\t\tbg.setOpaque(OPAQUE);\n" + "\t\tconfigureActiveComponet(bg);\n" + "\n" + "\t\tfinal JLabel label = createLabel(\"You don't need a GlassPane to be cool!\");\n" + "\t\tlabel.setFont(label.getFont().deriveFont(30f));\n" + "\t\tlabel.setForeground(new Color(255, 255, 255, 0));\n" + "\t\tbg.add(label, \"align 50% 30%\");\n" + "\n" + "\t\tglassPanel.add(bg, \"pos visual.x visual.y visual.x2 visual.y2\", 0);\n" + "\t\tfinal long startTime = System.nanoTime();\n" + "\t\tfinal long endTime = startTime + 500000000L;\n" + "\n" + "\t\tglassPanel.revalidate();\n" + "\n" + "\t\tfinal javax.swing.Timer timer = new Timer(25, null);\n" + "\n" + "\t\ttimer.addActionListener(new ActionListener() {\n" + "\t\t\tpublic void actionPerformed(ActionEvent e)\n" + "\t\t\t{\n" + "\t\t\t\tlong now = System.nanoTime();\n" + "\t\t\t\tint alpha = (int) (((now - startTime) / (double) (endTime - startTime)) * 300);\n" + "\t\t\t\tif (alpha < 150)\n" + "\t\t\t\t\tbg.setBackground(new Color(100, 100, 100, alpha));\n" + "\n" + "\t\t\t\tif (alpha > 150 && alpha < 405) {\n" + "\t\t\t\t\tlabel.setForeground(new Color(255, 255, 255, (alpha - 150)));\n" + "\t\t\t\t\tbg.repaint();\n" + "\t\t\t\t}\n" + "\t\t\t\tif (alpha > 405)\n" + "\t\t\t\t\ttimer.stop();\n" + "\t\t\t}\n" + "\t\t});\n" + "\t\ttimer.start();\n" + "\t}\n" + "});\n" + "\n" + "tabbedPane.addTab(\"X Y Positions\", posPanel);\n" + "tabbedPane.addTab(\"X1 Y1 X2 Y2 Bounds\", boundsPanel);\n" + "tabbedPane.addTab(\"GlassPane Substitute\", glassPanel);\n" + "\n" + "addComponentListener(new ComponentAdapter() {\n" + "\tpublic void componentMoved(ComponentEvent e) {\n" + "\t\tif (posPanel.isDisplayable()) {\n" + "\t\t\tposPanel.revalidate();\n" + "\t\t} else {\n" + "\t\t\tremoveComponentListener(this);\n" + "\t\t}\n" + "\t}\n" + "});"); return tabbedPane; } public JComponent createComponent_Links() { JTabbedPane tabbedPane = new JTabbedPane(); JPanel linksPanel = createTabPanel(new MigLayout()); // Links tab JButton mini = createButton("Mini"); mini.setMargin(new Insets(0, 1, 0, 1)); linksPanel.add(mini, "pos null ta.y ta.x2 null"); linksPanel.add(createTextArea("Components, Please Link to Me!\nMy ID is: 'ta'", 3, 30), "id ta, pos 0.5al 0.5al"); linksPanel.add(createButton(), "id b1,pos ta.x2 ta.y2"); linksPanel.add(createButton(), "pos b1.x2+rel b1.y visual.x2 null"); linksPanel.add(createButton(), "pos ta.x2+rel ta.y visual.x2 null"); linksPanel.add(createButton(), "pos null ta.y+(ta.h-pref)/2 ta.x-rel null"); linksPanel.add(createButton(), "pos ta.x ta.y2+100 ta.x2 null"); linksPanel.add(createCheck("pos (ta.x+indent) (ta.y2+rel)"), "pos (ta.x+indent) (ta.y2+rel)"); // External tab JPanel externalPanel = createTabPanel(new MigLayout()); JButton extButt = createButton("Bounds Externally Set!"); extButt.setBounds(250, 130, 200, 40); externalPanel.add(extButt, "id ext, external"); externalPanel.add(createButton(), "pos ext.x2 ext.y2"); externalPanel.add(createButton(), "pos null null ext.x ext.y"); // Start/End Group tab JPanel egPanel = createTabPanel(new MigLayout()); egPanel.add(createButton(), "id b1, endgroupx g1, pos 200 200"); egPanel.add(createButton(), "id b2, endgroupx g1, pos (b1.x+2ind) (b1.y2+rel)"); egPanel.add(createButton(), "id b3, endgroupx g1, pos (b1.x+4ind) (b2.y2+rel)"); egPanel.add(createButton(), "id b4, endgroupx g1, pos (b1.x+6ind) (b3.y2+rel)"); // Group Bounds tab JPanel gpPanel = createTabPanel(new MigLayout()); gpPanel.add(createButton(), "id grp1.b1, pos n 0.5al 50% n"); gpPanel.add(createButton(), "id grp1.b2, pos 50% 0.5al n n"); gpPanel.add(createButton(), "id grp1.b3, pos 0.5al n n b1.y"); gpPanel.add(createButton(), "id grp1.b4, pos 0.5al b1.y2 n n"); gpPanel.add(createButton(), "pos n grp1.y2 grp1.x n"); gpPanel.add(createButton(), "pos n n grp1.x grp1.y"); gpPanel.add(createButton(), "pos grp1.x2 n n grp1.y"); gpPanel.add(createButton(), "pos grp1.x2 grp1.y2"); JPanel boundsPanel = new JPanel(null); boundsPanel.setBackground(new Color(200, 200, 255)); gpPanel.add(boundsPanel, "pos grp1.x grp1.y grp1.x2 grp1.y2"); tabbedPane.addTab("Component Links", linksPanel); tabbedPane.addTab("External Components", externalPanel); tabbedPane.addTab("End Grouping", egPanel); tabbedPane.addTab("Group Bounds", gpPanel); // Disregard. Just forgetting the source code text close to the source code. setSource("JTabbedPane tabbedPane = new JTabbedPane();\n" + "\n" + "JPanel linksPanel = createTabPanel(new MigLayout());\n" + "\n" + "// Links tab\n" + "JButton mini = createButton(\"Mini\");\n" + "mini.setMargin(new Insets(0, 1, 0, 1));\n" + "linksPanel.add(mini, \"pos null ta.y ta.x2 null\");\n" + "linksPanel.add(createTextArea(\"Components, Please Link to Me!\\nMy ID is: 'ta'\", 3, 30), \"id ta, pos 0.5al 0.5al\");\n" + "linksPanel.add(createButton(), \"id b1,pos ta.x2 ta.y2\");\n" + "linksPanel.add(createButton(), \"pos b1.x2+rel b1.y visual.x2 null\");\n" + "linksPanel.add(createButton(), \"pos ta.x2+rel ta.y visual.x2 null\");\n" + "linksPanel.add(createButton(), \"pos null ta.y+(ta.h-pref)/2 ta.x-rel null\");\n" + "linksPanel.add(createButton(), \"pos ta.x ta.y2+100 ta.x2 null\");\n" + "linksPanel.add(createCheck(\"pos (ta.x+indent) (ta.y2+rel)\"),\n" + " \"pos (ta.x+indent) (ta.y2+rel)\");\n" + "\n" + "// External tab\n" + "JPanel externalPanel = createTabPanel(new MigLayout());\n" + "\n" + "JButton extButt = createButton(\"Bounds Externally Set!\");\n" + "extButt.setBounds(250, 130, 200, 40);\n" + "externalPanel.add(extButt, \"id ext, external\");\n" + "externalPanel.add(createButton(), \"pos ext.x2 ext.y2\");\n" + "externalPanel.add(createButton(), \"pos null null ext.x ext.y\");\n" + "\n" + "// Start/End Group tab\n" + "JPanel egPanel = createTabPanel(new MigLayout());\n" + "\n" + "egPanel.add(createButton(), \"id b1, endgroupx g1, pos 200 200\");\n" + "egPanel.add(createButton(), \"id b2, endgroupx g1, pos (b1.x+2ind) (b1.y2+rel)\");\n" + "egPanel.add(createButton(), \"id b3, endgroupx g1, pos (b1.x+4ind) (b2.y2+rel)\");\n" + "egPanel.add(createButton(), \"id b4, endgroupx g1, pos (b1.x+6ind) (b3.y2+rel)\");\n" + "\n" + "// Group Bounds tab\n" + "JPanel gpPanel = createTabPanel(new MigLayout());\n" + "\n" + "gpPanel.add(createButton(), \"id grp1.b1, pos n 0.5al 50% n\");\n" + "gpPanel.add(createButton(), \"id grp1.b2, pos 50% 0.5al n n\");\n" + "gpPanel.add(createButton(), \"id grp1.b3, pos 0.5al n n b1.y\");\n" + "gpPanel.add(createButton(), \"id grp1.b4, pos 0.5al b1.y2 n n\");\n" + "\n" + "gpPanel.add(createButton(), \"pos n grp1.y2 grp1.x n\");\n" + "gpPanel.add(createButton(), \"pos n n grp1.x grp1.y\");\n" + "gpPanel.add(createButton(), \"pos grp1.x2 n n grp1.y\");\n" + "gpPanel.add(createButton(), \"pos grp1.x2 grp1.y2\");\n" + "\n" + "JPanel boundsPanel = new JPanel(null);\n" + "boundsPanel.setBackground(new Color(200, 200, 255));\n" + "gpPanel.add(boundsPanel, \"pos grp1.x grp1.y grp1.x2 grp1.y2\");\n" + "\n" + "\n" + "tabbedPane.addTab(\"Component Links\", linksPanel);\n" + "tabbedPane.addTab(\"External Components\", externalPanel);\n" + "tabbedPane.addTab(\"End Grouping\", egPanel);\n" + "tabbedPane.addTab(\"Group Bounds\", gpPanel);"); return tabbedPane; } public JComponent createFlow_Direction() { JTabbedPane tabbedPane = new JTabbedPane(); tabbedPane.addTab("Layout: flowx, Cell: flowx", createFlowPanel("", "flowx")); tabbedPane.addTab("Layout: flowx, Cell: flowy", createFlowPanel("", "flowy")); tabbedPane.addTab("Layout: flowy, Cell: flowx", createFlowPanel("flowy", "flowx")); tabbedPane.addTab("Layout: flowy, Cell: flowy", createFlowPanel("flowy", "flowy")); // Disregard. Just forgetting the source code text close to the source code. setSource("JTabbedPane tabbedPane = new JTabbedPane();\n" + "\n" + "tabbedPane.addTab(\"Layout: flowx, Cell: flowx\", createFlowPanel(\"\", \"flowx\"));\n" + "tabbedPane.addTab(\"Layout: flowx, Cell: flowy\", createFlowPanel(\"\", \"flowy\"));\n" + "tabbedPane.addTab(\"Layout: flowy, Cell: flowx\", createFlowPanel(\"flowy\", \"flowx\"));\n" + "tabbedPane.addTab(\"Layout: flowy, Cell: flowy\", createFlowPanel(\"flowy\", \"flowy\"));" + "\n\tpublic JPanel createFlowPanel(String gridFlow, String cellFlow)\n" + "\t{\n" + "MigLayout lm = new MigLayout(\"center, wrap 3,\" + gridFlow,\n" + " \"[110,fill]\",\n" + " \"[110,fill]\");\n" + "JPanel panel = createTabPanel(lm);\n" + "\n" + "for (int i = 0; i < 9; i++) {\n" + "\tJButton b = createButton(\"\" + (i + 1));\n" + "\tb.setFont(b.getFont().deriveFont(20f));\n" + "\tpanel.add(b, cellFlow);\n" + "}\n" + "\n" + "JButton b = createButton(\"5:2\");\n" + "b.setFont(b.getFont().deriveFont(20f));\n" + "panel.add(b, cellFlow + \",cell 1 1\");\n" + "\n" + "return panel;\n" + "\t}"); return tabbedPane; } public JPanel createFlowPanel(String gridFlow, String cellFlow) { MigLayout lm = new MigLayout("center, wrap 3," + gridFlow, "[110,fill]", "[110,fill]"); JPanel panel = createTabPanel(lm); Font f = panel.getFont().deriveFont(20f); for (int i = 0; i < 9; i++) { JComponent b = createPanel("" + (i + 1)); b.setFont(f); panel.add(b, cellFlow); } JComponent b = createPanel("5:2"); b.setFont(f); panel.add(b, cellFlow + ",cell 1 1"); return panel; } public JComponent createDebug() { return createPlainImpl(true); } public JComponent createButton_Bars() { MigLayout lm = new MigLayout("ins 0 0 15lp 0", "[grow]", "[grow][baseline,nogrid]"); final JPanel mainPanel = new JPanel(lm); final JLabel formatLabel = createLabel(""); formatLabel.setFont(formatLabel.getFont().deriveFont(Font.BOLD)); JTabbedPane tabbedPane = new JTabbedPane(); JToggleButton winButt = createToggleButton("Windows"); JToggleButton macButt = createToggleButton("Mac OS X"); JButton helpButt = createButton("Help"); if (benchRuns == 0) { winButt.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { PlatformDefaults.setPlatform(PlatformDefaults.WINDOWS_XP); formatLabel.setText("'" + PlatformDefaults.getButtonOrder() + "'"); ((JPanel) ((JFrame) Frame.getFrames()[0]).getContentPane()).revalidate(); } }); macButt.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { PlatformDefaults.setPlatform(PlatformDefaults.MAC_OSX); formatLabel.setText(PlatformDefaults.getButtonOrder()); ((JPanel) ((JFrame) Frame.getFrames()[0]).getContentPane()).revalidate(); } }); helpButt.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JOptionPane.showMessageDialog(mainPanel, "See JavaDoc for PlatformDefaults.setButtonOrder(..) for details on the format string."); } }); } ButtonGroup bg = new ButtonGroup(); bg.add(winButt); bg.add(macButt); if (benchRuns == 0) { if (PlatformDefaults.getCurrentPlatform() == PlatformDefaults.MAC_OSX) { macButt.doClick(); } else { winButt.doClick(); } } tabbedPane.addTab("Buttons", createButtonBarsPanel("help", false)); tabbedPane.addTab("Buttons with Help2", createButtonBarsPanel("help2", false)); tabbedPane.addTab("Buttons (Same width)", createButtonBarsPanel("help", true)); mainPanel.add(tabbedPane, "grow,wrap"); mainPanel.add(createLabel("Button Order:")); mainPanel.add(formatLabel, "growx"); mainPanel.add(winButt); mainPanel.add(macButt); mainPanel.add(helpButt, "gapbefore unrel"); // Disregard. Just forgetting the source code text close to the source code. setSource("MigLayout lm = new MigLayout(\"ins 0 0 15lp 0\",\n" + " \"[grow]\",\n" + " \"[grow][baseline,nogrid,gap unrelated]\");\n" + "\n" + "final JPanel mainPanel = new JPanel(lm);\n" + "final JLabel formatLabel = createLabel(\"\");\n" + "formatLabel.setFont(formatLabel.getFont().deriveFont(Font.BOLD));\n" + "JTabbedPane tabbedPane = new JTabbedPane();\n" + "\n" + "JToggleButton winButt = createToggleButton(\"Windows\");\n" + "\n" + "winButt.addActionListener(new ActionListener() {\n" + "\tpublic void actionPerformed(ActionEvent e) {\n" + "\t\tPlatformDefaults.setPlatform(PlatformDefaults.WINDOWS_XP);\n" + "\t\tformatLabel.setText(\"'\" + PlatformDefaults.getButtonOrder() + \"'\");\n" + "\t\tSwingUtilities.updateComponentTreeUI(mainPanel);\n" + "\t}\n" + "});\n" + "\n" + "JToggleButton macButt = createToggleButton(\"Mac OS X\");\n" + "macButt.addActionListener(new ActionListener() {\n" + "\tpublic void actionPerformed(ActionEvent e) {\n" + "\t\tPlatformDefaults.setPlatform(PlatformDefaults.MAC_OSX);\n" + "\t\tformatLabel.setText(PlatformDefaults.getButtonOrder());\n" + "\t\tSwingUtilities.updateComponentTreeUI(mainPanel);\n" + "\t}\n" + "});\n" + "\n" + "JButton helpButt = createButton(\"Help\");\n" + "helpButt.addActionListener(new ActionListener() {\n" + "\tpublic void actionPerformed(ActionEvent e) {\n" + "\t\tJOptionPane.showMessageDialog(mainPanel, \"See JavaDoc for PlatformDefaults.setButtonOrder(..) for details on the format string.\");\n" + "\t}\n" + "});\n" + "\n" + "ButtonGroup bg = new ButtonGroup();\n" + "bg.add(winButt);\n" + "bg.add(macButt);\n" + "winButt.doClick();\n" + "\n" + "tabbedPane.addTab(\"Buttons\", createButtonBarsPanel(\"help\", false));\n" + "tabbedPane.addTab(\"Buttons with Help2\", createButtonBarsPanel(\"help2\", false));\n" + "tabbedPane.addTab(\"Buttons (Same width)\", createButtonBarsPanel(\"help\", true));\n" + "\n" + "mainPanel.add(tabbedPane, \"grow,wrap\");\n" + "\n" + "mainPanel.add(createLabel(\"Button Order:\"));\n" + "mainPanel.add(formatLabel, \"growx\");\n" + "mainPanel.add(winButt);\n" + "mainPanel.add(macButt);\n" + "mainPanel.add(helpButt, \"gapbefore unrel\");"); return mainPanel; } private JComponent createButtonBarsPanel(String helpTag, boolean sizeLocked) { MigLayout lm = new MigLayout("nogrid, fillx, aligny 100%, gapy unrel"); JPanel panel = createTabPanel(lm); // Notice that the order in the rows below does not matter... String[][] buttons = new String[][] { {"OK"}, {"No", "Yes"}, {"Help", "Close"}, {"OK", "Help"}, {"OK", "Cancel", "Help"}, {"OK", "Cancel", "Apply", "Help"}, {"No", "Yes", "Cancel"}, {"Help", "< Back", "Forward >", "Cancel"}, {"Print...", "Cancel", "Help"} }; for (int r = 0; r < buttons.length; r++) { for (int i = 0; i < buttons[r].length; i++) { String txt = buttons[r][i]; String tag = txt; if (txt.equals("Help")) { tag = helpTag; } else if (txt.equals("< Back")) { tag = "back"; } else if (txt.equals("Close")) { tag = "cancel"; } else if (txt.equals("Forward >")) { tag = "next"; } else if (txt.equals("Print...")) { tag = "other"; } String wrap = (i == buttons[r].length - 1) ? ",wrap" : ""; String sizeGroup = sizeLocked ? ("sgx " + r + ",") : ""; panel.add(createButton(txt), sizeGroup + "tag " + tag + wrap); } } return panel; } public JComponent createOrientation() { JTabbedPane tabbedPane = new JTabbedPane(); MigLayout lm = new MigLayout("flowy", "[grow,fill]", "[]20[]20[]20[]"); JPanel mainPanel = createTabPanel(lm); // Default orientation MigLayout defLM = new MigLayout("", "[trailing][grow,fill]", ""); JPanel defPanel = createTabPanel(defLM); addSeparator(defPanel, "Default Orientation"); defPanel.add(createLabel("Level of Trust")); defPanel.add(createTextField(""), "span,growx"); defPanel.add(createLabel("Radar Presentation")); defPanel.add(createTextField("")); defPanel.add(createTextField("")); // Right-to-left, Top-to-bottom MigLayout rtlLM = new MigLayout("rtl,ttb", "[trailing][grow,fill]", ""); JPanel rtlPanel = createTabPanel(rtlLM); addSeparator(rtlPanel, "Right to Left"); rtlPanel.add(createLabel("Level of Trust")); rtlPanel.add(createTextField(""), "span,growx"); rtlPanel.add(createLabel("Radar Presentation")); rtlPanel.add(createTextField("")); rtlPanel.add(createTextField("")); // Right-to-left, Bottom-to-top MigLayout rtlbLM = new MigLayout("rtl,btt", "[trailing][grow,fill]", ""); JPanel rtlbPanel = createTabPanel(rtlbLM); addSeparator(rtlbPanel, "Right to Left, Bottom to Top"); rtlbPanel.add(createLabel("Level of Trust")); rtlbPanel.add(createTextField(""), "span,growx"); rtlbPanel.add(createLabel("Radar Presentation")); rtlbPanel.add(createTextField("")); rtlbPanel.add(createTextField("")); // Left-to-right, Bottom-to-top MigLayout ltrbLM = new MigLayout("ltr,btt", "[trailing][grow,fill]", ""); JPanel ltrbPanel = createTabPanel(ltrbLM); addSeparator(ltrbPanel, "Left to Right, Bottom to Top"); ltrbPanel.add(createLabel("Level of Trust")); ltrbPanel.add(createTextField(""), "span,growx"); ltrbPanel.add(createLabel("Radar Presentation")); ltrbPanel.add(createTextField("")); ltrbPanel.add(createTextField("")); mainPanel.add(defPanel); mainPanel.add(rtlPanel); mainPanel.add(rtlbPanel); mainPanel.add(ltrbPanel); tabbedPane.addTab("Orientation", mainPanel); // Disregard. Just forgetting the source code text close to the source code. setSource("JTabbedPane tabbedPane = new JTabbedPane();\n" + "\n" + "MigLayout lm = new MigLayout(\"flowy\", \"[grow,fill]\", \"[]0[]15lp[]0[]\");\n" + "JPanel mainPanel = createTabPanel(lm);\n" + "\n" + "// Default orientation\n" + "MigLayout defLM = new MigLayout(\"\", \"[][grow,fill]\", \"\");\n" + "\n" + "JPanel defPanel = createTabPanel(defLM);\n" + "addSeparator(defPanel, \"Default Orientation\");\n" + "defPanel.add(createLabel(\"Level\"));\n" + "defPanel.add(createTextField(\"\"), \"span,growx\");\n" + "defPanel.add(createLabel(\"Radar\"));\n" + "defPanel.add(createTextField(\"\"));\n" + "defPanel.add(createTextField(\"\"));\n" + "\n" + "// Right-to-left, Top-to-bottom\n" + "MigLayout rtlLM = new MigLayout(\"rtl,ttb\",\n" + " \"[][grow,fill]\",\n" + " \"\");\n" + "JPanel rtlPanel = createTabPanel(rtlLM);\n" + "addSeparator(rtlPanel, \"Right to Left\");\n" + "rtlPanel.add(createLabel(\"Level\"));\n" + "rtlPanel.add(createTextField(\"\"), \"span,growx\");\n" + "rtlPanel.add(createLabel(\"Radar\"));\n" + "rtlPanel.add(createTextField(\"\"));\n" + "rtlPanel.add(createTextField(\"\"));\n" + "\n" + "// Right-to-left, Bottom-to-top\n" + "MigLayout rtlbLM = new MigLayout(\"rtl,btt\",\n" + " \"[][grow,fill]\",\n" + " \"\");\n" + "JPanel rtlbPanel = createTabPanel(rtlbLM);\n" + "addSeparator(rtlbPanel, \"Right to Left, Bottom to Top\");\n" + "rtlbPanel.add(createLabel(\"Level\"));\n" + "rtlbPanel.add(createTextField(\"\"), \"span,growx\");\n" + "rtlbPanel.add(createLabel(\"Radar\"));\n" + "rtlbPanel.add(createTextField(\"\"));\n" + "rtlbPanel.add(createTextField(\"\"));\n" + "\n" + "// Left-to-right, Bottom-to-top\n" + "MigLayout ltrbLM = new MigLayout(\"ltr,btt\",\n" + " \"[][grow,fill]\",\n" + " \"\");\n" + "JPanel ltrbPanel = createTabPanel(ltrbLM);\n" + "addSeparator(ltrbPanel, \"Left to Right, Bottom to Top\");\n" + "ltrbPanel.add(createLabel(\"Level\"));\n" + "ltrbPanel.add(createTextField(\"\"), \"span,growx\");\n" + "ltrbPanel.add(createLabel(\"Radar\"));\n" + "ltrbPanel.add(createTextField(\"\"));\n" + "ltrbPanel.add(createTextField(\"\"));\n" + "\n" + "mainPanel.add(defPanel);\n" + "mainPanel.add(rtlPanel);\n" + "mainPanel.add(rtlbPanel);\n" + "mainPanel.add(ltrbPanel);\n" + "\n" + "tabbedPane.addTab(\"Orientation\", mainPanel);"); return tabbedPane; } public JComponent createCell_Position() { JTabbedPane tabbedPane = new JTabbedPane(); // Absolute grid position MigLayout absLM = new MigLayout("", "[100:pref,fill]", "[100:pref,fill]"); JPanel absPanel = createTabPanel(absLM); absPanel.add(createButton(), "cell 0 0"); absPanel.add(createButton(), "cell 2 0"); absPanel.add(createButton(), "cell 3 0"); absPanel.add(createButton(), "cell 1 1"); absPanel.add(createButton(), "cell 0 2"); absPanel.add(createButton(), "cell 2 2"); absPanel.add(createButton(), "cell 2 2"); // Relative grid position with wrap MigLayout relAwLM = new MigLayout("wrap", "[100:pref,fill][100:pref,fill][100:pref,fill][100:pref,fill]", "[100:pref,fill]"); JPanel relAwPanel = createTabPanel(relAwLM); relAwPanel.add(createButton()); relAwPanel.add(createButton(), "skip"); relAwPanel.add(createButton()); relAwPanel.add(createButton(), "skip,wrap"); relAwPanel.add(createButton()); relAwPanel.add(createButton(), "skip,split"); relAwPanel.add(createButton()); // Relative grid position with manual wrap MigLayout relWLM = new MigLayout("", "[100:pref,fill]", "[100:pref,fill]"); JPanel relWPanel = createTabPanel(relWLM); relWPanel.add(createButton()); relWPanel.add(createButton(), "skip"); relWPanel.add(createButton(), "wrap"); relWPanel.add(createButton(), "skip,wrap"); relWPanel.add(createButton()); relWPanel.add(createButton(), "skip,split"); relWPanel.add(createButton()); // Mixed relative and absolute grid position MigLayout mixLM = new MigLayout("", "[100:pref,fill]", "[100:pref,fill]"); JPanel mixPanel = createTabPanel(mixLM); mixPanel.add(createButton()); mixPanel.add(createButton(), "cell 2 0"); mixPanel.add(createButton()); mixPanel.add(createButton(), "cell 1 1,wrap"); mixPanel.add(createButton()); mixPanel.add(createButton(), "cell 2 2,split"); mixPanel.add(createButton()); tabbedPane.addTab("Absolute", absPanel); tabbedPane.addTab("Relative + Wrap", relAwPanel); tabbedPane.addTab("Relative", relWPanel); tabbedPane.addTab("Mixed", mixPanel); // Disregard. Just forgetting the source code text close to the source code. setSource("\t\tJTabbedPane tabbedPane = new JTabbedPane();\n" + "\n" + "\t\t// Absolute grid position\n" + "\t\tMigLayout absLM = new MigLayout(\"\",\n" + "\t\t \"[100:pref,fill]\",\n" + "\t\t \"[100:pref,fill]\");\n" + "\t\tJPanel absPanel = createTabPanel(absLM);\n" + "\t\tabsPanel.add(createPanel(), \"cell 0 0\");\n" + "\t\tabsPanel.add(createPanel(), \"cell 2 0\");\n" + "\t\tabsPanel.add(createPanel(), \"cell 3 0\");\n" + "\t\tabsPanel.add(createPanel(), \"cell 1 1\");\n" + "\t\tabsPanel.add(createPanel(), \"cell 0 2\");\n" + "\t\tabsPanel.add(createPanel(), \"cell 2 2\");\n" + "\t\tabsPanel.add(createPanel(), \"cell 2 2\");\n" + "\n" + "\n" + "\t\t// Relative grid position with wrap\n" + "\t\tMigLayout relAwLM = new MigLayout(\"wrap\",\n" + "\t\t \"[100:pref,fill][100:pref,fill][100:pref,fill][100:pref,fill]\",\n" + "\t\t \"[100:pref,fill]\");\n" + "\t\tJPanel relAwPanel = createTabPanel(relAwLM);\n" + "\t\trelAwPanel.add(createPanel());\n" + "\t\trelAwPanel.add(createPanel(), \"skip\");\n" + "\t\trelAwPanel.add(createPanel());\n" + "\t\trelAwPanel.add(createPanel(), \"skip,wrap\");\n" + "\t\trelAwPanel.add(createPanel());\n" + "\t\trelAwPanel.add(createPanel(), \"skip,split\");\n" + "\t\trelAwPanel.add(createPanel());\n" + "\n" + "\n" + "\t\t// Relative grid position with manual wrap\n" + "\t\tMigLayout relWLM = new MigLayout(\"\",\n" + "\t\t \"[100:pref,fill]\",\n" + "\t\t \"[100:pref,fill]\");\n" + "\t\tJPanel relWPanel = createTabPanel(relWLM);\n" + "\t\trelWPanel.add(createPanel());\n" + "\t\trelWPanel.add(createPanel(), \"skip\");\n" + "\t\trelWPanel.add(createPanel(), \"wrap\");\n" + "\t\trelWPanel.add(createPanel(), \"skip,wrap\");\n" + "\t\trelWPanel.add(createPanel());\n" + "\t\trelWPanel.add(createPanel(), \"skip,split\");\n" + "\n" + "\t\trelWPanel.add(createPanel());\n" + "\n" + "\n" + "\t\t// Mixed relative and absolute grid position\n" + "\t\tMigLayout mixLM = new MigLayout(\"\",\n" + "\t\t \"[100:pref,fill]\",\n" + "\t\t \"[100:pref,fill]\");\n" + "\t\tJPanel mixPanel = createTabPanel(mixLM);\n" + "\t\tmixPanel.add(createPanel());\n" + "\t\tmixPanel.add(createPanel(), \"cell 2 0\");\n" + "\t\tmixPanel.add(createPanel());\n" + "\t\tmixPanel.add(createPanel(), \"cell 1 1,wrap\");\n" + "\t\tmixPanel.add(createPanel());\n" + "\t\tmixPanel.add(createPanel(), \"cell 2 2,split\");\n" + "\t\tmixPanel.add(createPanel());\n" + "\n" + "\t\ttabbedPane.addTab(\"Absolute\", absPanel);\n" + "\t\ttabbedPane.addTab(\"Relative + Wrap\", relAwPanel);\n" + "\t\ttabbedPane.addTab(\"Relative\", relWPanel);\n" + "\t\ttabbedPane.addTab(\"Mixed\", mixPanel);"); return tabbedPane; } public JComponent createPlain() { return createPlainImpl(false); } private JComponent createPlainImpl(boolean debug) { JTabbedPane tabbedPane = new JTabbedPane(); MigLayout lm = new MigLayout((debug && benchRuns == 0 ? "debug, inset 20" : "ins 20"), "[para]0[][100lp, fill][60lp][95lp, fill]", ""); JPanel panel = createTabPanel(lm); addSeparator(panel, "Manufacturer"); panel.add(createLabel("Company"), "skip"); panel.add(createTextField(""), "span, growx"); panel.add(createLabel("Contact"), "skip"); panel.add(createTextField(""), "span, growx"); panel.add(createLabel("Order No"), "skip"); panel.add(createTextField(15), "wrap para"); addSeparator(panel, "Inspector"); panel.add(createLabel("Name"), "skip"); panel.add(createTextField(""), "span, growx"); panel.add(createLabel("Reference No"), "skip"); panel.add(createTextField(""), "wrap"); panel.add(createLabel("Status"), "skip"); panel.add(createCombo(new String[] {"In Progress", "Finnished", "Released"}), "wrap para"); addSeparator(panel, "Ship"); panel.add(createLabel("Shipyard"), "skip"); panel.add(createTextField(""), "span, growx"); panel.add(createLabel("Register No"), "skip"); panel.add(createTextField("")); panel.add(createLabel("Hull No"), "right"); panel.add(createTextField(15), "wrap"); panel.add(createLabel("Project StructureType"), "skip"); panel.add(createCombo(new String[] {"New Building", "Convention", "Repair"})); if (debug) panel.add(createLabel("Red is cell bounds. Blue is component bounds."), "newline,ax left,span,gaptop 40,"); tabbedPane.addTab("Plain", panel); // Disregard. Just forgetting the source code text close to the source code. setSource("JTabbedPane tabbedPane = new JTabbedPane();\n" + "\n" + "MigLayout lm = new MigLayout((debug && benchRuns == 0 ? \"debug, inset 20\" : \"ins 20\"), \"[para]0[][100lp, fill][60lp][95lp, fill]\", \"\");\n" + "JPanel panel = createTabPanel(lm);\n" + "\n" + "addSeparator(panel, \"Manufacturer\");\n" + "\n" + "panel.add(createLabel(\"Company\"), \"skip\");\n" + "panel.add(createTextField(\"\"), \"span, growx\");\n" + "panel.add(createLabel(\"Contact\"), \"skip\");\n" + "panel.add(createTextField(\"\"), \"span, growx\");\n" + "panel.add(createLabel(\"Order No\"), \"skip\");\n" + "panel.add(createTextField(15), \"wrap para\");\n" + "\n" + "addSeparator(panel, \"Inspector\");\n" + "\n" + "panel.add(createLabel(\"Name\"), \"skip\");\n" + "panel.add(createTextField(\"\"), \"span, growx\");\n" + "panel.add(createLabel(\"Reference No\"), \"skip\");\n" + "panel.add(createTextField(\"\"), \"wrap\");\n" + "panel.add(createLabel(\"Status\"), \"skip\");\n" + "panel.add(createCombo(new String[] {\"In Progress\", \"Finnished\", \"Released\"}), \"wrap para\");\n" + "\n" + "addSeparator(panel, \"Ship\");\n" + "\n" + "panel.add(createLabel(\"Shipyard\"), \"skip\");\n" + "panel.add(createTextField(\"\"), \"span, growx\");\n" + "panel.add(createLabel(\"Register No\"), \"skip\");\n" + "panel.add(createTextField(\"\"));\n" + "panel.add(createLabel(\"Hull No\"), \"right\");\n" + "panel.add(createTextField(15), \"wrap\");\n" + "panel.add(createLabel(\"Project StructureType\"), \"skip\");\n" + "panel.add(createCombo(new String[] {\"New Building\", \"Convention\", \"Repair\"}));\n" + "\n" + "if (debug)\n" + "\tpanel.add(createLabel(\"Red is cell bounds. Blue is component bounds.\"), \"newline,ax left,span,gaptop 40,\");\n" + "\n" + "tabbedPane.addTab(\"Plain\", panel);"); return tabbedPane; } public JComponent createBound_Sizes() { JTabbedPane tabbedPane = new JTabbedPane(); for (int i = 0; i < 2; i++) { // Jumping for 0 and Stable for 1 String colConstr = i == 0 ? "[right][300]" : "[right, 100lp:pref][300]"; MigLayout LM1 = new MigLayout("wrap", colConstr, ""); JPanel panel1 = createTabPanel(LM1); panel1.add(createLabel("File Number:")); panel1.add(createTextField(""), "growx"); panel1.add(createLabel("RFQ Number:")); panel1.add(createTextField(""), "growx"); panel1.add(createLabel("Entry Date:")); panel1.add(createTextField(6)); panel1.add(createLabel("Sales Person:")); panel1.add(createTextField(""), "growx"); MigLayout LM2 = new MigLayout("wrap", colConstr, ""); JPanel panel2 = createTabPanel(LM2); panel2.add(createLabel("Shipper:")); panel2.add(createTextField(6), "split 2"); panel2.add(createTextField(""), "growx"); panel2.add(createLabel("Consignee:")); panel2.add(createTextField(6), "split 2"); panel2.add(createTextField(""), "growx"); panel2.add(createLabel("Departure:")); panel2.add(createTextField(6), "split 2"); panel2.add(createTextField(""), "growx"); panel2.add(createLabel("Destination:")); panel2.add(createTextField(6), "split 2"); panel2.add(createTextField(""), "growx"); tabbedPane.addTab(i == 0 ? "Jumping 1" : "Stable 1", panel1); tabbedPane.addTab(i == 0 ? "Jumping 2" : "Stable 2", panel2); } // Disregard. Just forgetting the source code text close to the source code. setSource("JTabbedPane tabbedPane = new JTabbedPane();\n" + "\n" + "for (int i = 0; i < 2; i++) { // Jumping for 0 and Stable for 1\n" + "\tString colConstr = i == 0 ? \"[right][300]\" : \"[right, 100lp:pref][300]\";\n" + "\n" + "\tMigLayout LM1 = new MigLayout(\"wrap\", colConstr, \"\");\n" + "\tJPanel panel1 = createTabPanel(LM1);\n" + "\tpanel1.add(createLabel(\"File Number:\"));\n" + "\tpanel1.add(createTextField(\"\"), \"growx\");\n" + "\tpanel1.add(createLabel(\"RFQ Number:\"));\n" + "\tpanel1.add(createTextField(\"\"), \"growx\");\n" + "\tpanel1.add(createLabel(\"Entry Date:\"));\n" + "\tpanel1.add(createTextField(6));\n" + "\tpanel1.add(createLabel(\"Sales Person:\"));\n" + "\tpanel1.add(createTextField(\"\"), \"growx\");\n" + "\n" + "\tMigLayout LM2 = new MigLayout(\"wrap\", colConstr, \"\");\n" + "\tJPanel panel2 = createTabPanel(LM2);\n" + "\tpanel2.add(createLabel(\"Shipper:\"));\n" + "\tpanel2.add(createTextField(6), \"split 2\");\n" + "\tpanel2.add(createTextField(\"\"), \"growx\");\n" + "\tpanel2.add(createLabel(\"Consignee:\"));\n" + "\tpanel2.add(createTextField(6), \"split 2\");\n" + "\tpanel2.add(createTextField(\"\"), \"growx\");\n" + "\tpanel2.add(createLabel(\"Departure:\"));\n" + "\tpanel2.add(createTextField(6), \"split 2\");\n" + "\tpanel2.add(createTextField(\"\"), \"growx\");\n" + "\tpanel2.add(createLabel(\"Destination:\"));\n" + "\tpanel2.add(createTextField(6), \"split 2\");\n" + "\tpanel2.add(createTextField(\"\"), \"growx\");\n" + "\n" + "\ttabbedPane.addTab(i == 0 ? \"Jumping 1\" : \"Stable 2\", panel1);\n" + "\ttabbedPane.addTab(i == 0 ? \"Jumping 2\" : \"Stable 2\", panel2);\n" + "}"); return tabbedPane; } public JComponent createComponent_Sizes() { JTabbedPane tabbedPane = new JTabbedPane(); MigLayout LM = new MigLayout("wrap", "[right][0:pref,grow]", ""); JPanel panel = createTabPanel(LM); JScrollPane descrText = createTextAreaScroll("Use slider to see how the components grow and shrink depending on the constraints set on them.", 0, 0, false); descrText.setOpaque(OPAQUE); descrText.setBorder(new EmptyBorder(10, 10, 10, 10)); ((JTextArea) descrText.getViewport().getView()).setOpaque(OPAQUE); descrText.getViewport().setOpaque(OPAQUE); JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, panel, descrText); splitPane.setOpaque(OPAQUE); splitPane.setBorder(null); panel.add(createLabel("\"\"")); panel.add(createTextField("")); panel.add(createLabel("\"min!\"")); panel.add(createTextField("3", 3), "width min!"); panel.add(createLabel("\"pref!\"")); panel.add(createTextField("3", 3), "width pref!"); panel.add(createLabel("\"min:pref\"")); panel.add(createTextField("8", 8), "width min:pref"); panel.add(createLabel("\"min:100:150\"")); panel.add(createTextField("8", 8), "width min:100:150"); panel.add(createLabel("\"min:100:150, growx\"")); panel.add(createTextField("8", 8), "width min:100:150, growx"); panel.add(createLabel("\"min:100, growx\"")); panel.add(createTextField("8", 8), "width min:100, growx"); panel.add(createLabel("\"40!\"")); panel.add(createTextField("8", 8), "width 40!"); panel.add(createLabel("\"40:40:40\"")); panel.add(createTextField("8", 8), "width 40:40:40"); tabbedPane.addTab("Component Sizes", splitPane); // Disregard. Just forgetting the source code text close to the source code. setSource("JTabbedPane tabbedPane = new JTabbedPane();\n" + "\n" + "\t\tMigLayout LM = new MigLayout(\"wrap\", \"[right][0:pref,grow]\", \"\");\n" + "\n" + "\t\tJPanel panel = createTabPanel(LM);\n" + "\t\tJScrollPane descrText = createTextAreaScroll(\"Use slider to see how the components grow and shrink depending on the constraints set on them.\", 0, 0, false);\n" + "\n" + "\t\tdescrText.setOpaque(OPAQUE);\n" + "\t\tdescrText.setBorder(new EmptyBorder(10, 10, 10, 10));\n" + "\t\t((JTextArea) descrText.getViewport().getView()).setOpaque(OPAQUE);\n" + "\t\tdescrText.getViewport().setOpaque(OPAQUE);\n" + "\n" + "\t\tJSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, panel, descrText);\n" + "\t\tsplitPane.setOpaque(OPAQUE);\n" + "\t\tsplitPane.setBorder(null);\n" + "\n" + "\t\tpanel.add(createLabel(\"\\\"\\\"\"));\n" + "\t\tpanel.add(createTextField(\"\"));\n" + "\t\tpanel.add(createLabel(\"\\\"min!\\\"\"));\n" + "\t\tpanel.add(createTextField(\"3\", 3), \"width min!\");\n" + "\t\tpanel.add(createLabel(\"\\\"pref!\\\"\"));\n" + "\t\tpanel.add(createTextField(\"3\", 3), \"width pref!\");\n" + "\t\tpanel.add(createLabel(\"\\\"min:pref\\\"\"));\n" + "\t\tpanel.add(createTextField(\"8\", 8), \"width min:pref\");\n" + "\t\tpanel.add(createLabel(\"\\\"min:100:150\\\"\"));\n" + "\t\tpanel.add(createTextField(\"8\", 8), \"width min:100:150\");\n" + "\t\tpanel.add(createLabel(\"\\\"min:100:150, growx\\\"\"));\n" + "\t\tpanel.add(createTextField(\"8\", 8), \"width min:100:150, growx\");\n" + "\t\tpanel.add(createLabel(\"\\\"min:100, growx\\\"\"));\n" + "\t\tpanel.add(createTextField(\"8\", 8), \"width min:100, growx\");\n" + "\t\tpanel.add(createLabel(\"\\\"40!\\\"\"));\n" + "\t\tpanel.add(createTextField(\"8\", 8), \"width 40!\");\n" + "\t\tpanel.add(createLabel(\"\\\"40:40:40\\\"\"));\n" + "\t\tpanel.add(createTextField(\"8\", 8), \"width 40:40:40\");\n" + "\n" + "\t\ttabbedPane.addTab(\"Component Sizes\", splitPane);"); return tabbedPane; } public JComponent createCell_Alignments() { JTabbedPane tabbedPane = new JTabbedPane(); // Horizontal MigLayout hLM = new MigLayout("wrap", "[grow,left][grow,center][grow,right][grow,fill,center]", "[]unrel[][]"); JPanel hPanel = createTabPanel(hLM); String[] sizes = new String[] {"", "growx", "growx 0", "left", "center", "right", "leading", "trailing"}; hPanel.add(createLabel("[left]"), "c"); hPanel.add(createLabel("[center]"), "c"); hPanel.add(createLabel("[right]"), "c"); hPanel.add(createLabel("[fill,center]"), "c, growx 0"); for (int r = 0; r < sizes.length; r++) { for (int c = 0; c < 4; c++) { String text = sizes[r].length() > 0 ? sizes[r] : "default"; hPanel.add(createButton(text), sizes[r]); } } // Vertical MigLayout vLM = new MigLayout("wrap,flowy", "[right][]", "[grow,top][grow,center][grow,bottom][grow,fill,bottom][grow,fill,baseline]"); JPanel vPanel = createTabPanel(vLM); String[] vSizes = new String[] {"", "growy", "growy 0", "top", "aligny center", "bottom"}; vPanel.add(createLabel("[top]"), "aligny center"); vPanel.add(createLabel("[center]"), "aligny center"); vPanel.add(createLabel("[bottom]"), "aligny center"); vPanel.add(createLabel("[fill, bottom]"), "aligny center, growy 0"); vPanel.add(createLabel("[fill, baseline]"), "aligny center"); for (int c = 0; c < vSizes.length; c++) { for (int r = 0; r < 5; r++) { String text = vSizes[c].length() > 0 ? vSizes[c] : "default"; JButton b = createButton(text); if (r == 4 && c <= 1) b.setFont(new Font("sansserif", Font.PLAIN, 16 + c * 5)); vPanel.add(b, vSizes[c]); } } tabbedPane.addTab("Horizontal", hPanel); tabbedPane.addTab("Vertical", vPanel); // Disregard. Just forgetting the source code text close to the source code. setSource("JTabbedPane tabbedPane = new JTabbedPane();\n" + "\n" + "// Horizontal\n" + "MigLayout hLM = new MigLayout(\"wrap\",\n" + " \"[grow,left][grow,center][grow,right][grow,fill,center]\",\n" + " \"[]unrel[][]\");\n" + "JPanel hPanel = createTabPanel(hLM);\n" + "String[] sizes = new String[] {\"\", \"growx\", \"growx 0\", \"left\", \"center\", \"right\", \"leading\", \"trailing\"};\n" + "hPanel.add(createLabel(\"[left]\"), \"c\");\n" + "hPanel.add(createLabel(\"[center]\"), \"c\");\n" + "hPanel.add(createLabel(\"[right]\"), \"c\");\n" + "hPanel.add(createLabel(\"[fill,center]\"), \"c, growx 0\");\n" + "\n" + "for (int r = 0; r < sizes.length; r++) {\n" + "\tfor (int c = 0; c < 4; c++) {\n" + "\t\tString text = sizes[r].length() > 0 ? sizes[r] : \"default\";\n" + "\t\thPanel.add(createButton(text), sizes[r]);\n" + "\t}\n" + "}\n" + "\n" + "// Vertical\n" + "MigLayout vLM = new MigLayout(\"wrap,flowy\",\n" + " \"[right][]\",\n" + " \"[grow,top][grow,center][grow,bottom][grow,fill,bottom][grow,fill,baseline]\");\n" + "JPanel vPanel = createTabPanel(vLM);\n" + "String[] vSizes = new String[] {\"\", \"growy\", \"growy 0\", \"top\", \"center\", \"bottom\"};\n" + "vPanel.add(createLabel(\"[top]\"), \"center\");\n" + "vPanel.add(createLabel(\"[center]\"), \"center\");\n" + "vPanel.add(createLabel(\"[bottom]\"), \"center\");\n" + "vPanel.add(createLabel(\"[fill, bottom]\"), \"center, growy 0\");\n" + "vPanel.add(createLabel(\"[fill, baseline]\"), \"center\");\n" + "\n" + "for (int c = 0; c < vSizes.length; c++) {\n" + "\tfor (int r = 0; r < 5; r++) {\n" + "\t\tString text = vSizes[c].length() > 0 ? vSizes[c] : \"default\";\n" + "\t\tJButton b = createButton(text);\n" + "\t\tif (r == 4 && c <= 1)\n" + "\t\t\tb.setFont(new Font(\"sansserif\", Font.PLAIN, 16 + c * 5));\n" + "\t\tvPanel.add(b, vSizes[c]);\n" + "\t}\n" + "}\n" + "\n" + "tabbedPane.addTab(\"Horizontal\", hPanel);\n" + "tabbedPane.addTab(\"Vertical\", vPanel);"); return tabbedPane; } public JComponent createUnits() { JTabbedPane tabbedPane = new JTabbedPane(); // Horizontal MigLayout hLM = new MigLayout("wrap,nocache", "[right][]", ""); JPanel hPanel = createTabPanel(hLM); String[] sizes = new String[] {"72pt", "25.4mm", "2.54cm", "1in", "72px", "96px", "120px", "25%", "20sp"}; for (int i = 0; i < sizes.length; i++) { hPanel.add(createLabel(sizes[i])); hPanel.add(createTextField(""), "width " + sizes[i] + "!"); } // Horizontal lp MigLayout hlpLM = new MigLayout("nocache", "[right][][]", ""); JPanel hlpPanel = createTabPanel(hlpLM); hlpPanel.add(createLabel("9 cols")); hlpPanel.add(createTextField(9)); String[] lpSizes = new String[] {"75lp", "75px", "88px", "100px"}; hlpPanel.add(createLabel("Width of createTextField(9)"), "wrap"); for (int i = 0; i < lpSizes.length; i++) { hlpPanel.add(createLabel(lpSizes[i])); hlpPanel.add(createTextField(""), "width " + lpSizes[i] + "!, wrap"); } // Vertical MigLayout vLM = new MigLayout("wrap,flowy,nocache", "[c]", "[top][top]"); JPanel vPanel = createTabPanel(vLM); String[] vSizes = new String[] {"72pt", "25.4mm", "2.54cm", "1in", "72px", "96px", "120px", "25%", "20sp"}; for (int i = 0; i < sizes.length; i++) { vPanel.add(createLabel(vSizes[i])); vPanel.add(createTextArea("", 0, 5), "width 50!, height " + vSizes[i] + "!"); } // Vertical lp MigLayout vlpLM = new MigLayout("wrap,flowy,nocache", "[c]", "[top][top]40px[top][top]"); JPanel vlpPanel = createTabPanel(vlpLM); vlpPanel.add(createLabel("4 rows")); vlpPanel.add(createTextArea("", 4, 5), "width 50!"); vlpPanel.add(createLabel("field")); vlpPanel.add(createTextField(5)); String[] vlpSizes1 = new String[] {"63lp", "57px", "63px", "68px", "25%"}; String[] vlpSizes2 = new String[] {"21lp", "21px", "23px", "24px", "10%"}; for (int i = 0; i < vlpSizes1.length; i++) { vlpPanel.add(createLabel(vlpSizes1[i])); vlpPanel.add(createTextArea("", 1, 5), "width 50!, height " + vlpSizes1[i] + "!"); vlpPanel.add(createLabel(vlpSizes2[i])); vlpPanel.add(createTextField(5), "height " + vlpSizes2[i] + "!"); } vlpPanel.add(createLabel("button"), "skip 2"); vlpPanel.add(createButton("...")); tabbedPane.addTab("Horizontal", hPanel); tabbedPane.addTab("Horizontal LP", hlpPanel); tabbedPane.addTab("Vertical", vPanel); tabbedPane.addTab("Vertical LP", vlpPanel); // Disregard. Just forgetting the source code text close to the source code. setSource("JTabbedPane tabbedPane = new JTabbedPane();\n" + "\n" + "// Horizontal\n" + "MigLayout hLM = new MigLayout(\"wrap,nocache\",\n" + "\t\t\t\t\t\t\t \"[right][]\",\n" + "\t\t\t\t\t\t\t \"\");\n" + "JPanel hPanel = createTabPanel(hLM);\n" + "String[] sizes = new String[] {\"72pt\", \"25.4mm\", \"2.54cm\", \"1in\", \"72px\", \"96px\", \"120px\", \"25%\", \"20sp\"};\n" + "for (int i = 0; i < sizes.length; i++) {\n" + "\thPanel.add(createLabel(sizes[i]));\n" + "\thPanel.add(createTextField(\"\"), \"width \" + sizes[i] + \"!\");\n" + "}\n" + "\n" + "// Horizontal lp\n" + "MigLayout hlpLM = new MigLayout(\"nocache\", \"[right][][]\", \"\");\n" + "JPanel hlpPanel = createTabPanel(hlpLM);\n" + "hlpPanel.add(createLabel(\"9 cols\"));\n" + "hlpPanel.add(createTextField(9));\n" + "String[] lpSizes = new String[] {\"75lp\", \"75px\", \"88px\", \"100px\"};\n" + "hlpPanel.add(createLabel(\"Width of createTextField(9)\"), \"wrap\");\n" + "for (int i = 0; i < lpSizes.length; i++) {\n" + "\thlpPanel.add(createLabel(lpSizes[i]));\n" + "\thlpPanel.add(createTextField(\"\"), \"width \" + lpSizes[i] + \"!, wrap\");\n" + "}\n" + "\n" + "// Vertical\n" + "MigLayout vLM = new MigLayout(\"wrap,flowy,nocache\",\n" + "\t\t\t\t\t\t\t \"[c]\",\n" + "\t\t\t\t\t\t\t \"[top][top]\");\n" + "JPanel vPanel = createTabPanel(vLM);\n" + "String[] vSizes = new String[] {\"72pt\", \"25.4mm\", \"2.54cm\", \"1in\", \"72px\", \"96px\", \"120px\", \"25%\", \"20sp\"};\n" + "for (int i = 0; i < sizes.length; i++) {\n" + "\tvPanel.add(createLabel(vSizes[i]));\n" + "\tvPanel.add(createTextArea(\"\", 0, 5), \"width 50!, height \" + vSizes[i] + \"!\");\n" + "}\n" + "\n" + "// Vertical lp\n" + "MigLayout vlpLM = new MigLayout(\"wrap,flowy,nocache\",\n" + "\t\t\t\t\t\t\t\t\"[c]\",\n" + "\t\t\t\t\t\t\t\t\"[top][top]40px[top][top]\");\n" + "JPanel vlpPanel = createTabPanel(vlpLM);\n" + "vlpPanel.add(createLabel(\"4 rows\"));\n" + "vlpPanel.add(createTextArea(\"\", 4, 5), \"width 50!\");\n" + "vlpPanel.add(createLabel(\"field\"));\n" + "vlpPanel.add(createTextField(5));\n" + "\n" + "String[] vlpSizes1 = new String[] {\"63lp\", \"57px\", \"63px\", \"68px\", \"25%\"};\n" + "String[] vlpSizes2 = new String[] {\"21lp\", \"21px\", \"23px\", \"24px\", \"10%\"};\n" + "for (int i = 0; i < vlpSizes1.length; i++) {\n" + "\tvlpPanel.add(createLabel(vlpSizes1[i]));\n" + "\tvlpPanel.add(createTextArea(\"\", 1, 5), \"width 50!, height \" + vlpSizes1[i] + \"!\");\n" + "\tvlpPanel.add(createLabel(vlpSizes2[i]));\n" + "\tvlpPanel.add(createTextField(5), \"height \" + vlpSizes2[i] + \"!\");\n" + "}\n" + "\n" + "vlpPanel.add(createLabel(\"button\"), \"skip 2\");\n" + "vlpPanel.add(createButton(\"...\"));\n" + "\n" + "tabbedPane.addTab(\"Horizontal\", hPanel);\n" + "tabbedPane.addTab(\"Horizontal LP\", hlpPanel);\n" + "tabbedPane.addTab(\"Vertical\", vPanel);\n" + "tabbedPane.addTab(\"Vertical LP\", vlpPanel);"); return tabbedPane; } public JComponent createGrouping() { JTabbedPane tabbedPane = new JTabbedPane(); // Ungrouped MigLayout ugM = new MigLayout("", "[]push[][][]", ""); JPanel ugPanel = createTabPanel(ugM); ugPanel.add(createButton("Help")); ugPanel.add(createButton("< Back"), ""); ugPanel.add(createButton("Forward >"), "gap push"); ugPanel.add(createButton("Apply"), "gap unrel"); ugPanel.add(createButton("Cancel"), "gap unrel"); // Grouped Components MigLayout gM = new MigLayout("nogrid, fillx"); JPanel gPanel = createTabPanel(gM); gPanel.add(createButton("Help"), "sg"); gPanel.add(createButton("< Back"), "sg,gap push"); gPanel.add(createButton("Forward >"), "sg"); gPanel.add(createButton("Apply"), "sg,gap unrel"); gPanel.add(createButton("Cancel"), "sg,gap unrel"); // Grouped Columns MigLayout gcM = new MigLayout("", "[sg,fill]push[sg,fill][sg,fill]unrel[sg,fill]unrel[sg,fill]", ""); JPanel gcPanel = createTabPanel(gcM); gcPanel.add(createButton("Help")); gcPanel.add(createButton("< Back")); gcPanel.add(createButton("Forward >")); gcPanel.add(createButton("Apply")); gcPanel.add(createButton("Cancel")); // Ungrouped Rows MigLayout ugrM = new MigLayout(); // no "sg" is the only difference to next panel JPanel ugrPanel = createTabPanel(ugrM); ugrPanel.add(createLabel("File Number:")); ugrPanel.add(createTextField(30), "wrap"); ugrPanel.add(createLabel("BL/MBL number:")); ugrPanel.add(createTextField(7), "split 2"); ugrPanel.add(createTextField(7), "wrap"); ugrPanel.add(createLabel("Entry Date:")); ugrPanel.add(createTextField(7), "wrap"); ugrPanel.add(createLabel("RFQ Number:")); ugrPanel.add(createTextField(30), "wrap"); ugrPanel.add(createLabel("Goods:")); ugrPanel.add(createCheck("Dangerous"), "wrap"); ugrPanel.add(createLabel("Shipper:")); ugrPanel.add(createTextField(30), "wrap"); ugrPanel.add(createLabel("Customer:")); ugrPanel.add(createTextField(""), "split 2,growx"); ugrPanel.add(createButton("..."), "width 60px:pref,wrap"); ugrPanel.add(createLabel("Port of Loading:")); ugrPanel.add(createTextField(30), "wrap"); ugrPanel.add(createLabel("Destination:")); ugrPanel.add(createTextField(30), "wrap"); // Grouped Rows MigLayout grM = new MigLayout("", "[]", "[sg]"); // "sg" is the only difference to previous panel JPanel grPanel = createTabPanel(grM); grPanel.add(createLabel("File Number:")); grPanel.add(createTextField(30),"wrap"); grPanel.add(createLabel("BL/MBL number:")); grPanel.add(createTextField(7),"split 2"); grPanel.add(createTextField(7), "wrap"); grPanel.add(createLabel("Entry Date:")); grPanel.add(createTextField(7), "wrap"); grPanel.add(createLabel("RFQ Number:")); grPanel.add(createTextField(30), "wrap"); grPanel.add(createLabel("Goods:")); grPanel.add(createCheck("Dangerous"), "wrap"); grPanel.add(createLabel("Shipper:")); grPanel.add(createTextField(30), "wrap"); grPanel.add(createLabel("Customer:")); grPanel.add(createTextField(""), "split 2,growx"); grPanel.add(createButton("..."), "width 50px:pref,wrap"); grPanel.add(createLabel("Port of Loading:")); grPanel.add(createTextField(30), "wrap"); grPanel.add(createLabel("Destination:")); grPanel.add(createTextField(30), "wrap"); tabbedPane.addTab("Ungrouped", ugPanel); tabbedPane.addTab("Grouped (Components)", gPanel); tabbedPane.addTab("Grouped (Columns)", gcPanel); tabbedPane.addTab("Ungrouped Rows", ugrPanel); tabbedPane.addTab("Grouped Rows", grPanel); // Disregard. Just forgetting the source code text close to the source code. setSource("JTabbedPane tabbedPane = new JTabbedPane();\n" + "\n" + "// Ungrouped\n" + "MigLayout ugM = new MigLayout(\"\", \"[]push[][][]\", \"\");\n" + "JPanel ugPanel = createTabPanel(ugM);\n" + "ugPanel.add(createButton(\"Help\"));\n" + "ugPanel.add(createButton(\"< Back\"), \"\");\n" + "ugPanel.add(createButton(\"Forward >\"), \"gap push\");\n" + "ugPanel.add(createButton(\"Apply\"), \"gap unrel\");\n" + "ugPanel.add(createButton(\"Cancel\"), \"gap unrel\");\n" + "\n" + "// Grouped Components\n" + "MigLayout gM = new MigLayout(\"nogrid, fillx\");\n" + "JPanel gPanel = createTabPanel(gM);\n" + "gPanel.add(createButton(\"Help\"), \"sg\");\n" + "gPanel.add(createButton(\"< Back\"), \"sg,gap push\");\n" + "gPanel.add(createButton(\"Forward >\"), \"sg\");\n" + "gPanel.add(createButton(\"Apply\"), \"sg,gap unrel\");\n" + "gPanel.add(createButton(\"Cancel\"), \"sg,gap unrel\");\n" + "\n" + "// Grouped Columns\n" + "MigLayout gcM = new MigLayout(\"\", \"[sg,fill]push[sg,fill][sg,fill]unrel[sg,fill]unrel[sg,fill]\", \"\");\n" + "JPanel gcPanel = createTabPanel(gcM);\n" + "gcPanel.add(createButton(\"Help\"));\n" + "gcPanel.add(createButton(\"< Back\"));\n" + "gcPanel.add(createButton(\"Forward >\"));\n" + "gcPanel.add(createButton(\"Apply\"));\n" + "gcPanel.add(createButton(\"Cancel\"));\n" + "\n" + "// Ungrouped Rows\n" + "MigLayout ugrM = new MigLayout(); // no \"sg\" is the only difference to next panel\n" + "JPanel ugrPanel = createTabPanel(ugrM);\n" + "ugrPanel.add(createLabel(\"File Number:\"));\n" + "ugrPanel.add(createTextField(30), \"wrap\");\n" + "ugrPanel.add(createLabel(\"BL/MBL number:\"));\n" + "ugrPanel.add(createTextField(7), \"split 2\");\n" + "ugrPanel.add(createTextField(7), \"wrap\");\n" + "ugrPanel.add(createLabel(\"Entry Date:\"));\n" + "ugrPanel.add(createTextField(7), \"wrap\");\n" + "ugrPanel.add(createLabel(\"RFQ Number:\"));\n" + "ugrPanel.add(createTextField(30), \"wrap\");\n" + "ugrPanel.add(createLabel(\"Goods:\"));\n" + "ugrPanel.add(createCheck(\"Dangerous\"), \"wrap\");\n" + "ugrPanel.add(createLabel(\"Shipper:\"));\n" + "ugrPanel.add(createTextField(30), \"wrap\");\n" + "ugrPanel.add(createLabel(\"Customer:\"));\n" + "ugrPanel.add(createTextField(\"\"), \"split 2,growx\");\n" + "ugrPanel.add(createButton(\"...\"), \"width 60px:pref,wrap\");\n" + "ugrPanel.add(createLabel(\"Port of Loading:\"));\n" + "ugrPanel.add(createTextField(30), \"wrap\");\n" + "ugrPanel.add(createLabel(\"Destination:\"));\n" + "ugrPanel.add(createTextField(30), \"wrap\");\n" + "\n" + "// Grouped Rows\n" + "MigLayout grM = new MigLayout(\"\", \"[]\", \"[sg]\"); // \"sg\" is the only difference to previous panel\n" + "JPanel grPanel = createTabPanel(grM);\n" + "grPanel.add(createLabel(\"File Number:\"));\n" + "grPanel.add(createTextField(30),\"wrap\");\n" + "grPanel.add(createLabel(\"BL/MBL number:\"));\n" + "grPanel.add(createTextField(7),\"split 2\");\n" + "grPanel.add(createTextField(7), \"wrap\");\n" + "grPanel.add(createLabel(\"Entry Date:\"));\n" + "grPanel.add(createTextField(7), \"wrap\");\n" + "grPanel.add(createLabel(\"RFQ Number:\"));\n" + "grPanel.add(createTextField(30), \"wrap\");\n" + "grPanel.add(createLabel(\"Goods:\"));\n" + "grPanel.add(createCheck(\"Dangerous\"), \"wrap\");\n" + "grPanel.add(createLabel(\"Shipper:\"));\n" + "grPanel.add(createTextField(30), \"wrap\");\n" + "grPanel.add(createLabel(\"Customer:\"));\n" + "grPanel.add(createTextField(\"\"), \"split 2,growx\");\n" + "grPanel.add(createButton(\"...\"), \"width 50px:pref,wrap\");\n" + "grPanel.add(createLabel(\"Port of Loading:\"));\n" + "grPanel.add(createTextField(30), \"wrap\");\n" + "grPanel.add(createLabel(\"Destination:\"));\n" + "grPanel.add(createTextField(30), \"wrap\");\n" + "\n" + "tabbedPane.addTab(\"Ungrouped\", ugPanel);\n" + "tabbedPane.addTab(\"Grouped (Components)\", gPanel);\n" + "tabbedPane.addTab(\"Grouped (Columns)\", gcPanel);\n" + "tabbedPane.addTab(\"Ungrouped Rows\", ugrPanel);\n" + "tabbedPane.addTab(\"Grouped Rows\", grPanel);"); return tabbedPane; } public JComponent createSpan() { JTabbedPane tabbedPane = new JTabbedPane(); // Horizontal span MigLayout colLM = new MigLayout("nocache", "[fill][25%!,fill][105lp!,fill][100px!,fill]", "[]15[][]"); JPanel colPanel = createTabPanel(colLM); colPanel.add(createTextField("Col1 [ ]")); colPanel.add(createTextField("Col2 [25%!]")); colPanel.add(createTextField("Col3 [105lp!]")); colPanel.add(createTextField("Col4 [100px!]"), "wrap"); colPanel.add(createLabel("Full Name:")); colPanel.add(createTextField("span, growx", 40), "span,growx"); colPanel.add(createLabel("Phone:")); colPanel.add(createTextField(5), "span 3, split 5"); colPanel.add(createTextField(7)); colPanel.add(createTextField(7)); colPanel.add(createTextField(9)); colPanel.add(createLabel("(span 3, split 4)"), "wrap"); colPanel.add(createLabel("Zip/City:")); colPanel.add(createTextField(5)); colPanel.add(createTextField("span 2, growx", 5), "span 2,growx"); // Vertical span MigLayout rowLM = new MigLayout("wrap", "[225lp]para[225lp]", "[]3[]unrel[]3[]unrel[]3[]"); JPanel rowPanel = createTabPanel(rowLM); rowPanel.add(createLabel("Name")); rowPanel.add(createLabel("Notes")); rowPanel.add(createTextField("growx"), "growx"); rowPanel.add(createTextArea("spany,grow", 5, 20), "spany,grow"); rowPanel.add(createLabel("Phone")); rowPanel.add(createTextField("growx"), "growx"); rowPanel.add(createLabel("Fax")); rowPanel.add(createTextField("growx"), "growx"); tabbedPane.addTab("Column Span/Split", colPanel); tabbedPane.addTab("Row Span", rowPanel); // Disregard. Just forgetting the source code text close to the source code. setSource("\t\tJTabbedPane tabbedPane = new JTabbedPane();\n" + "\n" + "\t\t// Horizontal span\n" + "\t\tMigLayout colLM = new MigLayout(\"\",\n" + "\t\t \"[fill][25%!,fill][105lp!,fill][100px!,fill]\",\n" + "\t\t \"[]15[][]\");\n" + "\t\tJPanel colPanel = createTabPanel(colLM);\n" + "\t\tcolPanel.add(createTextField(\"Col1 [ ]\"));\n" + "\t\tcolPanel.add(createTextField(\"Col2 [25%!]\"));\n" + "\t\tcolPanel.add(createTextField(\"Col3 [105lp!]\"));\n" + "\t\tcolPanel.add(createTextField(\"Col4 [100px!]\"), \"wrap\");\n" + "\n" + "\t\tcolPanel.add(createLabel(\"Full Name:\"));\n" + "\t\tcolPanel.add(createTextField(\"span, growx\", 40), \"span,growx\");\n" + "\n" + "\t\tcolPanel.add(createLabel(\"Phone:\"));\n" + "\t\tcolPanel.add(createTextField(5), \"span 3, split 5\");\n" + "\t\tcolPanel.add(createTextField(7));\n" + "\t\tcolPanel.add(createTextField(7));\n" + "\t\tcolPanel.add(createTextField(9));\n" + "\t\tcolPanel.add(createLabel(\"(span 3, split 4)\"), \"wrap\");\n" + "\n" + "\t\tcolPanel.add(createLabel(\"Zip/City:\"));\n" + "\t\tcolPanel.add(createTextField(5));\n" + "\t\tcolPanel.add(createTextField(\"span 2, growx\", 5), \"span 2,growx\");\n" + "\n" + "\t\t// Vertical span\n" + "\t\tMigLayout rowLM = new MigLayout(\"wrap\",\n" + "\t\t \"[225lp]para[225lp]\",\n" + "\t\t \"[]3[]unrel[]3[]unrel[]3[]\");\n" + "\t\tJPanel rowPanel = createTabPanel(rowLM);\n" + "\t\trowPanel.add(createLabel(\"Name\"));\n" + "\t\trowPanel.add(createLabel(\"Notes\"));\n" + "\t\trowPanel.add(createTextField(\"growx\"), \"growx\");\n" + "\t\trowPanel.add(createTextArea(\"spany,grow\", 5, 20), \"spany,grow\");\n" + "\t\trowPanel.add(createLabel(\"Phone\"));\n" + "\t\trowPanel.add(createTextField(\"growx\"), \"growx\");\n" + "\t\trowPanel.add(createLabel(\"Fax\"));\n" + "\t\trowPanel.add(createTextField(\"growx\"), \"growx\");\n" + "\n" + "\t\ttabbedPane.addTab(\"Column Span/Split\", colPanel);\n" + "\t\ttabbedPane.addTab(\"Row Span\", rowPanel);"); return tabbedPane; } public JComponent createGrowing() { JTabbedPane tabbedPane = new JTabbedPane(); // All tab MigLayout allLM = new MigLayout("", "[pref!][grow,fill]", "[]15[]"); JPanel allTab = createTabPanel(allLM); allTab.add(createLabel("Fixed")); allTab.add(createLabel("Gets all extra space"), "wrap"); allTab.add(createTextField(5)); allTab.add(createTextField(5)); // Half tab MigLayout halfLM = new MigLayout("", "[pref!][grow,fill]", "[]15[]"); JPanel halfTab = createTabPanel(halfLM); halfTab.add(createLabel("Fixed")); halfTab.add(createLabel("Gets half of extra space")); halfTab.add(createLabel("Gets half of extra space"), "wrap"); halfTab.add(createTextField(5)); halfTab.add(createTextField(5)); halfTab.add(createTextField(5)); // Percent 1 tab MigLayout p1LM = new MigLayout("", "[pref!][0:0,grow 25,fill][0:0,grow 75,fill]", "[]15[]"); JPanel p1Tab = createTabPanel(p1LM); p1Tab.add(createLabel("Fixed")); p1Tab.add(createLabel("Gets 25% of extra space"), ""); p1Tab.add(createLabel("Gets 75% of extra space"), "wrap"); p1Tab.add(createTextField(5)); p1Tab.add(createTextField(5)); p1Tab.add(createTextField(5)); // Percent 2 tab MigLayout p2LM = new MigLayout("", "[0:0,grow 33,fill][0:0,grow 67,fill]", "[]15[]"); JPanel p2Tab = createTabPanel(p2LM); p2Tab.add(createLabel("Gets 33% of extra space"), ""); p2Tab.add(createLabel("Gets 67% of extra space"), "wrap"); p2Tab.add(createTextField(5)); p2Tab.add(createTextField(5)); // Vertical 1 tab MigLayout v1LM = new MigLayout("flowy", "[]15[]", "[][c,pref!][c,grow 25,fill][c,grow 75,fill]"); JPanel v1Tab = createTabPanel(v1LM); v1Tab.add(createLabel("Fixed"), "skip"); v1Tab.add(createLabel("Gets 25% of extra space")); v1Tab.add(createLabel("Gets 75% of extra space"), "wrap"); v1Tab.add(createLabel("new JTextArea(4, 30)")); v1Tab.add(createTextAreaScroll("", 4, 30, false)); v1Tab.add(createTextAreaScroll("", 4, 30, false)); v1Tab.add(createTextAreaScroll("", 4, 30, false)); // Vertical 2 tab MigLayout v2LM = new MigLayout("flowy", "[]15[]", "[][c,grow 33,fill][c,grow 67,fill]"); JPanel v2Tab = createTabPanel(v2LM); v2Tab.add(createLabel("Gets 33% of extra space"), "skip"); v2Tab.add(createLabel("Gets 67% of extra space"), "wrap"); v2Tab.add(createLabel("new JTextArea(4, 30)")); v2Tab.add(createTextAreaScroll("", 4, 30, false)); v2Tab.add(createTextAreaScroll("", 4, 30, false)); tabbedPane.addTab("All", allTab); tabbedPane.addTab("Half", halfTab); tabbedPane.addTab("Percent 1", p1Tab); tabbedPane.addTab("Percent 2", p2Tab); tabbedPane.addTab("Vertical 1", v1Tab); tabbedPane.addTab("Vertical 2", v2Tab); // Disregard. Just forgetting the source code text close to the source code. setSource("JTabbedPane tabbedPane = new JTabbedPane();\n" + "\n" + "// All tab\n" + "MigLayout allLM = new MigLayout(\"\",\n" + " \"[pref!][grow,fill]\",\n" + " \"[]15[]\");\n" + "JPanel allTab = createTabPanel(allLM);\n" + "allTab.add(createLabel(\"Fixed\"));\n" + "allTab.add(createLabel(\"Gets all extra space\"), \"wrap\");\n" + "allTab.add(createTextField(5));\n" + "allTab.add(createTextField(5));\n" + "\n" + "// Half tab\n" + "MigLayout halfLM = new MigLayout(\"\",\n" + " \"[pref!][grow,fill]\",\n" + " \"[]15[]\");\n" + "JPanel halfTab = createTabPanel(halfLM);\n" + "halfTab.add(createLabel(\"Fixed\"));\n" + "halfTab.add(createLabel(\"Gets half of extra space\"));\n" + "halfTab.add(createLabel(\"Gets half of extra space\"), \"wrap\");\n" + "halfTab.add(createTextField(5));\n" + "halfTab.add(createTextField(5));\n" + "halfTab.add(createTextField(5));\n" + "\n" + "// Percent 1 tab\n" + "MigLayout p1LM = new MigLayout(\"\",\n" + " \"[pref!][0:0,grow 25,fill][0:0,grow 75,fill]\",\n" + " \"[]15[]\");\n" + "JPanel p1Tab = createTabPanel(p1LM);\n" + "p1Tab.add(createLabel(\"Fixed\"));\n" + "p1Tab.add(createLabel(\"Gets 25% of extra space\"), \"\");\n" + "p1Tab.add(createLabel(\"Gets 75% of extra space\"), \"wrap\");\n" + "p1Tab.add(createTextField(5));\n" + "p1Tab.add(createTextField(5));\n" + "p1Tab.add(createTextField(5));\n" + "\n" + "// Percent 2 tab\n" + "MigLayout p2LM = new MigLayout(\"\",\n" + " \"[0:0,grow 33,fill][0:0,grow 67,fill]\",\n" + " \"[]15[]\");\n" + "JPanel p2Tab = createTabPanel(p2LM);\n" + "p2Tab.add(createLabel(\"Gets 33% of extra space\"), \"\");\n" + "p2Tab.add(createLabel(\"Gets 67% of extra space\"), \"wrap\");\n" + "p2Tab.add(createTextField(5));\n" + "p2Tab.add(createTextField(5));\n" + "\n" + "// Vertical 1 tab\n" + "MigLayout v1LM = new MigLayout(\"flowy\",\n" + " \"[]15[]\",\n" + " \"[][c,pref!][c,grow 25,fill][c,grow 75,fill]\");\n" + "JPanel v1Tab = createTabPanel(v1LM);\n" + "v1Tab.add(createLabel(\"Fixed\"), \"skip\");\n" + "v1Tab.add(createLabel(\"Gets 25% of extra space\"));\n" + "v1Tab.add(createLabel(\"Gets 75% of extra space\"), \"wrap\");\n" + "v1Tab.add(createLabel(\"new JTextArea(4, 30)\"));\n" + "v1Tab.add(createTextAreaScroll(\"\", 4, 30, false));\n" + "v1Tab.add(createTextAreaScroll(\"\", 4, 30, false));\n" + "v1Tab.add(createTextAreaScroll(\"\", 4, 30, false));\n" + "\n" + "// Vertical 2 tab\n" + "MigLayout v2LM = new MigLayout(\"flowy\",\n" + " \"[]15[]\",\n" + " \"[][c,grow 33,fill][c,grow 67,fill]\");\n" + "JPanel v2Tab = createTabPanel(v2LM);\n" + "v2Tab.add(createLabel(\"Gets 33% of extra space\"), \"skip\");\n" + "v2Tab.add(createLabel(\"Gets 67% of extra space\"), \"wrap\");\n" + "v2Tab.add(createLabel(\"new JTextArea(4, 30)\"));\n" + "v2Tab.add(createTextAreaScroll(\"\", 4, 30, false));\n" + "v2Tab.add(createTextAreaScroll(\"\", 4, 30, false));\n" + "\n" + "tabbedPane.addTab(\"All\", allTab);\n" + "tabbedPane.addTab(\"Half\", halfTab);\n" + "tabbedPane.addTab(\"Percent 1\", p1Tab);\n" + "tabbedPane.addTab(\"Percent 2\", p2Tab);\n" + "tabbedPane.addTab(\"Vertical 1\", v1Tab);\n" + "tabbedPane.addTab(\"Vertical 2\", v2Tab);"); return tabbedPane; } public JComponent createBasic_Sizes() { JTabbedPane tabbedPane = new JTabbedPane(); // Horizontal tab MigLayout horLM = new MigLayout("", "[]15[75px]25[min]25[]", "[]15"); JPanel horTab = createTabPanel(horLM); horTab.add(createLabel("75px"), "skip"); horTab.add(createLabel("Min")); horTab.add(createLabel("Pref"), "wrap"); horTab.add(createLabel("new TextField(15)")); horTab.add(createTextField(15)); horTab.add(createTextField(15)); horTab.add(createTextField(15)); // Vertical tab 1 MigLayout verLM = new MigLayout("flowy,wrap", "[]15[]", "[]15[c,45px]15[c,min]15[c,pref]"); JPanel verTab = createTabPanel(verLM); verTab.add(createLabel("45px"), "skip"); verTab.add(createLabel("Min")); verTab.add(createLabel("Pref")); verTab.add(createLabel("new JTextArea(10, 40)")); verTab.add(createTextArea("", 10, 40)); verTab.add(createTextArea("", 10, 40)); verTab.add(createTextArea("", 10, 40)); // Componentsized/Baseline 2 MigLayout verLM2 = new MigLayout("flowy,wrap", "[]15[]", "[]15[baseline]15[baseline]15[baseline]"); JPanel verTab2 = createTabPanel(verLM2); verTab2.add(createLabel("45px"), "skip"); verTab2.add(createLabel("Min")); verTab2.add(createLabel("Pref")); verTab2.add(createLabel("new JTextArea(10, 40)")); verTab2.add(createTextArea("", 10, 40), "height 45"); verTab2.add(createTextArea("", 10, 40), "height min"); verTab2.add(createTextArea("", 10, 40), "height pref"); tabbedPane.addTab("Horizontal - Column size set", horTab); tabbedPane.addTab("Vertical - Row sized", verTab); tabbedPane.addTab("Vertical - Component sized + Baseline", verTab2); // Disregard. Just forgetting the source code text close to the source code. setSource("JTabbedPane tabbedPane = new JTabbedPane();\n" + "\n" + "// Horizontal tab\n" + "MigLayout horLM = new MigLayout(\"\",\n" + " \"[]15[75px]25[min]25[]\",\n" + " \"[]15\");\n" + "JPanel horTab = createTabPanel(horLM);\n" + "horTab.add(createLabel(\"75px\"), \"skip\");\n" + "horTab.add(createLabel(\"Min\"));\n" + "horTab.add(createLabel(\"Pref\"), \"wrap\");\n" + "\n" + "horTab.add(createLabel(\"new TextField(15)\"));\n" + "horTab.add(createTextField(15));\n" + "horTab.add(createTextField(15));\n" + "horTab.add(createTextField(15));\n" + "\n" + "// Vertical tab 1\n" + "MigLayout verLM = new MigLayout(\"flowy,wrap\",\n" + " \"[]15[]\",\n" + " \"[]15[c,45px]15[c,min]15[c,pref]\");\n" + "JPanel verTab = createTabPanel(verLM);\n" + "verTab.add(createLabel(\"45px\"), \"skip\");\n" + "verTab.add(createLabel(\"Min\"));\n" + "verTab.add(createLabel(\"Pref\"));\n" + "\n" + "verTab.add(createLabel(\"new JTextArea(10, 40)\"));\n" + "verTab.add(createTextArea(\"\", 10, 40));\n" + "verTab.add(createTextArea(\"\", 10, 40));\n" + "verTab.add(createTextArea(\"\", 10, 40));\n" + "\n" + "// Componentsized/Baseline 2\n" + "MigLayout verLM2 = new MigLayout(\"flowy,wrap\",\n" + " \"[]15[]\",\n" + " \"[]15[baseline]15[baseline]15[baseline]\");\n" + "JPanel verTab2 = createTabPanel(verLM2);\n" + "verTab2.add(createLabel(\"45px\"), \"skip\");\n" + "verTab2.add(createLabel(\"Min\"));\n" + "verTab2.add(createLabel(\"Pref\"));\n" + "\n" + "verTab2.add(createLabel(\"new JTextArea(10, 40)\"));\n" + "verTab2.add(createTextArea(\"\", 10, 40), \"height 45\");\n" + "verTab2.add(createTextArea(\"\", 10, 40), \"height min\");\n" + "verTab2.add(createTextArea(\"\", 10, 40), \"height pref\");\n" + "\n" + "tabbedPane.addTab(\"Horizontal - Column size set\", horTab);\n" + "tabbedPane.addTab(\"Vertical - Row sized\", verTab);\n" + "tabbedPane.addTab(\"Vertical - Component sized + Baseline\", verTab2);"); return tabbedPane; } public JComponent createAlignments() { JTabbedPane tabbedPane = new JTabbedPane(); // Horizontal tab MigLayout horLM = new MigLayout("wrap", "[label]15[left]15[center]15[right]15[fill]15[]", "[]15[]"); String[] horLabels = new String[] {"[label]", "[left]", "[center]", "[right]", "[fill]", "[] (Default)"}; JPanel horTab = createTabPanel(horLM); String[] horNames = new String[] {"First Name", "Phone Number", "Facsmile", "Email", "Address", "Other"}; for (int c = 0; c < horLabels.length; c++) horTab.add(createLabel(horLabels[c])); for (int r = 0; r < horLabels.length; r++) { for (int c = 0; c < horNames.length; c++) horTab.add(c == 0 ? createLabel(horNames[r] + ":") : createButton(horNames[r])); } // Vertical tab MigLayout verLM = new MigLayout("wrap,flowy", "[]unrel[]rel[]", "[top]15[center]15[bottom]15[fill]15[fill,baseline]15[baseline]15[]"); String[] verLabels = new String[] {"[top]", "[center]", "[bottom]", "[fill]", "[fill,baseline]", "[baseline]", "[] (Default)"}; JPanel verTab = createTabPanel(verLM); String[] verNames = benchRuns == 0 ? new String[] {"One", "One
Two"} : new String[] {"One", "One/Two"}; for (int c = 0; c < verLabels.length; c++) verTab.add(createLabel(verLabels[c])); for (int r = 0; r < verNames.length; r++) { for (int c = 0; c < verLabels.length; c++) verTab.add(createButton(verNames[r])); } for (int c = 0; c < verLabels.length; c++) verTab.add(createTextField("JTextFied")); for (int c = 0; c < verLabels.length; c++) verTab.add(createTextArea("JTextArea", 1, 8)); for (int c = 0; c < verLabels.length; c++) verTab.add(createTextArea("JTextArea\nwith two lines", 1, 10)); for (int c = 0; c < verLabels.length; c++) verTab.add(createTextAreaScroll("Scrolling JTextArea\nwith two lines", 1, 15, true)); tabbedPane.addTab("Horizontal", horTab); tabbedPane.addTab("Vertical", verTab); // Disregard. Just forgetting the source code text close to the source code. setSource("JTabbedPane tabbedPane = new JTabbedPane();\n" + "\n" + "// Horizontal tab\n" + "MigLayout horLM = new MigLayout(\"wrap\",\n" + " \"[left]15[center]15[right]15[fill]15[]\",\n" + " \"rel[]rel\");\n" + "\n" + "String[] horLabels = new String[] {\"[left]\", \"[center]\", \"[right]\", \"[fill]\", \"[] (Default)\"};\n" + "JPanel horTab = createTabPanel(horLM);\n" + "String[] horNames = new String[] {\"First Name\", \"Phone Number\", \"Facsmile\", \"Email\", \"Address\"};\n" + "for (int c = 0; c < horLabels.length; c++)\n" + "\thorTab.add(createLabel(horLabels[c]));\n" + "\n" + "for (int r = 0; r < horLabels.length; r++) {\n" + "\tfor (int c = 0; c < horNames.length; c++)\n" + "\t\thorTab.add(createButton(horNames[r]));\n" + "}\n" + "\n" + "// Vertical tab\n" + "MigLayout verLM = new MigLayout(\"wrap,flowy\",\n" + " \"[]unrel[]rel[]\",\n" + " \"[top]15[center]15[bottom]15[fill]15[fill,baseline]15[baseline]15[]\");\n" + "\n" + "String[] verLabels = new String[] {\"[top]\", \"[center]\", \"[bottom]\", \"[fill]\", \"[fill,baseline]\", \"[baseline]\", \"[] (Default)\"};\n" + "JPanel verTab = createTabPanel(verLM);\n" + "\n" + "String[] verNames = new String[] {\"One\", \"One
Two\"};\n" + "for (int c = 0; c < verLabels.length; c++)\n" + "\tverTab.add(createLabel(verLabels[c]));\n" + "\n" + "for (int r = 0; r < verNames.length; r++) {\n" + "\tfor (int c = 0; c < verLabels.length; c++)\n" + "\t\tverTab.add(createButton(verNames[r]));\n" + "}\n" + "\n" + "for (int c = 0; c < verLabels.length; c++)\n" + "\tverTab.add(createTextField(\"JTextFied\"));\n" + "\n" + "for (int c = 0; c < verLabels.length; c++)\n" + "\tverTab.add(createTextArea(\"JTextArea\", 1, 8));\n" + "\n" + "for (int c = 0; c < verLabels.length; c++)\n" + "\tverTab.add(createTextArea(\"JTextArea\\nwith two lines\", 1, 10));\n" + "\n" + "for (int c = 0; c < verLabels.length; c++)\n" + "\tverTab.add(createTextAreaScroll(\"Scrolling JTextArea\\nwith two lines\", 1, 15, true));\n" + "\n" + "tabbedPane.addTab(\"Horizontal\", horTab);\n" + "tabbedPane.addTab(\"Vertical\", verTab);"); return tabbedPane; } public JComponent createQuick_Start() { JTabbedPane tabbedPane = new JTabbedPane(); JPanel p = createTabPanel(new MigLayout("inset 20")); addSeparator(p, "General"); p.add(createLabel("Company"), "gap para"); p.add(createTextField(""), "span, growx"); p.add(createLabel("Contact"), "gap para"); p.add(createTextField(""), "span, growx, wrap para"); addSeparator(p, "Propeller"); p.add(createLabel("PTI/kW"), "gap para"); p.add(createTextField(10)); p.add(createLabel("Power/kW"),"gap para"); p.add(createTextField(10), "wrap"); p.add(createLabel("R/mm"), "gap para"); p.add(createTextField(10)); p.add(createLabel("D/mm"), "gap para"); p.add(createTextField(10)); tabbedPane.addTab("Quick Start", p); // Disregard. Just forgetting the source code text close to the source code. setSource("JTabbedPane tabbedPane = new JTabbedPane();\n" + "\n" + "JPanel p = createTabPanel(new MigLayout());\n" + "\n" + "addSeparator(p, \"General\");\n" + "\n" + "p.add(createLabel(\"Company\"), \"gap para\");\n" + "p.add(createTextField(\"\"), \"span, growx, wrap\");\n" + "p.add(createLabel(\"Contact\"), \"gap para\");\n" + "p.add(createTextField(\"\"), \"span, growx, wrap para\");\n" + "\n" + "addSeparator(p, \"Propeller\");\n" + "\n" + "p.add(createLabel(\"PTI/kW\"), \"gap para\");\n" + "p.add(createTextField(10));\n" + "p.add(createLabel(\"Power/kW\"),\"gap para\");\n" + "p.add(createTextField(10), \"wrap\");\n" + "p.add(createLabel(\"R/mm\"), \"gap para\");\n" + "p.add(createTextField(10));\n" + "p.add(createLabel(\"D/mm\"), \"gap para\");\n" + "p.add(createTextField(10));\n" + "\n" + "tabbedPane.addTab(\"Quick Start\", p);"); return tabbedPane; } public JComponent createGrow_Shrink() { JTabbedPane tabbedPane = new JTabbedPane(); // shrink tab MigLayout slm = new MigLayout("nogrid"); JPanel sPanel = createTabPanel(slm); JScrollPane sDescrText = createTextAreaScroll("Use the slider to see how the components shrink depending on the constraints set on them.\n\n'shp' means Shrink Priority. " + "Lower values will be shrunk before higer ones and the default value is 100.\n\n'shrink' means Shrink Weight. " + "Lower values relative to other's means they will shrink less when space is scarse. " + "Shrink Weight is only relative to components with the same Shrink Priority. Default Shrink Weight is 100.\n\n" + "The component's minimum size will always be honored.", 0, 0, true); sDescrText.setOpaque(OPAQUE); sDescrText.setBorder(new EmptyBorder(10, 10, 10, 10)); ((JTextArea) sDescrText.getViewport().getView()).setOpaque(OPAQUE); sDescrText.getViewport().setOpaque(OPAQUE); JSplitPane sSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, sPanel, sDescrText); sSplitPane.setOpaque(OPAQUE); sSplitPane.setBorder(null); sPanel.add(createTextField("shp 110", 12), "shp 110"); sPanel.add(createTextField("Default (100)", 12), ""); sPanel.add(createTextField("shp 90", 12), "shp 90"); sPanel.add(createTextField("shrink 25", 20), "newline,shrink 25"); sPanel.add(createTextField("shrink 75", 20), "shrink 75"); sPanel.add(createTextField("Default", 20), "newline"); sPanel.add(createTextField("Default", 20), ""); sPanel.add(createTextField("shrink 0", 40), "newline,shrink 0"); sPanel.add(createTextField("shp 110", 12), "newline,shp 110"); sPanel.add(createTextField("shp 100,shrink 25", 12), "shp 100,shrink 25"); sPanel.add(createTextField("shp 100,shrink 75", 12), "shp 100,shrink 75"); tabbedPane.addTab("Shrink", sSplitPane); // Grow tab MigLayout glm = new MigLayout("nogrid", "[grow]", ""); JPanel gPanel = createTabPanel(glm); JScrollPane gDescrText = createTextAreaScroll("'gp' means Grow Priority. " + "Higher values will be grown before lower ones and the default value is 100.\n\n'grow' means Grow Weight. " + "Higher values relative to other's means they will grow more when space is up for takes. " + "Grow Weight is only relative to components with the same Grow Priority. Default Grow Weight is 0 which means " + "components will normally not grow. \n\nNote that the buttons in the first and last row have max width set to 170 to " + "emphasize Grow Priority.\n\nThe component's maximum size will always be honored.", 0, 0, true); gDescrText.setOpaque(OPAQUE); gDescrText.setBorder(new EmptyBorder(10, 10, 10, 10)); ((JTextArea) gDescrText.getViewport().getView()).setOpaque(OPAQUE); gDescrText.getViewport().setOpaque(OPAQUE); JSplitPane gSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, gPanel, gDescrText); gSplitPane.setOpaque(OPAQUE); gSplitPane.setBorder(null); gPanel.add(createButton("gp 110,grow"), "gp 110,grow,wmax 170"); gPanel.add(createButton("Default (100),grow"), "grow,wmax 170"); gPanel.add(createButton("gp 90,grow"), "gp 90,grow,wmax 170"); gPanel.add(createButton("Default Button"), "newline"); gPanel.add(createButton("growx"), "newline,growx,wrap"); gPanel.add(createButton("gp 110,grow"), "gp 110,grow,wmax 170"); gPanel.add(createButton("gp 100,grow 25"), "gp 100,grow 25,wmax 170"); gPanel.add(createButton("gp 100,grow 75"), "gp 100,grow 75,wmax 170"); tabbedPane.addTab("Grow", gSplitPane); // Disregard. Just forgetting the source code text close to the source code. setSource("JTabbedPane tabbedPane = new JTabbedPane();\n" + "\n" + "// shrink tab\n" + "MigLayout slm = new MigLayout(\"nogrid\");\n" + "JPanel sPanel = createTabPanel(slm);\n" + "\n" + "JScrollPane sDescrText = createTextAreaScroll(\"Use the slider to see how the components shrink depending on the constraints set on them.\\n\\n'shp' means Shrink Priority. \" +\n" + " \"Lower values will be shrunk before higer ones and the default value is 100.\\n\\n'shrink' means Shrink Weight. \" +\n" + " \"Lower values relative to other's means they will shrink less when space is scarse. \" +\n" + " \"Shrink Weight is only relative to components with the same Shrink Priority. Default Shrink Weight is 100.\\n\\n\" +\n" + " \"The component's minimum size will always be honored.\", 0, 0, true);\n" + "\n" + "sDescrText.setOpaque(OPAQUE);\n" + "sDescrText.setBorder(new EmptyBorder(10, 10, 10, 10));\n" + "((JTextArea) sDescrText.getViewport().getView()).setOpaque(OPAQUE);\n" + "sDescrText.getViewport().setOpaque(OPAQUE);\n" + "\n" + "JSplitPane sSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, sPanel, sDescrText);\n" + "sSplitPane.setOpaque(OPAQUE);\n" + "sSplitPane.setBorder(null);\n" + "\n" + "sPanel.add(createTextField(\"shp 110\", 12), \"shp 110\");\n" + "sPanel.add(createTextField(\"Default (100)\", 12), \"\");\n" + "sPanel.add(createTextField(\"shp 90\", 12), \"shp 90\");\n" + "\n" + "sPanel.add(createTextField(\"shrink 25\", 20), \"newline,shrink 25\");\n" + "sPanel.add(createTextField(\"shrink 75\", 20), \"shrink 75\");\n" + "\n" + "sPanel.add(createTextField(\"Default\", 20), \"newline\");\n" + "sPanel.add(createTextField(\"Default\", 20), \"\");\n" + "\n" + "sPanel.add(createTextField(\"shrink 0\", 40), \"newline,shrink 0\");\n" + "\n" + "sPanel.add(createTextField(\"shp 110\", 12), \"newline,shp 110\");\n" + "sPanel.add(createTextField(\"shp 100,shrink 25\", 12), \"shp 100,shrink 25\");\n" + "sPanel.add(createTextField(\"shp 100,shrink 75\", 12), \"shp 100,shrink 75\");\n" + "tabbedPane.addTab(\"Shrink\", sSplitPane);\n" + "\n" + "// Grow tab\n" + "MigLayout glm = new MigLayout(\"nogrid\", \"[grow]\", \"\");\n" + "JPanel gPanel = createTabPanel(glm);\n" + "\n" + "JScrollPane gDescrText = createTextAreaScroll(\"'gp' means Grow Priority. \" +\n" + " \"Higher values will be grown before lower ones and the default value is 100.\\n\\n'grow' means Grow Weight. \" +\n" + " \"Higher values relative to other's means they will grow more when space is up for takes. \" +\n" + " \"Grow Weight is only relative to components with the same Grow Priority. Default Grow Weight is 0 which means \" +\n" + " \"components will normally not grow. \\n\\nNote that the buttons in the first and last row have max width set to 170 to \" +\n" + " \"emphasize Grow Priority.\\n\\nThe component's maximum size will always be honored.\", 0, 0, true);\n" + "\n" + "gDescrText.setOpaque(OPAQUE);\n" + "gDescrText.setBorder(new EmptyBorder(10, 10, 10, 10));\n" + "((JTextArea) gDescrText.getViewport().getView()).setOpaque(OPAQUE);\n" + "gDescrText.getViewport().setOpaque(OPAQUE);\n" + "\n" + "JSplitPane gSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, gPanel, gDescrText);\n" + "gSplitPane.setOpaque(OPAQUE);\n" + "gSplitPane.setBorder(null);\n" + "\n" + "gPanel.add(createButton(\"gp 110,grow\"), \"gp 110,grow,wmax 170\");\n" + "gPanel.add(createButton(\"Default (100),grow\"), \"grow,wmax 170\");\n" + "gPanel.add(createButton(\"gp 90,grow\"), \"gp 90,grow,wmax 170\");\n" + "\n" + "gPanel.add(createButton(\"Default Button\"), \"newline\");\n" + "\n" + "gPanel.add(createButton(\"growx\"), \"newline,growx,wrap\");\n" + "\n" + "gPanel.add(createButton(\"gp 110,grow\"), \"gp 110,grow,wmax 170\");\n" + "gPanel.add(createButton(\"gp 100,grow 25\"), \"gp 100,grow 25,wmax 170\");\n" + "gPanel.add(createButton(\"gp 100,grow 75\"), \"gp 100,grow 75,wmax 170\");\n" + "tabbedPane.addTab(\"Grow\", gSplitPane);"); return tabbedPane; } public JComponent createPlainApi() { JTabbedPane tabbedPane = new JTabbedPane(); MigLayout lm = new MigLayout(new LC(), null, null); JPanel panel = createTabPanel(lm); addSeparator(panel, "Manufacturer"); panel.add(createLabel("Company")); panel.add(createTextField(""), "span,growx"); panel.add(createLabel("Contact")); panel.add(createTextField(""), "span,growx"); panel.add(createLabel("Order No")); panel.add(createTextField(15), "wrap"); addSeparator(panel, "Inspector"); panel.add(createLabel("Name")); panel.add(createTextField(""), "span,growx"); panel.add(createLabel("Reference No")); panel.add(createTextField(""), "wrap"); panel.add(createLabel("Status")); panel.add(createCombo(new String[] {"In Progress", "Finnished", "Released"}), "wrap"); addSeparator(panel, "Ship"); panel.add(createLabel("Shipyard")); panel.add(createTextField(""), "span,growx"); panel.add(createLabel("Register No")); panel.add(createTextField("")); panel.add(createLabel("Hull No"), "right"); panel.add(createTextField(15), "wrap"); panel.add(createLabel("Project StructureType")); panel.add(createCombo(new String[] {"New Building", "Convention", "Repair"})); tabbedPane.addTab("Plain", panel); return tabbedPane; } // ********************************************************** // * Helper Methods // ********************************************************** private final ToolTipListener toolTipListener = new ToolTipListener(); private final ConstraintListener constraintListener = new ConstraintListener(); private JLabel createLabel(String text) { return createLabel(text, SwingConstants.LEADING); } private JLabel createLabel(String text, int align) { final JLabel b = new JLabel(text, align); configureActiveComponet(b); return b; } public JComboBox createCombo(String[] items) { JComboBox combo = new JComboBox(items); if (PlatformDefaults.getCurrentPlatform() == PlatformDefaults.MAC_OSX) combo.setOpaque(false); return combo; } private JTextField createTextField(int cols) { return createTextField("", cols); } private JTextField createTextField(String text) { return createTextField(text, 0); } private JTextField createTextField(String text, int cols) { final JTextField b = new JTextField(text, cols); configureActiveComponet(b); return b; } private static final Font BUTT_FONT = new Font("monospaced", Font.PLAIN, 12); private JButton createButton() { return createButton(""); } private JButton createButton(String text) { return createButton(text, false); } private JButton createButton(String text, boolean bold) { JButton b = new JButton(text) { public void addNotify() { super.addNotify(); if (benchRuns == 0) { // Since this does not exist in the SWT version if (getText().length() == 0) { String lText = (String) ((MigLayout) getParent().getLayout()).getComponentConstraints(this); setText(lText != null && lText.length() > 0 ? lText : ""); } } else { setText("Benchmark Version"); } } }; if (bold) b.setFont(b.getFont().deriveFont(Font.BOLD)); configureActiveComponet(b); b.setOpaque(buttonOpaque); // Or window's buttons will have strange border b.setContentAreaFilled(contentAreaFilled); return b; } private JToggleButton createToggleButton(String text) { JToggleButton b = new JToggleButton(text); // configureActiveComponet(b); b.setOpaque(buttonOpaque); // Or window's buttons will have strange border return b; } private JCheckBox createCheck(String text) { JCheckBox b = new JCheckBox(text); configureActiveComponet(b); b.setOpaque(OPAQUE); // Or window's checkboxes will have strange border return b; } private JPanel createTabPanel(LayoutManager lm) { JPanel panel = new JPanel(lm); configureActiveComponet(panel); panel.setOpaque(OPAQUE); return panel; } private JComponent createPanel() { return createPanel(""); } private JComponent createPanel(String s) { JLabel panel = new JLabel(s, SwingConstants.CENTER) { public void addNotify() { super.addNotify(); if (benchRuns == 0) { // Since this does not exist in the SWT version if (getText().length() == 0) { String lText = (String) ((MigLayout) getParent().getLayout()).getComponentConstraints(this); setText(lText != null && lText.length() > 0 ? lText : ""); } } } }; panel.setBorder(new EtchedBorder()); panel.setOpaque(true); configureActiveComponet(panel); return panel; } private JTextArea createTextArea(String text, int rows, int cols) { JTextArea ta = new JTextArea(text, rows, cols); ta.setBorder(UIManager.getBorder("TextField.border")); ta.setFont(UIManager.getFont("TextField.font")); ta.setWrapStyleWord(true); ta.setLineWrap(true); configureActiveComponet(ta); return ta; } private JScrollPane createTextAreaScroll(String text, int rows, int cols, boolean hasVerScroll) { JTextArea ta = new JTextArea(text, rows, cols); ta.setFont(UIManager.getFont("TextField.font")); ta.setWrapStyleWord(true); ta.setLineWrap(true); JScrollPane scroll = new JScrollPane( ta, hasVerScroll ? ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED : ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); return scroll; } private JComponent configureActiveComponet(JComponent c) { if (benchRuns == 0) { c.addMouseMotionListener(toolTipListener); c.addMouseListener(constraintListener); } return c; } static final Color LABEL_COLOR = new Color(0, 70, 213); private void addSeparator(JPanel panel, String text) { JLabel l = createLabel(text); l.setForeground(LABEL_COLOR); panel.add(l, "gapbottom 1, span, split 2, aligny center"); panel.add(configureActiveComponet(new JSeparator()), "gapleft rel, growx"); } private class ConstraintListener extends MouseAdapter { public void mousePressed(MouseEvent e) { if (e.isPopupTrigger()) react(e); } public void mouseReleased(MouseEvent e) { if (e.isPopupTrigger()) react(e); } public void react(MouseEvent e) { JComponent c = (JComponent) e.getSource(); LayoutManager lm = c.getParent().getLayout(); if (lm instanceof MigLayout == false) lm = c.getLayout(); if (lm instanceof MigLayout) { MigLayout layout = (MigLayout) lm; boolean isComp = layout.isManagingComponent(c); Object compConstr = isComp ? layout.getComponentConstraints(c) : null; if (isComp && compConstr == null) compConstr = ""; Object rowsConstr = isComp ? null : layout.getRowConstraints(); Object colsConstr = isComp ? null : layout.getColumnConstraints(); Object layoutConstr = isComp ? null : layout.getLayoutConstraints(); ConstraintsDialog cDlg = new ConstraintsDialog(SwingDemo.this, layoutConstr instanceof LC ? IDEUtil.getConstraintString((LC) layoutConstr, false) : (String) layoutConstr, rowsConstr instanceof AC ? IDEUtil.getConstraintString((AC) rowsConstr, false, false) : (String) rowsConstr, colsConstr instanceof AC ? IDEUtil.getConstraintString((AC) colsConstr, false, false) : (String) colsConstr, compConstr instanceof CC ? IDEUtil.getConstraintString((CC) compConstr, false) : (String) compConstr); cDlg.pack(); cDlg.setLocationRelativeTo(c); if (cDlg.showDialog()) { try { if (isComp) { String constrStr = cDlg.componentConstrTF.getText().trim(); layout.setComponentConstraints(c, constrStr); if (c instanceof JButton) { c.setFont(BUTT_FONT); ((JButton) c).setText(constrStr.length() == 0 ? "" : constrStr); } } else { layout.setLayoutConstraints(cDlg.layoutConstrTF.getText()); layout.setRowConstraints(cDlg.rowsConstrTF.getText()); layout.setColumnConstraints(cDlg.colsConstrTF.getText()); } } catch(Exception ex) { StringWriter sw = new StringWriter(); ex.printStackTrace(new PrintWriter(sw)); JOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(c), sw.toString(), "Error parsing Constraint!", JOptionPane.ERROR_MESSAGE); return; } c.invalidate(); c.getParent().validate(); } } } } private static class ToolTipListener extends MouseMotionAdapter { public void mouseMoved(MouseEvent e) { JComponent c = (JComponent) e.getSource(); LayoutManager lm = c.getParent().getLayout(); if (lm instanceof MigLayout) { Object constr = ((MigLayout) lm).getComponentConstraints(c); if (constr instanceof String) c.setToolTipText((constr != null ? ("\"" + constr + "\"") : "null")); } } } private static class ConstraintsDialog extends JDialog implements ActionListener, KeyEventDispatcher { private static final Color ERROR_COLOR = new Color(255, 180, 180); private final JPanel mainPanel = new JPanel(new MigLayout("fillx,flowy,ins dialog", "[fill]", "2[]2")); final JTextField layoutConstrTF; final JTextField rowsConstrTF; final JTextField colsConstrTF; final JTextField componentConstrTF; private final JButton okButt = new JButton("OK"); private final JButton cancelButt = new JButton("Cancel"); private boolean okPressed = false; public ConstraintsDialog(Frame owner, String layoutConstr, String rowsConstr, String colsConstr, String compConstr) { super(owner, (compConstr != null ? "Edit Component Constraints" : "Edit Container Constraints"), true); layoutConstrTF = createConstraintField(layoutConstr); rowsConstrTF = createConstraintField(rowsConstr); colsConstrTF = createConstraintField(colsConstr); componentConstrTF = createConstraintField(compConstr); if (componentConstrTF != null) { mainPanel.add(new JLabel("Component Constraints")); mainPanel.add(componentConstrTF); } if (layoutConstrTF != null) { mainPanel.add(new JLabel("Layout Constraints")); mainPanel.add(layoutConstrTF); } if (colsConstrTF != null) { mainPanel.add(new JLabel("Column Constraints"), "gaptop unrel"); mainPanel.add(colsConstrTF); } if (rowsConstrTF != null) { mainPanel.add(new JLabel("Row Constraints"), "gaptop unrel"); mainPanel.add(rowsConstrTF); } mainPanel.add(okButt, "tag ok,split,flowx,gaptop 15"); mainPanel.add(cancelButt, "tag cancel,gaptop 15"); setContentPane(mainPanel); okButt.addActionListener(this); cancelButt.addActionListener(this); } public void addNotify() { super.addNotify(); KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(this); } public void removeNotify() { KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(this); super.removeNotify(); } public boolean dispatchKeyEvent(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ESCAPE) dispose(); return false; } public void actionPerformed(ActionEvent e) { if (e.getSource() == okButt) okPressed = true; dispose(); } private JTextField createConstraintField(String text) { if (text == null) return null; final JTextField tf = new JTextField(text, 50); tf.setFont(new Font("monospaced", Font.PLAIN, 12)); tf.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ENTER) { okButt.doClick(); return; } javax.swing.Timer timer = new Timer(50, new ActionListener() { public void actionPerformed(ActionEvent e) { String constr = tf.getText(); try { if (tf == layoutConstrTF) { ConstraintParser.parseLayoutConstraint(constr); } else if (tf == rowsConstrTF) { ConstraintParser.parseRowConstraints(constr); } else if (tf == colsConstrTF) { ConstraintParser.parseColumnConstraints(constr); } else if (tf == componentConstrTF) { ConstraintParser.parseComponentConstraint(constr); } tf.setBackground(Color.WHITE); okButt.setEnabled(true); } catch(Exception ex) { tf.setBackground(ERROR_COLOR); okButt.setEnabled(false); } } }); timer.setRepeats(false); timer.start(); } }); return tf; } private boolean showDialog() { setVisible(true); return okPressed; } } }miglayout-5.1/demo/src/main/java/net/miginfocom/demo/SwtDemo.java000077500000000000000000002510771324101563200250530ustar00rootroot00000000000000package net.miginfocom.demo; import net.miginfocom.layout.*; import net.miginfocom.swt.MigLayout; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.events.ControlAdapter; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.*; import java.io.FileWriter; import java.io.IOException; import java.util.Random; /* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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 */ public class SwtDemo { public static final int SELECTED_INDEX = 0; private static final String[][] panels = new String[][] { // {"BugTestApp", "BugTestApp, Disregard"}, {"Welcome", "\n\n \"MigLayout makes complex layouts easy and normal layouts one-liners.\""}, {"Quick Start", "This is an example of how to build a common dialog type. Note that there are no special components, nested panels or absolute references to cell positions. If you look at the source code you will see that the layout code is very simple to understand."}, {"Plain", "A simple example on how simple it is to create normal forms. No builders needed since the whole layout manager works like a builder."}, {"Alignments", "Shows how the alignment of components are specified. At the top/left is the alignment for the column/row. The components have no alignments specified.\n\nNote that baseline alignment will be interpreted as 'center' before JDK 6."}, {"Cell Alignments", "Shows how components are aligned when both column/row alignments and component constraints are specified. At the top/left are the alignment for the column/row and the text on the buttons is the component constraint that will override the column/row alignment if it is an alignment.\n\nNote that baseline alignment will be interpreted as 'center' before JDK 6."}, {"Basic Sizes", "A simple example that shows how to use the column or row min/preferred/max size to set the sizes of the contained components and also an example that shows how to do this directly in the component constraints."}, {"Growing", "A simple example that shows how to use the growx and growy constraint to set the sizes and how they should grow to fit the available size. Both the column/row and the component grow/shrink constraints can be set, but the components will always be confined to the space given by its column/row."}, {"Grow Shrink", "Demonstrates the very flexible grow and shrink constraints that can be set on a component.\nComponents can be divided into grow/shrink groups and also have grow/shrink weight within each of those groups.\n\nBy default " + "components shrink to their inherent (or specified) minimum size, but they don't grow."}, {"Span", "This example shows the powerful spanning and splitting that can be specified in the component constraints. With spanning any number of cells can be merged with the additional option to split that space for more than one component. This makes layouts very flexible and reduces the number of times you will need nested panels to very few."}, {"Flow Direction", "Shows the different flow directions. Flow direction for the layout specifies if the next cell will be in the x or y dimension. Note that it can be a different flow direction in the slit cell (the middle cell is slit in two). Wrap is set to 3 for all panels."}, {"Grouping", "Sizes for both components and columns/rows can be grouped so they get the same size. For instance buttons in a button bar can be given a size-group so that they will all get " + "the same minimum and preferred size (the largest within the group). Size-groups can be set for the width, height or both."}, {"Units", "Demonstrates the basic units that are understood by MigLayout. These units can be extended by the user by adding one or more UnitConverter(s)."}, {"Component Sizes", "Minimum, preferred and maximum component sizes can be overridden in the component constraints using any unit type. The format to do this is short and simple to understand. You simply specify the " + "min, preferred and max sizes with a colon between.\n\nAbove are some examples of this. An exclamation mark means that the value will be used for all sizes."}, {"Bound Sizes", "Shows how to create columns that are stable between tabs using minimum sizes."}, {"Cell Position", "Even though MigLayout has automatic grid flow you can still specify the cell position explicitly. You can even combine absolute (x, y) and flow (skip, wrap and newline) constraints to build your layout."}, {"Orientation", "MigLayout supports not only right-to-left orientation, but also bottom-to-top. You can even set the flow direction so that the flow is vertical instead of horizontal. It will automatically " + "pick up if right-to-left is to be used depending on the ComponentWrapper, but it can also be manually set for every layout."}, {"Absolute Position", "Demonstrates the option to place any number of components using absolute coordinates. This can be just the position (if min/preferred size) using \"x y p p\" format or" + "the bounds using the \"x1 y1 x2 y2\" format. Any unit can be used and percent is relative to the parent.\nAbsolute components will not disturb the flow or occupy cells in the grid. " + "Absolute positioned components will be taken into account when calculating the container's preferred size."}, {"Component Links", "Components can be linked to any side of any other component. It can be a forward, backward or cyclic link references, as long as it is stable and won't continue to change value over many iterations." + "Links are referencing the ID of another component. The ID can be overridden by the component's constrains or is provided by the ComponentWrapper. For instance it will use the component's 'name' on Swing.\n" + "Since the links can be combined with any expression (such as 'butt1.x+10' or 'max(button.x, 200)' the links are very customizable."}, {"Docking", "Docking components can be added around the grid. The docked component will get the whole width/height on the docked side by default, however this can be overridden. When all docked components are laid out, whatever space " + "is left will be available for the normal grid laid out components. Docked components does not in any way affect the flow in the grid.\n\nSince the docking runs in the same code path " + "as the normal layout code the same properties can be specified for the docking components. You can for instance set the sizes and alignment or link other components to their docked component's bounds."}, {"Button Bars", "Button order is very customizable and are by default different on the supported platforms. E.g. Gaps, button order and minimum button size are properties that are 'per platform'. MigLayout picks up the current platform automatically and adjusts the button order and minimum button size accordingly, all without using a button builder or any other special code construct."}, {"Debug", "Demonstrates the non-intrusive way to get visual debugging aid. There is no need to use a special DebugPanel or anything that will need code changes. The user can simply turn on debug on the layout manager by using the �debug� constraint and it will " + "continuously repaint the panel with debug information on top. This means you don't have to change your code to debug!"}, {"Layout Showdown", "This is an implementation of the Layout Showdown posted on java.net by John O'Conner. The first tab is a pure implemenetation of the showdown that follows all the rules. The second tab is a slightly fixed version that follows some improved layout guidelines." + "The source code is for bothe the first and for the fixed version. Note the simplification of the code for the fixed version. Writing better layouts with MiG Layout is reasier that writing bad.\n\nReference: http://weblogs.java.net/blog/joconner/archive/2006/10/more_informatio.html"}, {"API Constraints1", "This dialog shows the constraint API added to v2.0. It works the same way as the string constraints but with chained method calls. See the source code for details."}, {"API Constraints2", "This dialog shows the constraint API added to v2.0. It works the same way as the string constraints but with chained method calls. See the source code for details."}, }; private static int DOUBLE_BUFFER = 0;//SWT.DOUBLE_BUFFERED; private static int benchRuns = 0; private static long startupMillis = 0; private static long timeToShowMillis = 0; private static long benchRunTime = 0; private static String benchOutFileName = null; private static boolean append = false; private static long lastRunTimeStart = 0; private static StringBuffer runTimeSB = null; private static Display display = null; public static void main(String[] args) { startupMillis = System.currentTimeMillis(); if (args.length > 0) { for (int i = 0; i < args.length; i++) { String arg = args[i].trim(); if (arg.startsWith("-bench")) { benchRuns = 10; try { if (arg.length() > 6) benchRuns = Integer.parseInt(arg.substring(6)); } catch (Exception ex) {} } else if (arg.startsWith("-bout")) { benchOutFileName = arg.substring(5); } else if (arg.startsWith("-append")) { append = true; } else if (arg.startsWith("-verbose")) { runTimeSB = new StringBuffer(256); } else { System.out.println("Usage: [-bench[#_of_runs]] [-bout[benchmark_results_filename]] [-append]\n" + " -bench Run demo as benchmark. Run count can be appended. 10 is default.\n" + " -bout Benchmark results output filename.\n" + " -append Appends the result to the \"-bout\" file.\n" + " -verbose Print the times of every run.\n" + "\nExamples:\n" + " java -jar swtdemoapp.jar -bench -boutC:/bench.txt -append\n" + " java -jar swtdemoapp.jar -bench20\n" + "NOTE! swt-win32-3232.dll must be in the current directory!"); System.exit(0); } } } if (benchRuns == 0) LayoutUtil.setDesignTime(null, true); new SwtDemo(); } final List pickerList; final Composite layoutDisplayPanel; final StyledText descrTextArea; public SwtDemo() { display = new Display(); final Shell shell = new Shell(); shell.setLayout(new MigLayout("wrap", "[]u[grow,fill]", "[grow,fill][pref!]")); shell.setText("MigLayout SWT Demo v2.5 - MigLayout v" + LayoutUtil.getVersion()); TabFolder layoutPickerTabPane = new TabFolder(shell, DOUBLE_BUFFER); layoutPickerTabPane.setLayoutData("spany,grow"); pickerList = new List(layoutPickerTabPane, SWT.SINGLE | DOUBLE_BUFFER); pickerList.setBackground(layoutPickerTabPane.getBackground()); deriveFont(pickerList, SWT.BOLD, -1); TabItem tab = new TabItem(layoutPickerTabPane, DOUBLE_BUFFER); tab.setControl(pickerList); tab.setText("Example Browser"); for (int i = 0; i < panels.length; i++) pickerList.add(panels[i][0]); layoutDisplayPanel = new Composite(shell, DOUBLE_BUFFER); layoutDisplayPanel.setLayout(new MigLayout("fill, insets 0")); TabFolder descriptionTabPane = new TabFolder(shell, DOUBLE_BUFFER); descriptionTabPane.setLayoutData("growx,hmin 120,w 500:500"); descrTextArea = createTextArea(descriptionTabPane, "", "", SWT.MULTI | SWT.WRAP); descrTextArea.setBackground(descriptionTabPane.getBackground()); tab = new TabItem(descriptionTabPane, DOUBLE_BUFFER); tab.setControl(descrTextArea); tab.setText("Description"); pickerList.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { dispatchSelection(); } }); shell.setSize(900, 650); shell.open(); shell.layout(); if (benchRuns > 0) { doBenchmark(); } else { pickerList.select(SELECTED_INDEX); dispatchSelection(); display.addFilter(SWT.KeyDown, new Listener() { public void handleEvent(Event e) { if (e.character == 'b') { startupMillis = System.currentTimeMillis(); timeToShowMillis = System.currentTimeMillis() - startupMillis; benchRuns = 1; doBenchmark(); } } }); } System.out.println(Display.getCurrent().getDPI()); while(!shell.isDisposed()){ if(!display.readAndDispatch()) display.sleep(); } display.dispose(); } private static Control[] comps = null; // thread hack... private static Control[] tabs = null; // thread hack... private void doBenchmark() { final int pCnt = pickerList.getItemCount(); Thread benchThread = new Thread() { public void run() { for (int j = 0; j < benchRuns; j++) { lastRunTimeStart = System.currentTimeMillis(); final int jj = j; for (int i = 0; i < pCnt; i++) { final int ii = i; try { display.syncExec(new Runnable() { public void run () { pickerList.setSelection(ii); dispatchSelection(); } }); } catch (Exception e) { e.printStackTrace(); } display.syncExec(new Runnable() { public void run() { comps = layoutDisplayPanel.getChildren(); } }); for (int cIx = 0; cIx < comps.length; cIx++) { if (comps[cIx] instanceof TabFolder) { final TabFolder tp = (TabFolder) comps[cIx]; display.syncExec(new Runnable() { public void run() { tabs = tp.getTabList(); } }); for (int k = 0; k < tabs.length; k++) { final int kk = k; try { display.syncExec(new Runnable() { public void run() { tp.setSelection(kk); if (timeToShowMillis == 0) timeToShowMillis = System.currentTimeMillis() - startupMillis; } }); } catch (Exception e) { e.printStackTrace(); }; } } } } if (runTimeSB != null) { runTimeSB.append("Run ").append(jj).append(": "); runTimeSB.append(System.currentTimeMillis() - lastRunTimeStart).append(" millis.\n"); } } benchRunTime = System.currentTimeMillis() - startupMillis - timeToShowMillis; final String message = "Java Version: " + System.getProperty("java.version") + "\n" + "Time to Show: " + timeToShowMillis + " millis.\n" + (runTimeSB != null ? runTimeSB.toString() : "") + "Benchmark Run Time: " + benchRunTime + " millis.\n" + "Average Run Time: " + (benchRunTime / benchRuns) + " millis (" + benchRuns + " runs).\n\n"; display.syncExec(new Runnable() { public void run() { if (benchOutFileName == null) { MessageBox messageBox = new MessageBox(display.getActiveShell(), SWT.OK | SWT.ICON_INFORMATION); messageBox.setText("Results"); messageBox.setMessage(message); messageBox.open(); } else { FileWriter fw = null; try { fw = new FileWriter(benchOutFileName, append); fw.write(message); } catch(IOException ex) { ex.printStackTrace(); } finally { if (fw != null) try {fw.close();} catch(IOException ex) {} } } } }); System.out.println(message); if (benchOutFileName != null) System.exit(0); } }; benchThread.start(); } private void dispatchSelection() { int ix = pickerList.getSelectionIndex(); if (ix == -1) return; String methodName = "create" + panels[ix][0].replace(' ', '_'); Control[] children = layoutDisplayPanel.getChildren(); for (int i = 0; i < children.length; i++) children[i].dispose(); try { Control child = (Control) SwtDemo.class.getMethod(methodName, new Class[] {Composite.class}).invoke(SwtDemo.this, new Object[] {layoutDisplayPanel}); child.setLayoutData("grow, wmin 500"); descrTextArea.setText(panels[ix][1]); layoutDisplayPanel.layout(); } catch (Exception e1) { e1.printStackTrace(); // Should never happpen... } } public Control createTest(Composite parent) { // TabFolder tabFolder = new TabFolder(parent2, DOUBLE_BUFFER); Button button; Composite composite = new Composite(parent, SWT.NONE); composite.setLayout(new MigLayout("debug", "[right][grow]", "")); button = new Button(composite, SWT.PUSH); button.setText("New"); button.setLayoutData("span 2, align left, split, sgx button"); button = new Button(composite, SWT.PUSH); button.setText("Edit"); button.setLayoutData("sgx button"); button = new Button(composite, SWT.PUSH); button.setText("Cancel"); button.setLayoutData("sgx button"); button = new Button(composite, SWT.PUSH); button.setText("Save"); button.setLayoutData("sgx button, wrap"); new Label(composite, SWT.NONE).setText("Name"); Text text = new Text(composite, SWT.BORDER); text.setLayoutData("sgy control, pushx, growx, wrap"); new Label(composite, SWT.NONE).setText("Sex"); Combo combo = new Combo(composite, SWT.DROP_DOWN); combo.setLayoutData("sgy control, w 50!, wrap"); combo.setItems(new String[] { "M", "F", "-" }); return composite; } public Control createWelcome(Composite parent) { TabFolder tabbedPane = new TabFolder(parent, DOUBLE_BUFFER); TabItem tabPanel = createTabPanel(tabbedPane, "Welcome", new MigLayout()); MigLayout lm = new MigLayout("ins 20, fill"); Composite panel = createPanel(tabbedPane, lm); tabPanel.setControl(panel); String s = "MigLayout's main purpose is to make layouts for SWT and Swing, and possibly other frameworks, much more powerful and a lot easier to create, especially for manual coding.\n\n" + "The motto is: \"MigLayout makes complex layouts easy and normal layouts one-liners.\"\n\n" + "The layout engine is very flexible and advanced, something that is needed to make it simple to use yet handle almost all layout use-cases.\n\n" + "MigLayout can handle all layouts that the commonly used Swing Layout Managers can handle and this with a lot of extra features. " + "It also incorporates most, if not all, of the open source alternatives FormLayout's and TableLayout's functionality." + "\n\n\nThanks to Karsten Lentzsch from JGoodies.com for allowing the reuse of the main demo application layout and for his inspiring talks that led to this layout Manager." + "\n\n\nMikael Grev\n" + "MiG InfoCom AB\n" + "miglayout@miginfocom.com"; // One needs to set both min and pref for SWT wrapping text areas since it always returns the unwrapped size otherwise. StyledText textArea = createTextArea(panel, s, "w 500:500, ay top, grow, push", 0); textArea.setBackground(panel.getBackground()); textArea.setBackgroundMode(SWT.INHERIT_NONE); // deriveFont(textArea, SWT.PATH_LINE_TO, -1); return tabbedPane; } public Composite createAPI_Constraints1(Composite parent) { TabFolder tabbedPane = new TabFolder(parent, DOUBLE_BUFFER); LC layC = new LC().fill().wrap(); AC colC = new AC().align("right", 0).fill(1, 3).grow(100, 1, 3).align("right", 2).gap("15", 1); AC rowC = new AC().align("top", 7).gap("15!", 6).grow(100, 8); TabItem p1 = createTabPanel(tabbedPane, "Layout Showdown (improved)", new MigLayout(layC, colC, rowC)); // References to text fields not stored to reduce code clutter. createList(p1, "Mouse, Mickey", new CC().dockWest().minWidth("150").gapX(null, "10")); createLabel(p1, "Last Name", ""); createTextField(p1, "", ""); createLabel(p1, "First Name", ""); createTextField(p1, "", new CC().wrap()); createLabel(p1, "Phone", ""); createTextField(p1, "", ""); createLabel(p1, "Email", ""); createTextField(p1, "", ""); createLabel(p1, "Address 1", ""); createTextField(p1, "", new CC().spanX().growX()); createLabel(p1, "Address 2", ""); createTextField(p1, "", new CC().spanX().growX()); createLabel(p1, "City", ""); createTextField(p1, "", new CC().wrap()); createLabel(p1, "State", ""); createTextField(p1, "", ""); createLabel(p1, "Postal Code", ""); createTextField(p1, "", new CC().spanX(2).growX(0)); createLabel(p1, "Country", ""); createTextField(p1, "", new CC().wrap()); createButton(p1, "New", new CC().spanX(5).split(5).tag("other")); createButton(p1, "Delete", new CC().tag("other")); createButton(p1, "Edit", new CC().tag("other")); createButton(p1, "Save", new CC().tag("other")); createButton(p1, "Cancel", new CC().tag("cancel")); return tabbedPane; } public Composite createAPI_Constraints2(Composite parent) { TabFolder tabbedPane = new TabFolder(parent, DOUBLE_BUFFER); LC layC = new LC().fill().wrap(); AC colC = new AC().align("right", 0).fill(1, 3).grow(100, 1, 3).align("right", 2).gap("15", 1); AC rowC = new AC().index(6).gap("15!").align("top").grow(100, 8); TabItem p1 = createTabPanel(tabbedPane, "Layout Showdown (improved)", new MigLayout(layC, colC, rowC)); // References to text fields not stored to reduce code clutter. createLabel(p1, "Last Name", ""); createTextField(p1, "", ""); createLabel(p1, "First Name", ""); createTextField(p1, "", new CC().wrap()); createLabel(p1, "Phone", ""); createTextField(p1, "", ""); createLabel(p1, "Email", ""); createTextField(p1, "", ""); createLabel(p1, "Address 1", ""); createTextField(p1, "", new CC().spanX().growX()); createLabel(p1, "Address 2", ""); createTextField(p1, "", new CC().spanX().growX()); createLabel(p1, "City", ""); createTextField(p1, "", new CC().wrap()); createLabel(p1, "State", ""); createTextField(p1, "", ""); createLabel(p1, "Postal Code", ""); createTextField(p1, "", new CC().spanX(2).growX(0)); createLabel(p1, "Country", ""); createTextField(p1, "", new CC().wrap()); createButton(p1, "New", new CC().spanX(5).split(5).tag("other")); createButton(p1, "Delete", new CC().tag("other")); createButton(p1, "Edit", new CC().tag("other")); createButton(p1, "Save", new CC().tag("other")); createButton(p1, "Cancel", new CC().tag("cancel")); return tabbedPane; } public Composite createLayout_Showdown(Composite parent) { TabFolder tabbedPane = new TabFolder(parent, DOUBLE_BUFFER); TabItem p1 = createTabPanel(tabbedPane, "Layout Showdown (pure)", new MigLayout("", "[]15[][grow,fill]15[grow]")); // References to text fields not stored to reduce code clutter. createList(p1, "Mouse, Mickey", "spany, growy, wmin 150"); createLabel(p1, "Last Name", ""); createTextField(p1, "", ""); createLabel(p1, "First Name", "split"); // split divides the cell createTextField(p1, "", "growx, wrap"); createLabel(p1, "Phone", ""); createTextField(p1, "", ""); createLabel(p1, "Email", "split"); createTextField(p1, "", "growx, wrap"); createLabel(p1, "Address 1", ""); createTextField(p1, "", "span, growx"); // span merges cells createLabel(p1, "Address 2", ""); createTextField(p1, "", "span, growx"); createLabel(p1, "City", ""); createTextField(p1, "", "wrap"); // wrap continues on next line createLabel(p1, "State", ""); createTextField(p1, "", ""); createLabel(p1, "Postal Code", "split"); createTextField(p1, "", "growx, wrap"); createLabel(p1, "Country", ""); createTextField(p1, "", "wrap 15"); createButton(p1, "New", "span, split, align right"); createButton(p1, "Delete", ""); createButton(p1, "Edit", ""); createButton(p1, "Save", ""); createButton(p1, "Cancel", "wrap push"); // Fixed version ******************************************* TabItem p2 = createTabPanel(tabbedPane, "Layout Showdown (improved)", new MigLayout("", "[]15[][grow,fill]15[][grow,fill]")); // References to text fields not stored to reduce code clutter. createList(p2, "Mouse, Mickey", "spany, growy, wmin 150"); createLabel(p2, "Last Name", ""); createTextField(p2, "", ""); createLabel(p2, "First Name", ""); createTextField(p2, "", "wrap"); createLabel(p2, "Phone", ""); createTextField(p2, "", ""); createLabel(p2, "Email", ""); createTextField(p2, "", "wrap"); createLabel(p2, "Address 1", ""); createTextField(p2, "", "span"); createLabel(p2, "Address 2", ""); createTextField(p2, "", "span"); createLabel(p2, "City", ""); createTextField(p2, "", "wrap"); createLabel(p2, "State", ""); createTextField(p2, "", ""); createLabel(p2, "Postal Code", ""); createTextField(p2, "", "width 50, grow 0, wrap"); createLabel(p2, "Country", ""); createTextField(p2, "", "wrap 15"); createButton(p2, "New", "tag other, span, split"); createButton(p2, "Delete", "tag other"); createButton(p2, "Edit", "tag other"); createButton(p2, "Save", "tag other"); createButton(p2, "Cancel", "tag cancel, wrap push"); return tabbedPane; } public Composite createDocking(Composite parent) { TabFolder tabbedPane = new TabFolder(parent, DOUBLE_BUFFER); tabbedPane.setLayoutData("grow"); TabItem p1 = createTabPanel(tabbedPane, "Docking 1", new MigLayout("fill")); createPanel(p1, "1. North", "north"); createPanel(p1, "2. West", "west"); createPanel(p1, "3. East", "east"); createPanel(p1, "4. South", "south"); Table table = new Table(getComposite(p1), DOUBLE_BUFFER); for (int i = 0; i < 5; i++) { TableColumn tc = new TableColumn(table, SWT.LEFT | SWT.V_SCROLL | SWT.SCROLL_LINE); tc.setText("Column " + (i + 1)); tc.setWidth(100); } for (int r = 0; r < 15; r++) { TableItem item1 = new TableItem(table,0); String[] data = new String[6]; for (int c = 0; c < data.length; c++) data[c] = "Cell " + (r + 1) + ", " + (c + 1); item1.setText(data); } table.setHeaderVisible(true); table.setLinesVisible(true); table.setLayoutData("grow"); TabItem p2 = createTabPanel(tabbedPane, "Docking 2 (fill)", new MigLayout("fill", "[c]", "")); createPanel(p2, "1. North", "north"); createPanel(p2, "2. North", "north"); createPanel(p2, "3. West", "west"); createPanel(p2, "4. West", "west"); createPanel(p2, "5. South", "south"); createPanel(p2, "6. East", "east"); createButton(p2, "7. Normal", ""); createButton(p2, "8. Normal", ""); createButton(p2, "9. Normal", ""); TabItem p3 = createTabPanel(tabbedPane, "Docking 3", new MigLayout()); createPanel(p3, "1. North", "north"); createPanel(p3, "2. South", "south"); createPanel(p3, "3. West", "west"); createPanel(p3, "4. East", "east"); createButton(p3, "5. Normal", ""); TabItem p4 = createTabPanel(tabbedPane, "Docking 4", new MigLayout()); createPanel(p4, "1. North", "north"); createPanel(p4, "2. North", "north"); createPanel(p4, "3. West", "west"); createPanel(p4, "4. West", "west"); createPanel(p4, "5. South", "south"); createPanel(p4, "6. East", "east"); createButton(p4, "7. Normal", ""); createButton(p4, "8. Normal", ""); createButton(p4, "9. Normal", ""); TabItem p5 = createTabPanel(tabbedPane, "Docking 5 (fillx)", new MigLayout("fillx", "[c]", "")); createPanel(p5, "1. North", "north"); createPanel(p5, "2. North", "north"); createPanel(p5, "3. West", "west"); createPanel(p5, "4. West", "west"); createPanel(p5, "5. South", "south"); createPanel(p5, "6. East", "east"); createButton(p5, "7. Normal", ""); createButton(p5, "8. Normal", ""); createButton(p5, "9. Normal", ""); TabItem p6 = createTabPanel(tabbedPane, "Random Docking", new MigLayout("fill")); String[] sides = {"north", "east", "south", "west"}; Random rand = new Random(); for (int i = 0; i < 20; i++) { int side = rand.nextInt(4); createPanel(p6, ((i + 1) + " " + sides[side]), sides[side]); } createPanel(p6, "I'm in the Center!", "grow"); return tabbedPane; } public Control createAbsolute_Position(final Composite parent) { TabFolder tabbedPane = new TabFolder(parent, DOUBLE_BUFFER); // Pos tab TabItem posTabPanel = createTabPanel(tabbedPane, "X Y Positions", new FillLayout()); final Composite posPanel = createPanel(posTabPanel, new MigLayout()); createButton(posPanel, "pos 0.5al 0al", null); createButton(posPanel, "pos 1al 0al", null); createButton(posPanel, "pos 0.5al 0.5al", null); createButton(posPanel, "pos 5in 45lp", null); createButton(posPanel, "pos 0.5al 0.5al", null); createButton(posPanel, "pos 0.5al 1al", null); createButton(posPanel, "pos 1al .25al", null); createButton(posPanel, "pos visual.x2-pref visual.y2-pref", null); createButton(posPanel, "pos 1al -1in", null); createButton(posPanel, "pos 100 100", null); createButton(posPanel, "pos (10+(20*3lp)) 200", null); createButton(posPanel, "Drag Window! (pos 500-container.xpos 500-container.ypos)", "pos 500-container.xpos 500-container.ypos"); // Bounds tab TabItem boundsTabPanel = createTabPanel(tabbedPane, "X1 Y1 X2 Y2 Bounds", new FillLayout()); Composite boundsPanel = createPanel(boundsTabPanel, new MigLayout()); Label southLabel = createLabel(boundsPanel, "pos (visual.x+visual.w*0.1) visual.y2-40 (visual.x2-visual.w*0.1) visual.y2", null, SWT.CENTER | SWT.BORDER); southLabel.setBackground(new Color(display, 200, 200, 255)); deriveFont(southLabel, SWT.BOLD, 10); createButton(boundsPanel, "pos 0 0 container.x2 n", null); createButton(boundsPanel, "pos visual.x 40 visual.x2 70", null); createButton(boundsPanel, "pos visual.x 100 visual.x2 p", null); createButton(boundsPanel, "pos 0.1al 0.4al n visual.y2-10", null); createButton(boundsPanel, "pos 0.9al 0.4al n visual.y2-10", null); createButton(boundsPanel, "pos 0.5al 0.5al, pad 3 0 -3 0", null); createButton(boundsPanel, "pos n n 50% 50%", null); createButton(boundsPanel, "pos 50% 50% n n", null); createButton(boundsPanel, "pos 50% n n 50%", null); createButton(boundsPanel, "pos n 50% 50% n", null); // Glass pane tab // final TabItem glassPanel = createTabPanel(tabbedPane, "GlassPane Substitute", parent, new SwtMigLayout("align c c")); // final Button butt = new Button("Press me!!"); // glassPanel.add(butt); // // butt.addActionListener(new ActionListener() { // public void actionPerformed(ActionEvent e) // { // butt.setEnabled(false); // final JPanel bg = new JPanel(parent, new SwtMigLayout("align c c,fill")) { // public void paint(Graphics g) // { // g.setColor(getBackground()); // g.fillRect(0, 0, getWidth(), getHeight()); // super.paint(g); // } // }; // bg.setOpaque(false); // configureActiveComponet(bg); // // final Label label = createLabel("You don't need a GlassPane to be cool!"); // label.setFont(label.getFont().deriveFont(30f)); // label.setForeground(new Color(255, 255, 255, 0)); // bg.add(label, "align 50% 30%"); // // glassPanel.add(bg, "pos 0 0 visual.x2 visual.y2", 0); // final long startTime = System.nanoTime(); // final long endTime = startTime + 500000000L; // // glassPanel.revalidate(); // // final javax.swing.Timer timer = new Timer(25, null); // // timer.addActionListener(new ActionListener() { // public void actionPerformed(ActionEvent e) // { // long now = System.nanoTime(); // int alpha = (int) (((now - startTime) / (double) (endTime - startTime)) * 300); // if (alpha < 150) // bg.setBackground(new Color(100, 100, 100, alpha)); // // if (alpha > 150 && alpha < 405) { // label.setForeground(new Color(255, 255, 255, (alpha - 150))); // bg.repaint(); // } // if (alpha > 405) // timer.stop(); // } // }); // timer.start(); // } // }); // parent.getShell().addControlListener(new ControlAdapter() { public void controlMoved(ControlEvent e) { if (!posPanel.isDisposed()) { posPanel.layout(); } else { parent.getShell().removeControlListener(this); } } }); return tabbedPane; } public Control createComponent_Links(Composite parent) { TabFolder tabbedPane = new TabFolder(parent, DOUBLE_BUFFER); TabItem linksPanel = createTabPanel(tabbedPane, "Component Links", new MigLayout()); // Links tab createButton(linksPanel, "Mini", "pos null ta.y ta.x2 null, pad 3 0 -3 0"); createTextArea(linksPanel, "Components, Please Link to Me!\nMy ID is: 'ta'", "id ta, pos 0.5al 0.5al, w 300"); createButton(linksPanel, "id b1,pos ta.x2 ta.y2", null); createButton(linksPanel, "pos b1.x2+rel b1.y visual.x2 null", null); createCheck(linksPanel, "pos (ta.x+indent) (ta.y2+rel)", null); createButton(linksPanel, "pos ta.x2+rel ta.y visual.x2 null", null); createButton(linksPanel, "pos null ta.y+(ta.h-pref)/2 ta.x-rel null", null); createButton(linksPanel, "pos ta.x ta.y2+100 ta.x2 null", null); // External tab TabItem externalPanel = createTabPanel(tabbedPane, "External Components", new MigLayout()); Button extButt = createButton(externalPanel, "Bounds Externally Set!", "id ext, external"); extButt.setBounds(250, 130, 200, 40); createButton(externalPanel, "pos ext.x2 ext.y2", "pos ext.x2 ext.y2"); createButton(externalPanel, "pos null null ext.x ext.y", "pos null null ext.x ext.y"); TabItem egTabPanel = createTabPanel(tabbedPane, "End Grouping", new FillLayout()); final Composite egPanel = createPanel(egTabPanel, new MigLayout()); createButton(egPanel, "id b1, endgroupx g1, pos 200 200", null); createButton(egPanel, "id b2, endgroupx g1, pos (b1.x+2ind) (b1.y2+rel)", null); createButton(egPanel, "id b3, endgroupx g1, pos (b1.x+4ind) (b2.y2+rel)", null); createButton(egPanel, "id b4, endgroupx g1, pos (b1.x+6ind) (b3.y2+rel)", null); // Group Bounds tab TabItem gpTabPanel = createTabPanel(tabbedPane, "Group Bounds", new FillLayout()); final Composite gpPanel = createPanel(gpTabPanel, new MigLayout()); createButton(gpPanel, "id grp1.b1, pos n 0.5al 50% n", null); createButton(gpPanel, "id grp1.b2, pos 50% 0.5al n n", null); createButton(gpPanel, "id grp1.b3, pos 0.5al n n b1.y", null); createButton(gpPanel, "id grp1.b4, pos 0.5al b1.y2 n n", null); createButton(gpPanel, "pos n grp1.y2 grp1.x n", null); createButton(gpPanel, "pos n n grp1.x grp1.y", null); createButton(gpPanel, "pos grp1.x2 n n grp1.y", null); createButton(gpPanel, "pos grp1.x2 grp1.y2", null); Composite boundsPanel = createPanel(gpPanel, (Layout) null); boundsPanel.setLayoutData("pos grp1.x grp1.y grp1.x2 grp1.y2"); boundsPanel.setBackground(new Color(display, 200, 200, 255)); return tabbedPane; } public Control createFlow_Direction(Composite parent) { TabFolder tabbedPane = new TabFolder(parent, DOUBLE_BUFFER); createFlowPanel(tabbedPane, "Layout: flowx, Cell: flowx", "", "flowx"); createFlowPanel(tabbedPane, "Layout: flowx, Cell: flowy", "", "flowy"); createFlowPanel(tabbedPane, "Layout: flowy, Cell: flowx", "flowy", "flowx"); createFlowPanel(tabbedPane, "Layout: flowy, Cell: flowy", "flowy", "flowy"); return tabbedPane; } private TabItem createFlowPanel(TabFolder parent, String text, String gridFlow, String cellFlow) { MigLayout lm = new MigLayout("center, wrap 3," + gridFlow, "[110,fill]", "[110,fill]"); TabItem panel = createTabPanel(parent, text, lm); for (int i = 0; i < 9; i++) { Composite b = createPanel(panel, "" + (i + 1), cellFlow); Font f = deriveFont(b, SWT.DEFAULT, 20); b.getChildren()[0].setFont(f); } Composite b = createPanel(panel, "5:2", cellFlow + ",cell 1 1"); Font f = deriveFont(b, SWT.DEFAULT, 20); b.getChildren()[0].setFont(f); return panel; } public Control createDebug(Composite parent) { return createPlainImpl(parent, true); } public Control createButton_Bars(final Composite parent) { MigLayout lm = new MigLayout("ins 0 0 15lp 0", "[grow]", "[grow]u[baseline,nogrid]"); final Composite mainPanel = new Composite(parent, DOUBLE_BUFFER); mainPanel.setLayout(lm); TabFolder tabbedPane = new TabFolder(mainPanel, DOUBLE_BUFFER); tabbedPane.setLayoutData("grow, wrap"); createButtonBarsPanel(tabbedPane, "Buttons", "help", false); createButtonBarsPanel(tabbedPane, "Buttons with Help2", "help2", false); createButtonBarsPanel(tabbedPane, "Buttons (Same width)", "help", true); createLabel(mainPanel, "Button Order:", ""); final Label formatLabel = createLabel(mainPanel, "", "growx"); deriveFont(formatLabel, SWT.BOLD , -1); final Button winButt = createToggleButton(mainPanel, "Windows", "wmin button"); final Button macButt = createToggleButton(mainPanel, "Mac OS X", "wmin button"); winButt.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { if (winButt.getSelection()) { PlatformDefaults.setPlatform(PlatformDefaults.WINDOWS_XP); formatLabel.setText("'" + PlatformDefaults.getButtonOrder() + "'"); macButt.setSelection(false); mainPanel.layout(); } } }); macButt.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { if (macButt.getSelection()) { PlatformDefaults.setPlatform(PlatformDefaults.MAC_OSX); formatLabel.setText("'" + PlatformDefaults.getButtonOrder() + "'"); winButt.setSelection(false); mainPanel.layout(); } } }); Button helpButt = createButton(mainPanel, "Help", "gap unrel,wmin button"); helpButt.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { MessageBox msgBox = new MessageBox(parent.getShell()); msgBox.setMessage("See JavaDoc for PlatformDefaults.setButtonOrder(..) for details on the format string."); msgBox.open(); } }); (PlatformDefaults.getPlatform() == PlatformDefaults.WINDOWS_XP ? winButt : macButt).setSelection(true); return mainPanel; } private TabItem createButtonBarsPanel(TabFolder parent, String text, String helpTag, boolean sizeLocked) { MigLayout lm = new MigLayout("nogrid, fillx, aligny 100%, gapy unrel"); TabItem panel = createTabPanel(parent, text, lm); // Notice that the order in the rows below does not matter... String[][] buttons = new String[][] { {"No", "Yes"}, {"Help", "Close"}, {"OK", "Help"}, {"OK", "Cancel", "Help"}, {"OK", "Cancel", "Apply", "Help"}, {"No", "Yes", "Cancel"}, {"Help", "< Move Back", "Move Forward >", "Cancel"}, {"Print...", "Cancel", "Help"}, }; for (int r = 0; r < buttons.length; r++) { for (int i = 0; i < buttons[r].length; i++) { String txt = buttons[r][i]; String tag = txt; if (txt.equals("Help")) { tag = helpTag; } else if (txt.equals("< Move Back")) { tag = "back"; } else if (txt.equals("Close")) { tag = "cancel"; } else if (txt.equals("Move Forward >")) { tag = "next"; } else if (txt.equals("Print...")) { tag = "other"; } String wrap = (i == buttons[r].length - 1) ? ",wrap" : ""; String sizeGroup = sizeLocked ? ("sgx " + r + ",") : ""; createButton(panel, txt, sizeGroup + "tag " + tag + wrap); } } return panel; } public Control createOrientation(Composite parent) { TabFolder tabbedPane = new TabFolder(parent, DOUBLE_BUFFER); MigLayout lm = new MigLayout("flowy", "[grow,fill]", "[]0[]15lp[]0[]"); TabItem mainPanel = createTabPanel(tabbedPane, "Orientation", lm); // Default orientation MigLayout defLM = new MigLayout("", "[][grow,fill]", ""); Composite defPanel = createPanel(mainPanel, defLM); addSeparator(defPanel, "Default Orientation"); createLabel(defPanel, "Level", ""); createTextField(defPanel, "", "span,growx"); createLabel(defPanel, "Radar", ""); createTextField(defPanel, "", ""); createTextField(defPanel, "", ""); // Right-to-left, Top-to-bottom MigLayout rtlLM = new MigLayout("rtl,ttb", "[][grow,fill]", ""); Composite rtlPanel = createPanel(mainPanel, rtlLM); addSeparator(rtlPanel, "Right to Left"); createLabel(rtlPanel, "Level", ""); createTextField(rtlPanel, "", "span,growx"); createLabel(rtlPanel, "Radar", ""); createTextField(rtlPanel, "", ""); createTextField(rtlPanel, "", ""); // Right-to-left, Bottom-to-top MigLayout rtlbLM = new MigLayout("rtl,btt", "[][grow,fill]", ""); Composite rtlbPanel = createPanel(mainPanel, rtlbLM); addSeparator(rtlbPanel, "Right to Left, Bottom to Top"); createLabel(rtlbPanel, "Level", ""); createTextField(rtlbPanel, "", "span,growx"); createLabel(rtlbPanel, "Radar", ""); createTextField(rtlbPanel, "", ""); createTextField(rtlbPanel, "", ""); // Left-to-right, Bottom-to-top MigLayout ltrbLM = new MigLayout("ltr,btt", "[][grow,fill]", ""); Composite ltrbPanel = createPanel(mainPanel, ltrbLM); addSeparator(ltrbPanel, "Left to Right, Bottom to Top"); createLabel(ltrbPanel, "Level", ""); createTextField(ltrbPanel, "", "span,growx"); createLabel(ltrbPanel, "Radar", ""); createTextField(ltrbPanel, "", ""); createTextField(ltrbPanel, "", ""); return tabbedPane; } public Control createCell_Position(Composite parent) { TabFolder tabbedPane = new TabFolder(parent, DOUBLE_BUFFER); // Absolute grid position MigLayout absLM = new MigLayout("", "[100:pref,fill]", "[100:pref,fill]"); TabItem absPanel = createTabPanel(tabbedPane, "Absolute", absLM); createPanel(absPanel, "cell 0 0", null); createPanel(absPanel, "cell 2 0", null); createPanel(absPanel, "cell 3 0", null); createPanel(absPanel, "cell 1 1", null); createPanel(absPanel, "cell 0 2", null); createPanel(absPanel, "cell 2 2", null); createPanel(absPanel, "cell 2 2", null); // Relative grid position with wrap MigLayout relAwLM = new MigLayout("wrap", "[100:pref,fill][100:pref,fill][100:pref,fill][100:pref,fill]", "[100:pref,fill]"); TabItem relAwPanel = createTabPanel(tabbedPane, "Relative + Wrap", relAwLM); createPanel(relAwPanel, "", null); createPanel(relAwPanel, "skip", null); createPanel(relAwPanel, "", null); createPanel(relAwPanel, "skip,wrap", null); createPanel(relAwPanel, "", null); createPanel(relAwPanel, "skip,split", null); createPanel(relAwPanel, "", null); // Relative grid position with manual wrap MigLayout relWLM = new MigLayout("", "[100:pref,fill]", "[100:pref,fill]"); TabItem relWPanel = createTabPanel(tabbedPane, "Relative", relWLM); createPanel(relWPanel, "", null); createPanel(relWPanel, "skip", null); createPanel(relWPanel, "wrap", null); createPanel(relWPanel, "skip,wrap", null); createPanel(relWPanel, "", null); createPanel(relWPanel, "skip,split", null); createPanel(relWPanel, "", null); // Mixed relative and absolute grid position MigLayout mixLM = new MigLayout("", "[100:pref,fill]", "[100:pref,fill]"); TabItem mixPanel = createTabPanel(tabbedPane, "Mixed", mixLM); createPanel(mixPanel, "", null); createPanel(mixPanel, "cell 2 0", null); createPanel(mixPanel, "", null); createPanel(mixPanel, "cell 1 1,wrap", null); createPanel(mixPanel, "", null); createPanel(mixPanel, "cell 2 2,split", null); createPanel(mixPanel, "", null); return tabbedPane; } public Control createPlain(Composite parent) { return createPlainImpl(parent, false); } private Control createPlainImpl(Composite parent, boolean debug) { TabFolder tabbedPane = new TabFolder(parent, DOUBLE_BUFFER); MigLayout lm = new MigLayout((debug && benchRuns == 0 ? "debug" : ""), "[r][100lp, fill][60lp][95lp, fill]", ""); TabItem panel = createTabPanel(tabbedPane, "Plain", lm); addSeparator(panel, "Manufacturer"); createLabel(panel, "Company", ""); createTextField(panel, "", "span,growx"); createLabel(panel, "Contact", ""); createTextField(panel, "", "span,growx"); createLabel(panel, "Order No", ""); createTextField(panel, "", "wmin 15*6,wrap"); addSeparator(panel, "Inspector"); createLabel(panel, "Name", ""); createTextField(panel, "", "span,growx"); createLabel(panel, "Reference No", ""); createTextField(panel, "", "wrap"); createLabel(panel, "Status", ""); createCombo(panel, new String[] {"In Progress", "Finnished", "Released"}, "wrap"); addSeparator(panel, "Ship"); createLabel(panel, "Shipyard", ""); createTextField(panel, "", "span,growx"); createLabel(panel, "Register No", ""); createTextField(panel, "", ""); createLabel(panel, "Hull No", "right"); createTextField(panel, "", "wmin 15*6,wrap"); createLabel(panel, "Project StructureType", ""); createCombo(panel, new String[] {"New Building", "Convention", "Repair"}, "wrap"); if (debug) createLabel(panel, "Blue is component bounds. Cell bounds (red) can not be shown in SWT", "newline,ax left,span,gaptop 40"); return tabbedPane; } public Control createBound_Sizes(Composite parent) { TabFolder tabbedPane = new TabFolder(parent, DOUBLE_BUFFER); for (int i = 0; i < 2; i++) { // Jumping for 0 and Stable for 1 String colConstr = i == 0 ? "[right][300]" : "[right, 150lp:pref][300]"; MigLayout LM1 = new MigLayout("wrap", colConstr, ""); TabItem panel1 = createTabPanel(tabbedPane, i == 0 ? "Jumping 1" : "Stable 1", LM1); createLabel(panel1, "File Number:", ""); createTextField(panel1, "", "growx"); createLabel(panel1, "RFQ Number:", ""); createTextField(panel1, "", "growx"); createLabel(panel1, "Entry Date:", ""); createTextField(panel1, " ", "wmin 6*6"); createLabel(panel1, "Sales Person:", ""); createTextField(panel1, "", "growx"); MigLayout LM2 = new MigLayout("wrap", colConstr, ""); TabItem panel2 = createTabPanel(tabbedPane, i == 0 ? "Jumping 2" : "Stable 2", LM2); createLabel(panel2, "Shipper:", ""); createTextField(panel2, " ", "split 2"); createTextField(panel2, "", "growx"); createLabel(panel2, "Consignee:", ""); createTextField(panel2, " ", "split 2"); createTextField(panel2, "", "growx"); createLabel(panel2, "Departure:", ""); createTextField(panel2, " ", "split 2"); createTextField(panel2, "", "growx"); createLabel(panel2, "Destination:", ""); createTextField(panel2, " ", "split 2"); createTextField(panel2, "", "growx"); } return tabbedPane; } public Control createComponent_Sizes(Composite parent) { TabFolder tabbedPane = new TabFolder(parent, DOUBLE_BUFFER); MigLayout lm = new MigLayout("wrap", "[right][0:pref,grow]", ""); TabItem tabPanel = createTabPanel(tabbedPane, "Component Sizes", new FillLayout()); SashForm sashForm = new SashForm(getComposite(tabPanel), SWT.HORIZONTAL | SWT.SMOOTH); sashForm.setBackground(new Color(display, 255, 255, 255)); sashForm.setBackgroundMode(SWT.INHERIT_FORCE); Composite panel = createPanel(sashForm, lm, SWT.BORDER); createTextArea(sashForm, "Use slider to see how the components grow and shrink depending on the constraints set on them.", ""); createLabel(panel, "", ""); createTextField(panel, "8 ", ""); createLabel(panel, "width min!", null); createTextField(panel, "3 ", "width min!"); createLabel(panel, "width pref!", ""); createTextField(panel, "3 ", "width pref!"); createLabel(panel, "width min:pref", null); createTextField(panel, "8 ", "width min:pref"); createLabel(panel, "width min:100:150", null); createTextField(panel, "8 ", "width min:100:150"); createLabel(panel, "width min:100:150, growx", null); createTextField(panel, "8 ", "width min:100:150, growx"); createLabel(panel, "width min:100, growx", null); createTextField(panel, "8 ", "width min:100, growx"); createLabel(panel, "width 40!", null); createTextField(panel, "8 ", "width 40!"); createLabel(panel, "width 40:40:40", null); createTextField(panel, "8 ", "width 40:40:40"); return tabbedPane; } public Control createCell_Alignments(Composite parent) { TabFolder tabbedPane = new TabFolder(parent, DOUBLE_BUFFER); // Horizontal MigLayout hLM = new MigLayout("wrap", "[grow,left][grow,center][grow,right][grow,fill,center]", "[]unrel[][]"); TabItem hPanel = createTabPanel(tabbedPane, "Horizontal", hLM); String[] sizes = new String[] {"", "growx", "growx 0", "left", "center", "right", "leading", "trailing"}; createLabel(hPanel, "[left]", "c"); createLabel(hPanel, "[center]", "c"); createLabel(hPanel, "[right]", "c"); createLabel(hPanel, "[fill,center]", "c, growx 0"); for (int r = 0; r < sizes.length; r++) { for (int c = 0; c < 4; c++) { String text = sizes[r].length() > 0 ? sizes[r] : "default"; createButton(hPanel, text, sizes[r]); } } // Vertical MigLayout vLM = new MigLayout("wrap,flowy", "[right][]", "[grow,top][grow,center][grow,bottom][grow,fill,bottom][grow,fill,baseline]"); TabItem vPanel = createTabPanel(tabbedPane, "Vertical", vLM); String[] vSizes = new String[] {"", "growy", "growy 0", "top", "center", "bottom"}; createLabel(vPanel, "[top]", "center"); createLabel(vPanel, "[center]", "center"); createLabel(vPanel, "[bottom]", "center"); createLabel(vPanel, "[fill, bottom]", "center, growy 0"); createLabel(vPanel, "[fill, baseline]", "center"); for (int c = 0; c < vSizes.length; c++) { for (int r = 0; r < 5; r++) { String text = vSizes[c].length() > 0 ? vSizes[c] : "default"; createButton(vPanel, text, vSizes[c]); } } return tabbedPane; } public Control createUnits(Composite parent) { TabFolder tabbedPane = new TabFolder(parent, DOUBLE_BUFFER); // Horizontal MigLayout hLM = new MigLayout("wrap", "[right][]", ""); TabItem hPanel = createTabPanel(tabbedPane, "Horizontal", hLM); String[] sizes = new String[] {"72pt", "25.4mm", "2.54cm", "1in", "72px", "96px", "120px", "25%", "30sp"}; for (int i = 0; i < sizes.length; i++) { createLabel(hPanel, sizes[i], ""); createTextField(hPanel, "", "width " + sizes[i] + ""); } // Horizontal lp MigLayout hlpLM = new MigLayout("", "[right][][]", ""); TabItem hlpPanel = createTabPanel(tabbedPane, "Horizontal LP", hlpLM); createLabel(hlpPanel, "9 cols", ""); createTextField(hlpPanel, "", "wmin 9*6"); String[] lpSizes = new String[] {"75lp", "75px", "88px", "100px"}; createLabel(hlpPanel, "", "wrap"); for (int i = 0; i < lpSizes.length; i++) { createLabel(hlpPanel, lpSizes[i], ""); createTextField(hlpPanel, "", "width " + lpSizes[i] + ", wrap"); } // Vertical MigLayout vLM = new MigLayout("wrap,flowy", "[c]", "[top][top]"); TabItem vPanel = createTabPanel(tabbedPane, "Vertical", vLM); String[] vSizes = new String[] {"72pt", "25.4mm", "2.54cm", "1in", "72px", "96px", "120px", "25%", "30sp"}; for (int i = 0; i < sizes.length; i++) { createLabel(vPanel, vSizes[i], ""); createTextArea(vPanel, "", "width 50!, height " + vSizes[i] + ""); } // Vertical lp MigLayout vlpLM = new MigLayout("wrap,flowy", "[c]", "[top][top]40px[top][top]"); TabItem vlpPanel = createTabPanel(tabbedPane, "Vertical LP", vlpLM); createLabel(vlpPanel, "4 rows", ""); createTextArea(vlpPanel, "\n\n\n\n", "width 50!"); createLabel(vlpPanel, "field", ""); createTextField(vlpPanel, "", "wmin 5*9"); String[] vlpSizes1 = new String[] {"63lp", "57px", "63px", "68px", "25%"}; String[] vlpSizes2 = new String[] {"21lp", "21px", "23px", "24px", "10%"}; for (int i = 0; i < vlpSizes1.length; i++) { createLabel(vlpPanel, vlpSizes1[i], ""); createTextArea(vlpPanel, "", "width 50!, height " + vlpSizes1[i] + ""); createLabel(vlpPanel, vlpSizes2[i], ""); createTextField(vlpPanel, "", "height " + vlpSizes2[i] + "!,wmin 5*6"); } createLabel(vlpPanel, "button", "skip 2"); createButton(vlpPanel, "...", ""); return tabbedPane; } public Control createGrouping(Composite parent) { TabFolder tabbedPane = new TabFolder(parent, DOUBLE_BUFFER); // Ungrouped MigLayout ugM = new MigLayout("", "[]push[][][]", ""); TabItem ugPanel = createTabPanel(tabbedPane, "Ungrouped", ugM); createButton(ugPanel, "Help", ""); createButton(ugPanel, "< Back", "gap push"); createButton(ugPanel, "Forward >", ""); createButton(ugPanel, "Apply", "gap unrel"); createButton(ugPanel, "Cancel", "gap unrel"); // Grouped Components MigLayout gM = new MigLayout("nogrid, fillx"); TabItem gPanel = createTabPanel(tabbedPane, "Grouped (Components)", gM); createButton(gPanel, "Help", "sg"); createButton(gPanel, "< Back", "sg, gap push"); createButton(gPanel, "Forward >", "sg"); createButton(gPanel, "Apply", "sg, gap unrel"); createButton(gPanel, "Cancel", "sg, gap unrel"); // Grouped Columns MigLayout gcM = new MigLayout("", "[sg,fill]push[sg,fill][sg,fill]unrel[sg,fill]unrel[sg,fill]", ""); TabItem gcPanel = createTabPanel(tabbedPane, "Grouped (Columns)", gcM); createButton(gcPanel, "Help", ""); createButton(gcPanel, "< Back", ""); createButton(gcPanel, "Forward >", ""); createButton(gcPanel, "Apply", ""); createButton(gcPanel, "Cancel", ""); // Ungrouped Rows MigLayout ugrM = new MigLayout(); // no "sg" is the only difference to next panel TabItem ugrPanel = createTabPanel(tabbedPane, "Ungrouped Rows", ugrM); createLabel(ugrPanel, "File Number:", ""); createTextField(ugrPanel, "30 ", "wrap"); createLabel(ugrPanel, "BL/MBL number:", ""); createTextField(ugrPanel, "7 ", "split 2"); createTextField(ugrPanel, "7 ", "wrap"); createLabel(ugrPanel, "Entry Date:", ""); createTextField(ugrPanel, "7 ", "wrap"); createLabel(ugrPanel, "RFQ Number:", ""); createTextField(ugrPanel, "30 ", "wrap"); createLabel(ugrPanel, "Goods:", ""); createCheck(ugrPanel, "Dangerous", "wrap"); createLabel(ugrPanel, "Shipper:", ""); createTextField(ugrPanel, "30 ", "wrap"); createLabel(ugrPanel, "Customer:", ""); createTextField(ugrPanel, "", "split 2,growx"); createButton(ugrPanel, "...", "width 60px:pref,wrap"); createLabel(ugrPanel, "Port of Loading:", ""); createTextField(ugrPanel, "30 ", "wrap"); createLabel(ugrPanel, "Destination:", ""); createTextField(ugrPanel, "30 ", "wrap"); // Grouped Rows MigLayout grM = new MigLayout("", "[]", "[sg]"); // "sg" is the only difference to previous panel TabItem grPanel = createTabPanel(tabbedPane, "Grouped Rows", grM); createLabel(grPanel, "File Number:", ""); createTextField(grPanel, "30 ","wrap"); createLabel(grPanel, "BL/MBL number:", ""); createTextField(grPanel, "7 ","split 2"); createTextField(grPanel, "7 ", "wrap"); createLabel(grPanel, "Entry Date:", ""); createTextField(grPanel, "7 ", "wrap"); createLabel(grPanel, "RFQ Number:", ""); createTextField(grPanel, "30 ", "wrap"); createLabel(grPanel, "Goods:", ""); createCheck(grPanel, "Dangerous", "wrap"); createLabel(grPanel, "Shipper:", ""); createTextField(grPanel, "30 ", "wrap"); createLabel(grPanel, "Customer:", ""); createTextField(grPanel, "", "split 2,growx"); createButton(grPanel, "...", "width 50px:pref,wrap"); createLabel(grPanel, "Port of Loading:", ""); createTextField(grPanel, "30 ", "wrap"); createLabel(grPanel, "Destination:", ""); createTextField(grPanel, "30 ", "wrap"); return tabbedPane; } public Control createSpan(Composite parent) { TabFolder tabbedPane = new TabFolder(parent, DOUBLE_BUFFER); // Horizontal span MigLayout colLM = new MigLayout("", "[fill][25%,fill][105lp!,fill][150px!,fill]", "[]15[][]"); TabItem colPanel = createTabPanel(tabbedPane, "Column Span/Split", colLM); createTextField(colPanel, "Col1 [ ]", ""); createTextField(colPanel, "Col2 [25%]", ""); createTextField(colPanel, "Col3 [105lp!]", ""); createTextField(colPanel, "Col4 [150px!]", "wrap"); createLabel(colPanel, "Full Name:", ""); createTextField(colPanel, "span, growx ", "span,growx"); createLabel(colPanel, "Phone:", ""); createTextField(colPanel, " ", "span 3, split 5"); createTextField(colPanel, " ", null); createTextField(colPanel, " ", null); createTextField(colPanel, " ", null); createLabel(colPanel, "(span 3, split 4)", "wrap"); createLabel(colPanel, "Zip/City:", ""); createTextField(colPanel, " ", ""); createTextField(colPanel, "span 2, growx", null); // Vertical span MigLayout rowLM = new MigLayout("wrap", "[225lp]para[225lp]", "[]3[]unrel[]3[]unrel[]3[]"); TabItem rowPanel = createTabPanel(tabbedPane, "Row Span", rowLM); createLabel(rowPanel, "Name", ""); createLabel(rowPanel, "Notes", ""); createTextField(rowPanel, "growx", null); createTextArea(rowPanel, "spany,grow ", "spany,grow,hmin 13*5"); createLabel(rowPanel, "Phone", ""); createTextField(rowPanel, "growx", null); createLabel(rowPanel, "Fax", ""); createTextField(rowPanel, "growx", null); return tabbedPane; } public Control createGrowing(Composite parent) { TabFolder tabbedPane = new TabFolder(parent, DOUBLE_BUFFER); // All tab MigLayout allLM = new MigLayout("", "[pref!][grow,fill]", "[]15[]"); TabItem allTab = createTabPanel(tabbedPane, "All", allLM); createLabel(allTab, "Fixed", ""); createLabel(allTab, "Gets all extra space", "wrap"); createTextField(allTab, " ", ""); createTextField(allTab, " ", ""); // Half tab MigLayout halfLM = new MigLayout("", "[pref!][grow,fill]", "[]15[]"); TabItem halfTab = createTabPanel(tabbedPane, "Half", halfLM); createLabel(halfTab, "Fixed", ""); createLabel(halfTab, "Gets half of extra space", ""); createLabel(halfTab, "Gets half of extra space", "wrap"); createTextField(halfTab, " ", ""); createTextField(halfTab, " ", ""); createTextField(halfTab, " ", ""); // Percent 1 tab MigLayout p1LM = new MigLayout("", "[pref!][0:0,grow 25,fill][0:0,grow 75,fill]", "[]15[]"); TabItem p1Tab = createTabPanel(tabbedPane, "Percent 1", p1LM); createLabel(p1Tab, "Fixed", ""); createLabel(p1Tab, "Gets 25% of extra space", ""); createLabel(p1Tab, "Gets 75% of extra space", "wrap"); createTextField(p1Tab, " ", ""); createTextField(p1Tab, " ", ""); createTextField(p1Tab, " ", ""); // Percent 2 tab MigLayout p2LM = new MigLayout("", "[0:0,grow 33,fill][0:0,grow 67,fill]", "[]15[]"); TabItem p2Tab = createTabPanel(tabbedPane, "Percent 2", p2LM); createLabel(p2Tab, "Gets 33% of extra space", ""); createLabel(p2Tab, "Gets 67% of extra space", "wrap"); createTextField(p2Tab, " ", ""); createTextField(p2Tab, " ", ""); // Vertical 1 tab MigLayout v1LM = new MigLayout("flowy", "[]15[]", "[][c,pref!][c,grow 25,fill][c,grow 75,fill]"); TabItem v1Tab = createTabPanel(tabbedPane, "Vertical 1", v1LM); createLabel(v1Tab, "Fixed", "skip"); createLabel(v1Tab, "Gets 25% of extra space", ""); createLabel(v1Tab, "Gets 75% of extra space", "wrap"); createLabel(v1Tab, "new Text(SWT.MULTI | SWT.WRAP | SWT.BORDER)", ""); createTextArea(v1Tab, "", "hmin 4*13"); createTextArea(v1Tab, "", "hmin 4*13"); createTextArea(v1Tab, "", "hmin 4*13"); // Vertical 2 tab MigLayout v2LM = new MigLayout("flowy", "[]15[]", "[][c,grow 33,fill][c,grow 67,fill]"); TabItem v2Tab = createTabPanel(tabbedPane, "Vertical 2", v2LM); createLabel(v2Tab, "Gets 33% of extra space", "skip"); createLabel(v2Tab, "Gets 67% of extra space", "wrap"); createLabel(v2Tab, "new Text(SWT.MULTI | SWT.WRAP | SWT.BORDER)", ""); createTextArea(v2Tab, "", "hmin 4*13"); createTextArea(v2Tab, "", "hmin 4*13"); return tabbedPane; } public Control createBasic_Sizes(Composite parent) { TabFolder tabbedPane = new TabFolder(parent, DOUBLE_BUFFER); // Horizontal tab MigLayout horLM = new MigLayout("", "[]15[75px]25[min]25[]", "[]15"); TabItem horTab = createTabPanel(tabbedPane, "Horizontal - Column size set", horLM); createLabel(horTab, "75px", "skip"); createLabel(horTab, "Min", ""); createLabel(horTab, "Pref", "wrap"); createLabel(horTab, "new Text(15)", ""); createTextField(horTab, " ", "wmin 10"); createTextField(horTab, " ", "wmin 10"); createTextField(horTab, " ", "wmin 10"); // Vertical tab 1 MigLayout verLM = new MigLayout("flowy,wrap", "[]15[]", "[]15[c,45:45]15[c,min]15[c,pref]"); TabItem verTab = createTabPanel(tabbedPane, "\"Vertical - Row sized\"", verLM); createLabel(verTab, "45px", "skip"); createLabel(verTab, "Min", ""); createLabel(verTab, "Pref", ""); createLabel(verTab, "new Text(SWT.MULTI)", ""); createTextArea(verTab, "", ""); createTextArea(verTab, "", ""); createTextArea(verTab, "", ""); // Componentsized/Baseline 2 MigLayout verLM2 = new MigLayout("flowy,wrap", "[]15[]", "[]15[baseline]15[baseline]15[baseline]"); TabItem verTab2 = createTabPanel(tabbedPane, "\"Vertical - Component sized + Baseline\"", verLM2); createLabel(verTab2, "45px", "skip"); createLabel(verTab2, "Min", ""); createLabel(verTab2, "Pref", ""); createLabel(verTab2, "new Text(SWT.MULTI)", ""); createTextArea(verTab2, "", "height 45"); createTextArea(verTab2, "", "height min"); createTextArea(verTab2, "", "height pref"); return tabbedPane; } public Control createAlignments(Composite parent) { TabFolder tabbedPane = new TabFolder(parent, DOUBLE_BUFFER); // Horizontal tab MigLayout horLM = new MigLayout("wrap", "[label]15[left]15[center]15[right]15[fill]15[]", "[]15[]"); String[] horLabels = new String[] {"[label]", "[left]", "[center]", "[right]", "[fill]", "[] (Default)"}; TabItem horTab = createTabPanel(tabbedPane, "Horizontal", horLM); String[] horNames = new String[] {"First Name", "Phone Number", "Facsmile", "Email", "Address", "Other"}; for (int c = 0; c < horLabels.length; c++) createLabel(horTab, horLabels[c], ""); for (int r = 0; r < horLabels.length; r++) { for (int c = 0; c < horNames.length; c++) { if (c == 0) { createLabel(horTab, horNames[r] + ":", ""); } else { createButton(horTab, horNames[r], ""); } } } // Vertical tab MigLayout verLM = new MigLayout("wrap,flowy", "[]unrel[]rel[]", "[top]15[center]15[bottom]15[fill]15[fill,baseline]15[baseline]15[]"); String[] verLabels = new String[] {"[top]", "[center]", "[bottom]", "[fill]", "[fill,baseline]", "[baseline]", "[] (Default)"}; TabItem verTab = createTabPanel(tabbedPane, "Vertical", verLM); for (int c = 0; c < verLabels.length; c++) createLabel(verTab, verLabels[c], ""); for (int c = 0; c < verLabels.length; c++) createButton(verTab, "A Button", ""); for (int c = 0; c < verLabels.length; c++) createTextField(verTab, "JTextFied", ""); for (int c = 0; c < verLabels.length; c++) createTextArea(verTab, "Text ", ""); for (int c = 0; c < verLabels.length; c++) createTextArea(verTab, "Text\nwith two lines", ""); for (int c = 0; c < verLabels.length; c++) createTextArea(verTab, "Scrolling Text\nwith two lines", ""); return tabbedPane; } public Control createQuick_Start(Composite parent) { TabFolder tabbedPane = new TabFolder(parent, DOUBLE_BUFFER); MigLayout lm = new MigLayout("wrap", "[right][fill,sizegroup]unrel[right][fill,sizegroup]", ""); TabItem p = createTabPanel(tabbedPane, "Quick Start", lm); addSeparator(p, "General"); createLabel(p, "Company", "gap indent"); createTextField(p, "", "span,growx"); createLabel(p, "Contact", "gap indent"); createTextField(p, "", "span,growx"); addSeparator(p, "Propeller"); createLabel(p, "PTI/kW", "gap indent"); createTextField(p, "", "wmin 130"); createLabel(p, "Power/kW", "gap indent"); createTextField(p, "", "wmin 130"); createLabel(p, "R/mm", "gap indent"); createTextField(p, "", "wmin 130"); createLabel(p, "D/mm", "gap indent"); createTextField(p, "", "wmin 130"); return tabbedPane; } public Control createGrow_Shrink(Composite parent) { TabFolder tabbedPane = new TabFolder(parent, DOUBLE_BUFFER); // shrink tab MigLayout slm = new MigLayout("nogrid"); TabItem shrinkTabPanel = createTabPanel(tabbedPane, "Shrink", new FillLayout()); SashForm shrinkSash = new SashForm(getComposite(shrinkTabPanel), SWT.HORIZONTAL | SWT.SMOOTH); shrinkSash.setBackground(new Color(display, 255, 255, 255)); shrinkSash.setBackgroundMode(SWT.INHERIT_FORCE); Composite shrinkPanel = createPanel(shrinkSash, slm, SWT.BORDER); shrinkPanel.setLayoutData("wmin 100"); createTextField(shrinkPanel, "shp 110", "shp 110,w 10:130"); createTextField(shrinkPanel, "Default (100)", "w 10:130"); createTextField(shrinkPanel, "shp 90", "shp 90,w 10:130"); createTextField(shrinkPanel, "shrink 25", "newline,shrink 25,w 10:130"); createTextField(shrinkPanel, "shrink 75", "shrink 75,w 10:130"); createTextField(shrinkPanel, "Default", "newline, w 10:130"); createTextField(shrinkPanel, "Default", "w 10:130"); createTextField(shrinkPanel, "shrink 0", "newline,shrink 0,w 10:130"); createTextField(shrinkPanel, "shp 110", "newline,shp 110,w 10:130"); createTextField(shrinkPanel, "shp 100,shrink 25", "shp 100,shrink 25,w 10:130"); createTextField(shrinkPanel, "shp 100,shrink 75", "shp 100,shrink 75,w 10:130"); createTextArea(shrinkSash, "Use the slider to see how the components shrink depending on the constraints set on them.\n\n'shp' means Shrink Priority. " + "Lower values will be shrunk before higer ones and the default value is 100.\n\n'shrink' means Shrink Weight. " + "Lower values relative to other's means they will shrink less when space is scarse. " + "Shrink Weight is only relative to components with the same Shrink Priority. Default Shrink Weight is 100.\n\n" + "The component's minimum size will always be honored.\n\nFor SWT, which doesn't have a component notion of minimum, " + "preferred or maximum size, those sizes are set explicitly to minimum 10 and preferred 130 pixels.", ""); // Grow tab TabItem growTabPanel = createTabPanel(tabbedPane, "Grow", new FillLayout()); SashForm growSash = new SashForm(getComposite(growTabPanel), SWT.HORIZONTAL | SWT.SMOOTH); growSash.setBackground(new Color(display, 255, 255, 255)); growSash.setBackgroundMode(SWT.INHERIT_FORCE); Composite growPanel = createPanel(growSash, new MigLayout("nogrid", "[grow]"), SWT.BORDER); growPanel.setLayoutData("wmin 100"); createButton(growPanel, "gp 110, grow", "gp 110, grow, wmax 170"); createButton(growPanel, "Default (100), grow", "grow, wmax 170"); createButton(growPanel, "gp 90, grow", "gp 90, grow, wmax 170"); createButton(growPanel, "Default Button", "newline"); createButton(growPanel, "growx", "newline,growx,wrap"); createButton(growPanel, "gp 110, grow", "gp 110, grow, wmax 170"); createButton(growPanel, "gp 100, grow 25", "gp 100, grow 25, wmax 170"); createButton(growPanel, "gp 100, grow 75", "gp 100, grow 75, wmax 170"); createTextArea(growSash, "'gp' means Grow Priority. " + "Lower values will be grown before higher ones and the default value is 100.\n\n'grow' means Grow Weight. " + "Higher values relative to other's means they will grow more when space is up for takes. " + "Grow Weight is only relative to components with the same Grow Priority. Default Grow Weight is 0 which means " + "components will normally not grow. \n\nNote that the buttons in the first and last row have max width set to 170 to " + "emphasize Grow Priority.\n\nThe component's maximum size will always be honored.", ""); return tabbedPane; } // ********************************************************** // * Helper Methods // ********************************************************** // private final ToolTipListener toolTipListener = new ToolTipListener(); // private final ConstraintListener constraintListener = new ConstraintListener(); private Combo createCombo(Object parent, String[] texts, Object layout) { Combo b = new Combo(getComposite(parent), SWT.DROP_DOWN); for (int i = 0; i < texts.length; i++) b.add(texts[i]); b.setLayoutData(layout); // configureActiveComponet(b); return b; } private Label createLabel(Object parent, String text, Object layout) { return createLabel(parent, text, layout, SWT.LEFT); } private Label createLabel(Object parent, String text, Object layout, int style) { final Label b = new Label(getComposite(parent), style | DOUBLE_BUFFER); b.setText(text); b.setLayoutData(layout != null ? layout : text); // b.setAlignment(); // configureActiveComponet(b); return b; } private Text createTextField(Object parent, String text, Object layout) { final Text b = new Text(getComposite(parent), SWT.SINGLE | SWT.BORDER | DOUBLE_BUFFER); b.setText(text); b.setLayoutData(layout != null ? layout : text); // configureActiveComponet(b); return b; } private Button createButton(Object parent, String text, Object layout) { return createButton(getComposite(parent), text, layout, false); } private Button createButton(Object parent, String text, Object layout, boolean bold) { Button b = new Button(getComposite(parent), SWT.PUSH | SWT.NO_BACKGROUND | DOUBLE_BUFFER); b.setText(text.length() == 0 ? "\"\"" : text); b.setLayoutData(layout != null ? layout : text); // configureActiveComponet(b); return b; } private Composite createPanel(Object parent, String text, Object layout) { Color bg = new Color(display.getActiveShell().getDisplay(), 255, 255, 255); Composite panel = new Composite(getComposite(parent), DOUBLE_BUFFER | SWT.BORDER); panel.setLayout(new MigLayout("fill")); panel.setBackground(bg); panel.setLayoutData(layout != null ? layout : text); text = text.length() == 0 ? "\"\"" : text; Label label = createLabel(panel, text, "grow", SWT.NO_BACKGROUND | SWT.CENTER); label.setBackground(bg); // configureActiveComponet(panel); return panel; } private TabItem createTabPanel(TabFolder parent, String text, Layout lm) { Composite panel = new Composite(parent, DOUBLE_BUFFER); // panel.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_WHITE)); TabItem tab = new TabItem(parent, DOUBLE_BUFFER); tab.setControl(panel); tab.setText(text); if (lm != null) panel.setLayout(lm); // configureActiveComponet(panel); return tab; } private Composite createPanel(Object parent, Layout lm) { return createPanel(parent, lm, 0); } private Composite createPanel(Object parent, Layout lm, int style) { Composite panel = new Composite(getComposite(parent), DOUBLE_BUFFER | style); panel.setLayout(lm); return panel; } private Button createToggleButton(Object parent, String text, Object layout) { Button b = new Button(getComposite(parent), SWT.TOGGLE | DOUBLE_BUFFER); b.setText(text.length() == 0 ? "\"\"" : text); b.setLayoutData(layout != null ? layout : text); // configureActiveComponet(b); return b; } private Button createCheck(Object parent, String text, Object layout) { Button b = new Button(getComposite(parent), SWT.CHECK | DOUBLE_BUFFER); b.setText(text); b.setLayoutData(layout != null ? layout : text); // configureActiveComponet(b); return b; } private List createList(Object parent, String text, Object layout) { List list = new List(getComposite(parent), DOUBLE_BUFFER | SWT.BORDER); list.add(text); list.setLayoutData(layout); return list; } private StyledText createTextArea(Object parent, String text, String layout) { return createTextArea(parent, text, layout, SWT.MULTI | SWT.WRAP | SWT.BORDER | DOUBLE_BUFFER); } private StyledText createTextArea(Object parent, String text, String layout, int style) { StyledText ta = new StyledText(getComposite(parent), SWT.MULTI | SWT.WRAP | style | DOUBLE_BUFFER); ta.setText(text); // ta.setMargins(5, 5, 5, 5); ta.setLayoutData(layout != null ? layout : text); // configureActiveComponet(ta); return ta; } public Composite getComposite(Object c) { if (c instanceof Control) return (Composite) c; return (Composite) ((TabItem) c).getControl(); } private Font deriveFont(Control cont, int style, int height) { Font f = cont.getFont(); FontData fd = f.getFontData()[0]; if (style != SWT.DEFAULT) fd.setStyle(style); if (height != -1) fd.setHeight(height); Font font = new Font(display, fd); cont.setFont(font); return font; } // private Control configureActiveComponet(Control c) // { // c.addMouseMotionListener(toolTipListener); // c.addMouseListener(constraintListener); // return c; // } private void addSeparator(Object panel, String text) { Label l = createLabel(panel, text, "gaptop para, span, split 2"); l.setForeground(new Color(display, 0, 70, 213)); Label s = new Label(getComposite(panel), SWT.SEPARATOR | SWT.HORIZONTAL | DOUBLE_BUFFER); s.setLayoutData("gapleft rel, gaptop para, growx"); // configureActiveComponet(s); } // private class ConstraintListener extends MouseAdapter // { // public void mousePressed(MouseEvent e) // { // if (e.isPopupTrigger()) // react(e); // } // // public void mouseReleased(MouseEvent e) // { // if (e.isPopupTrigger()) // react(e); // } // // public void react(MouseEvent e) // { // Control c = (Control) e.getSource(); // LayoutManager lm = c.getParent().getLayout(); // if (lm instanceof SwtMigLayout == false) // lm = c.getLayout(); // // if (lm instanceof SwtMigLayout) { // MigLayout ffl = (MigLayout) lm; // boolean isComp = ffl.isManagingComponent(c); // String compConstr = isComp ? ffl.getComponentConstraints(c) : null; // String rowsConstr = isComp ? null : ffl.getRowConstraints(); // String colsConstr = isComp ? null : ffl.getColumnConstraints(); // String layoutConstr = isComp ? null : ffl.getLayoutConstraints(); // // ConstraintsDialog cDlg = new ConstraintsDialog(SwingDemo.this, layoutConstr, rowsConstr, colsConstr, compConstr); // cDlg.pack(); // cDlg.setLocationRelativeTo(c); // // if (cDlg.showDialog()) { // try { // if (isComp) { // String constrStr = cDlg.componentConstrTF.getText().trim(); // ffl.setComponentConstraints(c, constrStr); // if (c instanceof Button) { // c.setFont(BUTT_FONT); // ((Button) c).setText(constrStr.length() == 0 ? "" : constrStr); // } // } else { // ffl.setLayoutConstraints(cDlg.layoutConstrTF.getText()); // ffl.setRowConstraints(cDlg.rowsConstrTF.getText()); // ffl.setColumnConstraints(cDlg.colsConstrTF.getText()); // } // } catch(Exception ex) { // StringWriter sw = new StringWriter(); // ex.printStackTrace(new PrintWriter(sw)); // JOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(c), sw.toString(), "Error parsing Constraint!", JOptionPane.ERROR_MESSAGE); // return; // } // // c.invalidate(); // c.getParent().validate(); // } // } // } // } // // private static class ToolTipListener extends MouseMotionAdapter // { // public void mouseMoved(MouseEvent e) // { // Control c = (Control) e.getSource(); // LayoutManager lm = c.getParent().getLayout(); // if (lm instanceof SwtMigLayout) { // String constr = ((MigLayout) lm).getComponentConstraints(c); // c.setToolTipText((constr != null ? ("\"" + constr + "\"") : "null")); // } // } // } // // private static class ConstraintsDialog extends JDialog implements ActionListener, KeyEventDispatcher // { // private static final Color ERROR_COLOR = new Color(255, 180, 180); // private final JPanel mainPanel = new JPanel(parent, new SwtMigLayout("fillx,flowy,ins dialog", // "[fill]", // "2[]2")); // final Text layoutConstrTF; // final Text rowsConstrTF; // final Text colsConstrTF; // final Text componentConstrTF; // // private final Button okButt = new Button("OK"); // private final Button cancelButt = new Button("Cancel"); // // private boolean okPressed = false; // // public ConstraintsDialog(Frame owner, String layoutConstr, String rowsConstr, String colsConstr, String compConstr) // { // super(owner, (compConstr != null ? "Edit Component Constraints" : "Edit Container Constraints"), true); // // layoutConstrTF = createConstraintField(layoutConstr); // rowsConstrTF = createConstraintField(rowsConstr); // colsConstrTF = createConstraintField(colsConstr); // componentConstrTF = createConstraintField(compConstr); // // if (componentConstrTF != null) { // mainPanel.add(new Label("Component Constraints")); // mainPanel.add(componentConstrTF); // } // // if (layoutConstrTF != null) { // mainPanel.add(new Label("Container Layout Constraints")); // mainPanel.add(layoutConstrTF); // } // // if (rowsConstrTF != null) { // mainPanel.add(new Label("Container Row Constraints"), "gaptop unrel"); // mainPanel.add(rowsConstrTF); // } // // if (colsConstrTF != null) { // mainPanel.add(new Label("Container Column Constraints"), "gaptop unrel"); // mainPanel.add(colsConstrTF); // } // // mainPanel.add(okButt, "tag ok,split,flowx,gaptop 15"); // mainPanel.add(cancelButt, "tag cancel,gaptop 15"); // // setContentPane(mainPanel); // // okButt.addActionListener(this); // cancelButt.addActionListener(this); // } // // public void addNotify() // { // super.addNotify(); // KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(this); // } // // public void removeNotify() // { // KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(this); // super.removeNotify(); // } // // public boolean dispatchKeyEvent(KeyEvent e) // { // if (e.getKeyCode() == KeyEvent.VK_ESCAPE) // dispose(); // return false; // } // // public void actionPerformed(ActionEvent e) // { // if (e.getSource() == okButt) // okPressed = true; // dispose(); // } // // private Text createConstraintField(String text) // { // if (text == null) // return null; // // final Text tf = new Text(text, 50); // tf.setFont(new Font("monospaced", Font.PLAIN, 12)); // // tf.addKeyListener(new KeyAdapter() { // public void keyPressed(KeyEvent e) // { // if (e.getKeyCode() == KeyEvent.VK_ENTER) { // okButt.doClick(); // return; // } // // javax.swing.Timer timer = new Timer(50, new ActionListener() { // public void actionPerformed(ActionEvent e) // { // String constr = tf.getText(); // try { // if (tf == layoutConstrTF) { // MigLayout.validateLayoutConstraint(constr); // } else if (tf == rowsConstrTF) { // MigLayout.validateRowConstraints(constr); // } else if (tf == colsConstrTF) { // MigLayout.validateColumnConstraints(constr); // } else if (tf == componentConstrTF) { // MigLayout.validateComponentConstraint(constr); // } // tf.setBackground(Color.WHITE); // okButt.setEnabled(true); // } catch(Exception ex) { // tf.setBackground(ERROR_COLOR); // okButt.setEnabled(false); // } // } // }); // timer.setRepeats(false); // timer.start(); // } // }); // // return tf; // } // // private boolean showDialog() // { // setVisible(true); // return okPressed; // } // } } miglayout-5.1/demo/src/main/java/net/miginfocom/demo/SwtTest.java000077500000000000000000000050361324101563200250760ustar00rootroot00000000000000package net.miginfocom.demo; import net.miginfocom.swt.MigLayout; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Layout; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; public class SwtTest extends Composite { private Combo combo; private Control control; public SwtTest(Composite parent, int style, Layout layout) { super(parent, style); setLayout(layout); createControls(); } private void createControls() { Label label = new Label(this, SWT.None); label.setText("Select Control: "); combo = new Combo(this, SWT.READ_ONLY | SWT.DROP_DOWN); combo.setLayoutData("wrap"); combo.add("Text Box"); combo.add("Combo"); combo.add("Radio Button"); combo.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (control != null) control.dispose(); switch (combo.getSelectionIndex()) { case 0: control = new Text(SwtTest.this, SWT.BORDER); break; case 1: control = new Combo(SwtTest.this, SWT.DROP_DOWN); break; case 2: control = new Button(SwtTest.this, SWT.RADIO); break; } if (SwtTest.this.getLayout() instanceof GridLayout) { GridData data = new GridData(SWT.FILL, SWT.NONE, false, false); data.horizontalSpan = 2; control.setLayoutData(data); } else if (SwtTest.this.getLayout() instanceof MigLayout) { control.setLayoutData("spanx 2, grow"); } SwtTest.this.layout(true); } }); } public static void main(String[] args) { Display display = new Display(); Shell shell = new Shell(display); shell.setText("SWT"); shell.setLayout(new FillLayout()); /** * Swap out GridLayout for MigLayout to profile and see resources cleaned up. */ // GridLayout layout = new GridLayout(2, false); MigLayout layout = new MigLayout(); new SwtTest(shell, SWT.NONE, layout); shell.open(); // Set up the event loop. while (!shell.isDisposed()) { if (!display.readAndDispatch()) { // If no more entries in event queue display.sleep(); } } display.dispose(); } }miglayout-5.1/demo/src/main/java/net/miginfocom/demo/Test.java000077500000000000000000000011121324101563200243670ustar00rootroot00000000000000package net.miginfocom.demo; import net.miginfocom.swing.MigLayout; import javax.swing.*; import java.awt.Color; import java.awt.HeadlessException; import java.awt.Toolkit; public class Test extends JFrame { public Test() throws HeadlessException { System.out.println("res " + Toolkit.getDefaultToolkit().getScreenResolution()); JPanel panel = new JPanel(); panel.setBackground(Color.BLACK); setLayout(new MigLayout()); add(panel, "w 100mm"); pack(); setLocationRelativeTo(null); setVisible(true); } public static void main(String[] argv) { new Test(); } } miglayout-5.1/examples/000077500000000000000000000000001324101563200152045ustar00rootroot00000000000000miglayout-5.1/examples/pom.xml000077500000000000000000000020451324101563200165250ustar00rootroot00000000000000 4.0.0 com.miglayout miglayout-parent 5.1-SNAPSHOT ../pom.xml miglayout-examples jar MiGLayout Examples MiGLayout - Examples for Swing and SWT ${project.groupId} miglayout-swing ${project.version} ${project.groupId} miglayout-swt ${project.version} miglayout-5.1/examples/src/000077500000000000000000000000001324101563200157735ustar00rootroot00000000000000miglayout-5.1/examples/src/main/000077500000000000000000000000001324101563200167175ustar00rootroot00000000000000miglayout-5.1/examples/src/main/java/000077500000000000000000000000001324101563200176405ustar00rootroot00000000000000miglayout-5.1/examples/src/main/java/net/000077500000000000000000000000001324101563200204265ustar00rootroot00000000000000miglayout-5.1/examples/src/main/java/net/miginfocom/000077500000000000000000000000001324101563200225555ustar00rootroot00000000000000miglayout-5.1/examples/src/main/java/net/miginfocom/examples/000077500000000000000000000000001324101563200243735ustar00rootroot00000000000000miglayout-5.1/examples/src/main/java/net/miginfocom/examples/BugTestApp.java000077500000000000000000000100741324101563200272610ustar00rootroot00000000000000package net.miginfocom.examples; import javax.swing.*; import net.miginfocom.swing.MigLayout; import java.awt.Color; import java.awt.LayoutManager; /* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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 */ /** * @author Mikael Grev, MiG InfoCom AB * Date: Dec 15, 2008 * Time: 7:04:50 PM */ public class BugTestApp { private static JPanel createPanel() { JPanel c = new JPanel(); c.setBackground(new Color(200, 255, 200)); c.setLayout(new MigLayout("debug")); JLabel lab = new JLabel("Qwerty"); lab.setFont(lab.getFont().deriveFont(30f)); c.add(lab, "pos 0%+5 0%+5 50%-5 50%-5"); c.add(new JTextField("Qwerty")); JFrame f = new JFrame(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setLayout(new MigLayout()); f.add(c, "w 400, h 100"); f.setLocationRelativeTo(null); f.pack(); f.setVisible(true); return null; } private static JPanel createPanel2() { JFrame tst = new JFrame(); tst.setLayout(new MigLayout("debug, fillx","","")); tst.add(new JTextField(),"span 2, grow, wrap"); tst.add(new JTextField(10)); tst.add(new JLabel("End")); tst.setSize(600, 400); tst.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); tst.setVisible(true); return null; } public static void main2(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception ex) { ex.printStackTrace(); } createPanel(); // JFrame frame = new JFrame("Bug Test App"); // frame.getContentPane().add(createPanel2()); // frame.pack(); // frame.setLocationRelativeTo(null); // frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); // frame.setVisible(true); } }); } public static void main(String[] args) throws Exception { // createFrame(new GridLayout(1,1)); createFrame(new MigLayout()); } private static void createFrame(LayoutManager outerPanelLayout) { JPanel innerPanel = new JPanel(new MigLayout()); for (int i = 0; i < 2000; i++) innerPanel.add(new JLabel("label nr "+i), "wrap"); JPanel outerPanel = new JPanel(outerPanelLayout); outerPanel.add(innerPanel); JFrame f1 = new JFrame(outerPanelLayout.getClass().getSimpleName()); f1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f1.getContentPane().add(new JScrollPane(outerPanel)); f1.pack(); f1.setLocation((int)(Math.random() * 800.0), 0); f1.setVisible(true); } } miglayout-5.1/examples/src/main/java/net/miginfocom/examples/Example.java000077500000000000000000000060141324101563200266350ustar00rootroot00000000000000package net.miginfocom.examples; import net.miginfocom.swt.MigLayout; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableItem; /* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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 */ public class Example { protected void buildControls(Composite parent) { parent.setLayout(new MigLayout("inset 0", "[fill, grow]", "[fill, grow]")); Table table = new Table(parent, SWT.BORDER|SWT.H_SCROLL|SWT.V_SCROLL); table.setLayoutData("id table, hmin 100, wmin 300"); table.setHeaderVisible(true); table.setLinesVisible(true); Label statusLabel = new Label(parent, SWT.BORDER); statusLabel.setText("Label Text"); statusLabel.moveAbove(null); statusLabel.setLayoutData("pos table.x table.y"); for (int i = 0; i < 10; i++) { TableItem ti = new TableItem(table, SWT.NONE); ti.setText("item #" + i); } } public static void main(String[] args) { final Display display = new Display(); final Shell shell = new Shell(display); new Example().buildControls(shell); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } display.dispose(); } } miglayout-5.1/examples/src/main/java/net/miginfocom/examples/Example01.java000077500000000000000000000055231324101563200270020ustar00rootroot00000000000000package net.miginfocom.examples; import javax.swing.*; import net.miginfocom.swing.MigLayout; /* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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 */ /** */ public class Example01 { private static JPanel createPanel() { JPanel panel = new JPanel(new MigLayout()); panel.add(new JLabel("First Name")); panel.add(new JTextField(10)); panel.add(new JLabel("Surname"), "gap unrelated"); // Unrelated size is resolved per platform panel.add(new JTextField(10), "wrap"); // Wraps to the next row panel.add(new JLabel("Address")); panel.add(new JTextField(), "span, grow"); // Spans cells in row and grows to fit that return panel; } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception ex) { ex.printStackTrace(); } JFrame frame = new JFrame("Example 01"); frame.getContentPane().add(createPanel()); frame.pack(); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); frame.setVisible(true); } }); } } miglayout-5.1/examples/src/main/java/net/miginfocom/examples/Example02.java000077500000000000000000000061351324101563200270030ustar00rootroot00000000000000package net.miginfocom.examples; import javax.swing.*; import javax.swing.border.CompoundBorder; import javax.swing.border.EmptyBorder; import javax.swing.border.EtchedBorder; import net.miginfocom.swing.MigLayout; /* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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 */ public class Example02 { private static JPanel createPanel() { JPanel panel = new JPanel(new MigLayout()); panel.add(createLabel("West Panel"), "dock west"); panel.add(createLabel("North 1 Panel"), "dock north"); panel.add(createLabel("North 2 Panel"), "dock north"); panel.add(createLabel("South Panel"), "dock south"); panel.add(createLabel("East Panel"), "dock east"); panel.add(createLabel("Center Panel"), "grow, push"); // "dock center" from v3.0 return panel; } private static JLabel createLabel(String text) { JLabel label = new JLabel(text); label.setHorizontalAlignment(JLabel.CENTER); label.setBorder(new CompoundBorder(new EtchedBorder(), new EmptyBorder(5, 10, 5, 10))); return label; } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception ex) { ex.printStackTrace(); } JFrame frame = new JFrame("Example 02"); frame.getContentPane().add(createPanel()); frame.pack(); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); frame.setVisible(true); } }); } } miglayout-5.1/examples/src/main/java/net/miginfocom/examples/ExampleGood.java000077500000000000000000000060111324101563200274430ustar00rootroot00000000000000package net.miginfocom.examples; import net.miginfocom.swt.MigLayout; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableItem; /* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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 */ public class ExampleGood { protected void buildControls(Composite parent) { parent.setLayout(new MigLayout("inset 0", "[fill, grow]", "[fill, grow]")); Table table = new Table(parent, SWT.BORDER|SWT.H_SCROLL|SWT.V_SCROLL); table.setLayoutData("id table, hmin 100, wmin 300"); table.setHeaderVisible(true); table.setLinesVisible(true); Label statusLabel = new Label(parent, SWT.BORDER); statusLabel.setText("Label Text"); statusLabel.moveAbove(null); statusLabel.setLayoutData("pos 0 0"); for (int i = 0; i < 10; i++) { TableItem ti = new TableItem(table, SWT.NONE); ti.setText("item #" + i); } } public static void main(String[] args) { final Display display = new Display(); final Shell shell = new Shell(display); new ExampleGood().buildControls(shell); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } display.dispose(); } } miglayout-5.1/examples/src/main/java/net/miginfocom/examples/JavaOneShrink.java000077500000000000000000000075511324101563200277530ustar00rootroot00000000000000package net.miginfocom.examples; import javax.swing.*; import javax.swing.border.LineBorder; import net.miginfocom.swing.MigLayout; import java.awt.Color; import java.awt.Container; import java.awt.Dimension; import java.awt.Font; /* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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 */ /** * @author Mikael Grev, MiG InfoCom AB * Date: Apr 20, 2008 * Time: 10:32:58 PM */ public class JavaOneShrink { private static JComponent createPanel(String ... args) { JPanel panel = new JPanel(new MigLayout("nogrid")); panel.add(createTextArea(args[0].replace(", ", "\n ")), args[0] + ", w 200"); panel.add(createTextArea(args[1].replace(", ", "\n ")), args[1] + ", w 200"); panel.add(createTextArea(args[2].replace(", ", "\n ")), args[2] + ", w 200"); panel.add(createTextArea(args[3].replace(", ", "\n ")), args[3] + ", w 200"); JSplitPane gSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, panel, new JPanel()); gSplitPane.setOpaque(true); gSplitPane.setBorder(null); return gSplitPane; } private static JComponent createTextArea(String s) { JTextArea ta = new JTextArea("\n\n " + s, 6, 20); ta.setBorder(new LineBorder(new Color(200, 200, 200))); ta.setFont(new Font("Helvetica", Font.BOLD, 20)); ta.setMinimumSize(new Dimension(20, 20)); ta.setFocusable(false); return ta; } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception ex) { ex.printStackTrace(); } JFrame frame = new JFrame("JavaOne Shrink Demo"); Container cp = frame.getContentPane(); cp.setLayout(new MigLayout("wrap 1")); cp.add(createPanel("", "", "", "")); cp.add(createPanel("shrinkprio 1", "shrinkprio 1", "shrinkprio 2", "shrinkprio 3")); cp.add(createPanel("shrink 25", "shrink 50", "shrink 75", "shrink 100")); cp.add(createPanel("shrinkprio 1, shrink 50", "shrinkprio 1, shrink 100", "shrinkprio 2, shrink 50", "shrinkprio 2, shrink 100")); frame.pack(); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } } miglayout-5.1/examples/src/main/java/net/miginfocom/examples/MigLayoutBug.java000066400000000000000000000016711324101563200276130ustar00rootroot00000000000000package net.miginfocom.examples; import net.miginfocom.swing.MigLayout; import javax.swing.*; import java.awt.Color; /** * @author Mikael Grev, MiG InfoCom AB * Date: 14-06-03 * Time: 21:31 */ public class MigLayoutBug { public static void main(String[] args) { JFrame frame = new JFrame(); frame.setSize(500, 500); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLocationRelativeTo(null); JPanel mainPanel = new JPanel(new MigLayout("debug", "", "")); JPanel greyPanel = new JPanel(); greyPanel.setBackground(Color.GRAY); JTextArea label = new JTextArea("text \n" + "over \n" + "two \n" + "rows"); mainPanel.add(label, "spany 2"); mainPanel.add(new JLabel("First row"), "wrap"); mainPanel.add(new JLabel("Second row"), "wrap"); mainPanel.add(greyPanel, "spanx 2, pushy, grow"); frame.setContentPane(mainPanel); frame.setVisible(true); } } miglayout-5.1/examples/src/main/java/net/miginfocom/examples/SwtTest.java000077500000000000000000000071701324101563200266630ustar00rootroot00000000000000package net.miginfocom.examples; import net.miginfocom.swt.MigLayout; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; /* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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 */ public class SwtTest { public static void main(final String[] args) { final Display display = new Display(); final Shell shell = new Shell(display); shell.setLayout(new FillLayout(SWT.VERTICAL)); final Composite cmpLabels = new Composite(shell, SWT.BORDER); cmpLabels.setLayout(new MigLayout("wrap 5")); final Label l0 = new Label(cmpLabels, SWT.NONE); l0.setText("L 0"); final Label l1 = new Label(cmpLabels, SWT.NONE); final Label l2 = new Label(cmpLabels, SWT.NONE); l2.setText("L 2"); final Label l3 = new Label(cmpLabels, SWT.NONE); final Label l4 = new Label(cmpLabels, SWT.NONE); l4.setText("L 4"); final Composite cmpButtons = new Composite(shell, SWT.NONE); cmpButtons.setLayout(new FillLayout()); final Button btn1 = new Button(cmpButtons, SWT.PUSH); btn1.setText("Set 1"); btn1.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { l3.setText(""); l1.setText("Some Text"); cmpLabels.layout(); cmpLabels.redraw(); } }); final Button btn3 = new Button(cmpButtons, SWT.PUSH); btn3.setText("Set 3"); btn3.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { l1.setText(""); l3.setText("Some Text"); cmpLabels.layout(); cmpLabels.redraw(); } }); shell.setSize(300, 100); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } display.dispose(); } }miglayout-5.1/examples/src/main/java/net/miginfocom/examples/VisualPaddingOSX.java000077500000000000000000000134301324101563200303660ustar00rootroot00000000000000package net.miginfocom.examples; import javax.swing.*; import javax.swing.border.Border; import javax.swing.border.EmptyBorder; import javax.swing.border.LineBorder; import javax.swing.border.MatteBorder; import net.miginfocom.swing.MigLayout; import java.awt.Color; import java.awt.image.BufferedImage; public class VisualPaddingOSX extends JFrame { public VisualPaddingOSX() { super("MigLayout Test"); setDefaultCloseOperation(EXIT_ON_CLOSE); setLayout(new MigLayout("nogrid, debug")); String cc = ""; add(createButton(null), cc); add(createButton("square"), cc); add(createButton("gradient"), cc); add(createButton("bevel"), cc); add(createButton("textured"), cc); add(createButton("roundRect"), cc); add(createButton("recessed"), cc); add(createButton("help"), cc); add(createIconButton(null), cc + ", newline"); add(createIconButton("square"), cc); add(createIconButton("gradient"), cc); add(createIconButton("bevel"), cc); add(createIconButton("textured"), cc); add(createIconButton("roundRect"), cc); add(createIconButton("recessed"), cc); add(createIconButton("help"), cc); add(createToggleButton(null), cc + ", newline"); add(createToggleButton("square"), cc); add(createToggleButton("gradient"), cc); add(createToggleButton("bevel"), cc); add(createToggleButton("textured"), cc); add(createToggleButton("roundRect"), cc); add(createToggleButton("recessed"), cc); add(createToggleButton("help"), cc); add(createBorderButton("button", null), cc + ", newline"); add(createBorderButton("button", new LineBorder(Color.BLACK)), cc); add(createBorderButton("button", new MatteBorder(3, 3, 3, 3, Color.BLACK)), cc); add(createCombo("JComboBox.isPopDown", false), cc + ", newline"); add(createCombo("JComboBox.isSquare", false), cc); add(createCombo(null, false), ""); add(createCombo("JComboBox.isPopDown", true), cc + ", newline"); add(createCombo("JComboBox.isSquare", true), cc); add(createCombo(null, true), cc); JTextField ta = new JTextField("No Border"); ta.setBorder(new EmptyBorder(0, 0, 0, 0)); add(ta, cc + ", newline"); JTextField tfo = new JTextField("Opaque"); tfo.setOpaque(true); add(tfo, cc); add(new JTextArea("A text"), cc); add(new JTextField("A text"), cc); add(new JScrollPane(new JTextPane()), cc); add(new JScrollPane(new JTextArea("A text", 1, 20)), cc); JList list = new JList(new Object[] {"A text"}); list.setVisibleRowCount(1); add(new JScrollPane(list), cc); add(new JTextField("Compared to"), cc + ", newline"); add(new JSpinner(new SpinnerNumberModel(1, 1, 10000, 1)), cc); add(new JSpinner(new SpinnerDateModel()), cc); add(new JSpinner(new SpinnerListModel(new Object[]{"One", "Two", "Fifteen"})), cc); JSpinner spinner = new JSpinner(); spinner.setEditor(new JTextField()); add(spinner, cc); add(createToggle("toggle", null, true, new EmptyBorder(0, 0, 0, 0)), cc + ", newline"); add(createToggle("toggle", null, true, null), cc); add(createToggle("toggle", "regular", true, null), cc); add(createToggle("toggle", "small", true, null), cc); add(createToggle("toggle", "mini", true, null), cc); add(createToggle("toggle", null, false, new EmptyBorder(0, 0, 0, 0)), cc); add(createToggle("toggle", null, false, null), cc); add(createToggle("toggle", "regular", false, null), cc); add(createToggle("toggle", "small", false, null), cc); add(createToggle("toggle", "mini", false, null), cc); add(createTabbedPane(), cc + ", newline, growx"); pack(); setLocationRelativeTo(null); } private JToggleButton createToggle(String name, String size, boolean radio, Border border) { JToggleButton button = radio ? new JRadioButton(name) : new JCheckBox(name); if (size != null) button.putClientProperty("JComponent.sizeVariant", size); button.setFocusable(false); if (border != null) button.setBorder(border); return button; } private JButton createButton(String type) { String name = String.valueOf(type); if (name.equals("help")) name = ""; JButton button = new JButton(name); button.setDefaultCapable(false); button.setFocusable(false); if (type != null && type.equals("...") == false) button.putClientProperty("JButton.buttonType", type); return button; } private JButton createIconButton(String type) { String name = String.valueOf(type); if (name.equals("help")) name = ""; JButton button = new JButton(name); button.setIcon(new ImageIcon(new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB))); button.setDefaultCapable(false); button.setFocusable(false); if (type != null && type.equals("...") == false) button.putClientProperty("JButton.buttonType", type); return button; } private JToggleButton createToggleButton(String type) { String name = String.valueOf(type); if (name.equals("help")) name = ""; JToggleButton button = new JToggleButton(name); button.setFocusable(false); if (type != null) button.putClientProperty("JButton.buttonType", type); return button; } private JButton createBorderButton(String name, Border border) { JButton button = new JButton(name); button.setDefaultCapable(false); button.setFocusable(false); button.setBorder(border); return button; } private JComboBox createCombo(String key, boolean editable) { JComboBox comboBox = new JComboBox(new Object[]{ String.valueOf(key)}); comboBox.setFocusable(editable); comboBox.setEditable(editable); if (key != null) comboBox.putClientProperty(key, Boolean.TRUE); return comboBox; } private JTabbedPane createTabbedPane() { JTabbedPane tabbedPane = new JTabbedPane(); tabbedPane.addTab("tab1", new JLabel("tab1")); tabbedPane.addTab("tab2", new JLabel("tab2")); return tabbedPane; } public static void main(String args[]) { VisualPaddingOSX migTest = new VisualPaddingOSX(); migTest.setVisible(true); } }miglayout-5.1/ideutil/000077500000000000000000000000001324101563200150255ustar00rootroot00000000000000miglayout-5.1/ideutil/pom.xml000077500000000000000000000015351324101563200163510ustar00rootroot00000000000000 4.0.0 com.miglayout miglayout-parent 5.1-SNAPSHOT ../pom.xml miglayout-ideutil jar MiGLayout IDEUtil MiGLayout - IDEUtil class for EDI integration ${project.groupId} miglayout-core ${project.version} miglayout-5.1/ideutil/src/000077500000000000000000000000001324101563200156145ustar00rootroot00000000000000miglayout-5.1/ideutil/src/main/000077500000000000000000000000001324101563200165405ustar00rootroot00000000000000miglayout-5.1/ideutil/src/main/java/000077500000000000000000000000001324101563200174615ustar00rootroot00000000000000miglayout-5.1/ideutil/src/main/java/net/000077500000000000000000000000001324101563200202475ustar00rootroot00000000000000miglayout-5.1/ideutil/src/main/java/net/miginfocom/000077500000000000000000000000001324101563200223765ustar00rootroot00000000000000miglayout-5.1/ideutil/src/main/java/net/miginfocom/layout/000077500000000000000000000000001324101563200237135ustar00rootroot00000000000000miglayout-5.1/ideutil/src/main/java/net/miginfocom/layout/IDEUtil.java000077500000000000000000000717571324101563200260410ustar00rootroot00000000000000package net.miginfocom.layout; import java.util.HashMap; /* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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 */ /** This class contains static methods to be used by IDE vendors to convert to and from String/API constraints. *

* Note that {@link LayoutUtil#setDesignTime(ContainerWrapper, boolean)} should be set to true for this class' * methods to work. */ public class IDEUtil { /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}. */ public static final UnitValue ZERO = UnitValue.ZERO; /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}. */ public static final UnitValue TOP = UnitValue.TOP; /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}. */ public static final UnitValue LEADING = UnitValue.LEADING; /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}. */ public static final UnitValue LEFT = UnitValue.LEFT; /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}. */ public static final UnitValue CENTER = UnitValue.CENTER; /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}. */ public static final UnitValue TRAILING = UnitValue.TRAILING; /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}. */ public static final UnitValue RIGHT = UnitValue.RIGHT; /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}. */ public static final UnitValue BOTTOM = UnitValue.BOTTOM; /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}. */ public static final UnitValue LABEL = UnitValue.LABEL; /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}. */ public static final UnitValue INF = UnitValue.INF; /** A direct reference to the corresponding value for predefined UnitValues in {@link UnitValue}. */ public static final UnitValue BASELINE_IDENTITY = UnitValue.BASELINE_IDENTITY; private final static String[] X_Y_STRINGS = new String[] {"x", "y", "x2", "y2"}; /** Returns the version of IDEUtil * @return The version. */ public String getIDEUtilVersion() { return "1.0"; } /** Returns the grid cells that the components in parentContainer has. * @param parentContainer The parent container. It is an object since MigLayout is GUI toolkit * independent. * @return A new hashmap with the components mapped to an array [x, y, spanx, spany]. *

* Dock components will always have x and y less than -30000 or more than 30000. This is since they * are actually part of the grid, but on the outer edges. *

* Components that span the "rest of the row/column" have really large span values. Actually 30000-x or * 30000-y. *

* Generally, the grid does not need to have the upper left at 0, 0. Though it normally does if you * don't set the cells explicitly to other values. Rows and columns that are completely empty and * that does not have an explicit row/column constraint will be totally disregarded. */ public static HashMap getGridPositions(Object parentContainer) { return Grid.getGridPositions(parentContainer); } /** Returns the sizes of the rows and gaps for a container. * There will be two arrays returned [0] and [1]. *

* The first array will be the indexes of the rows where indexes that * are less than 30000 or larger than 30000 is docking rows. There might be extra docking rows that aren't * visible but they always have size 0. Non docking indexes will probably always be 0, 1, 2, 3, etc.. *

* The second array is the sizes of the form:
* [left inset][row size 1][gap 1][row size 2][gap 2][row size n][right inset]. *

* The returned sizes will be the ones calculated in the last layout cycle. * @param parentContainer The container to return the row sizes and gaps for. In Swing it will be a {@link java.awt.Container} and * in SWT it will be a {@link org.eclipse.swt.widgets.Composite}. * @return The sizes or null if {@link LayoutUtil#isDesignTime(ContainerWrapper)} is false or * parentContainer does not have a MigLayout layout manager. * The returned sizes will be the ones calculated in the last layout cycle. * @see LayoutUtil#isDesignTime(ContainerWrapper) */ public static int[][] getRowSizes(Object parentContainer) { return Grid.getSizesAndIndexes(parentContainer, true); } /** Returns the sizes of the columns and gaps for a container. * There will be two arrays returned [0] and [1]. *

* The first array will be the indexes of the columns where indexes that * are less than 30000 or larger than 30000 is docking columns. There might be extra docking columns that aren't * visible but they always have size 0. Non docking indexes will probably always be 0, 1, 2, 3, etc.. *

* The second array is the sizes of the form:
* [top inset][column size 1][gap 1][column size 2][gap 2][column size n][bottom inset]. *

* The returned sizes will be the ones calculated in the last layout cycle. * @param parentContainer The container to return the column sizes and gaps for. In Swing it will be a {@link java.awt.Container} and * in SWT it will be a {@link org.eclipse.swt.widgets.Composite}. * @return The sizes and indexes or null if {@link LayoutUtil#isDesignTime(ContainerWrapper)} is false or * parentContainer does not have a MigLayout layout manager. * The returned sizes will be the ones calculated in the last layout cycle. * @see LayoutUtil#isDesignTime(ContainerWrapper) */ public static int[][] getColumnSizes(Object parentContainer) { return Grid.getSizesAndIndexes(parentContainer, false); } /** Returns the a constraint string that can be re-parsed to be the exact same AxisConstraint. * @param ac The axis constraint to return as a constraint string. * @param asAPI If the returned string should be of API type (e.g. .flowX().gap("rel").align("right")) or * as a String type (e.g. "flowx, gap rel, right"). * @param isCols The the constraint should be returned for columns rather than rows. * @return A String. Never null. */ public static String getConstraintString(AC ac, boolean asAPI, boolean isCols) { StringBuffer sb = new StringBuffer(32); DimConstraint[] dims = ac.getConstaints(); BoundSize defGap = isCols ? PlatformDefaults.getGridGapX() : PlatformDefaults.getGridGapY(); for (int i = 0; i < dims.length; i++) { DimConstraint dc = dims[i]; addRowDimConstraintString(dc, sb, asAPI); if (i < dims.length - 1) { BoundSize gap = dc.getGapAfter(); if (gap == defGap || gap == null) gap = dims[i + 1].getGapBefore(); if (gap != null) { String gapStr = getBS(gap); if (asAPI) { sb.append(".gap(\"").append(gapStr).append("\")"); } else { sb.append(gapStr); } } else { if (asAPI) sb.append(".gap()"); } } } return sb.toString(); } /** Adds the a constraint string that can be re-parsed to be the exact same DimConstraint. * @param dc The layout constraint to return as a constraint string. * @param asAPI If the returned string should be of API type (e.g. .flowX().gap("rel").align("right")) or * as a String type (e.g. "flowx, gap rel, right"). */ private static void addRowDimConstraintString(DimConstraint dc, StringBuffer sb, boolean asAPI) { int gp = dc.getGrowPriority(); int firstComma = sb.length(); BoundSize size = dc.getSize(); if (size.isUnset() == false) { if (asAPI) { sb.append(".size(\"").append(getBS(size)).append("\")"); } else { sb.append(',').append(getBS(size)); } } if (gp != 100) { if (asAPI) { sb.append(".growPrio(").append(gp).append(")"); } else { sb.append(",growprio ").append(gp); } } Float gw = dc.getGrow(); if (gw != null) { String g = gw != 100f ? floatToString(gw, asAPI) : ""; if (asAPI) { if (g.length() == 0) { sb.append(".grow()"); } else { sb.append(".grow(").append(g).append(")"); } } else { sb.append(",grow").append(g.length() > 0 ? (" " + g) : ""); } } int sp = dc.getShrinkPriority(); if (sp != 100) { if (asAPI) { sb.append(".shrinkPrio(").append(sp).append(")"); } else { sb.append(",shrinkprio ").append(sp); } } Float sw = dc.getShrink(); if (sw != null && sw.intValue() != 100) { String s = floatToString(sw, asAPI); if (asAPI) { sb.append(".shrink(").append(s).append(")"); } else { sb.append(",shrink ").append(s); } } String eg = dc.getEndGroup(); if (eg != null) { if (asAPI) { sb.append(".endGroup(\"").append(eg).append("\")"); } else { sb.append(",endgroup ").append(eg); } } String sg = dc.getSizeGroup(); if (sg != null) { if (asAPI) { sb.append(".sizeGroup(\"").append(sg).append("\")"); } else { sb.append(",sizegroup ").append(sg); removeTrailingSpace(sb); } } UnitValue al = dc.getAlign(); if (al != null) { if (asAPI) { sb.append(".align(\"").append(getUV(al)).append("\")"); } else { String s = getUV(al); String alKw = (s.equals("top") || s.equals("bottom") || s.equals("left") || s.equals("label") || s.equals("leading") || s.equals("center") || s.equals("trailing") || s.equals("right") || s.equals("baseline")) ? "" : "align "; sb.append(',').append(alKw).append(s); } } if (dc.isNoGrid()) { if (asAPI) { sb.append(".noGrid()"); } else { sb.append(",nogrid"); } } if (dc.isFill()) { if (asAPI) { sb.append(".fill()"); } else { sb.append(",fill"); } } if (asAPI == false) { if (sb.length() > firstComma) { sb.setCharAt(firstComma, '['); sb.append(']'); } else { sb.append("[]"); } } } /** Returns the a constraint string that can be re-parsed to be the exact same DimConstraint. * @param dc The layout constraint to return as a constraint string. * @param asAPI If the returned string should be of API type (e.g. .flowX().gap("rel").align("right")) or * as a String type (e.g. "flowx, gap rel, right"). * @param isHor The the DimConstraint is decoration something horizontal (column or x). * @param noGrowAdd If true no grow constraints will be added. * @return A constraint string. Never null. */ private static void addComponentDimConstraintString(DimConstraint dc, StringBuffer sb, boolean asAPI, boolean isHor, boolean noGrowAdd) { int gp = dc.getGrowPriority(); if (gp != 100) { if (asAPI) { sb.append(isHor ? ".growPrioX(" : ".growPrioY(").append(gp).append(')'); } else { sb.append(isHor ? ",growpriox " : ",growprioy ").append(gp); } } if (noGrowAdd == false) { Float gw = dc.getGrow(); if (gw != null) { String g = gw != 100f ? floatToString(gw, asAPI) : ""; if (asAPI) { sb.append(isHor ? ".growX(" : ".growY(").append(g).append(')'); } else { sb.append(isHor ? ",growx" : ",growy").append(g.length() > 0 ? (" " + g) : ""); } } } int sp = dc.getShrinkPriority(); if (sp != 100) { if (asAPI) { sb.append(isHor ? ".shrinkPrioX(" : ".shrinkPrioY(").append(sp).append(')'); } else { sb.append(isHor ? ",shrinkpriox " : ",shrinkprioy ").append(sp); } } Float sw = dc.getShrink(); if (sw != null && sw.intValue() != 100) { String s = floatToString(sw, asAPI); if (asAPI) { sb.append(isHor ? ".shrinkX(" : ".shrinkY(").append(s).append(')'); } else { sb.append(isHor ? ",shrinkx " : ",shrinky ").append(s); } } String eg = dc.getEndGroup(); if (eg != null) { if (asAPI) { sb.append(isHor ? ".endGroupX(\"" : ".endGroupY(\"").append(eg).append("\")"); } else { sb.append(isHor ? ",endgroupx " : ",endgroupy ").append(eg); removeTrailingSpace(sb); } } String sg = dc.getSizeGroup(); if (sg != null) { if (asAPI) { sb.append(isHor ? ".sizeGroupX(\"" : ".sizeGroupY(\"").append(sg).append("\")"); } else { sb.append(isHor ? ",sizegroupx " : ",sizegroupy ").append(sg); removeTrailingSpace(sb); } } appendBoundSize(dc.getSize(), sb, isHor, asAPI); UnitValue al = dc.getAlign(); if (al != null) { if (asAPI) { sb.append(isHor ? ".alignX(\"" : ".alignY(\"").append(getUV(al)).append("\")"); } else { sb.append(isHor ? ",alignx " : ",aligny ").append(getUV(al)); } } BoundSize gapBef = dc.getGapBefore(); BoundSize gapAft= dc.getGapAfter(); if (gapBef != null || gapAft != null) { if (asAPI) { sb.append(isHor ? ".gapX(" : ".gapY(").append(getBS(gapBef, asAPI)).append(", ").append(getBS(gapAft, asAPI)).append(")"); } else { sb.append(isHor ? ",gapx " : ",gapy ").append(getBS(gapBef)); if (gapAft != null) sb.append(' ').append(getBS(gapAft)); } } } private static void appendBoundSize(BoundSize size, StringBuffer sb, boolean isHor, boolean asAPI) { if (size.isUnset() == false) { if (size.getPreferred() == null) { if (size.getMin() == null) { if (asAPI) { sb.append(isHor ? ".maxWidth(\"" : ".maxHeight(\"").append(getUV(size.getMax())).append("\")"); } else { sb.append(isHor ? ",wmax " : ",hmax ").append(getUV(size.getMax())); } } else if (size.getMax() == null) { if (asAPI) { sb.append(isHor ? ".minWidth(\"" : ".minHeight(\"").append(getUV(size.getMin())).append("\")"); } else { sb.append(isHor ? ",wmin " : ",hmin ").append(getUV(size.getMin())); } } else { // None are null if (asAPI) { sb.append(isHor ? ".width(\"" : ".height(\"").append(getUV(size.getMin())).append("::").append(getUV(size.getMax())).append("\")"); } else { sb.append(isHor ? ",width " : ",height ").append(getUV(size.getMin())).append("::").append(getUV(size.getMax())); } } } else { if (asAPI) { sb.append(isHor ? ".width(\"" : ".height(\"").append(getBS(size)).append("\")"); } else { sb.append(isHor ? ",width " : ",height ").append(getBS(size)); } } } } /** Returns the a constraint string that can be re-parsed to be the exact same LayoutConstraint. * @param cc The component constraint to return as a constraint string. * @param asAPI If the returned string should be of API type (e.g. .flowX().gap("rel").align("right")) or * as a String type (e.g. "flowx, gap rel, right"). * @return A String. Never null. */ public static String getConstraintString(CC cc, boolean asAPI) { StringBuffer sb = new StringBuffer(16); if (cc.isNewline()) { sb.append(asAPI ? ".newline(" : ",newline"); BoundSize newlineGapSize = cc.getNewlineGapSize(); if (newlineGapSize != null) sb.append(asAPI ? "" : " ").append(getBS(newlineGapSize, asAPI)); if (asAPI) sb.append(')'); } if (cc.isExternal()) sb.append(asAPI ? ".external()" : ",external"); Boolean flowX = cc.getFlowX(); if (flowX != null) { if (asAPI) { sb.append(flowX ? ".flowX()" : ".flowY()"); } else { sb.append(flowX ? ",flowx" : ",flowy"); } } UnitValue[] pad = cc.getPadding(); if (pad != null) { sb.append(asAPI ? ".pad(\"" : ",pad "); for (int i = 0; i < pad.length; i++) sb.append(getUV(pad[i])).append(i < pad.length - 1 ? " " : ""); if (asAPI) sb.append("\")"); } UnitValue[] pos = cc.getPos(); if (pos != null) { if (cc.isBoundsInGrid()) { for (int i = 0; i < 4; i++) { if (pos[i] != null) { if (asAPI) { sb.append('.').append(X_Y_STRINGS[i]).append("(\"").append(getUV(pos[i])).append("\")"); } else { sb.append(',').append(X_Y_STRINGS[i]).append(' ').append(getUV(pos[i])); } } } } else { sb.append(asAPI ? ".pos(" : ",pos "); int iSz = (pos[2] != null || pos[3] != null) ? 4 : 2; // "pos x y" vs "pos x1 y1 x2 y2". for (int i = 0; i < iSz; i++) sb.append(getUV(pos[i], asAPI)).append(i < iSz - 1 ? (asAPI ? ", " : " ") : ""); if (asAPI) sb.append(")"); } } String id = cc.getId(); if (id != null) { if (asAPI) { sb.append(".id(\"").append(id).append("\")"); } else { sb.append(",id ").append(id); } } String tag = cc.getTag(); if (tag != null) { if (asAPI) { sb.append(".tag(\"").append(tag).append("\")"); } else { sb.append(",tag ").append(tag); } } int hideMode = cc.getHideMode(); if (hideMode >= 0) { if (asAPI) { sb.append(".hideMode(").append(hideMode).append(')'); } else { sb.append(",hidemode ").append(hideMode); } } int skip = cc.getSkip(); if (skip > 0) { if (asAPI) { sb.append(".skip(").append(skip).append(')'); } else { sb.append(",skip ").append(skip); } } int split = cc.getSplit(); if (split > 1) { String s = split == LayoutUtil.INF ? "" : String.valueOf(split); if (asAPI) { sb.append(".split(").append(s).append(')'); } else { sb.append(",split ").append(s); removeTrailingSpace(sb); } } int cx = cc.getCellX(); int cy = cc.getCellY(); int spanX = cc.getSpanX(); int spanY = cc.getSpanY(); if (cx >= 0 && cy >= 0) { if (asAPI) { sb.append(".cell(").append(cx).append(", ").append(cy); if (spanX > 1 || spanY > 1) sb.append(", ").append(spanX).append(", ").append(spanY); sb.append(')'); } else { sb.append(",cell ").append(cx).append(' ').append(cy); if (spanX > 1 || spanY > 1) sb.append(' ').append(spanX).append(' ').append(spanY); } } else if (spanX > 1 || spanY > 1) { if (spanX > 1 && spanY > 1) { sb.append(asAPI ? ".span(" : ",span ").append(spanX).append(asAPI ? ", " : " ").append(spanY); } else if (spanX > 1) { sb.append(asAPI ? ".spanX(" : ",spanx ").append(spanX == LayoutUtil.INF ? "" : (String.valueOf(spanX))); } else if (spanY > 1) { sb.append(asAPI ? ".spanY(" : ",spany ").append(spanY == LayoutUtil.INF ? "" : (String.valueOf(spanY))); } if (asAPI) sb.append(')'); else removeTrailingSpace(sb); } Float pushX = cc.getPushX(); Float pushY = cc.getPushY(); if (pushX != null || pushY != null) { if (pushX != null && pushY != null) { sb.append(asAPI ? ".push(" : ",push "); if (pushX != 100.0 || pushY != 100.0) sb.append(floatObjectToString(pushX, asAPI)).append(asAPI ? ", " : " ").append(floatObjectToString(pushY, asAPI)); } else if (pushX != null) { sb.append(asAPI ? ".pushX(" : ",pushx ").append(pushX == 100 ? "" : (floatObjectToString(pushX, asAPI))); } else if (pushY != null) { sb.append(asAPI ? ".pushY(" : ",pushy ").append(pushY == 100 ? "" : (floatObjectToString(pushY, asAPI))); } if (asAPI) sb.append(')'); else removeTrailingSpace(sb); } int dock = cc.getDockSide(); if (dock >= 0) { String ds = CC.DOCK_SIDES[dock]; if (asAPI) { sb.append(".dock").append(Character.toUpperCase(ds.charAt(0))).append(ds.substring(1)).append("()"); } else { sb.append(",").append(ds); } } boolean noGrowAdd = cc.getHorizontal().getGrow() != null && cc.getHorizontal().getGrow().intValue() == 100 && cc.getVertical().getGrow() != null && cc.getVertical().getGrow().intValue() == 100; addComponentDimConstraintString(cc.getHorizontal(), sb, asAPI, true, noGrowAdd); addComponentDimConstraintString(cc.getVertical(), sb, asAPI, false, noGrowAdd); if (noGrowAdd) sb.append(asAPI ? ".grow()" : ",grow"); // Combine ".growX().growY()" into ".grow()". if (cc.isWrap()) { BoundSize wrap = cc.getWrapGapSize(); if (wrap != null) sb.append(asAPI ? ".wrap(\"" : ",wrap ").append(getBS(wrap)).append(asAPI ? "\")" : ""); else sb.append(asAPI ? ".wrap()" : ",wrap"); } String s = sb.toString(); return s.length() == 0 || s.charAt(0) != ',' ? s : s.substring(1); } /** Returns the a constraint string that can be re-parsed to be the exact same LayoutConstraint. * @param lc The layout constraint to return as a constraint string. * @param asAPI If the returned string should be of API type (e.g. .flowX().gap("rel").align("right")) or * as a String type (e.g. "flowx, gap rel, right"). * @return A String. Never null. */ public static String getConstraintString(LC lc, boolean asAPI) { StringBuffer sb = new StringBuffer(16); if (lc.isFlowX() == false) sb.append(asAPI ? ".flowY()" : ",flowy"); boolean fillX = lc.isFillX(); boolean fillY = lc.isFillY(); if (fillX || fillY) { if (fillX == fillY) { sb.append(asAPI ? ".fill()" : ",fill"); } else { sb.append(asAPI ? (fillX ? ".fillX()" : ".fillY()") : (fillX ? ",fillx" : ",filly")); } } Boolean leftToRight = lc.getLeftToRight(); if (leftToRight != null) { if (asAPI) { sb.append(".leftToRight(").append(leftToRight).append(')'); } else { sb.append(leftToRight ? ",ltr" : ",rtl"); } } if (!lc.getPackWidth().isUnset() || !lc.getPackHeight().isUnset()) { if (asAPI) { String w = getBS(lc.getPackWidth()); String h = getBS(lc.getPackHeight()); sb.append(".pack("); if (w.equals("pref") && h.equals("pref")) { sb.append(')'); } else { sb.append('\"').append(w).append("\", \"").append(h).append("\")"); } } else { sb.append(",pack"); String size = getBS(lc.getPackWidth()) + " " + getBS(lc.getPackHeight()); if (size.equals("pref pref") == false) sb.append(' ').append(size); } } if (lc.getPackWidthAlign() != 0.5f || lc.getPackHeightAlign() != 1f) { if (asAPI) { sb.append(".packAlign(").append(floatToString(lc.getPackWidthAlign(), asAPI)).append(", ").append(floatToString(lc.getPackHeightAlign(), asAPI)).append(')'); } else { sb.append(",packalign ").append(floatToString(lc.getPackWidthAlign(), asAPI)).append(' ').append(floatToString(lc.getPackHeightAlign(), asAPI)); } } if (lc.isTopToBottom() == false) sb.append(asAPI ? ".bottomToTop()" : ",btt"); UnitValue[] insets = lc.getInsets(); if (insets != null) { String cs = LayoutUtil.getCCString(insets); if (cs != null) { if (asAPI) { sb.append(".insets(\"").append(cs).append("\")"); } else { sb.append(",insets ").append(cs); } } else if (isDialogInsets(insets)) { sb.append(asAPI ? ".insets(\"dialog\")" : ",insets dialog"); } else if (isPanelInsets(insets)) { sb.append(asAPI ? ".insets(\"panel\")" : ",insets panel"); } else { sb.append(asAPI ? ".insets(\"" : ",insets "); for (int i = 0; i < insets.length; i++) sb.append(getUV(insets[i])).append(i < insets.length - 1 ? " " : ""); if (asAPI) sb.append("\")"); } } if (lc.isNoGrid()) sb.append(asAPI ? ".noGrid()" : ",nogrid"); if (lc.isVisualPadding() == false) sb.append(asAPI ? ".noVisualPadding()" : ",novisualpadding"); int hideMode = lc.getHideMode(); if (hideMode > 0) { if (asAPI) { sb.append(".hideMode(").append(hideMode).append(')'); } else { sb.append(",hidemode ").append(hideMode); } } appendBoundSize(lc.getWidth(), sb, true, asAPI); appendBoundSize(lc.getHeight(), sb, false, asAPI); UnitValue alignX = lc.getAlignX(); UnitValue alignY = lc.getAlignY(); if (alignX != null || alignY != null) { if (alignX != null && alignY != null) { sb.append(asAPI ? ".align(\"" : ",align ").append(getUV(alignX)).append(asAPI ? "\", \"" : " ").append(getUV(alignY)); } else if (alignX != null) { sb.append(asAPI ? ".alignX(\"" : ",alignx ").append(getUV(alignX)); } else if (alignY != null) { sb.append(asAPI ? ".alignY(\"" : ",aligny ").append(getUV(alignY)); } if (asAPI) sb.append("\")"); } BoundSize gridGapX = lc.getGridGapX(); BoundSize gridGapY = lc.getGridGapY(); if (gridGapX != null || gridGapY != null) { if (gridGapX != null && gridGapY != null) { sb.append(asAPI ? ".gridGap(\"" : ",gap ").append(getBS(gridGapX)).append(asAPI ? "\", \"" : " ").append(getBS(gridGapY)); } else if (gridGapX != null) { sb.append(asAPI ? ".gridGapX(\"" : ",gapx ").append(getBS(gridGapX)); } else if (gridGapY != null) { sb.append(asAPI ? ".gridGapY(\"" : ",gapy ").append(getBS(gridGapY)); } if (asAPI) sb.append("\")"); } int wrapAfter = lc.getWrapAfter(); if (wrapAfter != LayoutUtil.INF) { String ws = wrapAfter > 0 ? String.valueOf(wrapAfter) : ""; if (asAPI) { if (ws.isEmpty()) sb.append(".wrap()"); else sb.append(".wrapAfter(").append(ws).append(')'); } else { sb.append(",wrap ").append(ws); removeTrailingSpace(sb); } } int debugMillis = lc.getDebugMillis(); if (debugMillis > 0) { if (asAPI) { sb.append(".debug(").append(debugMillis).append(')'); } else { sb.append(",debug ").append(debugMillis); } } if (lc.isNoCache()) sb.append(asAPI ? ".noCache()" : ",nocache"); String s = sb.toString(); return s.length() == 0 || s.charAt(0) != ',' ? s : s.substring(1); } private static String getUV(UnitValue uv) { return uv != null ? uv.getConstraintString() : "null"; } private static String getUV(UnitValue uv, boolean asAPI) { return uv != null ? (asAPI ? ('"' + uv.getConstraintString() + '"') : uv.getConstraintString()) : "null"; } private static String getBS(BoundSize bs) { return bs != null ? bs.getConstraintString() : "null"; } private static String getBS(BoundSize bs, boolean asAPI) { return bs != null ? (asAPI ? ('"' + bs.getConstraintString() + '"') : bs.getConstraintString()) : "null"; } private static boolean isDialogInsets(UnitValue[] insets) { for (int i = 0; i < 4; i++) { if (PlatformDefaults.getDialogInsets(i) != insets[i]) return false; } return true; } private static boolean isPanelInsets(UnitValue[] insets) { for (int i = 0; i < 4; i++) { if (PlatformDefaults.getPanelInsets(i) != insets[i]) return false; } return true; } /** Converts a float to a string and is removing the ".0" if the float is an integer. * @param f the float. * @return f as a string. Never null. */ private static String floatToString(float f, boolean asAPI) { String valS = String.valueOf(f); return valS.endsWith(".0") ? valS.substring(0, valS.length() - 2) : (valS + (asAPI ? "f" : "")); } private static String floatObjectToString(float f, boolean asAPI) { String valS = floatToString(f, asAPI); // trailing 'f' is required if Java method parameter is of type java.lang.Float if (asAPI && !valS.endsWith("f")) valS = valS.concat("f"); return valS; } private static void removeTrailingSpace(StringBuffer sb) { int length = sb.length(); if (length > 0 && sb.charAt(length - 1) == ' ') sb.setLength(length - 1); } } miglayout-5.1/ideutil/src/test/000077500000000000000000000000001324101563200165735ustar00rootroot00000000000000miglayout-5.1/ideutil/src/test/java/000077500000000000000000000000001324101563200175145ustar00rootroot00000000000000miglayout-5.1/ideutil/src/test/java/net/000077500000000000000000000000001324101563200203025ustar00rootroot00000000000000miglayout-5.1/ideutil/src/test/java/net/miginfocom/000077500000000000000000000000001324101563200224315ustar00rootroot00000000000000miglayout-5.1/ideutil/src/test/java/net/miginfocom/layout/000077500000000000000000000000001324101563200237465ustar00rootroot00000000000000miglayout-5.1/ideutil/src/test/java/net/miginfocom/layout/IDEUtilTest.java000066400000000000000000000471231324101563200267170ustar00rootroot00000000000000/* * License (BSD): * ============== * * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com) * 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. */ package net.miginfocom.layout; import static org.junit.Assert.*; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ErrorCollector; /** * Unit tests for {@link IDEUtil}. * * @author Karl Tauber */ public class IDEUtilTest { @Rule public ErrorCollector errorCollector = new ErrorCollector(); @BeforeClass public static void initialize() { // MigLayout: enable design time for LayoutUtil.putCCString() LayoutUtil.setDesignTime( null, true ); } @Test public void testMigLayoutConstraints() { // wrap testLC( "wrap", null, new LC().wrap(), ".wrap()" ); testLC( "wrap 4", null, new LC().wrapAfter(4), ".wrapAfter(4)" ); // gap testLC( "gap 5px", "gap 5px 5px", new LC().gridGap("5px", "5px"), ".gridGap(\"5px\", \"5px\")" ); testLC( "gap 5px 10px", null, new LC().gridGap("5px", "10px"), ".gridGap(\"5px\", \"10px\")" ); testLC( "gap null 10px", "gapy 10px", new LC().gridGap(null, "10px"), ".gridGapY(\"10px\")" ); testLC( "gapx 10::50", null, new LC().gridGapX("10::50"), ".gridGapX(\"10::50\")" ); testLC( "gapy 0:rel:null", null, new LC().gridGapY("0:rel:null"), ".gridGapY(\"0:rel:null\")" ); // debug testLC( "debug", "debug 1000", new LC().debug(1000), ".debug(1000)" ); testLC( "debug 300", null, new LC().debug(), ".debug(300)" ); testLC( "debug 4000", null, new LC().debug(4000), ".debug(4000)" ); // nogrid testLC( "nogrid", null, new LC().noGrid(), ".noGrid()" ); // novisualpadding testLC( "novisualpadding", null, new LC().noVisualPadding(), ".noVisualPadding()" ); // fill testLC( "fill", null, new LC().fill(), ".fill()" ); testLC( "fillx", null, new LC().fillX(), ".fillX()" ); testLC( "filly", null, new LC().fillY(), ".fillY()" ); // insets testLC( "insets panel", null, new LC().insets("panel"), ".insets(\"panel\")" ); testLC( "insets dialog", null, new LC().insets("dialog"), ".insets(\"dialog\")" ); testLC( "insets", "insets dialog", new LC().insets(""), ".insets(\"dialog\")" ); testLC( "insets 0", "insets 0 0 0 0", new LC().insetsAll( "0" ), ".insets(\"0 0 0 0\")" ); testLC( "insets 0 1", "insets 0 1 1 1", new LC().insets( "0 1" ), ".insets(\"0 1 1 1\")" ); testLC( "insets 0 1 2", "insets 0 1 2 2", new LC().insets( "0 1 2" ), ".insets(\"0 1 2 2\")" ); testLC( "insets 0 1 2 3", null, new LC().insets("0 1 2 3"), ".insets(\"0 1 2 3\")" ); testLC( "insets 0 1 2 3", null, new LC().insets("0", "1", "2", "3"), ".insets(\"0 1 2 3\")" ); testLC( "insets 0 null 2 3", null, new LC().insets("0", null, "2", "3"), ".insets(\"0 null 2 3\")" ); // flowy testLC( "flowy", null, new LC().flowY(), ".flowY()" ); // align testLC( "align left", "alignx left", new LC().alignX("left"), ".alignX(\"left\")" ); testLC( "align null top", "aligny top", new LC().alignY("top"), ".alignY(\"top\")" ); testLC( "align left top", null, new LC().align("left", "top"), ".align(\"left\", \"top\")" ); testLC( "alignx left", null, new LC().alignX("left"), ".alignX(\"left\")" ); testLC( "aligny top", null, new LC().alignY("top"), ".alignY(\"top\")" ); // lefttoright, righttoleft testLC( "ltr", null, new LC().leftToRight(true), ".leftToRight(true)" ); testLC( "rtl", null, new LC().rightToLeft(), ".leftToRight(false)" ); // toptobottom, bottomtotop testLC( "ttb", "", new LC().topToBottom(), "" ); testLC( "btt", null, new LC().bottomToTop(), ".bottomToTop()" ); // hidemode testLC( "hidemode 1", null, new LC().hideMode(1), ".hideMode(1)" ); // nocache testLC( "nocache", null, new LC().noCache(), ".noCache()" ); } @Test public void testMigColumnRowConstraints() { // gaps testAC( "[]", null, new AC(), "" ); testAC( "[][]", null, new AC().gap(), ".gap()" ); testAC( "[][][]", null, new AC().gap().gap(), ".gap().gap()" ); testAC( "[]10[]", null, new AC().gap("10"), ".gap(\"10\")" ); testAC( "[]para[]unrel[]", null, new AC().gap("para").gap("unrel"), ".gap(\"para\").gap(\"unrel\")" ); // complex samples from white paper testAC( false, "[fill]10[10:20,top]", null, new AC().fill().gap("10").size("10:20").align("top"), ".fill().gap(\"10\").size(\"10:20\").align(\"top\")" ); testAC( "[fill]push[]", null, new AC().fill().gap("push"), ".fill().gap(\"push\")" ); testAC( false, "[fill]10:10:100:push[10:20,top]", null, new AC().fill().gap("10:10:100:push").size("10:20").align("top"), ".fill().gap(\"10:10:100:push\").size(\"10:20\").align(\"top\")" ); // size testAC( "[100]", null, new AC().size("100"), ".size(\"100\")"); testAC( "[100][200]", null, new AC().size("100").gap().size("200"), ".size(\"100\").gap().size(\"200\")"); testAC( "[pref]", null, new AC().size("pref"), ".size(\"pref\")" ); testAC( "[pref,fill]", null, new AC().size("pref").fill(), ".size(\"pref\").fill()" ); // sizegroup testAC( "[sizegroup]", null, new AC().sizeGroup(), ".sizeGroup(\"\")" ); testAC( "[sizegroup grp1]", null, new AC().sizeGroup("grp1"), ".sizeGroup(\"grp1\")" ); // fill testAC( "[fill]", null, new AC().fill(), ".fill()" ); // nogrid testAC( "[nogrid]", null, new AC().noGrid(), ".noGrid()" ); // grow testAC( "[grow]", null, new AC().grow(), ".grow()" ); testAC( "[grow 50]", null, new AC().grow(50), ".grow(50)" ); // growprio testAC( "[growprio 50]", null, new AC().growPrio(50), ".growPrio(50)" ); // shrink testAC( "[shrink 50]", null, new AC().shrink(50), ".shrink(50)" ); // shrinkprio testAC( "[shrinkprio 50]", null, new AC().shrinkPrio(50), ".shrinkPrio(50)" ); // align testAC( "[align 50%]", null, null, null ); // no API because AC().align() does not support UnitValues testAC( "[align 100px]", null, null, null ); // no API because AC().align() does not support UnitValues testAC( true, "[align left]", "[left]", new AC().align("left"), ".align(\"left\")" ); testAC( false, "[align top]", "[top]", new AC().align("top"), ".align(\"top\")" ); } @Test public void testMigComponentConstraints() { // wrap testCC( "wrap", null, new CC().wrap(), ".wrap()" ); testCC( "wrap 15px", null, new CC().wrap("15px"), ".wrap(\"15px\")" ); testCC( "wrap push", null, new CC().wrap("push"), ".wrap(\"push\")" ); testCC( "wrap 15:push", null, new CC().wrap("15:push"), ".wrap(\"15:push\")" ); // newline testCC( "newline", null, new CC().newline(), ".newline()" ); testCC( "newline 15px", null, new CC().newline("15px"), ".newline(\"15px\")" ); // push testCC( "push", null, new CC().push(), ".push()" ); testCC( "push 200", "push 200 100", new CC().push(200f, 100f), ".push(200f, 100f)" ); testCC( "push 200 300", null, new CC().push(200f, 300f), ".push(200f, 300f)" ); testCC( "pushx", null, new CC().pushX(), ".pushX()" ); testCC( "pushx 200", null, new CC().pushX(200f), ".pushX(200f)" ); testCC( "pushy", null, new CC().pushY(), ".pushY()" ); testCC( "pushy 200", null, new CC().pushY(200f), ".pushY(200f)" ); // skip testCC( "skip", "skip 1", new CC().skip(), ".skip(1)" ); testCC( "skip 3", null, new CC().skip(3), ".skip(3)" ); // span testCC( "span", "spanx", new CC().span(), ".spanX()" ); testCC( "span 4", "spanx 4", new CC().span(4), ".spanX(4)" ); testCC( "span 2 3", null, new CC().span(2, 3), ".span(2, 3)" ); testCC( "spanx", null, new CC().spanX(), ".spanX()" ); testCC( "spanx 10", null, new CC().spanX(10), ".spanX(10)" ); testCC( "spany", null, new CC().spanY(), ".spanY()" ); testCC( "spany 2", null, new CC().spanY(2), ".spanY(2)" ); // split testCC( "split", null, new CC().split(), ".split()" ); testCC( "split 4", null, new CC().split(4), ".split(4)" ); // cell testCC( "cell 2 2", null, new CC().cell(2, 2), ".cell(2, 2)" ); testCC( "cell 0 1 2", "cell 0 1 2 1", new CC().cell(0, 1, 2), ".cell(0, 1, 2, 1)" ); testCC( "cell 0 1 2 3", null, new CC().cell(0, 1, 2, 3), ".cell(0, 1, 2, 3)" ); // flowx, flowy testCC( "flowx", null, new CC().flowX(), ".flowX()" ); testCC( "flowy", null, new CC().flowY(), ".flowY()" ); // width, height testCC( "width 10", null, new CC().width("10"), ".width(\"10\")" ); testCC( "height pref!", null, new CC().height("pref!"), ".height(\"pref!\")" ); // wmin, wmax, hmin, hmax testCC( "wmin 10", null, new CC().minWidth("10"), ".minWidth(\"10\")" ); testCC( "wmax 10", null, new CC().maxWidth("10"), ".maxWidth(\"10\")" ); testCC( "hmin 10", null, new CC().minHeight("10"), ".minHeight(\"10\")" ); testCC( "hmax 10", null, new CC().maxHeight("10"), ".maxHeight(\"10\")" ); // grow testCC( "grow", null, new CC().grow(), ".grow()" ); testCC( "grow 100", "grow", new CC().grow(100, 100), ".grow()" ); testCC( "grow 50", "growx 50,growy", new CC().grow(50, 100), ".growX(50).growY()" ); testCC( "grow 50 20", "growx 50,growy 20", new CC().grow(50, 20), ".growX(50).growY(20)" ); testCC( "grow 50 50", "growx 50,growy 50", new CC().grow(50, 50), ".growX(50).growY(50)" ); testCC( "grow 100 20", "growx,growy 20", new CC().grow(100, 20), ".growX().growY(20)" ); testCC( "grow 50 100", "growx 50,growy", new CC().grow(50, 100), ".growX(50).growY()" ); testCC( "growx", null, new CC().growX(), ".growX()" ); testCC( "growx 50", null, new CC().growX(50), ".growX(50)" ); testCC( "growy", null, new CC().growY(), ".growY()" ); testCC( "growy 0", null, new CC().growY(0), ".growY(0)" ); // growprio testCC( "growprio 50", "growpriox 50", new CC().growPrio(50), ".growPrioX(50)" ); testCC( "growprio 50 80", "growpriox 50,growprioy 80", new CC().growPrio(50, 80), ".growPrioX(50).growPrioY(80)" ); testCC( "growpriox 50", null, new CC().growPrioX(50), ".growPrioX(50)" ); testCC( "growprioy 80", null, new CC().growPrioY(80), ".growPrioY(80)" ); // shrink testCC( "shrink 50", "shrinkx 50", new CC().shrink(50, 100), ".shrinkX(50)" ); testCC( "shrink 50 20", "shrinkx 50,shrinky 20", new CC().shrink(50, 20), ".shrinkX(50).shrinkY(20)" ); testCC( "shrink 100 20", "shrinky 20", new CC().shrink(100, 20), ".shrinkY(20)" ); testCC( "shrinkx 50", null, new CC().shrinkX(50), ".shrinkX(50)" ); testCC( "shrinky 20", null, new CC().shrinkY(20), ".shrinkY(20)" ); // shrinkprio testCC( "shrinkprio 50", "shrinkpriox 50", new CC().shrinkPrio(50), ".shrinkPrioX(50)" ); testCC( "shrinkprio 50 80", "shrinkpriox 50,shrinkprioy 80", new CC().shrinkPrio(50, 80), ".shrinkPrioX(50).shrinkPrioY(80)" ); testCC( "shrinkpriox 50", null, new CC().shrinkPrioX(50), ".shrinkPrioX(50)" ); testCC( "shrinkprioy 80", null, new CC().shrinkPrioY(80), ".shrinkPrioY(80)" ); // sizegroup testCC( "sizegroup", "sizegroupx,sizegroupy", new CC().sizeGroup("", ""), ".sizeGroupX(\"\").sizeGroupY(\"\")" ); testCC( "sizegroup g1", "sizegroupx g1,sizegroupy g1", new CC().sizeGroup("g1", "g1"), ".sizeGroupX(\"g1\").sizeGroupY(\"g1\")" ); testCC( "sizegroupx", null, new CC().sizeGroupX(""), ".sizeGroupX(\"\")" ); testCC( "sizegroupx g1", null, new CC().sizeGroupX("g1"), ".sizeGroupX(\"g1\")" ); testCC( "sizegroupy", null, new CC().sizeGroupY(""), ".sizeGroupY(\"\")" ); testCC( "sizegroupy g1", null, new CC().sizeGroupY("g1"), ".sizeGroupY(\"g1\")" ); // endgroup testCC( "endgroupx", null, new CC().endGroupX(""), ".endGroupX(\"\")" ); testCC( "endgroupx g1", null, new CC().endGroupX("g1"), ".endGroupX(\"g1\")" ); testCC( "endgroupy", null, new CC().endGroupY(""), ".endGroupY(\"\")" ); testCC( "endgroupy g1", null, new CC().endGroupY("g1"), ".endGroupY(\"g1\")" ); // gap, gaptop, gapleft, gapbottom, gapright, gapbefore, gapafter testCC( "gap 5", "gapx 5", new CC().gap("5"), ".gapX(\"5\", null)" ); testCC( "gap 5 6", "gapx 5 6", new CC().gap("5", "6"), ".gapX(\"5\", \"6\")" ); testCC( "gap 5 6 7", "gapx 5 6,gapy 7", new CC().gap("5", "6", "7"), ".gapX(\"5\", \"6\").gapY(\"7\", null)" ); testCC( "gap 5 6 7 8", "gapx 5 6,gapy 7 8", new CC().gap("5", "6", "7", "8"), ".gapX(\"5\", \"6\").gapY(\"7\", \"8\")" ); testCC( "gaptop 5", "gapy 5", new CC().gapTop("5"), ".gapY(\"5\", null)" ); testCC( "gapleft 5", "gapx 5", new CC().gapLeft("5"), ".gapX(\"5\", null)" ); testCC( "gapbottom 5", "gapy null 5", new CC().gapBottom("5"), ".gapY(null, \"5\")" ); testCC( "gapright 5", "gapx null 5", new CC().gapRight("5"), ".gapX(null, \"5\")" ); testCC( "gapbefore 5", "gapx 5", new CC().gapBefore("5"), ".gapX(\"5\", null)" ); testCC( "gapafter 5", "gapx null 5", new CC().gapAfter("5"), ".gapX(null, \"5\")" ); // gapx, gapy testCC( "gapx 5", null, new CC().gapX("5", null), ".gapX(\"5\", null)" ); testCC( "gapx 5 10", null, new CC().gapX("5", "10"), ".gapX(\"5\", \"10\")" ); testCC( "gapy unrel", null, new CC().gapY("unrel", null), ".gapY(\"unrel\", null)" ); testCC( "gapy unrel rel", null, new CC().gapY("unrel", "rel"), ".gapY(\"unrel\", \"rel\")" ); // id testCC( "id button1", null, new CC().id("button1"), ".id(\"button1\")" ); // pos testCC( "pos 50% 80%", null, new CC().pos("50%", "80%"), ".pos(\"50%\", \"80%\")" ); testCC( "pos 50% 80%", null, new CC().pos("50%", "80%"), ".pos(\"50%\", \"80%\")" ); testCC( "pos 50% 80% 200 100", null, new CC().pos("50%", "80%", "200", "100"), ".pos(\"50%\", \"80%\", \"200\", \"100\")" ); testCC( "pos null null 200 100", null, new CC().pos(null, null, "200", "100"), ".pos(null, null, \"200\", \"100\")" ); testCC( "pos (b1.x+b1.w/2) (b1.y2+rel)", null, new CC().pos("(b1.x+b1.w/2)", "(b1.y2+rel)"), ".pos(\"(b1.x+b1.w/2)\", \"(b1.y2+rel)\")" ); testCC( "pos (visual.x2 - pref) 200", null, new CC().pos("(visual.x2 - pref)", "200"), ".pos(\"(visual.x2 - pref)\", \"200\")" ); testCC( "pos null b1.y b1.x-rel b1.y2", null, new CC().pos(null, "b1.y", "b1.x-rel", "b1.y2"), ".pos(null, \"b1.y\", \"b1.x-rel\", \"b1.y2\")" ); // x, x2, y, y2 testCC( "x 10", null, new CC().x("10"), ".x(\"10\")" ); testCC( "x button1.x", null, new CC().x("button1.x"), ".x(\"button1.x\")" ); testCC( "x2 (visual.x2-50)", null, new CC().x2("(visual.x2-50)"), ".x2(\"(visual.x2-50)\")" ); testCC( "y 10", null, new CC().y("10"), ".y(\"10\")" ); testCC( "y2 10", null, new CC().y2("10"), ".y2(\"10\")" ); // dock testCC( "dock north", "north", new CC().dockNorth(), ".dockNorth()" ); testCC( "dock west", "west", new CC().dockWest(), ".dockWest()" ); testCC( "dock south", "south", new CC().dockSouth(), ".dockSouth()" ); testCC( "dock east", "east", new CC().dockEast(), ".dockEast()" ); testCC( "dock center", "push,grow", new CC().push().grow(), ".push().grow()" ); testCC( "north", null, new CC().dockNorth(), ".dockNorth()" ); testCC( "west", null, new CC().dockWest(), ".dockWest()" ); testCC( "south", null, new CC().dockSouth(), ".dockSouth()" ); testCC( "east", null, new CC().dockEast(), ".dockEast()" ); // pad testCC( "pad 5", "pad 5 5 5 5", new CC().pad("5"), ".pad(\"5 5 5 5\")" ); testCC( "pad 5 6", "pad 5 6 6 6", new CC().pad("5 6"), ".pad(\"5 6 6 6\")" ); testCC( "pad 5 6 7", "pad 5 6 7 7", new CC().pad("5 6 7"), ".pad(\"5 6 7 7\")" ); testCC( "pad 5 6 7 8", null, new CC().pad("5 6 7 8"), ".pad(\"5 6 7 8\")" ); testCC( "pad 5.0px 6.0px 7.0px 8.0px", null, new CC().pad(5, 6, 7, 8), ".pad(\"5.0px 6.0px 7.0px 8.0px\")" ); // align testCC( "align left", "alignx left", new CC().alignX("left"), ".alignX(\"left\")" ); testCC( "align left top", "alignx left,aligny top", new CC().alignX("left").alignY("top"), ".alignX(\"left\").alignY(\"top\")" ); testCC( "align null top", "aligny top", new CC().alignY("top"), ".alignY(\"top\")" ); testCC( "alignx left", null, new CC().alignX("left"), ".alignX(\"left\")" ); testCC( "aligny top", null, new CC().alignY("top"), ".alignY(\"top\")" ); // external testCC( "external", null, new CC().external(), ".external()" ); // hidemode testCC( "hidemode 1", null, new CC().hideMode(1), ".hideMode(1)" ); // tag testCC( "tag ok", null, new CC().tag("ok"), ".tag(\"ok\")" ); } private void testLC( String input, String expected, LC inputAPI, String expectedAPI ) { LC lc = ConstraintParser.parseLayoutConstraint( input ); String actual = IDEUtil.getConstraintString( lc, false ); String actualAPI = IDEUtil.getConstraintString( inputAPI, true ); String actualAPI2 = IDEUtil.getConstraintString( lc, true ); myAssertEquals( input, (expected != null) ? expected : input, actual ); myAssertEquals( input, expectedAPI, actualAPI ); myAssertEquals( input, actualAPI2, actualAPI ); } private void testAC( String input, String expected, AC inputAPI, String expectedAPI ) { testAC( true, input, expected, inputAPI, expectedAPI ); testAC( false, input, expected, inputAPI, expectedAPI ); } private void testAC( boolean isCols, String input, String expected, AC inputAPI, String expectedAPI ) { AC ac = isCols ? ConstraintParser.parseColumnConstraints( input ) : ConstraintParser.parseRowConstraints( input ); String actual = IDEUtil.getConstraintString( ac, false, isCols ); myAssertEquals( input, (expected != null) ? expected : input, actual ); if( inputAPI != null ) { String actualAPI = IDEUtil.getConstraintString( inputAPI, true, isCols ); String actualAPI2 = IDEUtil.getConstraintString( ac, true, isCols ); myAssertEquals( input, expectedAPI, actualAPI ); myAssertEquals( input, actualAPI2, actualAPI ); } } private void testCC( String input, String expected, CC inputAPI, String expectedAPI ) { CC cc = ConstraintParser.parseComponentConstraint( input ); String actual = IDEUtil.getConstraintString( cc, false ); String actualAPI = IDEUtil.getConstraintString( inputAPI, true ); String actualAPI2 = IDEUtil.getConstraintString( cc, true ); myAssertEquals( input, (expected != null) ? expected : input, actual ); myAssertEquals( input, expectedAPI, actualAPI ); myAssertEquals( input, actualAPI2, actualAPI ); } private void myAssertEquals( String message, Object expected, Object actual ) { try { assertEquals( message, expected, actual ); } catch( Throwable ex ) { errorCollector.addError( ex ); } } } miglayout-5.1/javafx/000077500000000000000000000000001324101563200146455ustar00rootroot00000000000000miglayout-5.1/javafx/maven.txt000077500000000000000000000036401324101563200165220ustar00rootroot00000000000000The JavaFX runtime is not available in any public Maven repository, it has to be installed in the local repository manually using the command below: mvn install:install-file -Dfile=/path-to/javafx-sdk2.0-beta/rt/lib/jfxrt.jar -DgroupId=com.oracle -DartifactId=javafx-runtime -Dversion=2.0 -Dpackaging=jar -DgeneratePom=true Naturally the path-to must be your path to where the JavaFX SDK is installed and make sure that the specified version matches the actual JavaFX release version (and naturally that should be the one the miglayout-javafx artifact depends on). This is enough to get the JavaFX plugin to compile, but the test classes cannot be run because the JavaFX binaries are missing. To run the test classes in the IDE, the easiest way is to modify the classpath or java library path to include the libs directory of the corresponding JavaFX installation. The easiest way to do this is to manually include the JavaFX runtime jar (C:\Program Files\Oracle\JavaFX Runtime 2.0\lib\jfxrt.jar) and make sure it is positioned before the maven dependency in your EDI. Some IDE's may be stubborn when the project is created from the POM and do not allow additional classpath entries, in this case specifying it in the run configuration of each test class will help. For example in Eclipse the run configuration of a test could be modified to include the following as "VM arguments": -Djava.library.path=C:\Progra~1\Oracle\JAVAFX~1.0\bin However, all this does not solve the actual problem, it just will get the test code to run in an EDI, and that is the reason why there are no unittest at this time. The JFXtras project has a workaround where the binaries are uploaded as a separate Maven artifact and a prelaunch method is used to make sure they are on the classpath, but we do not want MigLayout-JavaFX depending on JFXtras. So for now we have to live with this and wait for Oracle to improve the Maven support in JavaFX. miglayout-5.1/javafx/pom.xml000077500000000000000000000051751324101563200161750ustar00rootroot00000000000000 4.0.0 com.miglayout miglayout-parent 5.1-SNAPSHOT ../pom.xml miglayout-javafx jar MiGLayout JavaFX MiGLayout - Layout Manager for JavaFX ${project.groupId} miglayout-core ${project.version} org.loadui testFx 3.1.2 test org.jfxtras jfxtras-test-support 8.0-r3 test org.jfxtras jfxtras-common 8.0-r3 test org.apache.maven.plugins maven-compiler-plugin 3.7.0 1.8 1.8 true none -g:none tbee Tom Eugelink tbee@tbee.org Developer +1 http://www.tbee.org/ miglayout-5.1/javafx/src/000077500000000000000000000000001324101563200154345ustar00rootroot00000000000000miglayout-5.1/javafx/src/main/000077500000000000000000000000001324101563200163605ustar00rootroot00000000000000miglayout-5.1/javafx/src/main/java/000077500000000000000000000000001324101563200173015ustar00rootroot00000000000000miglayout-5.1/javafx/src/main/java/org/000077500000000000000000000000001324101563200200705ustar00rootroot00000000000000miglayout-5.1/javafx/src/main/java/org/tbee/000077500000000000000000000000001324101563200210075ustar00rootroot00000000000000miglayout-5.1/javafx/src/main/java/org/tbee/javafx/000077500000000000000000000000001324101563200222665ustar00rootroot00000000000000miglayout-5.1/javafx/src/main/java/org/tbee/javafx/scene/000077500000000000000000000000001324101563200233635ustar00rootroot00000000000000miglayout-5.1/javafx/src/main/java/org/tbee/javafx/scene/layout/000077500000000000000000000000001324101563200247005ustar00rootroot00000000000000miglayout-5.1/javafx/src/main/java/org/tbee/javafx/scene/layout/LayoutAnimator.java000066400000000000000000000137741324101563200305270ustar00rootroot00000000000000package org.tbee.javafx.scene.layout; import javafx.animation.FadeTransition; import javafx.animation.Interpolator; import javafx.animation.Transition; import javafx.application.Platform; import javafx.geometry.Bounds; import javafx.geometry.Rectangle2D; import javafx.scene.Node; import javafx.scene.SnapshotParameters; import javafx.scene.image.ImageView; import javafx.util.Duration; import java.util.ArrayList; import java.util.HashMap; import java.util.IdentityHashMap; /** * @author Mikael Grev, MiG InfoCom AB * Date: 14-09-24 * Time: 16:05 */ public class LayoutAnimator { private static final String ANIM_REPLACE_ID = "mig-anim"; enum TransType { BOUNDS, OPACITY } public static final Duration ANIM_DURATION = new Duration(2000); private final MigPane pane; private final ArrayList addedNodes = new ArrayList<>(); private final ArrayList removedNodes = new ArrayList<>(); private final IdentityHashMap> nodeAnimMap = new IdentityHashMap<>(); private final IdentityHashMap replacedNodeMap = new IdentityHashMap<>(); public LayoutAnimator(MigPane pane) { this.pane = pane; } /** Animates the node. * @param node The node to animate. Not null. * @param toBounds If != null the animation will be to these bounds. */ void animate(Node node, Rectangle2D toBounds) { nodeAnimMap.compute(node, (n, oldTrans) -> createOrUpdateAnimation(n, oldTrans, toBounds)); Node replNode = replacedNodeMap.get(node); if (replNode != null) nodeAnimMap.compute(replNode, (n, oldTrans) -> createOrUpdateAnimation(n, oldTrans, toBounds)); } private HashMap createOrUpdateAnimation(Node node, HashMap transMap, Rectangle2D toBounds) { if (transMap == null) transMap = new HashMap<>(); double toOpacity = extractOpacity(node); transMap.compute(TransType.OPACITY, (transType, oldTrans) -> { if (toOpacity != -1) { if (oldTrans != null) oldTrans.stop(); FadeTransition fadeTrans = new FadeTransition(ANIM_DURATION, node); fadeTrans.setToValue(toOpacity); if (isReplacement(node)) { fadeTrans.setOnFinished(event -> { Node realNode = (Node) node.getUserData(); if (realNode != null) { Rectangle2D rb = getBounds(node); realNode.resizeRelocate(rb.getMinX(), rb.getMinY(), rb.getWidth(), rb.getHeight()); realNode.setVisible(true); } pane.remove(node); }); } fadeTrans.play(); // System.out.println("fade to " + toOpacity); return fadeTrans; } return oldTrans; }); if (toBounds != null) { transMap.compute(TransType.BOUNDS, (transType, oldTrans) -> { Rectangle2D curBounds = getBounds(node); if (!curBounds.equals(toBounds) && (oldTrans == null || !(((LayoutTrans) oldTrans).toBounds.equals(toBounds)))) { if (oldTrans != null) oldTrans.stop(); if (toOpacity == -1) { LayoutTrans trans = new LayoutTrans(node, ANIM_DURATION, toBounds); trans.play(); // System.out.println("layout to " + toBounds.toString()); return trans; } else { node.resizeRelocate(toBounds.getMinX(), toBounds.getMinY(), toBounds.getWidth(), toBounds.getHeight()); } } return oldTrans; }); } return transMap; } private double extractOpacity(Node node) { if (addedNodes.remove(node)) { node.setOpacity(0); return 1; } else if (removedNodes.remove(node)) { return 0; } return -1; } void nodeAdded(Node node) { if (isReplacement(node)) return; Node replNode = createReplacement(node); addedNodes.add(replNode); removedNodes.remove(node); node.setVisible(false); Platform.runLater(() -> { pane.add(0, replNode); // animate(replNode, null); }); } void nodeRemoved(Node node) { if (isReplacement(node)) return; Node replNode = createReplacement(node); removedNodes.add(replNode); addedNodes.remove(node); Platform.runLater(() -> { pane.add(0, replNode); animate(replNode, null); }); } private static boolean isReplacement(Node node) { return ANIM_REPLACE_ID.equals(node.getId()); } public Node createReplacement(Node node) { Rectangle2D b = getBounds(node); Node replNode = new ImageView(node.snapshot(new SnapshotParameters(), null)); replacedNodeMap.put(node, replNode); replNode.setUserData(node); replNode.setManaged(false); replNode.setId(ANIM_REPLACE_ID); replNode.resizeRelocate(b.getMinX(), b.getMinY(), b.getWidth(), b.getHeight()); return replNode; } void start() { // if (status == PAUSED) // nodeAnimMap.values().forEach(map -> map.values().forEach(Animation::play)); // status = RUNNING; } private static Rectangle2D getBounds(Node node) { Bounds lBounds = node.getLayoutBounds(); return new Rectangle2D( node.getLayoutX(), node.getLayoutY(), lBounds.getWidth(), lBounds.getHeight() ); } private class LayoutTrans extends Transition { private final Node node; private final double fromX, fromY, fromW, fromH; private final Rectangle2D toBounds; /** * @param node The node to animate * @param toBounds Target bounds. Never null. */ LayoutTrans(Node node, Duration duration, Rectangle2D toBounds) { this.node = node; this.fromX = node.getLayoutX(); this.fromY = node.getLayoutY(); Bounds bounds = node.getLayoutBounds(); this.fromW = bounds.getWidth(); this.fromH = bounds.getHeight(); this.toBounds = toBounds; setCycleDuration(duration); // setInterpolator(Interpolator.SPLINE(0.8, 0.2, 0.2, 0.8)); setInterpolator(Interpolator.SPLINE(0.0, 0.0, 0.2, 0.8)); // setInterpolator(Interpolator.EASE_OUT); } @Override protected void interpolate(double frac) { double x = fromX + (toBounds.getMinX() - fromX) * frac; double y = fromY + (toBounds.getMinY() - fromY) * frac; double w = fromW + (toBounds.getWidth() - fromW) * frac; double h = fromH + (toBounds.getHeight() - fromH) * frac; pane.incLayoutInhibit(); node.resizeRelocate(x, y, w, h); pane.decLayoutInhibit(); } } } miglayout-5.1/javafx/src/main/java/org/tbee/javafx/scene/layout/MigPane.java000077500000000000000000000756331324101563200271040ustar00rootroot00000000000000package org.tbee.javafx.scene.layout; import javafx.application.Platform; import javafx.beans.value.ChangeListener; import javafx.collections.ListChangeListener; import javafx.geometry.*; import javafx.scene.Group; import javafx.scene.Node; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.scene.control.Control; import javafx.scene.control.TextArea; import javafx.scene.control.TextField; import javafx.scene.layout.Region; import javafx.scene.paint.Color; import javafx.scene.shape.Rectangle; import javafx.stage.Screen; import javafx.stage.Window; import net.miginfocom.layout.*; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; /** * Manages nodes with MigLayout added via add(node, CC) * * @author Tom Eugelink * */ public class MigPane extends javafx.scene.layout.Pane { static { // todo Made static to defeat JavaFX bug: https://bugs.openjdk.java.net/browse/JDK-8095013 PlatformDefaults.setDefaultDPI(96); } protected final static String FXML_CC_KEY = "MigPane.cc"; // We need to invalidate the grid since we can have a component with hidemode 3 // We need to request layout since JavaFX doesn't do this. private final ChangeListener gridInvalidator = (observable, oldValue, newValue) -> { invalidateGrid(); requestLayout(); }; // ============================================================================================================ // CONSTRUCTOR /** * */ public MigPane() { super(); construct(); } /** * use the class layout constraints */ public MigPane(LC layoutConstraints) { super(); setLayoutConstraints(layoutConstraints); construct(); } /** * use the class layout constraints */ public MigPane(LC layoutConstraints, AC colConstraints) { super(); setLayoutConstraints(layoutConstraints); setColumnConstraints(colConstraints); construct(); } /** * use the class layout constraints */ public MigPane(LC layoutConstraints, AC colConstraints, AC rowConstraints) { super(); setLayoutConstraints(layoutConstraints); setColumnConstraints(colConstraints); setRowConstraints(rowConstraints); construct(); } /** * use the string layout constraints */ public MigPane(String layoutConstraints) { super(); setLayoutConstraints(ConstraintParser.parseLayoutConstraint(ConstraintParser.prepare(layoutConstraints))); construct(); } /** * use the string layout constraints */ public MigPane(String layoutConstraints, String colConstraints) { super(); setLayoutConstraints(ConstraintParser.parseLayoutConstraint(ConstraintParser.prepare(layoutConstraints))); setColumnConstraints(ConstraintParser.parseColumnConstraints(ConstraintParser.prepare(colConstraints))); construct(); } /** * use the string layout constraints */ public MigPane(String layoutConstraints, String colConstraints, String rowConstraints) { super(); setLayoutConstraints(ConstraintParser.parseLayoutConstraint(ConstraintParser.prepare(layoutConstraints))); setColumnConstraints(ConstraintParser.parseColumnConstraints(ConstraintParser.prepare(colConstraints))); setRowConstraints(ConstraintParser.parseRowConstraints(ConstraintParser.prepare(rowConstraints))); construct(); } /* * */ private void construct() { // When Scene changes the grid needs to be cleared sceneProperty().addListener(e -> invalidateGrid()); // invalidate grid and request layout when node orientation changes nodeOrientationProperty().addListener(observable -> { invalidateGrid(); requestLayout(); }); // defaults if (layoutConstraints == null) setLayoutConstraints(new LC()); if (rowConstraints == null) setRowConstraints(new AC()); if (columnConstraints == null) setColumnConstraints(new AC()); // In case when someone sneakily removes a child the JavaFX way; prevent memory leaking getChildren().addListener((ListChangeListener) c -> { while (c.next()) { for (Node node : c.getRemoved()) { node.visibleProperty().removeListener(gridInvalidator); animateRemoved(node); int sizeBef = wrapperToCCMap.size(); wrapperToCCMap.remove(new FXComponentWrapper(node)); if (wrapperToCCMap.size() != sizeBef) // Can't use the return from wrapperToCCMap since it might be null anyway if no CC. invalidateGrid(); } for (Node node : c.getAddedSubList()) { // debug rectangles are not handled by miglayout, neither are not managed ones if (!node.isManaged()) continue; // get cc or use default CC cc = (CC) node.getProperties().remove(FXML_CC_KEY); FXComponentWrapper wrapper = new FXComponentWrapper(node); // Only put the value if this comes from FXML or from direct list manipulation (not in wrapperToCCMap yet) if (cc != null || !wrapperToCCMap.containsKey(wrapper)) wrapperToCCMap.put(wrapper, cc); animateAdded(node); node.visibleProperty().addListener(gridInvalidator); invalidateGrid(); } } }); } // ============================================================================================================ // PANE // @Override protected double computeMinWidth(double height) { return computeWidth(height, LayoutUtil.MIN); } @Override protected double computeMinHeight(double width) { return computeHeight(width, LayoutUtil.MIN); } @Override protected double computePrefWidth(double height) { return computeWidth(height, LayoutUtil.PREF); } @Override protected double computePrefHeight(double width) { return computeHeight(width, LayoutUtil.PREF); } @Override protected double computeMaxWidth(double height) { return computeWidth(height, LayoutUtil.MAX); } @Override protected double computeMaxHeight(double width) { return computeHeight(width, LayoutUtil.MAX); } protected double computeWidth(double refHeight, int type) { int ins = getHorIns(); int refSize = (int) Math.ceil(refHeight != -1 ? refHeight : getHeight()) - ins; return ins + LayoutUtil.getSizeSafe(getGrid().getWidth(refSize), type); } protected double computeHeight(double refWidth, int type) { int ins = getVerIns(); int refSize = (int) Math.ceil(refWidth != -1 ? refWidth : getWidth()) - ins; return ins + LayoutUtil.getSizeSafe(getGrid().getHeight(refSize), type); } private int getHorIns() { Insets insets = getInsets(); return (int) Math.ceil(snapSpace(insets.getLeft()) + snapSpace(insets.getRight())); } private int getVerIns() { Insets insets = getInsets(); return (int) Math.ceil(snapSpace(insets.getTop()) + snapSpace(insets.getBottom())); } private Orientation bias = null; private boolean biasDirty = true; private boolean debug = false; @Override public Orientation getContentBias() { if (biasDirty) { bias = null; for (Node child : getManagedChildren()) { Orientation ori = child.getContentBias(); if (ori == Orientation.HORIZONTAL) { bias = Orientation.HORIZONTAL; break; } if (ori != null) bias = ori; } biasDirty = false; } return bias; } // ============================================================================================================ // CONSTRAINTS /** LayoutConstraints: */ public LC getLayoutConstraints() { return this.layoutConstraints; } public void setLayoutConstraints(LC lc) { this.layoutConstraints = lc; // Set debug. Clear it if LC is null. debug = lc != null && lc.getDebugMillis() > 0; invalidateGrid(); requestLayout(); } public MigPane withLayoutConstraints(LC value) { setLayoutConstraints(value); return this; } private LC layoutConstraints = null; final static public String LAYOUTCONSTRAINTS_PROPERTY_ID = "layoutConstraints"; /** ColumnConstraints: */ public AC getColumnConstraints() { return this.columnConstraints; } public void setColumnConstraints(AC value) { this.columnConstraints = value; invalidateGrid(); requestLayout();} public MigPane withColumnConstraints(AC value) { setColumnConstraints(value); return this; } private AC columnConstraints = null; final static public String COLUMNCONSTRAINTS_PROPERTY_ID = "columnConstraints"; /** RowConstraints: */ public AC getRowConstraints() { return this.rowConstraints; } public void setRowConstraints(AC value) { this.rowConstraints = value; invalidateGrid(); requestLayout();} public MigPane withRowConstraints(AC value) { setRowConstraints(value); return this; } private AC rowConstraints = null; final static public String ROWCONSTRAINTS_PROPERTY_ID = "rowConstraints"; /** Returns the constraints for the node * @return May be null which means all default constraints. */ public CC getComponentConstraints(Node node) { return wrapperToCCMap.get(new FXComponentWrapper(node)); } /** Sets the constraints for the node * @param node The node. Must already be in the pane. * @param ccs The component constraints. Can be null. */ public void setComponentConstraints(Node node, String ccs) { FXComponentWrapper wrapper = new FXComponentWrapper(node); if (!wrapperToCCMap.containsKey(wrapper)) throw new IllegalArgumentException("Node not in pane: " + node); CC cc = ConstraintParser.parseComponentConstraint(ConstraintParser.prepare(ccs)); wrapperToCCMap.put(wrapper, cc); invalidateGrid(); requestLayout(); } private LayoutAnimator anim = null; // ============================================================================================================ // Animation private int animPrio = 0; /** * @return If there is a current animator, that is returned. Otherwise a new one is created and returned. Never null. */ private LayoutAnimator getAnimator() { if (anim == null) anim = new LayoutAnimator(this); return anim; } /** Starts animation if there is one. */ private void startQueuedAnimations() { if (anim != null) anim.start(); } public void animateAdded(Node node) { if (isNodeAnimated(node)) getAnimator().nodeAdded(node); } public void animateRemoved(Node node) { if (isNodeAnimated(node)) getAnimator().nodeRemoved(node); } public boolean animateBoundsChange(Node node, int x, int y, int width, int height) { if (!isNodeAnimated(node)) return false; getAnimator().animate(node, new Rectangle2D(x, y, width, height)); return true; } private boolean isNodeAnimated(Node node) { if (!isVisible()) return false; CC cc = wrapperToCCMap.get(new FXComponentWrapper(node)); int compPrio = cc != null ? cc.getAnimSpec().getPriority() : 0; return compPrio + (long) animPrio > 0; } // ============================================================================================================ // CALLBACK private ArrayList callbackList = null; /** Adds the callback function that will be called at different stages of the layout cycle. * @param callback The callback. Not null. */ public void addLayoutCallback(LayoutCallback callback) { if (callback == null) throw new NullPointerException(); if (callbackList == null) callbackList = new ArrayList<>(1); callbackList.add(callback); invalidateGrid(); } /** Removes the callback if it exists. * @param callback The callback. May be null. */ public void removeLayoutCallback(LayoutCallback callback) { if (callbackList != null) callbackList.remove(callback); } // ============================================================================================================ // SCENE public MigPane add(Node node, CC cc) { if (node.isManaged()) wrapperToCCMap.put(new FXComponentWrapper(node), cc); getChildren().add(node); return this; } public MigPane add(Node node) { add(node, (CC) null); return this; } public MigPane add(Node node, String sCc) { CC cc = ConstraintParser.parseComponentConstraint(ConstraintParser.prepare(sCc)); add(node, cc); return this; } public MigPane add(int index, Node node) { add(index, node, (CC) null); return this; } public MigPane add(int index, Node node, String sCc) { CC cc = ConstraintParser.parseComponentConstraint(ConstraintParser.prepare(sCc)); add(index, node, cc); return this; } public MigPane add(int index, Node node, CC cc) { if (node.isManaged()) wrapperToCCMap.put(new FXComponentWrapper(node), cc); getChildren().add(index, node); return this; } public boolean remove(Node node) { return getChildren().remove(node); } public Node remove(int ix) { return getChildren().remove(ix); } // ============================================================================================================ // LAYOUT // Store constraints. Key order important. Can have null values but all components that MigPane handles must be a key. final private LinkedHashMap wrapperToCCMap = new LinkedHashMap<>(); private long lastSize = 0; /** * This is where the actual layout happens */ @Override protected void layoutChildren() { incLayoutInhibit(); try { if (layoutConstraints.isNoCache()) _grid = null; // for debugging System.out.println("MigPane.layoutChildren"); Grid lGrid = getGrid(); // here the actual layout happens // this will use FXComponentWrapper.setBounds to actually place the components Insets ins = getInsets(); int[] lBounds = new int[]{(int) ins.getLeft(), (int) ins.getTop(), (int) Math.ceil(getWidth() - getHorIns()), (int) Math.ceil(getHeight() - getVerIns())}; lGrid.layout(lBounds, getLayoutConstraints().getAlignX(), getLayoutConstraints().getAlignY(), debug); // paint debug if (debug) { clearDebug(); lGrid.paintDebug(); } // Handle the "pack" keyword long newSize = lGrid.getHeight()[1] + (((long) lGrid.getWidth()[1]) << 32); if (lastSize != newSize) { lastSize = newSize; Platform.runLater(this::adjustWindowSize); } startQueuedAnimations(); } finally { decLayoutInhibit(); } } @Override protected void setWidth(double newWidth) { if (newWidth != getWidth()) { super.setWidth(newWidth); if (_grid != null) _grid.invalidateContainerSize(); } } @Override protected void setHeight(double newHeight) { if (newHeight != getHeight()) { super.setHeight(newHeight); if (_grid != null) _grid.invalidateContainerSize(); } } @Override public void requestLayout() { if (layoutInhibits > 0) return; biasDirty = true; if (_grid != null) _grid.invalidateContainerSize(); super.requestLayout(); } private Grid _grid; private int layoutInhibits = 0; // When > 0 request layouts should be inhibited void incLayoutInhibit() { layoutInhibits++; } void decLayoutInhibit() { layoutInhibits--; } /* * the _grid is valid if all hash codes are unchanged */ private Grid getGrid() { if (_grid == null) _grid = new Grid(new FXContainerWrapper(this), getLayoutConstraints(), getRowConstraints(), getColumnConstraints(), wrapperToCCMap, callbackList); return _grid; } /** Removes the grid so it is recreated as needed next time. Should only be needed when the grid structure, or the interpretation of it, * has changed. Should normally don't have to be called by client code since this should be fully handled by MigPane. */ public void invalidateGrid() { _grid = null; biasDirty = true; } /** Checks the parent window/popup if its size is within parameters as set by the LC. */ private void adjustWindowSize() { BoundSize wBounds = layoutConstraints.getPackWidth(); BoundSize hBounds = layoutConstraints.getPackHeight(); Scene scene = getScene(); Window window = scene != null ? scene.getWindow() : null; if (window == null || wBounds == BoundSize.NULL_SIZE && hBounds == BoundSize.NULL_SIZE) return; Parent root = scene.getRoot(); double winWidth = window.getWidth(); double winHeight = window.getHeight(); double prefWidth = root.prefWidth(-1); double prefHeight = root.prefHeight(-1); FXContainerWrapper container = new FXContainerWrapper(root); double horIns = winWidth - scene.getWidth(); double verIns = winHeight - scene.getHeight(); double targetW = constrain(container, winWidth, prefWidth, wBounds) + horIns; double targetH = constrain(container, winHeight, prefHeight, hBounds) + verIns; double x = window.getX() - ((targetW - winWidth) * (1 - layoutConstraints.getPackWidthAlign())); double y = window.getY() - ((targetH - winHeight) * (1 - layoutConstraints.getPackHeightAlign())); window.setX(x); window.setY(y); window.setWidth(targetW); window.setHeight(targetH); } private double constrain(ContainerWrapper parent, double winSize, double prefSize, BoundSize constrain) { if (constrain == null) return winSize; double retSize = winSize; UnitValue wUV = constrain.getPreferred(); if (wUV != null) retSize = wUV.getPixels((float) prefSize, parent, parent); retSize = constrain.constrain((int) Math.ceil(retSize), (float) prefSize, parent); return constrain.getGapPush() ? Math.max(winSize, retSize) : retSize; } @Override public boolean usesMirroring() { // do not use mirroring transformation for right-to-left node orientation return false; } // ============================================================================================================ // DEBUG public void clearDebug() { // for debugging System.out.println("clearDebug"); MigPane.this.getChildren().removeAll(this.debugRectangles); this.debugRectangles.clear(); } final private List debugRectangles = new ArrayList(); private void addDebugRectangle(double x, double y, double w, double h, DebugRectangleType type) { DebugRectangle lRectangle = new DebugRectangle( snap(x), snap(y), snap(x + w - 1) - snap(x), snap(y + h - 1) - snap(y) ); if (type == DebugRectangleType.CELL) { //System.out.print(getId() + ": " + "paintDebugCell "); lRectangle.setStroke(getDebugCellColor()); lRectangle.getStrokeDashArray().addAll(3d,3d); } else if (type == DebugRectangleType.EXTERNAL) { //System.out.print(getId() + ": " + "paintDebugExternal "); lRectangle.setStroke(getDebugExternalColor()); lRectangle.getStrokeDashArray().addAll(5d,5d); } else if (type == DebugRectangleType.OUTLINE) { //System.out.print(getId() + ": " + "paintDebugOutline "); lRectangle.setStroke(getDebugOutlineColor()); lRectangle.getStrokeDashArray().addAll(4d,4d); } else if (type == DebugRectangleType.CONTAINER_OUTLINE) { //System.out.print(getId() + ": " + "paintDebugContainerOutline "); lRectangle.setStroke(getDebugContainerOutlineColor()); lRectangle.getStrokeDashArray().addAll(7d,7d); } else { throw new IllegalStateException("Unknown debug rectangle type"); } // for debugging System.out.println(lRectangle.getX() + "," + lRectangle.getY() + "/" + lRectangle.getWidth() + "x" + lRectangle.getHeight()); //lRectangle.setStrokeWidth(0.5f); lRectangle.setFill(null); lRectangle.mouseTransparentProperty().set(true); // just to be sure // add as child MigPane.this.getChildren().add(lRectangle); this.debugRectangles.add(lRectangle); } private enum DebugRectangleType { CELL, OUTLINE, CONTAINER_OUTLINE, EXTERNAL } class DebugRectangle extends Rectangle { public DebugRectangle(double x, double y, double w, double h) { super(x,y,w,h); setManaged(false); } } private double snap(double v) { return ((int) v) + .5; } /** debugCellColor */ public Color getDebugCellColor() { return this.debugCellColor; } public void setDebugCellColor(Color value) { this.debugCellColor = value; } private Color debugCellColor = Color.RED; /** debugExternalColor */ public Color getDebugExternalColor() { return this.debugExternalColor; } public void setDebugExternalColor(Color value) { this.debugExternalColor = value; } private Color debugExternalColor = Color.BLUE; /** debugOutlineColor */ public Color getDebugOutlineColor() { return this.debugOutlineColor; } public void setDebugOutlineColor(Color value) { this.debugOutlineColor = value; } private Color debugOutlineColor = Color.GREEN; /** debugContainerOutlineColor */ public Color getDebugContainerOutlineColor() { return this.debugContainerOutlineColor; } public void setDebugContainerOutlineColor(Color value) { this.debugContainerOutlineColor = value; } private Color debugContainerOutlineColor = Color.PURPLE; // ============================================================================================================ // ContainerWrapper /* * This class provides the data for MigLayout for the container */ class FXContainerWrapper extends FXComponentWrapper implements net.miginfocom.layout.ContainerWrapper { public FXContainerWrapper(Parent node) { super(node); } @Override public FXComponentWrapper[] getComponents() { // for debugging System.out.println("MigPane.FXContainerWrapper.getComponents " + MigPane.this.componentWrapperList.size()); // return getManagedChildren().stream().map(node -> new FXComponentWrapper(node)).toArray(FXComponentWrapper[]::new); List lFXComponentWrappers = new ArrayList<>(); for (Node node : getManagedChildren()) { lFXComponentWrappers.add(new FXComponentWrapper(node)); } return lFXComponentWrappers.toArray(new FXComponentWrapper[]{}); } @Override public int getComponentCount() { // for debugging System.out.println("MigPane.FXContainerWrapper.getComponentCount " + MigPane.this.wrapperToCCMap.size()); return MigPane.this.wrapperToCCMap.size(); } @Override public Object getLayout() { return MigPane.this; } @Override public boolean isLeftToRight() { return getEffectiveNodeOrientation() != NodeOrientation.RIGHT_TO_LEFT; } @Override public void paintDebugCell(int x, int y, int w, int h) { addDebugRectangle((double)x, (double)y, (double)w, (double)h, DebugRectangleType.CELL); } @Override public void paintDebugOutline(boolean useVisualPadding) { addDebugRectangle( 0, 0, getWidth(), getHeight(), DebugRectangleType.CONTAINER_OUTLINE); } } // ============================================================================================================ // ComponentWrapper /* * This class provides the data for MigLayout for a single component */ class FXComponentWrapper implements net.miginfocom.layout.ComponentWrapper { final protected Node node; // wrap this node public FXComponentWrapper(Node node) { this.node = node; } // get the wrapped node @Override public Object getComponent() { return this.node; } // get the parent @Override public ContainerWrapper getParent() { Parent parent = node.getParent(); return parent != null ? new FXContainerWrapper(node.getParent()) : null; } // what type are we wrapping @Override public int getComponentType(boolean arg0) { if (node instanceof TextField || node instanceof TextArea) { return TYPE_TEXT_FIELD; } else if (node instanceof Group) { return TYPE_CONTAINER; } else { return TYPE_UNKNOWN; } } @Override public int getX() { int v = (int) node.getLayoutX(); return v; } @Override public int getY() { int v = (int) node.getLayoutY(); return v; } @Override public int getWidth() { // for debugging if (getComponent() instanceof MigPane == false) System.out.println(getComponent() + " getWidth " + node.getLayoutBounds().getWidth()); int v = (int) Math.ceil(node.getLayoutBounds().getWidth()); return v; } @Override public int getMinimumWidth(int height) { int v = (int) Math.ceil(this.node.minWidth(height)); // for debugging System.out.println(getComponent() + " getMinimumWidth " + v); return v; } @Override public int getPreferredWidth(int height) { int v = (int) Math.ceil(this.node.prefWidth(height)); // for debugging System.out.println(getComponent() + " getPreferredWidth " + v); return v; } @Override public int getMaximumWidth(int height) { // backwards compatibility with JavaFX2 (control does not extend Region there) if (node instanceof Region || node instanceof Control) { double prefWidth = node instanceof Region ? ((Region) node).getMaxWidth() : ((Control) node).getMaxWidth(); if (prefWidth == USE_COMPUTED_SIZE || prefWidth == USE_PREF_SIZE) return LayoutUtil.INF; } return (int) Math.ceil(node.maxWidth(height)); } @Override public int getHeight() { int v = (int) Math.ceil(node.getLayoutBounds().getHeight()); return v; } @Override public int getMinimumHeight(int width) { int v = (int) Math.ceil(this.node.minHeight(width)); return v; } @Override public int getPreferredHeight(int width) { int v = (int) Math.ceil(this.node.prefHeight(width)); // for debugging System.out.println(getComponent() + " FXComponentWrapper.getPreferredHeight -> node.prefHeight(" + width + ")=" + this.node.prefHeight(width)); return v; } @Override public int getMaximumHeight(int width) { // backwards compatibility with JavaFX2 (control does not extend Region there) if (node instanceof Region || node instanceof Control) { double prefWidth = node instanceof Region ? ((Region) node).getMaxHeight() : ((Control) node).getMaxHeight(); if (prefWidth == USE_COMPUTED_SIZE || prefWidth == USE_PREF_SIZE) return LayoutUtil.INF; } return (int) Math.ceil(node.maxHeight(width)); } @Override public int getBaseline(int width, int height) { return (int) Math.round(node.getBaselineOffset()); } @Override public boolean hasBaseline() { // For some reason not resizable just return their height as the baseline, not BASELINE_OFFSET_SAME_AS_HEIGHT as logic would suggest. // For more info : https://bugs.openjdk.java.net/browse/JDK-8091288 return node.isResizable() && node.getBaselineOffset() != BASELINE_OFFSET_SAME_AS_HEIGHT; } @Override public int getScreenLocationX() { // this code is called when absolute layout is used Bounds lBoundsInSceneNode = node.localToScene(node.getBoundsInLocal()); int v = (int) (node.getScene().getX() + node.getScene().getX() + lBoundsInSceneNode.getMinX()); // for debugging System.out.println(getComponent() + " getScreenLocationX =" + v); return v; } @Override public int getScreenLocationY() { // this code is called when absolute layout is used Bounds lBoundsInSceneNode = node.localToScene(node.getBoundsInLocal()); int v = (int) (node.getScene().getY() + node.getScene().getY() + lBoundsInSceneNode.getMinY()); // for debugging System.out.println(getComponent() + " getScreenLocationX =" + v); return v; } @Override public int getScreenHeight() { // this code is never called? int v = (int) Math.ceil(Screen.getPrimary().getBounds().getHeight()); // for debugging System.out.println(getComponent() + " getScreenHeight=" + v); return v; } @Override public int getScreenWidth() { // this code is never called? int v = (int) Math.ceil(Screen.getPrimary().getBounds().getWidth()); // for debugging System.out.println(getComponent() + " getScreenWidth=" + v); return v; } @Override public int[] getVisualPadding() { return null; } @Override public int getHorizontalScreenDPI() { // todo Made static to defeat JavaFX bug: https://bugs.openjdk.java.net/browse/JDK-8095013 // todo NOTE Also remove the static block at the top of this file that sets the default DPI on the platform to 96 DPI which makes LP and PX 1:1. // todo All references to Screen.getPrimary() should be replaced with getting the actual screen the Node is on. return 96; // E.g. 101 on a 30" and 109 on 27" Apple Cinema Display. // return (int) Math.ceil(Screen.getPrimary().getDpi()); } @Override public int getVerticalScreenDPI() { // todo Made static to defeat JavaFX bug: https://bugs.openjdk.java.net/browse/JDK-8095013 return 96; // E.g. 101 on a 30" and 109 on 27" Apple Cinema Display. // return (int) Math.ceil(Screen.getPrimary().getDpi()); } @Override public float getPixelUnitFactor(boolean isHor) { switch (PlatformDefaults.getLogicalPixelBase()) { case PlatformDefaults.BASE_FONT_SIZE: return 1.0f; // todo case PlatformDefaults.BASE_SCALE_FACTOR: Float s = isHor ? PlatformDefaults.getHorizontalScaleFactor() : PlatformDefaults.getVerticalScaleFactor(); if (s == null) s = 1.0f; return s * (isHor ? getHorizontalScreenDPI() : getVerticalScreenDPI()) / (float) PlatformDefaults.getDefaultDPI(); default: return 1f; } } @Override public int getLayoutHashCode() { return 0; // Not used in MigPane. } @Override public String getLinkId() { return node.getId(); } @Override public boolean isVisible() { return node.isVisible(); } @Override public int getContentBias() { Orientation bias = node.getContentBias(); return bias == null ? -1 : bias.ordinal(); // 0 == Orientation.HORIZONTAL and Orientation.HORIZONTAL, 1 = Orientation.VERTICAL and LayoutUtil.VERTICAL } @Override public void paintDebugOutline(boolean useVisualPadding) { CC lCC = wrapperToCCMap.get(this); DebugRectangleType type = lCC != null && lCC.isExternal() ? DebugRectangleType.EXTERNAL : DebugRectangleType.OUTLINE; addDebugRectangle(this.node.getLayoutX() + this.node.getLayoutBounds().getMinX(), (double) this.node.getLayoutY() + this.node.getLayoutBounds().getMinY(), getWidth(), getHeight(), type); // always draws node size, even if less is used } @Override public int hashCode() { return node.hashCode(); } /** * This needs to be overridden so that different wrappers that hold the same component compare * as equal. Otherwise, Grid won't be able to layout the components correctly. */ @Override public boolean equals(Object o) { if (!(o instanceof FXComponentWrapper)) return false; return getComponent().equals(((FXComponentWrapper) o).getComponent()); } @Override public void setBounds(int x, int y, int width, int height) { // System.out.println(getComponent() + " FXComponentWrapper.setBound x=" + x + ",y=" + y + " / w=" + width + ",h=" + height + " / resizable=" + this.node.isResizable()); // System.out.println("x: " + x + ", y: " + y); // CC cc = wrapperToCCMap.get(this); if (!animateBoundsChange(node, x, y, width, height)) node.resizeRelocate((double) x, (double) y, (double) width, (double) height); } } } miglayout-5.1/javafx/src/main/java/org/tbee/javafx/scene/layout/fxml/000077500000000000000000000000001324101563200256465ustar00rootroot00000000000000miglayout-5.1/javafx/src/main/java/org/tbee/javafx/scene/layout/fxml/MigPane.java000077500000000000000000000037021324101563200300360ustar00rootroot00000000000000package org.tbee.javafx.scene.layout.fxml; import javafx.beans.DefaultProperty; import javafx.scene.Node; import net.miginfocom.layout.CC; import net.miginfocom.layout.ConstraintParser; /** * This class provides some API enhancements to implement FXML (and this keep the original's API clean) * @author User * */ @DefaultProperty(value = "children") // for FXML integration public class MigPane extends org.tbee.javafx.scene.layout.MigPane { // The FXML simply is matching tag- and attributes names to classes and properties (getter/setter) in the imported Java files // Many thanks to Michael Paus for the grunt work! /** layout called in FXML on MigPane itself */ public void setLayout(String value) { this.fxmLayoutConstraints = value; setLayoutConstraints( ConstraintParser.parseLayoutConstraint( ConstraintParser.prepare( value ) ) ); } public String getLayout() { return fxmLayoutConstraints; } private String fxmLayoutConstraints; /** cols called in FXML on MigPane itself */ public void setCols(String value) { this.fxmlColumConstraints = value; setColumnConstraints( ConstraintParser.parseColumnConstraints( ConstraintParser.prepare( value ) ) ); } public String getCols() { return fxmlColumConstraints; } private String fxmlColumConstraints; /** rows called in FXML on MigPane itself */ public void setRows(String value) { this.fxmlRowConstraints = value; setRowConstraints( ConstraintParser.parseRowConstraints( ConstraintParser.prepare( value ) ) ); } public String getRows() { return fxmlRowConstraints; } private String fxmlRowConstraints; /** called from the subnodes in FXML via MigPane.cc="..." */ public static void setCc(Node node, CC cc) { node.getProperties().put(FXML_CC_KEY, cc); } public static void setCc(Node node, String cc) { CC lCC = ConstraintParser.parseComponentConstraint( ConstraintParser.prepare( cc ) ); setCc(node, lCC); } } miglayout-5.1/javafx/src/test/000077500000000000000000000000001324101563200164135ustar00rootroot00000000000000miglayout-5.1/javafx/src/test/java/000077500000000000000000000000001324101563200173345ustar00rootroot00000000000000miglayout-5.1/javafx/src/test/java/org/000077500000000000000000000000001324101563200201235ustar00rootroot00000000000000miglayout-5.1/javafx/src/test/java/org/tbee/000077500000000000000000000000001324101563200210425ustar00rootroot00000000000000miglayout-5.1/javafx/src/test/java/org/tbee/javafx/000077500000000000000000000000001324101563200223215ustar00rootroot00000000000000miglayout-5.1/javafx/src/test/java/org/tbee/javafx/scene/000077500000000000000000000000001324101563200234165ustar00rootroot00000000000000miglayout-5.1/javafx/src/test/java/org/tbee/javafx/scene/layout/000077500000000000000000000000001324101563200247335ustar00rootroot00000000000000miglayout-5.1/javafx/src/test/java/org/tbee/javafx/scene/layout/test/000077500000000000000000000000001324101563200257125ustar00rootroot00000000000000miglayout-5.1/javafx/src/test/java/org/tbee/javafx/scene/layout/test/MigPaneInternalLayoutTest.java000066400000000000000000000412321324101563200336320ustar00rootroot00000000000000package org.tbee.javafx.scene.layout.test; import java.util.List; import javafx.scene.Parent; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.TextField; import javafx.scene.layout.Pane; import javafx.scene.paint.Color; import javafx.scene.shape.Rectangle; import javafx.scene.text.Font; import javafx.scene.text.TextAlignment; import javafx.stage.Stage; import jfxtras.test.AssertNode; import jfxtras.test.TestUtil; import jfxtras.util.PlatformUtil; import net.miginfocom.layout.AC; import net.miginfocom.layout.CC; import net.miginfocom.layout.LC; import net.miginfocom.layout.PlatformDefaults; import org.junit.Assert; import org.junit.Test; import org.tbee.javafx.scene.layout.MigPane; /** * TestFX is able to layout a single node per class. * Because we would be creating MigPane only once, this would result in one class with one test method per to-be-tested layout, and thus is a LOT of classes. * By placing MigPane in a presized Pane, it is possible to test different layouts each in a separate method, all in a single class. * The drawback is that MigPane is never tested stand alone, as the root node, so for each test it must be decided if we can put it in here, or if it needs a test class on its own. * * @author Tom Eugelink * */ public class MigPaneInternalLayoutTest extends org.loadui.testfx.GuiTest { @Override protected Parent getRootNode() { PlatformDefaults.setDefaultDPI(96); PlatformDefaults.setPlatform(PlatformDefaults.WINDOWS_XP); // use a pane to force the scene large enough, migpane is placed top-left pane = new Pane(); pane.setMinSize(1000, 600); // just for readability; place a label label = new Label(); label.layoutYProperty().bind(pane.minHeightProperty().subtract(20)); pane.getChildren().add(label); // done return pane; } private Pane pane = null; private Label label = null; @Test public void twoChildBasicLayout() { loadCSS(); setLabel("twoChildBasicLayout"); MigPane migPane = TestUtil.runThenWaitForPaintPulse( () -> { MigPane constructMigPane = new MigPane(new LC().debug(1000), new AC(), new AC()); pane.getChildren().add(constructMigPane); // add nodes constructMigPane.add(new TextField(), new CC()); constructMigPane.add(new Rectangle(30,30, Color.YELLOW), new CC()); return constructMigPane; }); //generateSource(migPane); assertWH(migPane, 187.0, 45.0); new AssertNode(migPane.getChildren().get(0)).assertXYWH(7.0, 7.0, 136.0, 31.0, 0.01).assertClass(javafx.scene.control.TextField.class); new AssertNode(migPane.getChildren().get(1)).assertXYWH(150.0, 8.0, 30.0, 30.0, 0.01).assertClass(javafx.scene.shape.Rectangle.class); } @Test public void wrappingLabel() { loadCSS(); setLabel("wrappingLabel"); MigPane migPane = TestUtil.runThenWaitForPaintPulse( () -> { MigPane constructMigPane = new MigPane(new LC().width("400px").debug(1000), new AC(), new AC()); pane.getChildren().add(constructMigPane); // add nodes Label label = new Label("Test long label to see if the wrap works ok in a Migpane. I am going to have to keep writing because this may not be long enough yet!!"); label.setWrapText(true); constructMigPane.add(label, new CC().grow()); return constructMigPane; }); //generateSource(migPane); assertWH(migPane, 400.0, 90.0); new AssertNode(migPane.getChildren().get(0)).assertXYWH(7.0, 7.0, 386.0, 76.0, 0.01).assertClass(javafx.scene.control.Label.class); } @Test public void size() { loadCSS(); setLabel("size"); MigPane migPane = TestUtil.runThenWaitForPaintPulse( () -> { MigPane constructMigPane = new MigPane(new LC().debug().fillX(), new AC(), new AC()); pane.getChildren().add(constructMigPane); // add nodes constructMigPane.add(new Button("500 logical pixels (def)"), "w 500, wrap"); constructMigPane.add(new Button("500 logical pixels"), "w 500lp, wrap"); constructMigPane.add(new Button("500 pixels"), "w 500px, wrap"); constructMigPane.add(new Button("10 centimeters"), "w 10cm, wrap"); constructMigPane.add(new Button("4 inches"), "w 4in, wrap"); constructMigPane.add(new Button("30% of screen"), "w 30sp, wrap"); constructMigPane.add(new Button("30% of container"), "w 30%, wrap"); return constructMigPane; }); //generateSource(migPane); assertWH(migPane, 781.0, 280.0); new AssertNode(migPane.getChildren().get(0)).assertXYWH(7.0, 7.0, 500.0, 31.0, 0.01).assertClass(javafx.scene.control.Button.class); new AssertNode(migPane.getChildren().get(1)).assertXYWH(7.0, 45.0, 500.0, 31.0, 0.01).assertClass(javafx.scene.control.Button.class); new AssertNode(migPane.getChildren().get(2)).assertXYWH(7.0, 83.0, 500.0, 31.0, 0.01).assertClass(javafx.scene.control.Button.class); new AssertNode(migPane.getChildren().get(3)).assertXYWH(7.0, 121.0, 378.0, 31.0, 0.01).assertClass(javafx.scene.control.Button.class); new AssertNode(migPane.getChildren().get(4)).assertXYWH(7.0, 159.0, 384.0, 31.0, 0.01).assertClass(javafx.scene.control.Button.class); new AssertNode(migPane.getChildren().get(5)).assertXYWH(7.0, 197.0, 767.0, 31.0, 0.01).assertClass(javafx.scene.control.Button.class); new AssertNode(migPane.getChildren().get(6)).assertXYWH(7.0, 235.0, 234.0, 31.0, 0.01).assertClass(javafx.scene.control.Button.class); } @Test public void pack() { loadCSS(); setLabel("pack"); final Label label = new Label("Pack it up!"); final MigPane migPane = TestUtil.runThenWaitForPaintPulse( () -> { MigPane constructMigPane = new MigPane(new LC().pack().packAlign(0.5f, 1f), new AC(), new AC()); pane.getChildren().add(constructMigPane); // add nodes constructMigPane.add(label, "alignx center, wrap unrel"); Label wrapLabel = new Label("The only thing changed\nis the font size"); wrapLabel.setTextAlignment(TextAlignment.CENTER); constructMigPane.add(wrapLabel, "alignx center"); return constructMigPane; }); //generateSource(migPane); assertWH(migPane, 226.0, 82.0); new AssertNode(migPane.getChildren().get(0)).assertXYWH(60.0, 7.0, 106.0, 19.0, 0.01).assertClass(javafx.scene.control.Label.class); new AssertNode(migPane.getChildren().get(1)).assertXYWH(7.0, 37.0, 212.0, 38.0, 0.01).assertClass(javafx.scene.control.Label.class); // increase font size TestUtil.runThenWaitForPaintPulse( () -> { label.setFont(new Font(50)); return null; }); //generateSource(migPane); assertWH(migPane, 244.0, 136.0); new AssertNode(migPane.getChildren().get(0)).assertXYWH(7.0, 7.0, 230.0, 73.0, 0.01).assertClass(javafx.scene.control.Label.class); new AssertNode(migPane.getChildren().get(1)).assertXYWH(16.0, 91.0, 212.0, 38.0, 0.01).assertClass(javafx.scene.control.Label.class); // increase font size TestUtil.runThenWaitForPaintPulse( () -> { label.setFont(new Font(100)); return null; }); //generateSource(migPane); assertWH(migPane, 474.0, 209.0); new AssertNode(migPane.getChildren().get(0)).assertXYWH(7.0, 7.0, 460.0, 146.0, 0.01).assertClass(javafx.scene.control.Label.class); new AssertNode(migPane.getChildren().get(1)).assertXYWH(131.0, 164.0, 212.0, 38.0, 0.01).assertClass(javafx.scene.control.Label.class); } @Test public void wrap() { loadCSS(); setLabel("wrap"); MigPane migPane = TestUtil.runThenWaitForPaintPulse( () -> { MigPane constructMigPane = new MigPane(new LC().debug().fillX(), new AC(), new AC()); pane.getChildren().add(constructMigPane); // add nodes for (int i = 0; i < 10; i++) { TextField lRectangle = new TextField(); CC lCC = new CC(); if ((i + 1) % 3 == 0) { lCC = lCC.growX().wrap(); // wrap every 3rd } constructMigPane.add(lRectangle, lCC); } return constructMigPane; }); //generateSource(migPane); assertWH(migPane, 436.0, 159.0); new AssertNode(migPane.getChildren().get(0)).assertXYWH(7.0, 7.0, 136.0, 31.0, 0.01).assertClass(javafx.scene.control.TextField.class); new AssertNode(migPane.getChildren().get(1)).assertXYWH(150.0, 7.0, 136.0, 31.0, 0.01).assertClass(javafx.scene.control.TextField.class); new AssertNode(migPane.getChildren().get(2)).assertXYWH(293.0, 7.0, 136.0, 31.0, 0.01).assertClass(javafx.scene.control.TextField.class); new AssertNode(migPane.getChildren().get(3)).assertXYWH(7.0, 45.0, 136.0, 31.0, 0.01).assertClass(javafx.scene.control.TextField.class); new AssertNode(migPane.getChildren().get(4)).assertXYWH(150.0, 45.0, 136.0, 31.0, 0.01).assertClass(javafx.scene.control.TextField.class); new AssertNode(migPane.getChildren().get(5)).assertXYWH(293.0, 45.0, 136.0, 31.0, 0.01).assertClass(javafx.scene.control.TextField.class); new AssertNode(migPane.getChildren().get(6)).assertXYWH(7.0, 83.0, 136.0, 31.0, 0.01).assertClass(javafx.scene.control.TextField.class); new AssertNode(migPane.getChildren().get(7)).assertXYWH(150.0, 83.0, 136.0, 31.0, 0.01).assertClass(javafx.scene.control.TextField.class); new AssertNode(migPane.getChildren().get(8)).assertXYWH(293.0, 83.0, 136.0, 31.0, 0.01).assertClass(javafx.scene.control.TextField.class); new AssertNode(migPane.getChildren().get(9)).assertXYWH(7.0, 121.0, 136.0, 31.0, 0.01).assertClass(javafx.scene.control.TextField.class); } @Test public void external() { loadCSS(); setLabel("external"); MigPane migPane = TestUtil.runThenWaitForPaintPulse( () -> { MigPane constructMigPane = new MigPane(new LC().debug().fillX(), new AC(), new AC()); pane.getChildren().add(constructMigPane); // add managed nodes constructMigPane.add(new TextField(), new CC()); constructMigPane.add(new Rectangle(30,30, Color.RED), new CC()); // add external (not unmanaged..) nodes Rectangle rectangle = new Rectangle(100, 50, 30, 30); constructMigPane.add(rectangle, new CC().external()); return constructMigPane; }); //generateSource(migPane); assertWH(migPane, 187.0, 45.0); new AssertNode(migPane.getChildren().get(0)).assertXYWH(7.0, 7.0, 136.0, 31.0, 0.01).assertClass(javafx.scene.control.TextField.class); new AssertNode(migPane.getChildren().get(1)).assertXYWH(150.0, 8.0, 30.0, 30.0, 0.01).assertClass(javafx.scene.shape.Rectangle.class); new AssertNode(migPane.getChildren().get(2)).assertXYWH(0.0, 0.0, 130.0, 80.0, 0.01).assertClass(javafx.scene.shape.Rectangle.class); } @Test public void defaultLayout() { loadCSS(); setLabel("defaultLayout"); MigPane migPane = TestUtil.runThenWaitForPaintPulse( () -> { MigPane constructMigPane = new MigPane(new LC().debug().fillX(), new AC(), new AC()); pane.getChildren().add(constructMigPane); // add nodes constructMigPane.add(new Label("First name"), ""); constructMigPane.add(new TextField(), ""); constructMigPane.add(new Label("Last name"), "gap unrelated"); constructMigPane.add(new TextField(), "wrap"); constructMigPane.add(new Label("Address"), ""); constructMigPane.add(new TextField(), "span, grow"); return constructMigPane; }); //generateSource(migPane); assertWH(migPane, 502.0, 83.0); new AssertNode(migPane.getChildren().get(0)).assertXYWH(7.0, 13.0, 97.0, 19.0, 0.01).assertClass(javafx.scene.control.Label.class); new AssertNode(migPane.getChildren().get(1)).assertXYWH(111.0, 7.0, 136.0, 31.0, 0.01).assertClass(javafx.scene.control.TextField.class); new AssertNode(migPane.getChildren().get(2)).assertXYWH(265.0, 13.0, 87.0, 19.0, 0.01).assertClass(javafx.scene.control.Label.class); new AssertNode(migPane.getChildren().get(3)).assertXYWH(359.0, 7.0, 136.0, 31.0, 0.01).assertClass(javafx.scene.control.TextField.class); new AssertNode(migPane.getChildren().get(4)).assertXYWH(7.0, 51.0, 68.0, 19.0, 0.01).assertClass(javafx.scene.control.Label.class); new AssertNode(migPane.getChildren().get(5)).assertXYWH(111.0, 45.0, 384.0, 31.0, 0.01).assertClass(javafx.scene.control.TextField.class); } @Test public void span() { loadCSS(); setLabel("span"); MigPane migPane = TestUtil.runThenWaitForPaintPulse( () -> { MigPane constructMigPane = new MigPane(new LC().debug().fillX(), new AC(), new AC()); pane.getChildren().add(constructMigPane); // add nodes for (int i = 0; i < 10; i++) { constructMigPane.add(new Button("MMMMMMMMMMMMMMMMMMMMMMMMMMMM".substring(0, i + 1)), i < 9 ? new CC() : new CC().wrap()); } for (int i = 1; i < 10; i++) { constructMigPane.add(new Button("MMMMMMMMMMMMMMMMMMMMMMMMMMMM".substring(0, i + 1)), new CC().wrap().spanX()); } return constructMigPane; }); //generateSource(migPane); assertWH(migPane, 831.0, 394.0); new AssertNode(migPane.getChildren().get(0)).assertXYWH(7.0, 7.0, 32.0, 31.0, 0.01).assertClass(javafx.scene.control.Button.class); new AssertNode(migPane.getChildren().get(1)).assertXYWH(46.0, 7.0, 42.0, 31.0, 0.01).assertClass(javafx.scene.control.Button.class); new AssertNode(migPane.getChildren().get(2)).assertXYWH(95.0, 7.0, 51.0, 31.0, 0.01).assertClass(javafx.scene.control.Button.class); new AssertNode(migPane.getChildren().get(3)).assertXYWH(153.0, 7.0, 61.0, 31.0, 0.01).assertClass(javafx.scene.control.Button.class); new AssertNode(migPane.getChildren().get(4)).assertXYWH(221.0, 7.0, 71.0, 31.0, 0.01).assertClass(javafx.scene.control.Button.class); new AssertNode(migPane.getChildren().get(5)).assertXYWH(299.0, 7.0, 80.0, 31.0, 0.01).assertClass(javafx.scene.control.Button.class); new AssertNode(migPane.getChildren().get(6)).assertXYWH(386.0, 7.0, 90.0, 31.0, 0.01).assertClass(javafx.scene.control.Button.class); new AssertNode(migPane.getChildren().get(7)).assertXYWH(483.0, 7.0, 99.0, 31.0, 0.01).assertClass(javafx.scene.control.Button.class); new AssertNode(migPane.getChildren().get(8)).assertXYWH(589.0, 7.0, 109.0, 31.0, 0.01).assertClass(javafx.scene.control.Button.class); new AssertNode(migPane.getChildren().get(9)).assertXYWH(705.0, 7.0, 119.0, 31.0, 0.01).assertClass(javafx.scene.control.Button.class); new AssertNode(migPane.getChildren().get(10)).assertXYWH(7.0, 45.0, 42.0, 31.0, 0.01).assertClass(javafx.scene.control.Button.class); new AssertNode(migPane.getChildren().get(11)).assertXYWH(7.0, 83.0, 51.0, 31.0, 0.01).assertClass(javafx.scene.control.Button.class); new AssertNode(migPane.getChildren().get(12)).assertXYWH(7.0, 121.0, 61.0, 31.0, 0.01).assertClass(javafx.scene.control.Button.class); new AssertNode(migPane.getChildren().get(13)).assertXYWH(7.0, 159.0, 71.0, 31.0, 0.01).assertClass(javafx.scene.control.Button.class); new AssertNode(migPane.getChildren().get(14)).assertXYWH(7.0, 197.0, 80.0, 31.0, 0.01).assertClass(javafx.scene.control.Button.class); new AssertNode(migPane.getChildren().get(15)).assertXYWH(7.0, 235.0, 90.0, 31.0, 0.01).assertClass(javafx.scene.control.Button.class); new AssertNode(migPane.getChildren().get(16)).assertXYWH(7.0, 273.0, 99.0, 31.0, 0.01).assertClass(javafx.scene.control.Button.class); new AssertNode(migPane.getChildren().get(17)).assertXYWH(7.0, 311.0, 109.0, 31.0, 0.01).assertClass(javafx.scene.control.Button.class); new AssertNode(migPane.getChildren().get(18)).assertXYWH(7.0, 349.0, 119.0, 31.0, 0.01).assertClass(javafx.scene.control.Button.class); } // ============================================================================================================================================================================================================================= // SUPPORT List EXCLUDED_CLASSES = java.util.Arrays.asList(new String[]{"org.tbee.javafx.scene.layout.MigPane$DebugRectangle"}); private void assertWH(MigPane migPane, double w, double h) { Assert.assertEquals(w, migPane.getWidth(), 0.01); Assert.assertEquals(h, migPane.getHeight(), 0.01); } private void setLabel(String s) { PlatformUtil.runAndWait( () -> { label.setText(s); }); } private void generateSource(Pane pane) { System.out.println(label.getText()); System.out.println("assertWH(migPane, " + pane.getWidth() + ", " + pane.getHeight() + ");"); AssertNode.generateSource("migPane", pane.getChildren(), EXCLUDED_CLASSES, false, AssertNode.A.XYWH, AssertNode.A.CLASS); TestUtil.sleep(3000); } private void loadCSS() { TestUtil.runThenWaitForPaintPulse( () -> { Stage lStage = (Stage)getWindows().get(0); lStage.getScene().getStylesheets().addAll(this.getClass().getResource("MigPaneInternalLayoutTest.css").toExternalForm()); }); } } miglayout-5.1/javafx/src/test/java/org/tbee/javafx/scene/layout/trial/000077500000000000000000000000001324101563200260465ustar00rootroot00000000000000miglayout-5.1/javafx/src/test/java/org/tbee/javafx/scene/layout/trial/AnimDemo.java000066400000000000000000000031651324101563200304070ustar00rootroot00000000000000package org.tbee.javafx.scene.layout.trial; import javafx.animation.KeyFrame; import javafx.animation.Timeline; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.paint.Color; import javafx.scene.shape.Rectangle; import javafx.stage.Stage; import javafx.util.Duration; import org.tbee.javafx.scene.layout.LayoutAnimator; import org.tbee.javafx.scene.layout.MigPane; import java.util.Random; import static javafx.animation.Timeline.INDEFINITE; /** * @author Mikael Grev, MiG InfoCom AB * Date: 14-09-25 * Time: 20:43 */ public class AnimDemo extends Application { private final Random random = new Random(1); private MigPane pane; public static void main(String[] args) { launch(args); } public void start(Stage stage) { pane = new MigPane("flowy, align center center"); stage.setScene(new Scene(pane, 600, 800)); stage.sizeToScene(); stage.show(); for (int i = 0; i++ < 3;) pane.add(getIx(), createRect()); Timeline timer = new Timeline(new KeyFrame(new Duration(LayoutAnimator.ANIM_DURATION.toMillis() + 300), e -> { if (Math.random() > 0.6 || pane.getChildren().size() < 3) { pane.add(getIx(), createRect(), ""); } else { pane.remove(getIx()); } })); timer.setCycleCount(INDEFINITE); timer.play(); } private int getIx() { int size = pane.getChildren().size(); return size == 0 ? 0 : random.nextInt(size); } private Rectangle createRect() { Rectangle rect = new Rectangle(500, 100); rect.setFill(Color.color(Math.random(), Math.random(), Math.random())); rect.setArcHeight(15); rect.setArcWidth(15); return rect; } } miglayout-5.1/javafx/src/test/java/org/tbee/javafx/scene/layout/trial/MigPaneBaselineTrial.java000066400000000000000000000021141324101563200326660ustar00rootroot00000000000000package org.tbee.javafx.scene.layout.trial; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.scene.control.TextField; import javafx.scene.text.Font; import javafx.stage.Stage; import net.miginfocom.layout.AC; import net.miginfocom.layout.LC; import org.tbee.javafx.scene.layout.MigPane; /** * Test miglayout managed and unmanaged nodes * @author Tom Eugelink * */ public class MigPaneBaselineTrial extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) { // root MigPane lRoot = new MigPane(new LC().debug(1000), new AC(), new AC()); // add managed nodes Label label = new Label("We should"); label.setFont(new Font(40)); lRoot.add(label, "split 2"); lRoot.add(new TextField("have the same baseline")); // lRoot.add(new Rectangle(30,30, Color.YELLOW), new CC()); // create scene Scene scene = new Scene(lRoot, -1, -1); // create stage stage.setTitle("Test"); stage.setScene(scene); stage.sizeToScene(); stage.show(); } }miglayout-5.1/javafx/src/test/java/org/tbee/javafx/scene/layout/trial/MigPaneHidemodeTrial.java000066400000000000000000000044611324101563200326710ustar00rootroot00000000000000package org.tbee.javafx.scene.layout.trial; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Separator; import javafx.scene.control.TextField; import javafx.stage.Stage; import net.miginfocom.layout.AC; import net.miginfocom.layout.LC; import org.tbee.javafx.scene.layout.MigPane; /** * @author Mikael Grev, MiG InfoCom AB * Date: 14-04-29 * Time: 14:22 */ public class MigPaneHidemodeTrial extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) { // add managed nodes Button button = new Button("Change Visibility"); TextField textField0 = new TextField("hidemode 0"); TextField textField1 = new TextField("hidemode 1"); TextField textField2 = new TextField("hidemode 2"); TextField textField3 = new TextField("hidemode 3"); MigPane pane = new MigPane(new LC().debug().pack(), new AC(), new AC()); pane.add(button, "wrap"); pane.add(new Separator(), "growx, wrap"); pane.add(textField0, "hidemode 0, gap 10 10 10 10, wrap"); pane.add(new Separator(), "growx, wrap"); pane.add(textField1, "hidemode 1, gap 10 10 10 10, wrap"); pane.add(new Separator(), "growx, wrap"); pane.add(textField2, "hidemode 2, gap 10 10 10 10, wrap"); pane.add(new Separator(), "growx, wrap"); pane.add(textField3, "hidemode 3, gap 10 10 10 10, wrap"); pane.add(new Separator(), "growx, wrap"); // VBox pane = new VBox(); // pane.getChildren().add(button); // pane.getChildren().add(new Separator()); // pane.getChildren().add(textField0); // pane.getChildren().add(new Separator()); // pane.getChildren().add(textField1); // pane.getChildren().add(new Separator()); // pane.getChildren().add(textField2);q // pane.getChildren().add(new Separator()); // pane.getChildren().add(textField3); // pane.getChildren().add(new Separator()); button.setOnAction(event -> { textField0.setVisible(!textField0.isVisible()); textField1.setVisible(!textField1.isVisible()); textField2.setVisible(!textField2.isVisible()); textField3.setVisible(!textField3.isVisible()); }); // create scene Scene scene = new Scene(pane, -1, -1); // create stage stage.setTitle("Test"); stage.setScene(scene); stage.sizeToScene(); stage.show(); } } miglayout-5.1/javafx/src/test/java/org/tbee/javafx/scene/layout/trial/MigPanePackTrial.java000066400000000000000000000032121324101563200320220ustar00rootroot00000000000000package org.tbee.javafx.scene.layout.trial; import javafx.animation.KeyFrame; import javafx.animation.Timeline; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.scene.text.Font; import javafx.scene.text.TextAlignment; import javafx.stage.Stage; import javafx.util.Duration; import net.miginfocom.layout.LC; import org.tbee.javafx.scene.layout.MigPane; import java.util.concurrent.atomic.AtomicBoolean; /** * Test miglayout managed and unmanaged nodes * @author Tom Eugelink * */ public class MigPanePackTrial extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) { // root MigPane rootMP = new MigPane(new LC().pack().packAlign(0.5f, 1f)); // add managed nodes Label label = new Label("Pack it up!"); rootMP.add(label, "alignx center, wrap unrel"); Label wrapLabel = new Label("The only thing changed\nis the font size"); wrapLabel.setTextAlignment(TextAlignment.CENTER); rootMP.add(wrapLabel, "alignx center"); // create scene Scene scene = new Scene(rootMP); // create stage stage.setTitle("Pack Trial"); stage.setScene(scene); stage.sizeToScene(); stage.show(); AtomicBoolean up = new AtomicBoolean(true); Timeline timeline = new Timeline(new KeyFrame(Duration.millis(40), event -> { double oldSize = label.getFont().getSize(); if (oldSize > 100) { up.set(false); } else if (oldSize < 10) { up.set(true); stage.centerOnScreen(); } label.setFont(new Font(oldSize + (up.get() ? 2 : -2))); })); timeline.setCycleCount(-1); timeline.play(); } }miglayout-5.1/javafx/src/test/java/org/tbee/javafx/scene/layout/trial/MigPanePosTrial.java000066400000000000000000000017701324101563200317140ustar00rootroot00000000000000package org.tbee.javafx.scene.layout.trial; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.scene.layout.FlowPane; import javafx.stage.Stage; import org.tbee.javafx.scene.layout.MigPane; /** * Created by user mikaelgrev on 18-01-16. */ public class MigPanePosTrial extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) { MigPane migPane = new MigPane("debug"); FlowPane flowPane = new FlowPane(); flowPane.getChildren().add(new Label("1")); flowPane.getChildren().add(new Label("2")); flowPane.getChildren().add(new Label("3")); migPane.add(new Label("3"), "pos container.x 0"); // migPane.add(new Label("3"), "pos 0 0"); // This instead of above made it always work. migPane.add(flowPane, ""); // Before fix to Grid.java in 2018-01-16 the flowpane became too large. Scene scene = new Scene(migPane); stage.setScene(scene); stage.show(); } } miglayout-5.1/javafx/src/test/java/org/tbee/javafx/scene/layout/trial/MigPaneSizeGroupTrial18.java000066400000000000000000000021621324101563200332470ustar00rootroot00000000000000package org.tbee.javafx.scene.layout.trial; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.stage.Stage; import org.tbee.javafx.scene.layout.MigPane; /** * @author Mikael Grev, MiG InfoCom AB * Date: 15-10-07 * Time: 21:11 */ public class MigPaneSizeGroupTrial18 extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) { // root MigPane pane = new MigPane("debug"); // add managed nodes pane.add(new Label("Should have same sizes as ->"), "sgx"); pane.add(new Label("Short"), "sgx"); // With this line the layout will not be correct pre 2015-10-07 fix since the Grid is created // with the Scene set to null pane.prefHeight(-1); // Add this and it till work again since it clears the grid. Adding "nocache" // to the LC in the constructor also works. // pane.invalidateGrid(); // create scene Scene scene = new Scene(pane, -1, -1); // create stage stage.setTitle("Test"); stage.setScene(scene); stage.sizeToScene(); stage.show(); } } miglayout-5.1/javafx/src/test/java/org/tbee/javafx/scene/layout/trial/MigPaneSizeTrial.java000066400000000000000000000025011324101563200320560ustar00rootroot00000000000000package org.tbee.javafx.scene.layout.trial; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.stage.Stage; import net.miginfocom.layout.LC; import org.tbee.javafx.scene.layout.MigPane; /** * @author Mikael Grev, MiG InfoCom AB * Date: 14-04-24 * Time: 16:33 */ public class MigPaneSizeTrial extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) { // root MigPane lRoot = new MigPane(new LC().debug().fillX()); // System.out.println(Screen.getPrimary().getDpi()); // System.out.println(Toolkit.getDefaultToolkit().getScreenResolution()); // add nodes lRoot.add(new Button("500 logical pixels (def)"), "w 500, wrap"); lRoot.add(new Button("500 logical pixels"), "w 500lp, wrap"); lRoot.add(new Button("500 pixels"), "w 500px, wrap"); lRoot.add(new Button("10 centimeters"), "w 10cm, wrap"); lRoot.add(new Button("4 inches"), "w 4in, wrap"); lRoot.add(new Button("30% of screen"), "w 30sp, wrap"); lRoot.add(new Button("30% of container"), "w 30%, wrap"); // create scene Scene scene = new Scene(lRoot); // create stage stage.setTitle("Test - resize to check container percentage"); stage.setScene(scene); stage.sizeToScene(); stage.show(); } } miglayout-5.1/javafx/src/test/java/org/tbee/javafx/scene/layout/trial/MigPaneTest11.java000066400000000000000000000062061324101563200312370ustar00rootroot00000000000000package org.tbee.javafx.scene.layout.trial; import javafx.application.Application; import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.scene.control.*; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import javafx.stage.Stage; import org.tbee.javafx.scene.layout.fxml.MigPane; import java.util.Date; /** * This test is ran out of memory because of a memory leak. * */ public class MigPaneTest11 extends Application { public static class ListElement extends MigPane { public ListElement(int i, Date date) { Label title = new Label("Element " + i); Label info = new Label("element created at: " + date); getChildren(). add(new VBox(title, info)); Button b1 = new Button("button-1"); Button b2 = new Button("button-2"); Button b3 = new Button("button-3"); b1.setMnemonicParsing(false); b2.setMnemonicParsing(false); b3.setMnemonicParsing(false); getChildren(). add(new HBox(b1, b2, b3)); } } public MigPaneTest11() { super(); // this.items = FXCollections.observableArrayList(); } // private ObservableList items; private Parent createRoot() { final ListView listView = new ListView(); // listView.setItems(this.items); Button testButton = new Button("Start test"); testButton.maxWidth(Double.MAX_VALUE); testButton.setOnAction(new EventHandler() { public void handle(final ActionEvent ev) { final Thread t = new Thread() { @Override public void run() { for (int loop = 0; loop < Integer.MAX_VALUE; loop++) { System.out.println("loop " + loop); Platform.runLater(new Runnable() { public void run() { // for (ListElement le : items) // { // le.getChildren().clear(); // } // items.clear(); ObservableList items = FXCollections.observableArrayList(); for (int i = 0; i < 10; i++) { items.add(new ListElement(i, new Date())); } listView.setItems(items); } }); try { Thread.sleep(10); } catch (final InterruptedException e) { // do nothing } } System.out.println("done"); } }; t.setDaemon(true); t.start(); } }); BorderPane borderPane = new BorderPane(); borderPane.setCenter(listView); borderPane.setBottom(testButton); return borderPane; } @Override public void start(Stage stage) throws Exception { Parent root = createRoot(); scene = new Scene(root); stage.setScene(scene); stage.setWidth(800); stage.setHeight(600); stage.show(); } static Scene scene = null; public static void main(String[] args) { launch(args); } } miglayout-5.1/javafx/src/test/java/org/tbee/javafx/scene/layout/trial/MigPaneTest14.java000066400000000000000000000023071324101563200312400ustar00rootroot00000000000000package org.tbee.javafx.scene.layout.trial; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.TextField; import javafx.scene.paint.Color; import javafx.scene.shape.Rectangle; import javafx.stage.Stage; import net.miginfocom.layout.AC; import net.miginfocom.layout.CC; import net.miginfocom.layout.LC; import org.tbee.javafx.scene.layout.MigPane; /** * Test miglayout managed and unmanaged nodes * @author Tom Eugelink * */ public class MigPaneTest14 extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) { // root MigPane lRoot = new MigPane(new LC().debug(1000), new AC(), new AC()); // add managed nodes lRoot.add(new TextField(), new CC()); lRoot.add(new Rectangle(30,30, Color.YELLOW), new CC()); // add unmanaged (not external..) nodes Rectangle rectangle = new Rectangle(100, 50, 30, 30); // should not affect bounds or preferred size of MigPane rectangle.setManaged(false); lRoot.add(rectangle); // create scene Scene scene = new Scene(lRoot, -1, -1); // create stage stage.setTitle("Test"); stage.setScene(scene); stage.sizeToScene(); stage.show(); } }miglayout-5.1/javafx/src/test/java/org/tbee/javafx/scene/layout/trial/MigPaneTest15.java000066400000000000000000000026031324101563200312400ustar00rootroot00000000000000package org.tbee.javafx.scene.layout.trial; import javafx.application.Application; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.ComboBox; import javafx.scene.control.Label; import javafx.stage.Stage; import org.tbee.javafx.scene.layout.MigPane; public class MigPaneTest15 extends Application { public static void main(String[] arguments) { launch(); } @Override public void start(Stage stage) throws Exception { Scene scene = createScene(); stage.setScene(scene); showStage(stage); } private Scene createScene() { final MigPane container = new MigPane(); Button control = new Button("Add Content"); control.setOnAction(new EventHandler() { @Override public void handle(ActionEvent actionEvent) { showContent(container); } }); MigPane parent = new MigPane(""); parent.add(control); parent.add(container); return new Scene(parent); } private void showContent(MigPane container) { container.getChildren().clear(); ComboBox comboBox = new ComboBox<>(); comboBox.getItems().add("There is a label to my left!"); Label label = new Label("I should be visible!"); container.add(label); container.add(comboBox); } private void showStage(Stage stage) { stage.setHeight(400); stage.setWidth(800); stage.show(); } }miglayout-5.1/javafx/src/test/java/org/tbee/javafx/scene/layout/trial/MigPaneTest3.java000077500000000000000000000035571324101563200311710ustar00rootroot00000000000000package org.tbee.javafx.scene.layout.trial; import javafx.application.Application; import javafx.collections.FXCollections; import javafx.scene.Scene; import javafx.scene.control.*; import javafx.stage.Stage; import net.miginfocom.layout.AC; import net.miginfocom.layout.CC; import net.miginfocom.layout.LC; import org.tbee.javafx.scene.layout.MigPane; /** * Testing if grow and push actually grow stuff * @author Tom Eugelink * */ public class MigPaneTest3 extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) { // root MigPane lRoot = new MigPane(new LC().debug(1000), new AC(), new AC()); // create 10 buttons for (int i = 0; i < 5*3; i++) { int lRow = (int)(i / 3); int lCol = (i + 1) % 3; String lText = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX".substring(0, i + 1); // add a node Control lControl = null; if ( lRow == 0) lControl = new CheckBox(lText); else if ( lRow == 1) { lControl = new TextField(); ((TextField)lControl).setText(lText); } else if ( lRow == 2) { lControl = new ChoiceBox(FXCollections.observableArrayList("X", lText, "XX")); ((ChoiceBox)lControl).getSelectionModel().select(1); } else if ( lRow == 3) { lControl = new ToggleButton(lText); } else lControl = new Button(lText); // wrong CC lCC = new CC(); if (lCol == 2) lCC = lCC.grow().push(); if (lCol == 0) lCC = lCC.wrap(); lRoot.add(lControl, lCC); } // create scene Scene scene = new Scene(lRoot, -1, -1); // create stage stage.setTitle("Test"); stage.setScene(scene); stage.sizeToScene(); stage.show(); } } miglayout-5.1/javafx/src/test/java/org/tbee/javafx/scene/layout/trial/MigPaneTest5.java000077500000000000000000000020351324101563200311610ustar00rootroot00000000000000package org.tbee.javafx.scene.layout.trial; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.TextField; import javafx.scene.shape.Rectangle; import javafx.stage.Stage; import net.miginfocom.layout.CC; import org.tbee.javafx.scene.layout.MigPane; /** * Using string constraints * @author Tom Eugelink * */ public class MigPaneTest5 extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) { // root MigPane lRoot = new MigPane("debug", "[grow,fill]", ""); // add managed nodes lRoot.add(new TextField(), ""); // add external (not unmanaged..) nodes lRoot.add(new Rectangle(100, 50, 30, 30), new CC().external()); // create scene Scene scene = new Scene(lRoot, -1, -1); // create stage stage.setTitle("Test"); stage.setScene(scene); stage.sizeToScene(); stage.show(); } } miglayout-5.1/javafx/src/test/java/org/tbee/javafx/scene/layout/trial/MigPaneTest8.java000077500000000000000000000020071324101563200311630ustar00rootroot00000000000000package org.tbee.javafx.scene.layout.trial; import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Scene; import javafx.stage.Stage; import org.tbee.javafx.scene.layout.MigPane; import java.io.IOException; import java.net.URL; /** * Load a layout from FXML * * @author Michael Paus and Tom Eugelink * */ public class MigPaneTest8 extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) throws IOException { // load FXML String lName = getClass().getSimpleName() + ".xml"; URL lURL = getClass().getResource("/" + lName); System.out.println("loading FXML " + lName + " -> " + lURL); MigPane lRoot = (MigPane)FXMLLoader.load(lURL); // create scene Scene scene = new Scene(lRoot, 800, 300); // create stage stage.setTitle(this.getClass().getSimpleName()); stage.setScene(scene); stage.show(); } } miglayout-5.1/javafx/src/test/java/org/tbee/javafx/scene/layout/trial/MigPaneTest8Controller.java000077500000000000000000000017161324101563200332350ustar00rootroot00000000000000package org.tbee.javafx.scene.layout.trial; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.control.Label; import javafx.scene.control.TextField; import org.tbee.javafx.scene.layout.MigPane; /** * Handler class for the FXML * * @author Michael Paus * @author Tom Eugelink * */ public class MigPaneTest8Controller extends MigPane { @FXML private TextField firstNameField; @FXML private TextField lastNameField; @FXML private Label messageLabel; @SuppressWarnings("unused") @FXML private void handleButtonAction(ActionEvent event) { String fullName = firstNameField.getText() + " " + lastNameField.getText(); if (fullName.length() > 1) { messageLabel.setText("Your name '" + fullName + "' was successfully entered into our spam database :-("); } else { messageLabel.setText("Sorry, but you have to provide your name!"); } } }miglayout-5.1/javafx/src/test/java/org/tbee/javafx/scene/layout/trial/MigPaneTest9.java000077500000000000000000000034151324101563200311700ustar00rootroot00000000000000package org.tbee.javafx.scene.layout.trial; import javafx.application.Application; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.control.ButtonBase; import javafx.scene.control.ToggleButton; import javafx.scene.layout.StackPane; import javafx.stage.Stage; import net.miginfocom.layout.AC; import net.miginfocom.layout.CC; import net.miginfocom.layout.LC; import org.tbee.javafx.scene.layout.MigPane; /** * Wrap MigPane in a number of other containers and set a padding. * * @author Tom Eugelink * */ public class MigPaneTest9 extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) { // root MigPane lMigPane = new MigPane(new LC().debug(1000).align("center", "center").gridGap("0px", "0px"), new AC(), new AC()); for (int i = 0; i < 9; i++) { CC lCC = new CC(); if ((i + 1) % 3 == 0) { lCC = lCC.wrap(); } final ButtonBase btn = new ToggleButton("MMMMMMMMMMMMMMMMMMMMMMMMMMMM".substring(0, i + 1)); if (i == 0) { btn.setStyle("-fx-padding: 10; "); } lMigPane.add(btn, lCC); } // include in stackpane and set a padding StackPane lStackPane = new StackPane(); lStackPane.getChildren().add(lMigPane); lStackPane.setStyle("-fx-background-color: yellow; -fx-padding: 10; "); // create scene Scene scene = new Scene(new Group(lStackPane), -1, -1); // create stage stage.setTitle("ButtonTest"); stage.setScene(scene); stage.sizeToScene(); stage.show(); } }miglayout-5.1/javafx/src/test/java/org/tbee/javafx/scene/layout/trial/MigPaneTrial1.java000066400000000000000000000017001324101563200313040ustar00rootroot00000000000000package org.tbee.javafx.scene.layout.trial; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.scene.control.Button; import javafx.stage.Stage; import net.miginfocom.layout.CC; import net.miginfocom.layout.LC; import org.tbee.javafx.scene.layout.MigPane; public class MigPaneTrial1 extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) throws Exception { MigPane migPane = new MigPane(new LC()); migPane.add(new Label("Label"), new CC().wrap()); migPane.add(new Label("Label"), new CC().wrap().push().grow()); migPane.add(new Label("Label"), new CC().wrap()); Button button = new Button("Button"); // migPane.add(button, new CC().dockWest().grow()); migPane.add(button, new CC().wrap().grow().push()); button.setRotate(90); Scene scene = new Scene(migPane); stage.setScene(scene); stage.show(); } }miglayout-5.1/javafx/src/test/java/org/tbee/javafx/scene/layout/trial/MigPaneTrial16.java000066400000000000000000000036121324101563200313760ustar00rootroot00000000000000package org.tbee.javafx.scene.layout.trial; import javafx.application.Application; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.ButtonBase; import javafx.scene.control.Label; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.stage.Stage; import net.miginfocom.layout.CC; import net.miginfocom.layout.LC; import org.tbee.javafx.scene.layout.MigPane; public class MigPaneTrial16 extends Application { public static final String PATH_TO_IMAGE = "/MigPaneTrial16.png"; public static void main(String[] arguments) { // URL url = new MigPaneTrial16().getClass().getResource(PATH_TO_IMAGE); // System.out.println(url); launch(); } @Override public void start(Stage stage) throws Exception { Scene scene = createScene(); stage.setScene(scene); stage.sizeToScene(); stage.show(); } private Scene createScene() { MigPane parent = new MigPane(new LC().debug(300)); addRowTo(parent); return new Scene(parent, 300, 100); } boolean b = true; private void addRowTo(MigPane parent) { ImageView mainIcon = new ImageView(); Button toggle = new Button("Hello", mainIcon); sizeUpButton(toggle); toggle.setOnAction(new EventHandler() { public void handle(ActionEvent event) { if (b) { mainIcon.setImage(new Image(PATH_TO_IMAGE)); // toggle.getBaselineOffset(); System.out.println("baseline img: " + toggle.getBaselineOffset()); } else { mainIcon.setImage(null); System.out.println("baseline: " + toggle.getBaselineOffset()); } b = !b; } }); parent.add(toggle, ""); parent.add(new Label("<-Click the Button"), new CC().growX().pushX()); } private void sizeUpButton(ButtonBase button) { // button.setMinSize(20, 20); // button.setPrefSize(20, 20); // button.setMaxSize(20, 20); } }miglayout-5.1/javafx/src/test/java/org/tbee/javafx/scene/layout/trial/MigPaneTrial17.java000066400000000000000000000011511324101563200313730ustar00rootroot00000000000000package org.tbee.javafx.scene.layout.trial; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.stage.Stage; import net.miginfocom.layout.LC; import org.tbee.javafx.scene.layout.MigPane; public class MigPaneTrial17 extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) throws Exception { MigPane migPane = new MigPane(new LC().wrapAfter(1)); migPane.getChildren().add(0, new Button("Test")); Scene scene = new Scene(migPane); stage.setScene(scene); stage.show(); } }miglayout-5.1/javafx/src/test/java/org/tbee/javafx/scene/layout/trial/MigTestTest10.java000066400000000000000000000025261324101563200312730ustar00rootroot00000000000000package org.tbee.javafx.scene.layout.trial; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.paint.Color; import javafx.stage.Stage; import org.tbee.javafx.scene.layout.MigPane; /** * Test a nested MigPane * */ public class MigTestTest10 extends Application { public static void main(String[] args) { launch(args); } @Override public void start(final Stage stage) throws InterruptedException { MigPane lOuterMigPane = new MigPane("debug"); lOuterMigPane.setId("outer"); lOuterMigPane.setDebugCellColor(null); lOuterMigPane.setDebugOutlineColor(Color.BLUE); lOuterMigPane.setDebugContainerOutlineColor(Color.BLUE); lOuterMigPane.add(new Button("In outer MigPane")); MigPane lNestedMigPane = new MigPane("debug"); lNestedMigPane.setId("nested"); lNestedMigPane.setDebugCellColor(null); lNestedMigPane.setDebugOutlineColor(Color.RED); lNestedMigPane.setDebugContainerOutlineColor(Color.RED); lNestedMigPane.add(new Button("In nested MigPane")); lOuterMigPane.add(lNestedMigPane); Scene scene = new Scene(lOuterMigPane); stage.setScene(scene); stage.sizeToScene(); stage.show(); } } miglayout-5.1/javafx/src/test/resources/000077500000000000000000000000001324101563200204255ustar00rootroot00000000000000miglayout-5.1/javafx/src/test/resources/MigPaneTest8.xml000077500000000000000000000013521324101563200234230ustar00rootroot00000000000000