miglayout-3.7.4/0000755000175000017500000000000011574447716012323 5ustar tonytonymiglayout-3.7.4/META-INF/0000755000175000017500000000000011521733276013452 5ustar tonytonymiglayout-3.7.4/META-INF/MANIFEST.MF0000644000175000017500000000014311521733274015100 0ustar tonytonyManifest-Version: 1.0 Archiver-Version: Plexus Archiver Created-By: 17.1-b03-307 (Apple Inc.) miglayout-3.7.4/net/0000755000175000017500000000000011252374660013077 5ustar tonytonymiglayout-3.7.4/net/miginfocom/0000755000175000017500000000000011252374662015230 5ustar tonytonymiglayout-3.7.4/net/miginfocom/swing/0000755000175000017500000000000011455506144016354 5ustar tonytonymiglayout-3.7.4/net/miginfocom/swing/SwingComponentWrapper.java0000644000175000017500000003106311521471106023526 0ustar tonytonypackage net.miginfocom.swing; /* * 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 net.miginfocom.layout.ComponentWrapper; import net.miginfocom.layout.ContainerWrapper; import net.miginfocom.layout.PlatformDefaults; import javax.swing.*; import javax.swing.text.JTextComponent; import java.awt.*; import java.awt.geom.Rectangle2D; import java.lang.reflect.Method; import java.util.IdentityHashMap; /** */ public class SwingComponentWrapper implements ComponentWrapper { private static boolean maxSet = false; private static boolean vp = true; /** Debug color for component bounds outline. */ private static final Color DB_COMP_OUTLINE = new Color(0, 0, 200); private final Component c; private int compType = TYPE_UNSET; private Boolean bl = null; private boolean prefCalled = false; public SwingComponentWrapper(Component c) { this.c = c; } public final int getBaseline(int width, int height) { if (BL_METHOD == null) return -1; try { Object[] args = new Object[] { Integer.valueOf(width < 0 ? c.getWidth() : width), Integer.valueOf(height < 0 ? c.getHeight() : height) }; return ((Integer) BL_METHOD.invoke(c, args)).intValue(); } catch (Exception e) { return -1; } } public final Object getComponent() { return c; } /** Cache. */ private final static IdentityHashMap FM_MAP = new IdentityHashMap(4); private final static Font SUBST_FONT = new Font("sansserif", Font.PLAIN, 11); public final float getPixelUnitFactor(boolean isHor) { switch (PlatformDefaults.getLogicalPixelBase()) { case PlatformDefaults.BASE_FONT_SIZE: Font font = c.getFont(); FontMetrics fm = c.getFontMetrics(font != null ? font : SUBST_FONT); Point.Float p = FM_MAP.get(fm); if (p == null) { Rectangle2D r = fm.getStringBounds("X", c.getGraphics()); p = new Point.Float(((float) r.getWidth()) / 6f, ((float) r.getHeight()) / 13.27734375f); FM_MAP.put(fm, p); } return isHor ? p.x : p.y; case PlatformDefaults.BASE_SCALE_FACTOR: Float s = isHor ? PlatformDefaults.getHorizontalScaleFactor() : PlatformDefaults.getVerticalScaleFactor(); if (s != null) return s.floatValue(); return (isHor ? getHorizontalScreenDPI() : getVerticalScreenDPI()) / (float) PlatformDefaults.getDefaultDPI(); default: return 1f; } } // /** Cache. // */ // private final static IdentityHashMap FM_MAP2 = new IdentityHashMap(4); // private final static Font SUBST_FONT2 = new Font("sansserif", Font.PLAIN, 11); // // public float getDialogUnit(boolean isHor) // { // Font font = c.getFont(); // FontMetrics fm = c.getFontMetrics(font != null ? font : SUBST_FONT2); // Point.Float dluP = FM_MAP2.get(fm); // if (dluP == null) { // float w = fm.charWidth('X') / 4f; // int ascent = fm.getAscent(); // float h = (ascent > 14 ? ascent : ascent + (15 - ascent) / 3) / 8f; // // dluP = new Point.Float(w, h); // FM_MAP2.put(fm, dluP); // } // return isHor ? dluP.x : dluP.y; // } public final int getX() { return c.getX(); } public final int getY() { return c.getY(); } public final int getHeight() { return c.getHeight(); } public final int getWidth() { return c.getWidth(); } public final int getScreenLocationX() { Point p = new Point(); SwingUtilities.convertPointToScreen(p, c); return p.x; } public final int getScreenLocationY() { Point p = new Point(); SwingUtilities.convertPointToScreen(p, c); return p.y; } public final int getMinimumHeight(int sz) { if (prefCalled == false) { c.getPreferredSize(); // To defeat a bug where the minimum size is different before and after the first call to getPreferredSize(); prefCalled = true; } return c.getMinimumSize().height; } public final int getMinimumWidth(int sz) { if (prefCalled == false) { c.getPreferredSize(); // To defeat a bug where the minimum size is different before and after the first call to getPreferredSize(); prefCalled = true; } return c.getMinimumSize().width; } public final int getPreferredHeight(int sz) { // If the component has not gotten size yet and there is a size hint, trick Swing to return a better height. if (c.getWidth() == 0 && c.getHeight() == 0 && sz != -1) c.setBounds(c.getX(), c.getY(), sz, 1); return c.getPreferredSize().height; } public final int getPreferredWidth(int sz) { // If the component has not gotten size yet and there is a size hint, trick Swing to return a better height. if (c.getWidth() == 0 && c.getHeight() == 0 && sz != -1) c.setBounds(c.getX(), c.getY(), 1, sz); return c.getPreferredSize().width; } public final int getMaximumHeight(int sz) { if (!isMaxSet(c)) return Short.MAX_VALUE; return c.getMaximumSize().height; } public final int getMaximumWidth(int sz) { if (!isMaxSet(c)) return Short.MAX_VALUE; return c.getMaximumSize().width; } private boolean isMaxSet(Component c) { if (IMS_METHOD != null) { try { return ((Boolean) IMS_METHOD.invoke(c, (Object[]) null)).booleanValue(); } catch (Exception e) { IMS_METHOD = null; // So we do not try every time. } } return isMaxSizeSetOn1_4(); } public final ContainerWrapper getParent() { Container p = c.getParent(); return p != null ? new SwingContainerWrapper(p) : null; } public final int getHorizontalScreenDPI() { return PlatformDefaults.getDefaultDPI(); } public final int getVerticalScreenDPI() { return PlatformDefaults.getDefaultDPI(); } public final int getScreenWidth() { try { return c.getToolkit().getScreenSize().width; } catch (HeadlessException ex) { return 1024; } } public final int getScreenHeight() { try { return c.getToolkit().getScreenSize().height; } catch (HeadlessException ex) { return 768; } } public final boolean hasBaseline() { if (bl == null) { try { if (BL_RES_METHOD == null || BL_RES_METHOD.invoke(c).toString().equals("OTHER")) { bl = Boolean.FALSE; } else { Dimension d = c.getMinimumSize(); bl = Boolean.valueOf(getBaseline(d.width, d.height) > -1); } } catch (Throwable ex) { bl = Boolean.FALSE; } } return bl.booleanValue(); } public final String getLinkId() { return c.getName(); } public final void setBounds(int x, int y, int width, int height) { c.setBounds(x, y, width, height); } public boolean isVisible() { return c.isVisible(); } public final int[] getVisualPadding() { if (vp && c instanceof JTabbedPane) { if (UIManager.getLookAndFeel().getClass().getName().endsWith("WindowsLookAndFeel")) return new int[] {-1, 0, 2, 2}; } return null; } public static boolean isMaxSizeSetOn1_4() { return maxSet; } public static void setMaxSizeSetOn1_4(boolean b) { maxSet = b; } public static boolean isVisualPaddingEnabled() { return vp; } public static void setVisualPaddingEnabled(boolean b) { vp = b; } public final void paintDebugOutline() { if (c.isShowing() == false) return; Graphics2D g = (Graphics2D) c.getGraphics(); if (g == null) return; g.setPaint(DB_COMP_OUTLINE); g.setStroke(new BasicStroke(1f, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10f, new float[] {2f, 4f}, 0)); g.drawRect(0, 0, getWidth() - 1, getHeight() - 1); } public int getComponetType(boolean disregardScrollPane) { if (compType == TYPE_UNSET) compType = checkType(disregardScrollPane); return compType; } public int getLayoutHashCode() { Dimension d = c.getMaximumSize(); int h = d.width + (d.height << 5); d = c.getPreferredSize(); h += (d.width << 10) + (d.height << 15); d = c.getMinimumSize(); h += (d.width << 20) + (d.height << 25); if (c.isVisible()) h += 1324511; String id = getLinkId(); if (id != null) h += id.hashCode(); return h; // Since 2.3 will check the isValid instead everything that affects that can be removed from the layout hashcode. // String id = getLinkId(); // return id != null ? id.hashCode() : 1; } private int checkType(boolean disregardScrollPane) { Component c = this.c; if (disregardScrollPane) { if (c instanceof JScrollPane) { c = ((JScrollPane) c).getViewport().getView(); } else if (c instanceof ScrollPane) { c = ((ScrollPane) c).getComponent(0); } } if (c instanceof JTextField || c instanceof TextField) { return TYPE_TEXT_FIELD; } else if (c instanceof JLabel || c instanceof Label) { return TYPE_LABEL; } else if (c instanceof JToggleButton || c instanceof Checkbox) { return TYPE_CHECK_BOX; } else if (c instanceof AbstractButton || c instanceof Button) { return TYPE_BUTTON; } else if (c instanceof JComboBox || c instanceof Choice) { return TYPE_LABEL; } else if (c instanceof JTextComponent || c instanceof TextComponent) { return TYPE_TEXT_AREA; } else if (c instanceof JPanel || c instanceof Canvas) { return TYPE_PANEL; } else if (c instanceof JList || c instanceof List) { return TYPE_LIST; } else if (c instanceof JTable) { return TYPE_TABLE; } else if (c instanceof JSeparator) { return TYPE_SEPARATOR; } else if (c instanceof JSpinner) { return TYPE_SPINNER; } else if (c instanceof JProgressBar) { return TYPE_PROGRESS_BAR; } else if (c instanceof JSlider) { return TYPE_SLIDER; } else if (c instanceof JScrollPane) { return TYPE_SCROLL_PANE; } else if (c instanceof JScrollBar || c instanceof Scrollbar) { return TYPE_SCROLL_BAR; } else if (c instanceof Container) { // only AWT components is not containers. return TYPE_CONTAINER; } return TYPE_UNKNOWN; } public final int hashCode() { return getComponent().hashCode(); } public final boolean equals(Object o) { if (o instanceof ComponentWrapper == false) return false; return getComponent().equals(((ComponentWrapper) o).getComponent()); } /** Cached method used for getting base line with reflection. */ private static Method BL_METHOD = null; private static Method BL_RES_METHOD = null; static { try { BL_METHOD = Component.class.getDeclaredMethod("getBaseline", new Class[] {int.class, int.class}); BL_RES_METHOD = Component.class.getDeclaredMethod("getBaselineResizeBehavior"); // 3.7.2: Removed Class null since that made the method inaccessible. } catch (Throwable e) { // No such method or security exception } } private static Method IMS_METHOD = null; static { try { IMS_METHOD = Component.class.getDeclaredMethod("isMaximumSizeSet", (Class[]) null); } catch (Throwable e) { // No such method or security exception } } } miglayout-3.7.4/net/miginfocom/swing/MigLayout.java0000644000175000017500000006100111521471050021116 0ustar tonytonypackage net.miginfocom.swing; /* * 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 net.miginfocom.layout.*; import javax.swing.*; import javax.swing.Timer; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.*; import java.util.*; /** A very flexible layout manager. *

* Read the documentation that came with this layout manager for information on usage. */ public final class MigLayout implements LayoutManager2, Externalizable { // ******** Instance part ******** /** The component to string constraints mappings. */ private final Map scrConstrMap = new IdentityHashMap(8); /** Hold the serializable text representation of the constraints. */ private Object layoutConstraints = "", colConstraints = "", rowConstraints = ""; // Should never be null! // ******** Transient part ******** private transient ContainerWrapper cacheParentW = null; private transient final Map ccMap = new HashMap(8); private transient javax.swing.Timer debugTimer = null; private transient LC lc = null; private transient AC colSpecs = null, rowSpecs = null; private transient Grid grid = null; private transient int lastModCount = PlatformDefaults.getModCount(); private transient int lastHash = -1; private transient Dimension lastInvalidSize = null; private transient boolean lastWasInvalid = false; // Added in 3.7.1. May have regressions private transient Dimension lastParentSize = null; private transient ArrayList callbackList = null; private transient boolean dirty = true; /** Constructor with no constraints. */ public MigLayout() { this("", "", ""); } /** Constructor. * @param layoutConstraints The constraints that concern the whole layout. null will be treated as "". */ public MigLayout(String layoutConstraints) { this(layoutConstraints, "", ""); } /** Constructor. * @param layoutConstraints The constraints that concern the whole layout. null will be treated as "". * @param colConstraints The constraints for the columns in the grid. null will be treated as "". */ public MigLayout(String layoutConstraints, String colConstraints) { this(layoutConstraints, colConstraints, ""); } /** Constructor. * @param layoutConstraints The constraints that concern the whole layout. null will be treated as "". * @param colConstraints The constraints for the columns in the grid. null will be treated as "". * @param rowConstraints The constraints for the rows in the grid. null will be treated as "". */ public MigLayout(String layoutConstraints, String colConstraints, String rowConstraints) { setLayoutConstraints(layoutConstraints); setColumnConstraints(colConstraints); setRowConstraints(rowConstraints); } /** Constructor. * @param layoutConstraints The constraints that concern the whole layout. null will be treated as an empty constraint. */ public MigLayout(LC layoutConstraints) { this(layoutConstraints, null, null); } /** Constructor. * @param layoutConstraints The constraints that concern the whole layout. null will be treated as an empty constraint. * @param colConstraints The constraints for the columns in the grid. null will be treated as an empty constraint. */ public MigLayout(LC layoutConstraints, AC colConstraints) { this(layoutConstraints, colConstraints, null); } /** Constructor. * @param layoutConstraints The constraints that concern the whole layout. null will be treated as an empty constraint. * @param colConstraints The constraints for the columns in the grid. null will be treated as an empty constraint. * @param rowConstraints The constraints for the rows in the grid. null will be treated as an empty constraint. */ public MigLayout(LC layoutConstraints, AC colConstraints, AC rowConstraints) { setLayoutConstraints(layoutConstraints); setColumnConstraints(colConstraints); setRowConstraints(rowConstraints); } /** Returns layout constraints either as a String or {@link net.miginfocom.layout.LC} depending what was sent in * to the constructor or set with {@link #setLayoutConstraints(Object)}. * @return The layout constraints either as a String or {@link net.miginfocom.layout.LC} depending what was sent in * to the constructor or set with {@link #setLayoutConstraints(Object)}. Never null. */ public Object getLayoutConstraints() { return layoutConstraints; } /** Sets the layout constraints for the layout manager instance as a String. *

* See the class JavaDocs for information on how this string is formatted. * @param constr The layout constraints as a String representation. null is converted to "" for storage. * @throws RuntimeException if the constraint was not valid. */ public void setLayoutConstraints(Object constr) { if (constr == null || constr instanceof String) { constr = ConstraintParser.prepare((String) constr); lc = ConstraintParser.parseLayoutConstraint((String) constr); } else if (constr instanceof LC) { lc = (LC) constr; } else { throw new IllegalArgumentException("Illegal constraint type: " + constr.getClass().toString()); } layoutConstraints = constr; dirty = true; } /** Returns the column layout constraints either as a String or {@link net.miginfocom.layout.AC}. * @return The column constraints either as a String or {@link net.miginfocom.layout.LC} depending what was sent in * to the constructor or set with {@link #setLayoutConstraints(Object)}. Never null. */ public Object getColumnConstraints() { return colConstraints; } /** Sets the column layout constraints for the layout manager instance as a String. *

* See the class JavaDocs for information on how this string is formatted. * @param constr The column layout constraints as a String representation. null is converted to "" for storage. * @throws RuntimeException if the constraint was not valid. */ public void setColumnConstraints(Object constr) { if (constr == null || constr instanceof String) { constr = ConstraintParser.prepare((String) constr); colSpecs = ConstraintParser.parseColumnConstraints((String) constr); } else if (constr instanceof AC) { colSpecs = (AC) constr; } else { throw new IllegalArgumentException("Illegal constraint type: " + constr.getClass().toString()); } colConstraints = constr; dirty = true; } /** Returns the row layout constraints as a String representation. This string is the exact string as set with {@link #setRowConstraints(Object)} * or sent into the constructor. *

* See the class JavaDocs for information on how this string is formatted. * @return The row layout constraints as a String representation. Never null. */ public Object getRowConstraints() { return rowConstraints; } /** Sets the row layout constraints for the layout manager instance as a String. *

* See the class JavaDocs for information on how this string is formatted. * @param constr The row layout constraints as a String representation. null is converted to "" for storage. * @throws RuntimeException if the constraint was not valid. */ public void setRowConstraints(Object constr) { if (constr == null || constr instanceof String) { constr = ConstraintParser.prepare((String) constr); rowSpecs = ConstraintParser.parseRowConstraints((String) constr); } else if (constr instanceof AC) { rowSpecs = (AC) constr; } else { throw new IllegalArgumentException("Illegal constraint type: " + constr.getClass().toString()); } rowConstraints = constr; dirty = true; } /** Returns a shallow copy of the constraints map. * @return A shallow copy of the constraints map. Never null. */ public Map getConstraintMap() { return new IdentityHashMap(scrConstrMap); } /** Sets the constraints map. * @param map The map. Will be copied. */ public void setConstraintMap(Map map) { scrConstrMap.clear(); ccMap.clear(); for (Map.Entry e : map.entrySet()) setComponentConstraintsImpl(e.getKey(), e.getValue(), true); } /** Returns the component constraints as a String representation. This string is the exact string as set with {@link #setComponentConstraints(java.awt.Component, Object)} * or set when adding the component to the parent component. *

* See the class JavaDocs for information on how this string is formatted. * @param comp The component to return the constraints for. * @return The component constraints as a String representation or null if the component is not registered * with this layout manager. The returned values is either a String or a {@link net.miginfocom.layout.CC} * depending on what constraint was sent in when the component was added. May be null. */ public Object getComponentConstraints(Component comp) { synchronized(comp.getParent().getTreeLock()) { return scrConstrMap.get(comp); } } /** Sets the component constraint for the component that already must be handled by this layout manager. *

* See the class JavaDocs for information on how this string is formatted. * @param constr The component constraints as a String or {@link net.miginfocom.layout.CC}. null is ok. * @param comp The component to set the constraints for. * @throws RuntimeException if the constraint was not valid. * @throws IllegalArgumentException If the component is not handling the component. */ public void setComponentConstraints(Component comp, Object constr) { setComponentConstraintsImpl(comp, constr, false); } /** Sets the component constraint for the component that already must be handled by this layout manager. *

* See the class JavaDocs for information on how this string is formatted. * @param constr The component constraints as a String or {@link net.miginfocom.layout.CC}. null is ok. * @param comp The component to set the constraints for. * @param noCheck Doe not check if the component is handled if true * @throws RuntimeException if the constraint was not valid. * @throws IllegalArgumentException If the component is not handling the component. */ private void setComponentConstraintsImpl(Component comp, Object constr, boolean noCheck) { Container parent = comp.getParent(); synchronized(parent != null ? parent.getTreeLock() : new Object()) { // 3.7.2. No sync if not added to a hierarchy. Defeats a NPE. if (noCheck == false && scrConstrMap.containsKey(comp) == false) throw new IllegalArgumentException("Component must already be added to parent!"); ComponentWrapper cw = new SwingComponentWrapper(comp); if (constr == null || constr instanceof String) { String cStr = ConstraintParser.prepare((String) constr); scrConstrMap.put(comp, constr); ccMap.put(cw, ConstraintParser.parseComponentConstraint(cStr)); } else if (constr instanceof CC) { scrConstrMap.put(comp, constr); ccMap.put(cw, (CC) constr); } else { throw new IllegalArgumentException("Constraint must be String or ComponentConstraint: " + constr.getClass().toString()); } dirty = true; } } /** Returns if this layout manager is currently managing this component. * @param c The component to check. If null then false will be returned. * @return If this layout manager is currently managing this component. */ public boolean isManagingComponent(Component c) { return scrConstrMap.containsKey(c); } /** Adds the callback function that will be called at different stages of the layout cylce. * @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); } /** Removes the callback if it exists. * @param callback The callback. May be null. */ public void removeLayoutCallback(LayoutCallback callback) { if (callbackList != null) callbackList.remove(callback); } /** Sets the debugging state for this layout manager instance. If debug is turned on a timer will repaint the last laid out parent * with debug information on top. *

* Red fill and dashed red outline is used to indicate occupied cells in the grid. Blue dashed outline indicate indicate * component bounds set. *

* Note that debug can also be set on the layout constraints. There it will be persisted. The value set here will not. See the class * JavaDocs for information. * @param parentW The parent to set debug for. * @param b true means debug is turned on. */ private void setDebug(final ComponentWrapper parentW, boolean b) { if (b && (debugTimer == null || debugTimer.getDelay() != getDebugMillis())) { if (debugTimer != null) debugTimer.stop(); ContainerWrapper pCW = parentW.getParent(); final Component parent = pCW != null ? (Component) pCW.getComponent() : null; debugTimer = new Timer(getDebugMillis(), new MyDebugRepaintListener()); if (parent != null) { SwingUtilities.invokeLater(new Runnable() { public void run() { Container p = parent.getParent(); if (p != null) { if (p instanceof JComponent) { ((JComponent) p).revalidate(); } else { parent.invalidate(); p.validate(); } } } }); } debugTimer.setInitialDelay(100); debugTimer.start(); } else if (!b && debugTimer != null) { debugTimer.stop(); debugTimer = null; } } /** Returns the current debugging state. * @return The current debugging state. */ private boolean getDebug() { return debugTimer != null; } /** Returns the debug millis. Combines the value from {@link net.miginfocom.layout.LC#getDebugMillis()} and {@link net.miginfocom.layout.LayoutUtil#getGlobalDebugMillis()} * @return The combined value. */ private int getDebugMillis() { int globalDebugMillis = LayoutUtil.getGlobalDebugMillis(); return globalDebugMillis > 0 ? globalDebugMillis : lc.getDebugMillis(); } /** Check if something has changed and if so recreate it to the cached objects. * @param parent The parent that is the target for this layout manager. */ private void checkCache(Container parent) { if (parent == null) return; if (dirty) grid = null; // Check if the grid is valid int mc = PlatformDefaults.getModCount(); if (lastModCount != mc) { grid = null; lastModCount = mc; } if (parent.isValid() == false) { if (lastWasInvalid == false) { lastWasInvalid = true; int hash = 0; boolean resetLastInvalidOnParent = false; // Added in 3.7.3 to resolve a timing regression introduced in 3.7.1 for (Iterator it = ccMap.keySet().iterator(); it.hasNext();) { ComponentWrapper wrapper = it.next(); Object component = wrapper.getComponent(); if (component instanceof JTextArea || component instanceof JEditorPane) resetLastInvalidOnParent = true; hash += wrapper.getLayoutHashCode(); } if (resetLastInvalidOnParent) resetLastInvalidOnParent(parent); if (hash != lastHash) { grid = null; lastHash = hash; } Dimension ps = parent.getSize(); if (lastInvalidSize == null || !lastInvalidSize.equals(ps)) { if (grid != null) grid.invalidateContainerSize(); lastInvalidSize = ps; } } } else { lastWasInvalid = false; } ContainerWrapper par = checkParent(parent); setDebug(par, getDebugMillis() > 0); if (grid == null) grid = new Grid(par, lc, rowSpecs, colSpecs, ccMap, callbackList); dirty = false; } /** * @since 3.7.3 */ private void resetLastInvalidOnParent(Container parent) { while (parent != null) { LayoutManager layoutManager = parent.getLayout(); if (layoutManager instanceof MigLayout) { ((MigLayout) layoutManager).lastWasInvalid = false; } parent = parent.getParent(); } } private ContainerWrapper checkParent(Container parent) { if (parent == null) return null; if (cacheParentW == null || cacheParentW.getComponent() != parent) cacheParentW = new SwingContainerWrapper(parent); return cacheParentW; } private long lastSize = 0; public void layoutContainer(final Container parent) { synchronized(parent.getTreeLock()) { checkCache(parent); Insets i = parent.getInsets(); int[] b = new int[] { i.left, i.top, parent.getWidth() - i.left - i.right, parent.getHeight() - i.top - i.bottom }; if (grid.layout(b, lc.getAlignX(), lc.getAlignY(), getDebug(), true)) { grid = null; checkCache(parent); grid.layout(b, lc.getAlignX(), lc.getAlignY(), getDebug(), false); } long newSize = grid.getHeight()[1] + (((long) grid.getWidth()[1]) << 32); if (lastSize != newSize) { lastSize = newSize; final ContainerWrapper containerWrapper = checkParent(parent); Window win = ((Window) SwingUtilities.getAncestorOfClass(Window.class, (Component)containerWrapper.getComponent())); if (win != null) { if (win.isVisible()) { SwingUtilities.invokeLater(new Runnable() { public void run() { adjustWindowSize(containerWrapper); } }); } else { adjustWindowSize(containerWrapper); } } } lastInvalidSize = null; } } /** Checks the parent window if its size is within parameters as set by the LC. * @param parent The parent who's window to possibly adjust the size for. */ private void adjustWindowSize(ContainerWrapper parent) { BoundSize wBounds = lc.getPackWidth(); BoundSize hBounds = lc.getPackHeight(); if (wBounds == null && hBounds == null) return; Window win = ((Window) SwingUtilities.getAncestorOfClass(Window.class, (Component) parent.getComponent())); if (win == null) return; Dimension prefSize = win.getPreferredSize(); int targW = constrain(checkParent(win), win.getWidth(), prefSize.width, wBounds); int targH = constrain(checkParent(win), win.getHeight(), prefSize.height, hBounds); int x = Math.round(win.getX() - ((targW - win.getWidth()) * (1 - lc.getPackWidthAlign()))); int y = Math.round(win.getY() - ((targH - win.getHeight()) * (1 - lc.getPackHeightAlign()))); win.setBounds(x, y, targW, targH); } private int constrain(ContainerWrapper parent, int winSize, int prefSize, BoundSize constrain) { if (constrain == null) return winSize; int retSize = winSize; UnitValue wUV = constrain.getPreferred(); if (wUV != null) retSize = wUV.getPixels(prefSize, parent, parent); retSize = constrain.constrain(retSize, prefSize, parent); return constrain.getGapPush() ? Math.max(winSize, retSize) : retSize; } public Dimension minimumLayoutSize(Container parent) { synchronized(parent.getTreeLock()) { return getSizeImpl(parent, LayoutUtil.MIN); } } public Dimension preferredLayoutSize(Container parent) { synchronized(parent.getTreeLock()) { if (lastParentSize == null || !parent.getSize().equals(lastParentSize)) { for (ComponentWrapper wrapper : ccMap.keySet()) { Component c = (Component) wrapper.getComponent(); if (c instanceof JTextArea || c instanceof JEditorPane || (c instanceof JComponent && Boolean.TRUE.equals(((JComponent)c).getClientProperty("migLayout.dynamicAspectRatio")))) { layoutContainer(parent); break; } } } lastParentSize = parent.getSize(); return getSizeImpl(parent, LayoutUtil.PREF); } } public Dimension maximumLayoutSize(Container parent) { return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE); } // Implementation method that does the job. private Dimension getSizeImpl(Container parent, int sizeType) { checkCache(parent); Insets i = parent.getInsets(); int w = LayoutUtil.getSizeSafe(grid != null ? grid.getWidth() : null, sizeType) + i.left + i.right; int h = LayoutUtil.getSizeSafe(grid != null ? grid.getHeight() : null, sizeType) + i.top + i.bottom; return new Dimension(w, h); } public float getLayoutAlignmentX(Container parent) { return lc != null && lc.getAlignX() != null ? lc.getAlignX().getPixels(1, checkParent(parent), null) : 0; } public float getLayoutAlignmentY(Container parent) { return lc != null && lc.getAlignY() != null ? lc.getAlignY().getPixels(1, checkParent(parent), null) : 0; } public void addLayoutComponent(String s, Component comp) { addLayoutComponent(comp, s); } public void addLayoutComponent(Component comp, Object constraints) { synchronized(comp.getParent().getTreeLock()) { setComponentConstraintsImpl(comp, constraints, true); } } public void removeLayoutComponent(Component comp) { synchronized(comp.getParent().getTreeLock()) { scrConstrMap.remove(comp); ccMap.remove(new SwingComponentWrapper(comp)); } } public void invalidateLayout(Container target) { // if (lc.isNoCache()) // Commented for 3.5 since there was too often that the "nocache" was needed and the user did not know. dirty = true; // the validity of components is maintained automatically. } // ************************************************ // Persistence Delegate and Serializable combined. // ************************************************ private Object readResolve() throws ObjectStreamException { return LayoutUtil.getSerializedObject(this); } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { LayoutUtil.setSerializedObject(this, LayoutUtil.readAsXML(in)); } public void writeExternal(ObjectOutput out) throws IOException { if (getClass() == MigLayout.class) LayoutUtil.writeAsXML(out, this); } private class MyDebugRepaintListener implements ActionListener { public void actionPerformed(ActionEvent e) { if (grid != null) { Component comp = (Component) grid.getContainer().getComponent(); if (comp.isShowing()) { grid.paintDebug(); return; } } debugTimer.stop(); debugTimer = null; } } }miglayout-3.7.4/net/miginfocom/swing/SwingContainerWrapper.java0000644000175000017500000000677311252374662023532 0ustar tonytonypackage net.miginfocom.swing; /* * 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 net.miginfocom.layout.ComponentWrapper; import net.miginfocom.layout.ContainerWrapper; import java.awt.*; /** */ public final class SwingContainerWrapper extends SwingComponentWrapper implements ContainerWrapper { /** Debug color for cell outline. */ private static final Color DB_CELL_OUTLINE = new Color(255, 0, 0); public SwingContainerWrapper(Container c) { super(c); } public ComponentWrapper[] getComponents() { Container c = (Container) getComponent(); ComponentWrapper[] cws = new ComponentWrapper[c.getComponentCount()]; for (int i = 0; i < cws.length; i++) cws[i] = new SwingComponentWrapper(c.getComponent(i)); return cws; } public int getComponentCount() { return ((Container) getComponent()).getComponentCount(); } public Object getLayout() { return ((Container) getComponent()).getLayout(); } public final boolean isLeftToRight() { return ((Container) getComponent()).getComponentOrientation().isLeftToRight(); } public final void paintDebugCell(int x, int y, int width, int height) { Component c = (Component) getComponent(); if (c.isShowing() == false) return; Graphics2D g = (Graphics2D) c.getGraphics(); if (g == null) return; g.setStroke(new BasicStroke(1f, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10f, new float[] {2f, 3f}, 0)); g.setPaint(DB_CELL_OUTLINE); g.drawRect(x, y, width - 1, height - 1); } public int getComponetType(boolean disregardScrollPane) { return TYPE_CONTAINER; } // Removed for 2.3 because the parent.isValid() in MigLayout will catch this instead. public int getLayoutHashCode() { int h = super.getLayoutHashCode(); if (isLeftToRight()) h += 416343; return 0; } } miglayout-3.7.4/net/miginfocom/layout/0000755000175000017500000000000011455506144016542 5ustar tonytonymiglayout-3.7.4/net/miginfocom/layout/PlatformDefaults.java0000644000175000017500000007171511367121130022662 0ustar tonytonypackage net.miginfocom.layout; import javax.swing.*; 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 { 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 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 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 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; 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: setRelatedGap(LPX4, LPY4); setUnrelatedGap(LPX7, LPY9); setParagraphGap(LPX14, LPY14); setIndentGap(LPX9, LPY9); setGridCellGap(LPX4, LPY4); setMinimumButtonWidth(new UnitValue(75, UnitValue.LPX, null)); setButtonOrder("L_E+U+YNBXOCAH_R"); setDialogInsets(LPY11, LPX11, LPY11, LPX11); setPanelInsets(LPY7, LPX7, LPY7, LPX7); break; case MAC_OSX: setRelatedGap(LPX4, LPY4); setUnrelatedGap(LPX7, LPY9); setParagraphGap(LPX14, LPY14); setIndentGap(LPX10, LPY10); setGridCellGap(LPX4, LPY4); setMinimumButtonWidth(new UnitValue(68, UnitValue.LPX, null)); setButtonOrder("L_HE+U+NYBXCOA_R"); setDialogInsets(LPY14, LPX20, LPY20, LPX20); setPanelInsets(LPY16, LPX16, LPY16, LPX16); // setRelatedGap(LPX8, LPY8); // setUnrelatedGap(LPX12, LPY12); // setParagraphGap(LPX16, LPY16); // setIndentGap(LPX10, LPY10); // setGridCellGap(LPX8, LPY8); // // setMinimumButtonWidth(new UnitValue(68, UnitValue.LPX, null)); // setButtonOrder("L_HE+U+NYBXCOA_R"); // setDialogInsets(LPY14, 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+UNYACBXIO_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.intValue() : getPlatformDPI(plaf); } private static int getPlatformDPI(int plaf) { switch (plaf) { case WINDOWS_XP: case GNOME: return 96; case MAC_OSX: try { return System.getProperty("java.version").compareTo("1.6") < 0 ? 72 : 96; // Default DPI was 72 prior to JSE 1.6 } 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.intValue() : 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) == false) { 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) == false) { 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_SCREEN_DPI_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_SCREEN_DPI_FACTOR * @see #BASE_REAL_PIXEL */ public static void setLogicalPixelBase(int base) { if (LP_BASE != base) { if (base < BASE_FONT_SIZE || base > BASE_SCALE_FACTOR) 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; } /** 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 final void setUnitValue(String[] unitStrings, UnitValue x, UnitValue y) { for (int i = 0; i < unitStrings.length; i++) { String s = unitStrings[i].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 final 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 final 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 staticall end up on the left end of the bar. *
  • 'R' - Buttons with this style tag will staticall 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". *
  • '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 dependant) *
  • '_' - (underscore) An "unrelated" gap. (Platform dependant) *
*

* 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+FBI_NYCOA_R", * for Windows is "L_E+U+FBI_YNOCAH_R", and for GNOME is * "L_HE+UNYACBXIO_R". * * @param order The new button order for the current platform. */ public static final 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 final 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 inset depending of the current platform. * @param side top == 0, left == 1, bottom = 2, right = 3. * @return The inset. 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 inset depending of the current platform. * @param side top == 0, left == 1, bottom = 2, right = 3. * @return The inset. 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} 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. */ 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; return (adjacentSide == SwingConstants.LEFT || adjacentSide == SwingConstants.RIGHT) ? 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 final 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 final 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 final 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 final 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-3.7.4/net/miginfocom/layout/CC.java0000644000175000017500000023231711302377550017700 0ustar tonytonypackage 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 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; // ***** 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 preferref 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 componet 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 componet 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 repsectively. 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 componet 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 componet 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 repsectively. 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 preferref 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; } /** 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 repectively. 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 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 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 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 gapLeft(String boundsSize) { hor.setGapBefore(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 gapBottom(String boundsSize) { ver.setGapAfter(ConstraintParser.parseBoundSize(boundsSize, true, false)); 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 gapRight(String boundsSize) { hor.setGapAfter(ConstraintParser.parseBoundSize(boundsSize, true, true)); return this; } /** Same functionality as {@link #setSpanY(int 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 cells)} 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 LayoutUtil.INF)} 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 cells)} 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) * @see #pushY() */ 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) * @see #pushX() */ 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 {@link #setExternal(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 #setExternal(boolean) */ public final CC external() { setExternal(true); return this; } /** Same functionality as {@link #setFlowX(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 {@link #setFlowX(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 {@link #setNewline(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 #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/colum 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 {@link #setWrap(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 #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/colum 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 {@link #setDockSide(int 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 {@link #setDockSide(int 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 {@link #setDockSide(int 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 {@link #setDockSide(int 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)} toghether. *

* 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)} toghether. *

* 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/shink 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/shink 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/shink 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/shink 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 thisproperty 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 thisproperty 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 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 componet 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 componet 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; } /** Optinal 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; } // ************************************************ // Persistence Delegate and Serializable combined. // ************************************************ private Object readResolve() throws ObjectStreamException { return LayoutUtil.getSerializedObject(this); } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { LayoutUtil.setSerializedObject(this, LayoutUtil.readAsXML(in)); } public void writeExternal(ObjectOutput out) throws IOException { if (getClass() == CC.class) LayoutUtil.writeAsXML(out, this); } }miglayout-3.7.4/net/miginfocom/layout/BoundSize.java0000644000175000017500000002323411252374662021316 0ustar tonytonypackage 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 serilization 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 serilization 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 noone 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 lenth 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 (min != null && min.isLinkedDeep() || pref != null && pref.isLinkedDeep() || max != null && max.isLinkedDeep()) throw new IllegalArgumentException("Size may not contain links"); } static { LayoutUtil.setDelegate(BoundSize.class, new PersistenceDelegate() { 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-3.7.4/net/miginfocom/layout/UnitValue.java0000644000175000017500000005030011521470652021315 0ustar tonytonypackage 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 botton 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", Integer.valueOf(PIXEL)); UNIT_MAP.put("lpx", Integer.valueOf(LPX)); UNIT_MAP.put("lpy", Integer.valueOf(LPY)); UNIT_MAP.put("%", Integer.valueOf(PERCENT)); UNIT_MAP.put("cm", Integer.valueOf(CM)); UNIT_MAP.put("in", Integer.valueOf(INCH)); UNIT_MAP.put("spx", Integer.valueOf(SPX)); UNIT_MAP.put("spy", Integer.valueOf(SPY)); UNIT_MAP.put("al", Integer.valueOf(ALIGN)); UNIT_MAP.put("mm", Integer.valueOf(MM)); UNIT_MAP.put("pt", Integer.valueOf(PT)); UNIT_MAP.put("min", Integer.valueOf(MIN_SIZE)); UNIT_MAP.put("minimum", Integer.valueOf(MIN_SIZE)); UNIT_MAP.put("p", Integer.valueOf(PREF_SIZE)); UNIT_MAP.put("pref", Integer.valueOf(PREF_SIZE)); UNIT_MAP.put("max", Integer.valueOf(MAX_SIZE)); UNIT_MAP.put("maximum", Integer.valueOf(MAX_SIZE)); UNIT_MAP.put("button", Integer.valueOf(BUTTON)); UNIT_MAP.put("label", Integer.valueOf(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); } 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.floatValue(); 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.intValue(); 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.getMinimumButtonWidth().getPixels(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.intValue(); if (unit == LINK_YPOS) return parent.getScreenLocationY() + v.intValue(); return v.intValue(); 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) return u.intValue(); 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 isLinked() { return linkId != null; } final boolean isLinkedDeep() { if (subUnits == null) return linkId != null; for (int i = 0; i < subUnits.length; i++) { if (subUnits[i].isLinkedDeep()) return true; } return false; } 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; } 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); } 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 { LayoutUtil.setDelegate(UnitValue.class, new PersistenceDelegate() { 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-3.7.4/net/miginfocom/layout/ContainerWrapper.java0000644000175000017500000000617611252374662022705 0ustar tonytonypackage 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 drwaing. * @param y The x coordinate to start the drwaing. * @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-3.7.4/net/miginfocom/layout/LC.java0000644000175000017500000013465711301446666017725 0ustar tonytonypackage 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 elememts 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 caclulated 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 caclulated 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 optinal 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 optinal 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 normaly 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 normaly 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 normaly 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 normaly 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/surpurflous 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/surpurflous 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/surpurflous 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/surpurflous 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 correspondig 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 correspondig 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 correspondig 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 correspondig 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, false) : 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 {@link #setWrapAfter(int 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 {@link #setNoCache(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 LayoutConstraint().noGrid().gap().fill(). */ public final LC noCache() { setNoCache(true); return this; } /** Same functionality as {@link #setFlowX(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 LayoutConstraint().noGrid().gap().fill(). */ public final LC flowY() { setFlowX(false); return this; } /** Same functionality as {@link #setFlowX(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 LayoutConstraint().noGrid().gap().fill(). */ public final LC flowX() { setFlowX(true); return this; } /** Same functionality as {@link #setFillX(boolean true)} and {@link #setFillY(boolean 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 {@link #setFillX(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 LayoutConstraint().noGrid().gap().fill(). */ public final LC fillX() { setFillX(true); return this; } /** Same functionality as {@link #setFillY(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 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); // Not .valueOf due to retroweaver... 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 {@link #setTopToBottom(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 LayoutConstraint().noGrid().gap().fill(). */ public final LC bottomToTop() { setTopToBottom(false); return this; } /** Same functionality as {@link #setTopToBottom(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 LayoutConstraint().noGrid().gap().fill(). * @since 3.7.2 */ public final LC topToBottom() { setTopToBottom(true); return this; } /** Same functionality as {@link #setNoGrid(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 LayoutConstraint().noGrid().gap().fill(). */ public final LC noGrid() { setNoGrid(true); return this; } /** Same functionality as {@link #setVisualPadding(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 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; } /** 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 caclulated 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 preferref 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 Boundwidth. 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 preferref 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 Boundheight. 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); } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { LayoutUtil.setSerializedObject(this, LayoutUtil.readAsXML(in)); } public void writeExternal(ObjectOutput out) throws IOException { if (getClass() == LC.class) LayoutUtil.writeAsXML(out, this); } } miglayout-3.7.4/net/miginfocom/layout/InCellGapProvider.java0000644000175000017500000000324011455506464022722 0ustar tonytonypackage net.miginfocom.layout; /** An interface to implement if you want to decide the gaps between two types of components within the same cell. *

* E.g.: * *

 * 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;
 * 
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-3.7.4/net/miginfocom/layout/ComponentWrapper.java0000644000175000017500000003376511366642712022731 0ustar tonytonypackage 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 shunted 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; /** 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. */ public abstract void paintDebugOutline(); /** Returns the type of component that this wrapper is wrapping. *

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

* NOTE! This is misspelled. Keeping it that way though since this is only used by developers who * port MigLayout. * @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 getComponetType(boolean disregardScrollPane); }miglayout-3.7.4/net/miginfocom/layout/LinkHandler.java0000644000175000017500000001470511521467274021613 0ustar tonytonypackage net.miginfocom.layout; import java.lang.ref.WeakReference; import java.util.ArrayList; 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 */ /** */ 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; private static final ArrayList> LAYOUTS = new ArrayList>(4); private static final ArrayList> VALUES = new ArrayList>(4); private static final ArrayList> VALUES_TEMP = new ArrayList>(4); private LinkHandler() { } public synchronized static Integer getValue(Object layout, String key, int type) { Integer ret = null; boolean cont = true; for (int i = LAYOUTS.size() - 1; i >= 0; i--) { Object l = LAYOUTS.get(i).get(); if (ret == null && l == layout) { int[] rect = VALUES_TEMP.get(i).get(key); if (cont && rect != null && rect[type] != LayoutUtil.NOT_SET) { ret = Integer.valueOf(rect[type]); } else { rect = VALUES.get(i).get(key); ret = (rect != null && rect[type] != LayoutUtil.NOT_SET) ? Integer.valueOf(rect[type]) : null; } cont = false; } if (l == null) { LAYOUTS.remove(i); VALUES.remove(i); VALUES_TEMP.remove(i); } } 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) { for (int i = LAYOUTS.size() - 1; i >= 0; i--) { Object l = LAYOUTS.get(i).get(); if (l == layout) { HashMap map = (temporary ? VALUES_TEMP : VALUES).get(i); 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; } } LAYOUTS.add(new WeakReference(layout)); int[] bounds = new int[] {x, y, width, height, x + width, y + height}; HashMap values = new HashMap(4); if (temporary) values.put(key, bounds); VALUES_TEMP.add(values); values = new HashMap(4); if (temporary == false) values.put(key, bounds); VALUES.add(values); 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) { for (int i = LAYOUTS.size() - 1; i >= 0; i--) { Object l = LAYOUTS.get(i).get(); if (l == layout) return VALUES.get(i).remove(key) != null; } return false; } synchronized static void clearTemporaryBounds(Object layout) { for (int i = LAYOUTS.size() - 1; i >= 0; i--) { Object l = LAYOUTS.get(i).get(); if (l == layout) { VALUES_TEMP.get(i).clear(); return; } } } } miglayout-3.7.4/net/miginfocom/layout/ResizeConstraint.java0000644000175000017500000000664511252374662022731 0ustar tonytonypackage 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 = new Float(100); /** How flexilble 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 twise 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); } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { LayoutUtil.setSerializedObject(this, LayoutUtil.readAsXML(in)); } public void writeExternal(ObjectOutput out) throws IOException { if (getClass() == ResizeConstraint.class) LayoutUtil.writeAsXML(out, this); } } miglayout-3.7.4/net/miginfocom/layout/AC.java0000644000175000017500000006203211521452542017667 0ustar tonytonypackage 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 AxisConstraint().size("100").gap("3").size("200").fill(). */ public final class AC implements Externalizable { private final ArrayList cList = new ArrayList(8); 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 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 emty 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 (int i = 0; i < constr.length; i++) cList.add(constr[i]); } /** 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/colum will have its components layed out * in one single cell. It is the same as to say that the cells in this column/row will all be merged (a.k.a spanned). *

* 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/colum will have its components layed out * in one single cell. It is the same as to say that the cells in this column/row will all be merged (a.k.a spanned). *

* 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++; 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); 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 horizonal 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 horizonal 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(1f, 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 withing 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 withing 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 withing 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 withing 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 withing 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); } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { LayoutUtil.setSerializedObject(this, LayoutUtil.readAsXML(in)); } public void writeExternal(ObjectOutput out) throws IOException { if (getClass() == AC.class) LayoutUtil.writeAsXML(out, this); } }miglayout-3.7.4/net/miginfocom/layout/LayoutUtil.java0000644000175000017500000005016111521470450021515 0ustar tonytonypackage 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 aa 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. */ 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; 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; 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 "3.7.4"; } /** 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), Boolean.valueOf(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 Beans.isDesignTime(); 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.booleanValue(); } /** 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 deligate 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 om 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(Integer.valueOf(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].intValue(); 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].floatValue(); } } } 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.floatValue() / 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.floatValue(); 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 fo no boundary). * @param upper The upper boundary (or null fo 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); } 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 ffc 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().booleanValue(); 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 inset 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 inset 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 objet 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 recieve the exeptions 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 boject 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() { 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-3.7.4/net/miginfocom/layout/LayoutCallback.java0000644000175000017500000000346411252374662022311 0ustar tonytonypackage net.miginfocom.layout; /** 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-3.7.4/net/miginfocom/layout/UnitConverter.java0000644000175000017500000000620511252374662022222 0ustar tonytonypackage 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-3.7.4/net/miginfocom/layout/ConstraintParser.java0000644000175000017500000014315211521452542022710 0ustar tonytonypackage 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 varables. * @param s The String to parse. Should not be null and must be lower case and trimmed. * @throws RuntimeException if the constaint was not valid. * @return The parsed constraint. Never null. */ public static LC parseLayoutConstraint(String s) { LC lc = new LC(); if (s.length() == 0) 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 (int i = 0; i < parts.length; i++) { String part = parts[i]; 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)); lc.setAlignY(gaps.length > 1 ? parseUnitValueOrAlign(gaps[1], false, null) : lc.getAlignX()); 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 manu are there exist "[...]" sections in the string that is parsed. * @throws RuntimeException if the constaint 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 manu are there exist "[...]" sections in the string that is parsed. * @throws RuntimeException if the constaint 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 manu are there exist "[...]" sections in the string that is parsed. * @throws RuntimeException if the constaint 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 constriant. * @param s The single constrint 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 constaint 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 contraint: '" + part + "'\n" + ex.getMessage()); } } return dimConstraint; } /** Parses all component constraints and stores the parsed values in the transient (cache) member varables. * @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. Should not be null and must be lower case and trimmed. * @throws RuntimeException if the constaint was not valid. * @return The parsed constraint. Never null. */ public static CC parseComponentConstraint(String s) { CC cc = new CC(); if (s.length() == 0) return cc; String[] parts = toTrimmedTokens(s, ','); for (int i = 0; i < parts.length; i++) { String part = parts[i]; 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(part.substring(ix).trim(), ResizeConstraint.WEIGHT_100)); if (shrinks.length > 1) cc.getVertical().setShrink(parseFloat(part.substring(ix).trim(), 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 gandle "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 gandle "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); // cc.getVertical().setGrow(ResizeConstraint.WEIGHT_100); 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); // cc.getVertical().setGrow(ResizeConstraint.WEIGHT_100); 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(new Float(100f)); cc.getVertical().setGrow(new Float(100f)); cc.setPushX(new Float(100f)); cc.setPushY(new Float(100f)); 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("Illegal Constraint: '" + part + "'\n" + ex.getMessage()); } } // 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 IllegalAccessError("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 + "'"); } } } /** Parses alignment keywords and returns the approprieate 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 resonably 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 excercises {@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 mimimum 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 charecters are matched onrecognized 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) && (sIx >= sSz || s.charAt(sIx) == ' ') ? 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 interprated 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 final static ArrayList getRowColAndGapsTrimmed(String s) { if (s.indexOf('|') != -1) s = s.replaceAll("\\|", "]["); ArrayList retList = new ArrayList(Math.max(s.length() >> 2 + 1, 3)); // Aprox 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 "", trimms and converts to lower case. * @param s The string * @return Not null. */ public static final 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-3.7.4/net/miginfocom/layout/DimConstraint.java0000644000175000017500000004644111521452542022170 0ustar tonytonypackage 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 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. *

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

* 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. * @see net.miginfocom.layout.ConstraintParser#parseBoundSize(String, boolean, boolean). */ 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/columnss/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/columnss/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 demension 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 demension 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 code>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); } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { LayoutUtil.setSerializedObject(this, LayoutUtil.readAsXML(in)); } public void writeExternal(ObjectOutput out) throws IOException { if (getClass() == DimConstraint.class) LayoutUtil.writeAsXML(out, this); } } miglayout-3.7.4/net/miginfocom/layout/IDEUtil.java0000644000175000017500000006555411455506030020655 0ustar tonytonypackage 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 retuern 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 retuern 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 final 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 final 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.floatValue() != 100f ? floatToString(gw.floatValue(), 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.floatValue(), 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); } } 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 final 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.floatValue() != 100f ? floatToString(gw.floatValue(), 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.floatValue(), 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); } } 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); } } 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)).append("\", \"").append(getBS(gapAft)).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 final String getConstraintString(CC cc, boolean asAPI) { StringBuffer sb = new StringBuffer(16); if (cc.isNewline()) sb.append(asAPI ? ".newline()" : ",newline"); if (cc.isExternal()) sb.append(asAPI ? ".external()" : ",external"); Boolean flowX = cc.getFlowX(); if (flowX != null) { if (asAPI) { sb.append(flowX.booleanValue() ? ".flowX()" : ".flowY()"); } else { sb.append(flowX.booleanValue() ? ",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(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])).append(i < iSz - 1 ? " " : ""); 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); } } 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(')'); } 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(pushX).append(asAPI ? ", " : " ").append(pushY); } else if (pushX != null) { sb.append(asAPI ? ".pushX(" : ",pushx ").append(pushX == 100 ? "" : (String.valueOf(pushX))); } else if (pushY != null) { sb.append(asAPI ? ".pushY(" : ",pushy ").append(pushY == 100 ? "" : (String.valueOf(pushY))); } if (asAPI) sb.append(')'); } 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()) 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 final 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.booleanValue() ? ",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 { 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(' ').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(' ').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) { sb.append(".wrap(").append(ws).append(')'); } else { sb.append(",wrap ").append(ws); } } int debugMillis = lc.getDebugMillis(); if (debugMillis > 0) { if (asAPI) { sb.append(".debug(").append(debugMillis).append(')'); } else { sb.append(",debug ").append(debugMillis); } } 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 getBS(BoundSize bs) { return bs != null ? bs.getConstraintString() : "null"; } /** 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 final String floatToString(float f, boolean asAPI) { String valS = String.valueOf(f); return valS.endsWith(".0") ? valS.substring(0, valS.length() - 2) : (valS + (asAPI ? "f" : "")); } } miglayout-3.7.4/net/miginfocom/layout/Grid.java0000644000175000017500000024763311521470362020305 0ustar tonytonypackage net.miginfocom.layout; 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); /** 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 alterted. * @param callbackList A list of callbacks or null if none. Will not be alterted. */ 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; 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. UnitValue[] pos = getPos(comp, rootCc); BoundSize[] cbSz = getCallbackSize(comp); if (pos != null || rootCc.isExternal()) { CompWrap cw = new CompWrap(comp, rootCc, hideMode, pos, cbSz); Cell cell = grid.get(null); if (cell == null) { grid.put(null, new Cell(cw)); } else { cell.compWraps.add(cw); } if (rootCc.isBoundsInGrid() == false || 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, pos, cbSz)); 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; } } } 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.booleanValue() : 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; } pos = getPos(compAdd, cc); cbSz = getCallbackSize(compAdd); } CompWrap cw = new CompWrap(compAdd, cc, hideMode, pos, cbSz); 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 (Iterator it = grid.values().iterator(); it.hasNext();) { Cell cell = it.next(); 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.horSizes); if (sgy != null && sizeGroupMapY != null) addToSizeGroup(sizeGroupMapY, sgy, cw.verSizes); sizeGroupCWs.add(cw); } } } // Set/equalize the sizeGroups to same the values. for (int i = 0; i < sizeGroupCWs.size(); i++) { CompWrap cw = sizeGroupCWs.get(i); if (sizeGroupMapX != null) cw.setSizes(sizeGroupMapX.get(cw.cc.getHorizontal().getSizeGroup()), true); // Target method handles null sizes if (sizeGroupMapY != null) cw.setSizes(sizeGroupMapY.get(cw.cc.getVertical().getSizeGroup()), false); // Target method handles null sizes } } // Component loop // 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 (Iterator it = grid.values().iterator(); it.hasNext();) { Cell cell = it.next(); 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.horSizes); if (sgy != null && sizeGroupMapY != null) addToSizeGroup(sizeGroupMapY, sgy, cw.verSizes); sizeGroupCWs.add(cw); } } } // Set/equalize the sizeGroups to same the values. for (int i = 0; i < sizeGroupCWs.size(); i++) { CompWrap cw = sizeGroupCWs.get(i); if (sizeGroupMapX != null) cw.setSizes(sizeGroupMapX.get(cw.cc.getHorizontal().getSizeGroup()), true); // Target method handles null sizes if (sizeGroupMapY != null) cw.setSizes(sizeGroupMapY.get(cw.cc.getVertical().getSizeGroup()), false); // Target method handles null sizes } } 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 (Iterator it = grid.values().iterator(); it.hasNext();) { Cell cell = it.next(); 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 for (int i = 0, iSz = rowConstr.getCount(); i < iSz; i++) rowIndexes.add(Integer.valueOf(i)); for (int i = 0, iSz = colConstr.getCount(); i < iSz; i++) colIndexes.add(Integer.valueOf(i)); 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 static CC getCC(ComponentWrapper comp, Map ccMap) { CC cc = ccMap.get(comp); return cc != null ? cc : new CC(); } private void addLinkIDs(CC cc) { String[] linkIDs = cc.getLinkTargets(); for (int lx = 0; lx < linkIDs.length; lx++) { if (linkTargetIDs == null) linkTargetIDs = new HashMap(); linkTargetIDs.put(linkIDs[lx], null); } } /** If the container (parent) that this grid is laying out has changed its bounds, call this method to * clear any cached values. */ public void invalidateContainerSize() { colFlowSpecs = null; } /** 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. * @param alignY The alignment for the y-axis. * @param debug If debug information should be saved in {@link #debugRects}. * @param checkPrefChange If a check should be done to see if the setting of any new bounds changes the preferred size * of a component. * @return If the layout has probably changed the preferred size and there is need for a new layout (normally only SWT). */ public boolean layout(int[] bounds, UnitValue alignX, UnitValue alignY, boolean debug, boolean checkPrefChange) { if (debug) debugRects = new ArrayList(); checkSizeCalcs(); 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 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 (Iterator it = grid.values().iterator(); it.hasNext();) { ArrayList compWraps = it.next().compWraps; for (int i = 0, iSz = compWraps.size(); i < iSz; i++) { CompWrap cw = compWraps.get(i); if (j == 0) { doAgain |= doAbsoluteCorrections(cw, bounds); if (doAgain == false) { // 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()).intValue() - cw.x; if (cw.cc.getVertical().getEndGroup() != null) cw.h = endGrpYMap.get(cw.cc.getVertical().getEndGroup()).intValue() - cw.y; cw.x += bounds[0]; cw.y += bounds[1]; layoutAgain |= cw.transferBounds(checkPrefChange && !layoutAgain); if (callbackList != null) { for (int cb = 0; cb < callbackList.size(); cb++) callbackList.get(cb).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) { Collection cwColl = grid.values(); for (Iterator it = cwColl.iterator(); it.hasNext();) { ArrayList compWraps = it.next().compWraps; for (int i = 0, iSz = compWraps.size(); i < iSz; i++) { CompWrap cw = compWraps.get(i); 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(); ArrayList painted = new ArrayList(); for (int i = 0, iSz = debugRects.size(); i < iSz; i++) { int[] r = debugRects.get(i); if (painted.contains(r) == false) { container.paintDebugCell(r[0], r[1], r[2], r[3]); painted.add(r); } } for (Iterator it = grid.values().iterator(); it.hasNext();) { ArrayList compWraps = it.next().compWraps; for (int i = 0, iSz = compWraps.size(); i < iSz; i++) compWraps.get(i).comp.paintDebugOutline(); } } } public ContainerWrapper getContainer() { return container; } public final int[] getWidth() { checkSizeCalcs(); return width.clone(); } public final int[] getHeight() { checkSizeCalcs(); return height.clone(); } private void checkSizeCalcs() { if (colFlowSpecs == null) { colFlowSpecs = calcRowsOrColsSizes(true); rowFlowSpecs = calcRowsOrColsSizes(false); width = getMinPrefMaxSumSize(true); height = getMinPrefMaxSumSize(false); 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[4], null, null, false, false); resetLinkValues(false, false); } adjustSizeForAbsolute(true); adjustSizeForAbsolute(false); } } private UnitValue[] getPos(ComponentWrapper cw, CC cc) { UnitValue[] cbPos = null; if (callbackList != null) { for (int i = 0; i < callbackList.size() && cbPos == null; i++) cbPos = 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 (cbPos == null || ccPos == null) return cbPos != null ? cbPos : ccPos; // Merge for (int i = 0; i < 4; i++) { UnitValue cbUv = cbPos[i]; if (cbUv != null) ccPos[i] = cbUv; } return ccPos; } private BoundSize[] getCallbackSize(ComponentWrapper cw) { if (callbackList != null) { for (int i = 0; i < callbackList.size(); i++) { BoundSize[] bs = callbackList.get(i).getSize(cw); // NOT a copy! if (bs != null) return bs; } } return null; } private static int getDockInsets(TreeSet set) { int c = 0; for (Iterator it = set.iterator(); it.hasNext();) { if (it.next().intValue() < -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 "incresing" 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(Integer.valueOf(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(Integer.valueOf(cellXY[1])); } else { colIndexes.add(Integer.valueOf(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 (Iterator it = cells.iterator(); it.hasNext();) { Cell cell = it.next(); 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))) { int min = PlatformDefaults.getMinimumButtonWidth().getPixels(0, parent, cw.comp); if (min > cw.horSizes[LayoutUtil.MIN]) cw.horSizes[LayoutUtil.MIN] = min; correctMinMax(cw.horSizes); } 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) { // if (hasPush == false && (isRows ? lc.isFillY() : lc.isFillX()) == false) // return null; 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 (int j = 0; j < grps.size(); j++) { LinkedDimGroup grp = grps.get(j); 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 (Iterator> it = linkTargetIDs.entrySet().iterator(); it.hasNext();) { Map.Entry o = it.next(); 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 (int i = 0; i < groupLists.length; i++) { ArrayList groups = groupLists[i]; 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; } 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()}; } } int[] plafPad = lc.isVisualPadding() ? cw.comp.getVisualPadding() : null; UnitValue[] pad = cw.cc.getPadding(); // If no changes do not create a lot of objects if (cw.pos == null && plafPad == 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 (cw.pos != null) { UnitValue stUV = cw.pos != null ? cw.pos[isHor ? 0 : 1] : null; UnitValue endUV = cw.pos != null ? cw.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); } // If the plaf converter has padding -> correct the start/size if (plafPad != null) { int p = plafPad[isHor ? 1 : 0]; st += p; sz += -p + (plafPad[isHor ? 3 : 2]); } 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.intValue(); 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 (int j = 0; j < linkedGroups.size(); j++) { LinkedDimGroup group = linkedGroups.get(j); 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(2); Integer oldEnd = endGroups.get(endGroup); if (oldEnd == null || end > oldEnd.intValue()) endGroups.put(endGroup, Integer.valueOf(end)); } return endGroups; } /** Calculates Min, Preferred and Max size for the columns OR rows. * @param isHor If it is the horizontal dimension to calculate. * @return The sizes in a {@link net.miginfocom.layout.Grid.FlowSizeSpec}. */ private FlowSizeSpec calcRowsOrColsSizes(boolean isHor) { ArrayList[] groupsLists = isHor ? colGroupLists : rowGroupLists; Float[] defPush = isHor ? pushXs : pushYs; int refSize = isHor ? container.getWidth() : container.getHeight(); BoundSize cSz = isHor ? lc.getWidth() : lc.getHeight(); if (cSz.isUnset() == false) refSize = cSz.constrain(refSize, 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(2); DimConstraint[] allDCs = new DimConstraint[primIndexes.size()]; Iterator primIt = primIndexes.iterator(); for (int r = 0; r < rowColBoundSizes.length; r++) { int cellIx = primIt.next().intValue(); 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(refSize, 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, refSize, 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) { ComponentWrapper p = cw.getParent(); return p != null ? (isHor ? cw.getWidth() : cw.getHeight()) : 0; } private int[] getMinPrefMaxSumSize(boolean isHor) { int[][] sizes = isHor ? colFlowSpecs.sizes : rowFlowSpecs.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) : 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 (int i = 0; i < groups.size(); i++) { LinkedDimGroup group = groups.get(i); 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) { 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(); ArrayList[] groupLists = new ArrayList[primIndexes.size()]; int gIx = 0; for (Iterator primIt = primIndexes.iterator(); primIt.hasNext();) { int i = primIt.next().intValue(); 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(2); groupLists[gIx++] = groupList; for (Iterator secIt = secIndexes.iterator(); secIt.hasNext();) { int j = secIt.next().intValue(); Cell cell = isRows ? getCell(i, j) : getCell(j, 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," + j, 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 un 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 (Iterator it = indexes.iterator(); it.hasNext();) { int ix = it.next(); if (ix <= curIx) continue; // We have not arrived to the correct index yet if (ix >= lastIx) break; retSpan++; } return retSpan; } private final boolean isCellFree(int r, int c, ArrayList occupiedRects) { if (getCell(r, c) != null) return false; for (int i = 0; i < occupiedRects.size(); i++) { int[] rect = occupiedRects.get(i); 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)); } private void setCell(int r, int c, Cell cell) { if (c < 0 || c > MAX_GRID || r < 0 || r > MAX_GRID) throw new IllegalArgumentException("Cell position out of bounds. row: " + r + ", col: " + c); rowIndexes.add(Integer.valueOf(r)); colIndexes.add(Integer.valueOf(c)); grid.put(Integer.valueOf((r << 16) + c), 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(Integer.valueOf(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(Integer.valueOf(dockInsets[2])); // Make sure there is a receiving cell break; default: throw new IllegalArgumentException("Internal error 123."); } rowIndexes.add(Integer.valueOf(r)); colIndexes.add(Integer.valueOf(c)); grid.put(Integer.valueOf((r << 16) + c), new Cell(cw, spanx, spany, spanx > 1)); } /** A simple representation of a cell in the grid. Contains a number of component wraps and 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(1); 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 ArrayList _compWraps = new ArrayList(4); private int[] sizes = null; 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); sizes = null; } private void setCompWraps(ArrayList cws) { if (_compWraps != cws) { _compWraps = cws; sizes = null; } } private void layout(DimConstraint dc, int start, int size, int spanCount) { lStart = start; lSize = size; if (_compWraps.size() == 0) 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() { if (sizes == null && _compWraps.size() > 0) { sizes = new int[3]; 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. */ private final static class CompWrap { private final ComponentWrapper comp; private final CC cc; private final UnitValue[] pos; 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. private CompWrap(ComponentWrapper c, CC cc, int eHideMode, UnitValue[] pos, BoundSize[] callbackSz) { this.comp = c; this.cc = cc; this.pos = pos; if (eHideMode <= 0) { BoundSize hBS = (callbackSz != null && callbackSz[0] != null) ? callbackSz[0] : cc.getHorizontal().getSize(); BoundSize vBS = (callbackSz != null && callbackSz[1] != null) ? callbackSz[1] : cc.getVertical().getSize(); int wHint = -1, hHint = -1; // Added for v3.7 if (comp.getWidth() > 0 && comp.getHeight() > 0) { hHint = comp.getHeight(); wHint = comp.getWidth(); } for (int i = LayoutUtil.MIN; i <= LayoutUtil.MAX; i++) { horSizes[i] = getSize(hBS, i, true, hHint); verSizes[i] = getSize(vBS, i, false, wHint > 0 ? wHint : horSizes[i]); } correctMinMax(horSizes); correctMinMax(verSizes); } if (eHideMode > 1) { gaps = new int[4][]; for (int i = 0; i < gaps.length; i++) gaps[i] = new int[3]; } } private int getSize(BoundSize uvs, int sizeType, boolean isHor, int sizeHint) { if (uvs == null || uvs.getSize(sizeType) == null) { switch(sizeType) { case LayoutUtil.MIN: return isHor ? comp.getMinimumWidth(sizeHint) : comp.getMinimumHeight(sizeHint); case LayoutUtil.PREF: return isHor ? comp.getPreferredWidth(sizeHint) : comp.getPreferredHeight(sizeHint); default: return isHor ? comp.getMaximumWidth(sizeHint) : comp.getMaximumHeight(sizeHint); } } ContainerWrapper par = comp.getParent(); return uvs.getSize(sizeType).getPixels(isHor ? par.getWidth() : par.getHeight(), par, comp); } 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) { x = start; w = size; } else { y = start; h = size; } } 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(); } /** * @return If the preferred size have changed because of the new bounds. */ private boolean transferBounds(boolean checkPrefChange) { comp.setBounds(x, y, w, h); if (checkPrefChange && w != horSizes[LayoutUtil.PREF]) { BoundSize vSz = cc.getVertical().getSize(); if (vSz.getPreferred() == null) { if (comp.getPreferredHeight(-1) != verSizes[LayoutUtil.PREF]) return true; } } return false; } private void setSizes(int[] sizes, boolean isHor) { if (sizes == null) return; int[] s = isHor ? horSizes : verSizes; s[LayoutUtil.MIN] = sizes[LayoutUtil.MIN]; s[LayoutUtil.PREF] = sizes[LayoutUtil.PREF]; s[LayoutUtil.MAX] = sizes[LayoutUtil.MAX]; } 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, isHor ? horSizes[sizeType] : verSizes[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)); } } //*************************************************************************************** //* 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 (int i = 0, iSz = compWraps.size(); i < iSz; i++) { CompWrap cw = compWraps.get(i); 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), (isHor ? cw.horSizes : cw.verSizes), 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 = Short.MIN_VALUE; int maxBelow = Short.MIN_VALUE; for (int i = 0, iSz = compWraps.size(); i < iSz; i++) { CompWrap cw = compWraps.get(i); 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 (int i = 0, iSz = compWraps.size(); i < iSz; i++) { CompWrap cw = compWraps.get(i); 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 (int i = 0, iSz = groups.size(); i < iSz; i++) { LinkedDimGroup group = groups.get(i); 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++) { CompWrap cw = compWraps.get(i); compSizes[i] = isHor ? cw.horSizes : cw.verSizes; } return compSizes; } /** Merges sizes and gaps together with Resize Constraints. For gaps {@link #GAP_RC_CONST} is used. * @param resConstr One resize constriant 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. *

    *
  • 0 - Grow only rows/columns which have the sizeType set to be the containing components AND which has a grow weight > 0. *
  • 1 - Grow only rows/columns which have the sizeType set to be the containing components AND which has a grow weight > 0 OR unspecified. *
  • 2 - Grow all rows/columns that have a grow weight > 0. *
  • 3 - Grow all rows/columns that have a grow weight > 0 OR unspecified. *
* @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; 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 (int[][]) 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>(); PARENT_GRIDPOS_MAP.put(parComp.getComponent(), grid); } static synchronized HashMap getGridPositions(Object parComp) { if (PARENT_GRIDPOS_MAP == null) return null; LinkedHashMap grid = PARENT_GRIDPOS_MAP.get(parComp); if (grid == null) return null; HashMap retMap = new HashMap(); for (Iterator> it = grid.entrySet().iterator(); it.hasNext();) { Map.Entry e = it.next(); Cell cell = e.getValue(); Integer xyInt = e.getKey(); if (xyInt != null) { int xy = xyInt.intValue(); int x = xy & 0x0000ffff; int y = xy >> 16; for (CompWrap cw : cell.compWraps) retMap.put(cw.comp.getComponent(), new int[] {x, y, cell.spanx, cell.spany}); } } return retMap; } } miglayout-3.7.4/net/miginfocom/demo/0000755000175000017500000000000011302377550016147 5ustar tonytonymiglayout-3.7.4/net/miginfocom/demo/HiDPISimulator.java0000644000175000017500000003743311252374660021624 0ustar tonytonypackage net.miginfocom.demo; import net.miginfocom.layout.PlatformDefaults; import net.miginfocom.layout.UnitValue; import net.miginfocom.swing.MigLayout; import org.jvnet.substance.SubstanceLookAndFeel; import org.jvnet.substance.fonts.SubstanceFontUtilities; import org.jvnet.substance.skin.SubstanceBusinessBlackSteelLookAndFeel; import javax.swing.*; import javax.swing.border.LineBorder; import javax.swing.plaf.FontUIResource; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.util.*; /** 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-3.7.4/net/miginfocom/demo/SwtDemo.java0000644000175000017500000025110011302377550020373 0ustar tonytonypackage 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 - Mig Layout 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 PlatformConverter.getButtonBarOrder(..) 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-3.7.4/net/miginfocom/demo/CallbackDemo.java0000644000175000017500000001135411252374660021322 0ustar tonytonypackage 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; 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("Can't you just feel the urge to 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-3.7.4/net/miginfocom/demo/SwingDemo.java0000644000175000017500000051575411301446666020733 0ustar tonytonypackage 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 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 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 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 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 happpen... } 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 on XP)", 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 on XP)\", 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 PlatformConverter.getButtonBarOrder(..) 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 PlatformConverter.getButtonBarOrder(..) 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-3.7.4/net/miginfocom/examples/0000755000175000017500000000000011521471344017040 5ustar tonytonymiglayout-3.7.4/net/miginfocom/examples/BugTestApp.java0000644000175000017500000000325011327653626021732 0ustar tonytonypackage net.miginfocom.examples; import net.miginfocom.swing.MigLayout; import javax.swing.*; import java.awt.*; /** * @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 main(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); } }); } } miglayout-3.7.4/net/miginfocom/examples/Example01.java0000644000175000017500000000217111366644342021447 0ustar tonytonypackage net.miginfocom.examples; import net.miginfocom.swing.MigLayout; import javax.swing.*; /** */ 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-3.7.4/net/miginfocom/examples/ExampleGood.java0000644000175000017500000000213211327653774022122 0ustar tonytonypackage net.miginfocom.examples; import net.miginfocom.swt.MigLayout; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.*; 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-3.7.4/net/miginfocom/examples/Example.java0000644000175000017500000000213311327653774021312 0ustar tonytonypackage net.miginfocom.examples; import net.miginfocom.swt.MigLayout; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.*; 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-3.7.4/net/miginfocom/examples/JavaOneShrink.java0000644000175000017500000000413411252374662022415 0ustar tonytonypackage net.miginfocom.examples; import net.miginfocom.swing.MigLayout; import javax.swing.*; import javax.swing.border.LineBorder; import java.awt.*; /** * @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-3.7.4/net/miginfocom/examples/SwtTest.java0000644000175000017500000000515011252374662021327 0ustar tonytonypackage net.miginfocom.examples; import net.miginfocom.swt.MigLayout; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; /** * @author Mikael Grev, MiG InfoCom AB * Date: Apr 12, 2008 * Time: 8:19:01 AM */ public class SwtTest { public static void main(String[] args) { Display display = new Display(); Shell shell = new Shell(); Composite parent = new Composite(shell, SWT.DOUBLE_BUFFERED); shell.setLayout(new FillLayout()); // parent.setLayoutData("wmin 100"); MigLayout layout = new MigLayout("debug,wrap 2"); parent.setLayout(layout); Label label1 = new Label(parent, SWT.WRAP); label1.setText("This is an even longer label that just goes on and on..."); label1.setLayoutData("wmin 50"); Label label = new Label(parent, SWT.NONE); label.setText("Label 2"); label = new Label(parent, SWT.NONE); label.setText("Label 3"); label = new Label(parent, SWT.NONE); label.setText("Label 4"); // layout.addLayoutCallback(new LayoutCallback() // { // public void correctBounds(ComponentWrapper comp) // { // if (comp.getComponent() instanceof Control) // { // if ((((Control) comp.getComponent()).getStyle() & SWT.WRAP) == SWT.WRAP) // { // Control c = (Control) comp.getComponent(); // Rectangle rect = c.getBounds(); // Point newSize = c.computeSize(rect.width, SWT.DEFAULT, false); // c.setBounds(rect.x, rect.y, newSize.x, newSize.y); // } // } // } // }); shell.setSize(300, 300); shell.open(); shell.layout(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } } } //public class SwtTest //{ // public static void main(String[] args) // { // Display display = new Display(); // Shell shell = new Shell(display); // shell.setMaximized(true); // // MigLayout migLayout = new MigLayout("fill", "[left]"); // shell.setLayout(migLayout); // // List list = new List(shell, SWT.V_SCROLL); // list.setLayoutData("grow"); // // for (int i = 0; i < 128; i++) { // list.add("Item " + i); // } // shell.pack(); // shell.open(); // // while (!shell.isDisposed()) { // if (!display.readAndDispatch()) // display.sleep(); // } // display.dispose(); // } //} miglayout-3.7.4/net/miginfocom/examples/Example02.java0000644000175000017500000000264211252374662021452 0ustar tonytonypackage net.miginfocom.examples; import net.miginfocom.swing.MigLayout; import javax.swing.*; import javax.swing.border.CompoundBorder; import javax.swing.border.EmptyBorder; import javax.swing.border.EtchedBorder; 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-3.7.4/net/miginfocom/swt/0000755000175000017500000000000011302377550016040 5ustar tonytonymiglayout-3.7.4/net/miginfocom/swt/SwtContainerWrapper.java0000644000175000017500000000700311252374662022671 0ustar tonytonypackage net.miginfocom.swt; /* * 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 net.miginfocom.layout.ComponentWrapper; import net.miginfocom.layout.ContainerWrapper; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; /** */ public final class SwtContainerWrapper extends SwtComponentWrapper implements ContainerWrapper { public SwtContainerWrapper(Composite c) { super(c); } public ComponentWrapper[] getComponents() { Composite c = (Composite) getComponent(); Control[] cons = c.getChildren(); ComponentWrapper[] cws = new ComponentWrapper[cons.length]; for (int i = 0; i < cws.length; i++) cws[i] = new SwtComponentWrapper(cons[i]); return cws; } public int getComponentCount() { return ((Composite) getComponent()).getChildren().length; } public Object getLayout() { return ((Composite) getComponent()).getLayout(); } public final boolean isLeftToRight() { return (((Composite) getComponent()).getStyle() & SWT.LEFT_TO_RIGHT) > 0; } public final void paintDebugCell(int x, int y, int width, int height) { // A Composite can not draw above its children, so the cells can not be painted. // if (c.isDisposed()) // return; // GC gc = new GC(c); // // gc.setLineStyle(SWT.LINE_DASHDOTDOT); // gc.setLineJoin(SWT.JOIN_MITER); // gc.setLineCap(SWT.CAP_SQUARE); // // gc.setBackground(DB_CELL_BG); // gc.fillRectangle(x, y, width, height); // // gc.setForeground(DB_CELL_OUTLINE); // gc.drawRectangle(x, y, width - 1, height - 1); // // gc.dispose(); } public int getComponetType(boolean disregardScrollPane) { return TYPE_CONTAINER; } public int getLayoutHashCode() { int h = super.getLayoutHashCode(); if (isLeftToRight()) h |= (1 << 26); return h; } } miglayout-3.7.4/net/miginfocom/swt/MigLayout.java0000644000175000017500000004474111313754622020630 0ustar tonytonypackage net.miginfocom.swt; /* * 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 net.miginfocom.layout.*; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Layout; import java.io.*; import java.lang.ref.WeakReference; import java.util.*; /** A very flexbile layout manager. *

* Read the documentation that came with this layout manager for information on usage. */ public final class MigLayout extends Layout implements Externalizable { static { // Mac Swing defaults to 96 DPI from Java6 though SWT is still on 72. if (PlatformDefaults.getPlatform() == PlatformDefaults.MAC_OSX) PlatformDefaults.setDefaultDPI(72); } // ******** Instance part ******** /** The component to string constraints mappings. */ private final Map scrConstrMap = new IdentityHashMap(8); /** Hold the serializable text representation of the constraints. */ private Object layoutConstraints = "", colConstraints = "", rowConstraints = ""; // Should never be null! // ******** Transient part ******** private transient ContainerWrapper cacheParentW = null; private transient final Map ccMap = new HashMap(8); private transient LC lc = null; private transient AC colSpecs = null, rowSpecs = null; private transient Grid grid = null; private transient java.util.Timer debugTimer = null; private transient long curDelay = -1; private transient int lastModCount = PlatformDefaults.getModCount(); private transient int lastHash = -1; private transient ArrayList callbackList = null; /** Constructor with no constraints. */ public MigLayout() { this("", "", ""); } /** Constructor. * @param layoutConstraints The constraints that concern the whole layout. null will be treated as "". */ public MigLayout(String layoutConstraints) { this(layoutConstraints, "", ""); } /** Constructor. * @param layoutConstraints The constraints that concern the whole layout. null will be treated as "". * @param colConstraints The constraints for the columns in the grid. null will be treated as "". */ public MigLayout(String layoutConstraints, String colConstraints) { this(layoutConstraints, colConstraints, ""); } /** Constructor. * @param layoutConstraints The constraints that concern the whole layout. null will be treated as "". * @param colConstraints The constraints for the columns in the grid. null will be treated as "". * @param rowConstraints The constraints for the rows in the grid. null will be treated as "". */ public MigLayout(String layoutConstraints, String colConstraints, String rowConstraints) { setLayoutConstraints(layoutConstraints); setColumnConstraints(colConstraints); setRowConstraints(rowConstraints); } /** Constructor. * @param layoutConstraints The constraints that concern the whole layout. null will be treated as an empty cosntraint. */ public MigLayout(LC layoutConstraints) { this(layoutConstraints, null, null); } /** Constructor. * @param layoutConstraints The constraints that concern the whole layout. null will be treated as an empty cosntraint. * @param colConstraints The constraints for the columns in the grid. null will be treated as an empty constraint. */ public MigLayout(LC layoutConstraints, AC colConstraints) { this(layoutConstraints, colConstraints, null); } /** Constructor. * @param layoutConstraints The constraints that concern the whole layout. null will be treated as an empty cosntraint. * @param colConstraints The constraints for the columns in the grid. null will be treated as an empty constraint. * @param rowConstraints The constraints for the rows in the grid. null will be treated as an empty constraint. */ public MigLayout(LC layoutConstraints, AC colConstraints, AC rowConstraints) { setLayoutConstraints(layoutConstraints); setColumnConstraints(colConstraints); setRowConstraints(rowConstraints); } /** Returns layout constraints eighter as a String or {@link net.miginfocom.layout.LC} depending what was sent in * to the constructor or set with {@link #setLayoutConstraints(Object)}. * @return The layout constraints eighter as a String or {@link net.miginfocom.layout.LC} depending what was sent in * to the constructor or set with {@link #setLayoutConstraints(Object)}. Never null. */ public Object getLayoutConstraints() { return layoutConstraints; } /** Sets the layout constraints for the layout manager instance as a String. *

* See the class JavaDocs for information on how this string is formatted. * @param s The layout constraints as a String representation. null is converted to "" for storage. * @throws RuntimeException if the constaint was not valid. */ public void setLayoutConstraints(Object s) { if (s == null || s instanceof String) { s = ConstraintParser.prepare((String) s); lc = ConstraintParser.parseLayoutConstraint((String) s); } else if (s instanceof LC) { lc = (LC) s; } else { throw new IllegalArgumentException("Illegal constraint type: " + s.getClass().toString()); } layoutConstraints = s; grid = null; } /** Returns the column layout constraints either as a String or {@link net.miginfocom.layout.AC}. * @return The column constraints eighter as a String or {@link net.miginfocom.layout.LC} depending what was sent in * to the constructor or set with {@link #setLayoutConstraints(Object)}. Never null. */ public Object getColumnConstraints() { return colConstraints; } /** Sets the column layout constraints for the layout manager instance as a String. *

* See the class JavaDocs for information on how this string is formatted. * @param constr The column layout constraints as a String representation. null is converted to "" for storage. * @throws RuntimeException if the constaint was not valid. */ public void setColumnConstraints(Object constr) { if (constr == null || constr instanceof String) { constr = ConstraintParser.prepare((String) constr); colSpecs = ConstraintParser.parseColumnConstraints((String) constr); } else if (constr instanceof AC) { colSpecs = (AC) constr; } else { throw new IllegalArgumentException("Illegal constraint type: " + constr.getClass().toString()); } colConstraints = constr; grid = null; } /** Returns the row layout constraints as a String representation. This string is the exact string as set with {@link #setRowConstraints(Object)} * or sent into the constructor. *

* See the class JavaDocs for information on how this string is formatted. * @return The row layout constraints as a String representation. Never null. */ public Object getRowConstraints() { return rowConstraints; } /** Sets the row layout constraints for the layout manager instance as a String. *

* See the class JavaDocs for information on how this string is formatted. * @param constr The row layout constraints as a String representation. null is converted to "" for storage. * @throws RuntimeException if the constaint was not valid. */ public void setRowConstraints(Object constr) { if (constr == null || constr instanceof String) { constr = ConstraintParser.prepare((String) constr); rowSpecs = ConstraintParser.parseRowConstraints((String) constr); } else if (constr instanceof AC) { rowSpecs = (AC) constr; } else { throw new IllegalArgumentException("Illegal constraint type: " + constr.getClass().toString()); } rowConstraints = constr; grid = null; } /** Returns a shallow copy of the constraints map. * @return A shallow copy of the constraints map. Never null. */ public Map getConstraintMap() { return new IdentityHashMap(scrConstrMap); } /** Sets the constraints map. * @param map The map. Will be copied. */ public void setConstraintMap(Map map) { scrConstrMap.clear(); ccMap.clear(); for (Map.Entry e : map.entrySet()) setComponentConstraintsImpl(e.getKey(), e.getValue(), true); } /** Sets the component constraint for the component that already must be handleded by this layout manager. *

* See the class JavaDocs for information on how this string is formatted. * @param constr The component constraints as a String or {@link net.miginfocom.layout.CC}. null is ok. * @param comp The component to set the constraints for. * @param noCheck Doesn't check if control already is managed. * @throws RuntimeException if the constaint was not valid. * @throws IllegalArgumentException If the component is not handling the component. */ private void setComponentConstraintsImpl(Control comp, Object constr, boolean noCheck) { if (noCheck == false && scrConstrMap.containsKey(comp) == false) throw new IllegalArgumentException("Component must already be added to parent!"); ComponentWrapper cw = new SwtComponentWrapper(comp); if (constr == null || constr instanceof String) { String cStr = ConstraintParser.prepare((String) constr); scrConstrMap.put(comp, constr); ccMap.put(cw, ConstraintParser.parseComponentConstraint(cStr)); } else if (constr instanceof CC) { scrConstrMap.put(comp, constr); ccMap.put(cw, (CC) constr); } else { throw new IllegalArgumentException("Constraint must be String or ComponentConstraint: " + constr.getClass().toString()); } grid = null; } /** Returns if this layout manager is currently managing this component. * @param c The component to check. If null then false will be returned. * @return If this layout manager is currently managing this component. */ public boolean isManagingComponent(Control c) { return scrConstrMap.containsKey(c); } /** Adds the callback function that will be called at different stages of the layout cylce. * @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); } /** Removes the callback if it exists. * @param callback The callback. May be null. */ public void removeLayoutCallback(LayoutCallback callback) { if (callbackList != null) callbackList.remove(callback); } /** Sets the debugging state for this layout manager instance. If debug is turned on a timer will repaint the last laid out parent * with debug information on top. *

* Red fill and dashed darked red outline is used to indicate occupied cells in the grid. Blue dashed outline indicate indicate * component bounds set. *

* Note that debug can also be set on the layout constraints. There it will be persisted. The calue set here will not. See the class * JavaDocs for information. * @param parentW The parent. Never null. * @param b true means debug is turned on. */ private synchronized void setDebug(final ComponentWrapper parentW, boolean b) { if (b && (debugTimer == null || curDelay != getDebugMillis())) { if (debugTimer != null) debugTimer.cancel(); debugTimer = new Timer(true); curDelay = getDebugMillis(); debugTimer.schedule(new MyDebugRepaintTask(this), curDelay, curDelay); ContainerWrapper pCW = parentW.getParent(); Composite parent = pCW != null ? (Composite) pCW.getComponent() : null; if (parent != null) parent.layout(); } else if (!b && debugTimer != null) { debugTimer.cancel(); debugTimer = null; } } /** Returns the current debugging state. * @return The current debugging state. */ private boolean getDebug() { return debugTimer != null; } /** Returns the debug millis. Combines the value from {@link net.miginfocom.layout.LC#getDebugMillis()} and {@link net.miginfocom.layout.LayoutUtil#getGlobalDebugMillis()} * @return The combined value. */ private int getDebugMillis() { int globalDebugMillis = LayoutUtil.getGlobalDebugMillis(); return globalDebugMillis > 0 ? globalDebugMillis : lc.getDebugMillis(); } /** Check if something has changed and if so recrete it to the cached objects. * @param parent The parent that is the target for this layout manager. */ private void checkCache(Composite parent) { if (parent == null) return; checkConstrMap(parent); ContainerWrapper par = checkParent(parent); // Check if the grid is valid int mc = PlatformDefaults.getModCount(); if (lastModCount != mc) { grid = null; lastModCount = mc; } int hash = parent.getSize().hashCode(); for (Iterator it = ccMap.keySet().iterator(); it.hasNext();) hash += it.next().getLayoutHashCode(); if (hash != lastHash) { grid = null; lastHash = hash; } setDebug(par, getDebugMillis() > 0); if (grid == null) grid = new Grid(par, lc, rowSpecs, colSpecs, ccMap, callbackList); } private boolean checkConstrMap(Composite parent) { Control[] comps = parent.getChildren(); boolean changed = comps.length != scrConstrMap.size(); if (changed == false) { for (int i = 0; i < comps.length; i++) { Control c = comps[i]; if (scrConstrMap.get(c) != c.getLayoutData()) { changed = true; break; } } } if (changed) { scrConstrMap.clear(); for (int i = 0; i < comps.length; i++) { Control c = comps[i]; setComponentConstraintsImpl(c, c.getLayoutData(), true); } } return changed; } private ContainerWrapper checkParent(Composite parent) { if (parent == null) return null; if (cacheParentW == null || cacheParentW.getComponent() != parent) cacheParentW = new SwtContainerWrapper(parent); return cacheParentW; } public float getLayoutAlignmentX(Composite parent) { return lc != null && lc.getAlignX() != null ? lc.getAlignX().getPixels(1, checkParent(parent), null) : 0; } public float getLayoutAlignmentY(Composite parent) { return lc != null && lc.getAlignY() != null ? lc.getAlignY().getPixels(1, checkParent(parent), null) : 0; } protected Point computeSize(Composite parent, int wHint, int hHint, boolean flushCache) { checkCache(parent); int w = LayoutUtil.getSizeSafe(grid != null ? grid.getWidth() : null, LayoutUtil.PREF); int h = LayoutUtil.getSizeSafe(grid != null ? grid.getHeight() : null, LayoutUtil.PREF); return new Point(w, h); } protected void layout(Composite parent, boolean flushCache) { checkCache(parent); Rectangle r = parent.getClientArea(); int[] b = new int[] {r.x, r.y, r.width, r.height}; final boolean layoutAgain = grid.layout(b, lc.getAlignX(), lc.getAlignY(), getDebug(), true); if (layoutAgain) { grid = null; checkCache(parent); grid.layout(b, lc.getAlignX(), lc.getAlignY(), getDebug(), false); } } protected boolean flushCache(Control control) { // if (lc.isNoCache()) // Commented for 3.5 since there was too often that the "nocache" was needed and the user did not know. grid = null; return true; } // ************************************************ // Persistence Delegate and Serializable combined. // ************************************************ private Object readResolve() throws ObjectStreamException { return LayoutUtil.getSerializedObject(this); } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { LayoutUtil.setSerializedObject(this, LayoutUtil.readAsXML(in)); } public void writeExternal(ObjectOutput out) throws IOException { if (getClass() == MigLayout.class) LayoutUtil.writeAsXML(out, this); } private static class MyDebugRepaintTask extends TimerTask { private final WeakReference layoutRef; private MyDebugRepaintTask(MigLayout layout) { this.layoutRef = new WeakReference(layout); } public void run() { final MigLayout layout = layoutRef.get(); if (layout != null && layout.grid != null) { Display.getDefault().asyncExec(new Runnable () { public void run () { if (layout.grid != null) layout.grid.paintDebug(); } }); } } } }miglayout-3.7.4/net/miginfocom/swt/SwtComponentWrapper.java0000644000175000017500000002174511301437376022717 0ustar tonytonypackage net.miginfocom.swt; /* * 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 net.miginfocom.layout.ComponentWrapper; import net.miginfocom.layout.ContainerWrapper; import net.miginfocom.layout.PlatformDefaults; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.graphics.*; import org.eclipse.swt.widgets.*; /** */ public class SwtComponentWrapper implements ComponentWrapper { /** Debug color for component bounds outline. */ private static Color DB_COMP_OUTLINE = new Color(Display.getCurrent(), 0, 0, 200); private static boolean vp = false; private static boolean mz = false; private final Control c; private int compType = TYPE_UNSET; public SwtComponentWrapper(Control c) { this.c = c; } public final int getBaseline(int width, int height) { return -1; } public final Object getComponent() { return c; } public final float getPixelUnitFactor(boolean isHor) { switch (PlatformDefaults.getLogicalPixelBase()) { case PlatformDefaults.BASE_FONT_SIZE: GC gc = new GC(c); FontMetrics fm = gc.getFontMetrics(); float f = isHor ? fm.getAverageCharWidth() / 5f : fm.getHeight() / 13f; gc.dispose(); return f; case PlatformDefaults.BASE_SCALE_FACTOR: Float s = isHor ? PlatformDefaults.getHorizontalScaleFactor() : PlatformDefaults.getVerticalScaleFactor(); if (s != null) return s.floatValue(); return (isHor ? getHorizontalScreenDPI() : getVerticalScreenDPI()) / (float) PlatformDefaults.getDefaultDPI(); default: return 1f; } } // /** Cache. // */ // private final static IdentityHashMap FM_MAP2 = new IdentityHashMap(4); // private final static Font SUBST_FONT2 = new Font("sansserif", Font.PLAIN, 11); // // public float getDialogUnit(boolean isHor) // { // Font font = c.getFont(); // FontMetrics fm = c.getFontMetrics(font != null ? font : SUBST_FONT2); // Point.Float dluP = FM_MAP2.get(fm); // if (dluP == null) { // float w = fm.charWidth('X') / 4f; // int ascent = fm.getAscent(); // float h = (ascent > 14 ? ascent : ascent + (15 - ascent) / 3) / 8f; // // dluP = new Point.Float(w, h); // FM_MAP2.put(fm, dluP); // } // return isHor ? dluP.x : dluP.y; // } public final int getX() { return c.getLocation().x; } public final int getY() { return c.getLocation().y; } public final int getWidth() { return c.getSize().x; } public final int getHeight() { return c.getSize().y; } public final int getScreenLocationX() { return c.toDisplay(0, 0).x; } public final int getScreenLocationY() { return c.toDisplay(0, 0).y; } public final int getMinimumHeight(int sz) { return mz ? 0 : computeSize(false, sz).y; } public final int getMinimumWidth(int sz) { return mz ? 0 : computeSize(true, sz).x; } public final int getPreferredHeight(int sz) { return computeSize(false, sz).y; } public final int getPreferredWidth(int sz) { return computeSize(true, sz).x; } public final int getMaximumHeight(int sz) { return Short.MAX_VALUE; } public final int getMaximumWidth(int sz) { return Short.MAX_VALUE; } private Point computeSize(boolean hor, int sz) { //Point p = c.getSize(); int wHint = hor ? SWT.DEFAULT : sz; //(hor || p.x <= 0) ? sz : p.x; int hHint = !hor ? SWT.DEFAULT : sz; //(!hor || p.y <= 0) ? sz : p.y; if (wHint != SWT.DEFAULT || hHint != SWT.DEFAULT) { int trim = 0; if (c instanceof Scrollable) { Rectangle rect = ((Scrollable) c).computeTrim(0, 0, 0, 0); trim = hor ? rect.width : rect.height; } else { trim = (c.getBorderWidth() << 1); } if (wHint == SWT.DEFAULT) { hHint = Math.max(0, hHint - trim); } else { wHint = Math.max(0, wHint - trim); } } return c.computeSize(wHint, hHint); } public final ContainerWrapper getParent() { return new SwtContainerWrapper(c.getParent()); } public int getHorizontalScreenDPI() { return c.getDisplay().getDPI().x; } public int getVerticalScreenDPI() { return c.getDisplay().getDPI().y; } public final int getScreenWidth() { return c.getDisplay().getBounds().width; } public final int getScreenHeight() { return c.getDisplay().getBounds().height; } public final boolean hasBaseline() { return false; } public final String getLinkId() { return null; } public final void setBounds(int x, int y, int width, int height) { c.setBounds(x, y, width, height); } public boolean isVisible() { return c.getVisible(); } public final int[] getVisualPadding() { return null; } public static boolean isUseVisualPadding() { return vp; } public static void setUseVisualPadding(boolean b) { vp = b; } /** Sets if minimum size for SWT components should be preferred size (default, false) or 0. * @return true means minimum size is 0. */ public static boolean isMinimumSizeZero() { return mz; } /** Sets if minimum size for SWT components should be preferred size (default, false) or 0. * @param b true means minimum size is 0. */ public static void setMinimumSizeZero(boolean b) { mz = b; } public int getLayoutHashCode() { if (c.isDisposed()) return -1; Point sz = c.getSize(); Point p = c.computeSize(SWT.DEFAULT, SWT.DEFAULT, false); int h = p.x + (p.y << 12) + (sz.x << 22) + (sz.y << 16); if (c.isVisible()) h |= (1 << 25); String id = getLinkId(); if (id != null) h += id.hashCode(); return h; } public final void paintDebugOutline() { if (c.isDisposed()) return; GC gc = new GC(c); gc.setLineJoin(SWT.JOIN_MITER); gc.setLineCap(SWT.CAP_SQUARE); gc.setLineStyle(SWT.LINE_DOT); gc.setForeground(DB_COMP_OUTLINE); gc.drawRectangle(0, 0, getWidth() - 1, getHeight() - 1); gc.dispose(); } public int getComponetType(boolean disregardScrollPane) { if (compType == TYPE_UNSET) compType = checkType(); return compType; } private int checkType() { int s = c.getStyle(); if (c instanceof Text || c instanceof StyledText) { return (s & SWT.MULTI) > 0 ? TYPE_TEXT_AREA : TYPE_TEXT_FIELD; } else if (c instanceof Label) { return (s & SWT.SEPARATOR) > 0 ? TYPE_SEPARATOR : TYPE_LABEL; } else if (c instanceof Button) { if ((s & SWT.CHECK) > 0 || (s & SWT.RADIO) > 0) return TYPE_CHECK_BOX; return TYPE_BUTTON; } else if (c instanceof Canvas) { return TYPE_PANEL; } else if (c instanceof List) { return TYPE_LIST; } else if (c instanceof Table) { return TYPE_TABLE; } else if (c instanceof Spinner) { return TYPE_SPINNER; } else if (c instanceof ProgressBar) { return TYPE_PROGRESS_BAR; } else if (c instanceof Slider) { return TYPE_SLIDER; } else if (c instanceof Composite) { // only AWT components is not containers. return TYPE_CONTAINER; } return TYPE_UNKNOWN; } public final int hashCode() { return c.hashCode(); } public final boolean equals(Object o) { if (o == null || o instanceof ComponentWrapper == false) return false; return getComponent().equals(((ComponentWrapper) o).getComponent()); } }