/* * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */package javax.swing; import java.awt.Component;import java.awt.Container;import java.awt.Dimension;import java.awt.FontMetrics;import java.awt.Insets;import java.awt.LayoutManager2;import java.awt.Rectangle;import java.util.*; /** * A <code>SpringLayout</code> lays out the children of its associated container * according to a set of constraints. * See <a href="http://java.sun.com/docs/books/tutorial/uiswing/layout/spring.html">How to Use SpringLayout</a> * in <em>The Java Tutorial</em> for examples of using * <code>SpringLayout</code>. * * <p> * Each constraint, * represented by a <code>Spring</code> object, * controls the vertical or horizontal distance * between two component edges. * The edges can belong to * any child of the container, * or to the container itself. * For example, * the allowable width of a component * can be expressed using a constraint * that controls the distance between the west (left) and east (right) * edges of the component. * The allowable <em>y</em> coordinates for a component * can be expressed by constraining the distance between * the north (top) edge of the component * and the north edge of its container. * * <P> * Every child of a <code>SpringLayout</code>-controlled container, * as well as the container itself, * has exactly one set of constraints * associated with it. * These constraints are represented by * a <code>SpringLayout.Constraints</code> object. * By default, * <code>SpringLayout</code> creates constraints * that make their associated component * have the minimum, preferred, and maximum sizes * returned by the component's * {@link java.awt.Component#getMinimumSize}, * {@link java.awt.Component#getPreferredSize}, and * {@link java.awt.Component#getMaximumSize} * methods. The <em>x</em> and <em>y</em> positions are initially not * constrained, so that until you constrain them the <code>Component</code> * will be positioned at 0,0 relative to the <code>Insets</code> of the * parent <code>Container</code>. * * <p> * You can change * a component's constraints in several ways. * You can * use one of the * {@link #putConstraint putConstraint} * methods * to establish a spring * linking the edges of two components within the same container. * Or you can get the appropriate <code>SpringLayout.Constraints</code> * object using * {@link #getConstraints getConstraints} * and then modify one or more of its springs. * Or you can get the spring for a particular edge of a component * using {@link #getConstraint getConstraint}, * and modify it. * You can also associate * your own <code>SpringLayout.Constraints</code> object * with a component by specifying the constraints object * when you add the component to its container * (using * {@link Container#add(Component, Object)}). * * <p> * The <code>Spring</code> object representing each constraint * has a minimum, preferred, maximum, and current value. * The current value of the spring * is somewhere between the minimum and maximum values, * according to the formula given in the * {@link Spring#sum} method description. * When the minimum, preferred, and maximum values are the same, * the current value is always equal to them; * this inflexible spring is called a <em>strut</em>. * You can create struts using the factory method * {@link Spring#constant(int)}. * The <code>Spring</code> class also provides factory methods * for creating other kinds of springs, * including springs that depend on other springs. * * <p> * In a <code>SpringLayout</code>, the position of each edge is dependent on * the position of just one other edge. If a constraint is subsequently added * to create a new binding for an edge, the previous binding is discarded * and the edge remains dependent on a single edge. * Springs should only be attached * between edges of the container and its immediate children; the behavior * of the <code>SpringLayout</code> when presented with constraints linking * the edges of components from different containers (either internal or * external) is undefined. * * <h3> * SpringLayout vs. Other Layout Managers * </h3> * * <blockquote> * <hr> * <strong>Note:</strong> * Unlike many layout managers, * <code>SpringLayout</code> doesn't automatically set the location of * the components it manages. * If you hand-code a GUI that uses <code>SpringLayout</code>, * remember to initialize component locations by constraining the west/east * and north/south locations. * <p> * Depending on the constraints you use, * you may also need to set the size of the container explicitly. * <hr> * </blockquote> * * <p> * Despite the simplicity of <code>SpringLayout</code>, * it can emulate the behavior of most other layout managers. * For some features, * such as the line breaking provided by <code>FlowLayout</code>, * you'll need to * create a special-purpose subclass of the <code>Spring</code> class. * * <p> * <code>SpringLayout</code> also provides a way to solve * many of the difficult layout * problems that cannot be solved by nesting combinations * of <code>Box</code>es. That said, <code>SpringLayout</code> honors the * <code>LayoutManager2</code> contract correctly and so can be nested with * other layout managers -- a technique that can be preferable to * creating the constraints implied by the other layout managers. * <p> * The asymptotic complexity of the layout operation of a <code>SpringLayout</code> * is linear in the number of constraints (and/or components). * <p> * <strong>Warning:</strong> * Serialized objects of this class will not be compatible with * future Swing releases. The current serialization support is * appropriate for short term storage or RMI between applications running * the same version of Swing. As of 1.4, support for long term storage * of all JavaBeans<sup><font size="-2">TM</font></sup> * has been added to the <code>java.beans</code> package. * Please see {@link java.beans.XMLEncoder}. * * @see Spring * @see SpringLayout.Constraints * * @author Philip Milne * @author Scott Violet * @author Joe Winchester * @since 1.4 */public class SpringLayout implements LayoutManager2 { private Map<Component, Constraints> componentConstraints = new HashMap<Component, Constraints>(); private Spring cyclicReference = Spring.constant(Spring.UNSET); private Set<Spring> cyclicSprings; private Set<Spring> acyclicSprings; /** * Specifies the top edge of a component's bounding rectangle. */ public static final String NORTH = "North"; /** * Specifies the bottom edge of a component's bounding rectangle. */ public static final String SOUTH = "South"; /** * Specifies the right edge of a component's bounding rectangle. */ public static final String EAST = "East"; /** * Specifies the left edge of a component's bounding rectangle. */ public static final String WEST = "West"; /** * Specifies the horizontal center of a component's bounding rectangle. * * @since 1.6 */ public static final String HORIZONTAL_CENTER = "HorizontalCenter"; /** * Specifies the vertical center of a component's bounding rectangle. * * @since 1.6 */ public static final String VERTICAL_CENTER = "VerticalCenter"; /** * Specifies the baseline of a component. * * @since 1.6 */ public static final String BASELINE = "Baseline"; /** * Specifies the width of a component's bounding rectangle. * * @since 1.6 */ public static final String WIDTH = "Width"; /** * Specifies the height of a component's bounding rectangle. * * @since 1.6 */ public static final String HEIGHT = "Height"; private static String[] ALL_HORIZONTAL = {WEST, WIDTH, EAST, HORIZONTAL_CENTER}; private static String[] ALL_VERTICAL = {NORTH, HEIGHT, SOUTH, VERTICAL_CENTER, BASELINE}; /** * A <code>Constraints</code> object holds the * constraints that govern the way a component's size and position * change in a container controlled by a <code>SpringLayout</code>. * A <code>Constraints</code> object is * like a <code>Rectangle</code>, in that it * has <code>x</code>, <code>y</code>, * <code>width</code>, and <code>height</code> properties. * In the <code>Constraints</code> object, however, * these properties have * <code>Spring</code> values instead of integers. * In addition, * a <code>Constraints</code> object * can be manipulated as four edges * -- north, south, east, and west -- * using the <code>constraint</code> property. * * <p> * The following formulas are always true * for a <code>Constraints</code> object (here WEST and <code>x</code> are synonyms, as are and NORTH and <code>y</code>): * * <pre> * EAST = WEST + WIDTH * SOUTH = NORTH + HEIGHT * HORIZONTAL_CENTER = WEST + WIDTH/2 * VERTICAL_CENTER = NORTH + HEIGHT/2 * ABSOLUTE_BASELINE = NORTH + RELATIVE_BASELINE* * </pre> * <p> * For example, if you have specified the WIDTH and WEST (X) location * the EAST is calculated as WEST + WIDTH. If you instead specified * the WIDTH and EAST locations the WEST (X) location is then calculated * as EAST - WIDTH. * <p> * [RELATIVE_BASELINE is a private constraint that is set automatically when * the SpringLayout.Constraints(Component) constuctor is called or when * a constraints object is registered with a SpringLayout object.] * <p> * <b>Note</b>: In this document, * operators represent methods * in the <code>Spring</code> class. * For example, "a + b" is equal to * <code>Spring.sum(a, b)</code>, * and "a - b" is equal to * <code>Spring.sum(a, Spring.minus(b))</code>. * See the * {@link Spring <code>Spring</code> API documentation} * for further details * of spring arithmetic. * * <p> * * Because a <code>Constraints</code> object's properties -- * representing its edges, size, and location -- can all be set * independently and yet are interrelated, * a <code>Constraints</code> object can become <em>over-constrained</em>. * For example, if the <code>WEST</code>, <code>WIDTH</code> and * <code>EAST</code> edges are all set, steps must be taken to ensure that * the first of the formulas above holds. To do this, the * <code>Constraints</code> * object throws away the <em>least recently set</em> * constraint so as to make the formulas hold. * @since 1.4 */ public static class Constraints { private Spring x; private Spring y; private Spring width; private Spring height; private Spring east; private Spring south; private Spring horizontalCenter; private Spring verticalCenter; private Spring baseline; private List<String> horizontalHistory = new ArrayList<String>(2); private List<String> verticalHistory = new ArrayList<String>(2); // Used for baseline calculations private Component c; /** * Creates an empty <code>Constraints</code> object. */ public Constraints() { } /** * Creates a <code>Constraints</code> object with the * specified values for its * <code>x</code> and <code>y</code> properties. * The <code>height</code> and <code>width</code> springs * have <code>null</code> values. * * @param x the spring controlling the component's <em>x</em> value * @param y the spring controlling the component's <em>y</em> value */ public Constraints(Spring x, Spring y) { setX(x); setY(y); } /** * Creates a <code>Constraints</code> object with the * specified values for its * <code>x</code>, <code>y</code>, <code>width</code>, * and <code>height</code> properties. * Note: If the <code>SpringLayout</code> class * encounters <code>null</code> values in the * <code>Constraints</code> object of a given component, * it replaces them with suitable defaults. * * @param x the spring value for the <code>x</code> property * @param y the spring value for the <code>y</code> property * @param width the spring value for the <code>width</code> property * @param height the spring value for the <code>height</code> property */ public Constraints(Spring x, Spring y, Spring width, Spring height) { setX(x); setY(y); setWidth(width); setHeight(height); } /** * Creates a <code>Constraints</code> object with * suitable <code>x</code>, <code>y</code>, <code>width</code> and * <code>height</code> springs for component, <code>c</code>. * The <code>x</code> and <code>y</code> springs are constant * springs initialised with the component's location at * the time this method is called. The <code>width</code> and * <code>height</code> springs are special springs, created by * the <code>Spring.width()</code> and <code>Spring.height()</code> * methods, which track the size characteristics of the component * when they change. * * @param c the component whose characteristics will be reflected by this Constraints object * @throws NullPointerException if <code>c</code> is null. * @since 1.5 */ public Constraints(Component c) { this.c = c; setX(Spring.constant(c.getX())); setY(Spring.constant(c.getY())); setWidth(Spring.width(c)); setHeight(Spring.height(c)); } private void pushConstraint(String name, Spring value, boolean horizontal) { boolean valid = true; List<String> history = horizontal ? horizontalHistory : verticalHistory; if (history.contains(name)) { history.remove(name); valid = false; } else if (history.size() == 2 && value != null) { history.remove(0); valid = false; } if (value != null) { history.add(name); } if (!valid) { String[] all = horizontal ? ALL_HORIZONTAL : ALL_VERTICAL; for (String s : all) { if (!history.contains(s)) { setConstraint(s, null); } } } } private Spring sum(Spring s1, Spring s2) { return (s1 == null || s2 == null) ? null : Spring.sum(s1, s2); } private Spring difference(Spring s1, Spring s2) { return (s1 == null || s2 == null) ? null : Spring.difference(s1, s2); } private Spring scale(Spring s, float factor) { return (s == null) ? null : Spring.scale(s, factor); } private int getBaselineFromHeight(int height) { if (height < 0) { // Bad Scott, Bad Scott! return -c.getBaseline(c.getPreferredSize().width, -height); } return c.getBaseline(c.getPreferredSize().width, height); } private int getHeightFromBaseLine(int baseline) { Dimension prefSize = c.getPreferredSize(); int prefHeight = prefSize.height; int prefBaseline = c.getBaseline(prefSize.width, prefHeight); if (prefBaseline == baseline) { // If prefBaseline < 0, then no baseline, assume preferred // height. // If prefBaseline == baseline, then specified baseline // matches preferred baseline, return preferred height return prefHeight; } // Valid baseline switch(c.getBaselineResizeBehavior()) { case CONSTANT_DESCENT: return prefHeight + (baseline - prefBaseline); case CENTER_OFFSET: return prefHeight + 2 * (baseline - prefBaseline); case CONSTANT_ASCENT: // Component baseline and specified baseline will NEVER // match, fall through to default default: // OTHER // No way to map from baseline to height. } return Integer.MIN_VALUE; } private Spring heightToRelativeBaseline(Spring s) { return new Spring.SpringMap(s) { protected int map(int i) { return getBaselineFromHeight(i); } protected int inv(int i) { return getHeightFromBaseLine(i); } }; } private Spring relativeBaselineToHeight(Spring s) { return new Spring.SpringMap(s) { protected int map(int i) { return getHeightFromBaseLine(i); } protected int inv(int i) { return getBaselineFromHeight(i); } }; } private boolean defined(List history, String s1, String s2) { return history.contains(s1) && history.contains(s2); } Lines 1–500 of 1233. Load more
/* * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javax.swing; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.FontMetrics; import java.awt.Insets; import java.awt.LayoutManager2; import java.awt.Rectangle; import java.util.*; /** * A <code>SpringLayout</code> lays out the children of its associated container * according to a set of constraints. * See <a href="http://java.sun.com/docs/books/tutorial/uiswing/layout/spring.html">How to Use SpringLayout</a> * in <em>The Java Tutorial</em> for examples of using * <code>SpringLayout</code>. * * <p> * Each constraint, * represented by a <code>Spring</code> object, * controls the vertical or horizontal distance * between two component edges. * The edges can belong to * any child of the container, * or to the container itself. * For example, * the allowable width of a component * can be expressed using a constraint * that controls the distance between the west (left) and east (right) * edges of the component. * The allowable <em>y</em> coordinates for a component * can be expressed by constraining the distance between * the north (top) edge of the component * and the north edge of its container. * * <P> * Every child of a <code>SpringLayout</code>-controlled container, * as well as the container itself, * has exactly one set of constraints * associated with it. * These constraints are represented by * a <code>SpringLayout.Constraints</code> object. * By default, * <code>SpringLayout</code> creates constraints * that make their associated component * have the minimum, preferred, and maximum sizes * returned by the component's * {@link java.awt.Component#getMinimumSize}, * {@link java.awt.Component#getPreferredSize}, and * {@link java.awt.Component#getMaximumSize} * methods. The <em>x</em> and <em>y</em> positions are initially not * constrained, so that until you constrain them the <code>Component</code> * will be positioned at 0,0 relative to the <code>Insets</code> of the * parent <code>Container</code>. * * <p> * You can change * a component's constraints in several ways. * You can * use one of the * {@link #putConstraint putConstraint} * methods * to establish a spring * linking the edges of two components within the same container. * Or you can get the appropriate <code>SpringLayout.Constraints</code> * object using * {@link #getConstraints getConstraints} * and then modify one or more of its springs. * Or you can get the spring for a particular edge of a component * using {@link #getConstraint getConstraint}, * and modify it. * You can also associate * your own <code>SpringLayout.Constraints</code> object * with a component by specifying the constraints object * when you add the component to its container * (using * {@link Container#add(Component, Object)}). * * <p> * The <code>Spring</code> object representing each constraint * has a minimum, preferred, maximum, and current value. * The current value of the spring * is somewhere between the minimum and maximum values, * according to the formula given in the * {@link Spring#sum} method description. * When the minimum, preferred, and maximum values are the same, * the current value is always equal to them; * this inflexible spring is called a <em>strut</em>. * You can create struts using the factory method * {@link Spring#constant(int)}. * The <code>Spring</code> class also provides factory methods * for creating other kinds of springs, * including springs that depend on other springs. * * <p> * In a <code>SpringLayout</code>, the position of each edge is dependent on * the position of just one other edge. If a constraint is subsequently added * to create a new binding for an edge, the previous binding is discarded * and the edge remains dependent on a single edge. * Springs should only be attached * between edges of the container and its immediate children; the behavior * of the <code>SpringLayout</code> when presented with constraints linking * the edges of components from different containers (either internal or * external) is undefined. * * <h3> * SpringLayout vs. Other Layout Managers * </h3> * * <blockquote> * <hr> * <strong>Note:</strong> * Unlike many layout managers, * <code>SpringLayout</code> doesn't automatically set the location of * the components it manages. * If you hand-code a GUI that uses <code>SpringLayout</code>, * remember to initialize component locations by constraining the west/east * and north/south locations. * <p> * Depending on the constraints you use, * you may also need to set the size of the container explicitly. * <hr> * </blockquote> * * <p> * Despite the simplicity of <code>SpringLayout</code>, * it can emulate the behavior of most other layout managers. * For some features, * such as the line breaking provided by <code>FlowLayout</code>, * you'll need to * create a special-purpose subclass of the <code>Spring</code> class. * * <p> * <code>SpringLayout</code> also provides a way to solve * many of the difficult layout * problems that cannot be solved by nesting combinations * of <code>Box</code>es. That said, <code>SpringLayout</code> honors the * <code>LayoutManager2</code> contract correctly and so can be nested with * other layout managers -- a technique that can be preferable to * creating the constraints implied by the other layout managers. * <p> * The asymptotic complexity of the layout operation of a <code>SpringLayout</code> * is linear in the number of constraints (and/or components). * <p> * <strong>Warning:</strong> * Serialized objects of this class will not be compatible with * future Swing releases. The current serialization support is * appropriate for short term storage or RMI between applications running * the same version of Swing. As of 1.4, support for long term storage * of all JavaBeans<sup><font size="-2">TM</font></sup> * has been added to the <code>java.beans</code> package. * Please see {@link java.beans.XMLEncoder}. * * @see Spring * @see SpringLayout.Constraints * * @author Philip Milne * @author Scott Violet * @author Joe Winchester * @since 1.4 */ public class SpringLayout implements LayoutManager2 { private Map<Component, Constraints> componentConstraints = new HashMap<Component, Constraints>(); private Spring cyclicReference = Spring.constant(Spring.UNSET); private Set<Spring> cyclicSprings; private Set<Spring> acyclicSprings; /** * Specifies the top edge of a component's bounding rectangle. */ public static final String NORTH = "North"; /** * Specifies the bottom edge of a component's bounding rectangle. */ public static final String SOUTH = "South"; /** * Specifies the right edge of a component's bounding rectangle. */ public static final String EAST = "East"; /** * Specifies the left edge of a component's bounding rectangle. */ public static final String WEST = "West"; /** * Specifies the horizontal center of a component's bounding rectangle. * * @since 1.6 */ public static final String HORIZONTAL_CENTER = "HorizontalCenter"; /** * Specifies the vertical center of a component's bounding rectangle. * * @since 1.6 */ public static final String VERTICAL_CENTER = "VerticalCenter"; /** * Specifies the baseline of a component. * * @since 1.6 */ public static final String BASELINE = "Baseline"; /** * Specifies the width of a component's bounding rectangle. * * @since 1.6 */ public static final String WIDTH = "Width"; /** * Specifies the height of a component's bounding rectangle. * * @since 1.6 */ public static final String HEIGHT = "Height"; private static String[] ALL_HORIZONTAL = {WEST, WIDTH, EAST, HORIZONTAL_CENTER}; private static String[] ALL_VERTICAL = {NORTH, HEIGHT, SOUTH, VERTICAL_CENTER, BASELINE}; /** * A <code>Constraints</code> object holds the * constraints that govern the way a component's size and position * change in a container controlled by a <code>SpringLayout</code>. * A <code>Constraints</code> object is * like a <code>Rectangle</code>, in that it * has <code>x</code>, <code>y</code>, * <code>width</code>, and <code>height</code> properties. * In the <code>Constraints</code> object, however, * these properties have * <code>Spring</code> values instead of integers. * In addition, * a <code>Constraints</code> object * can be manipulated as four edges * -- north, south, east, and west -- * using the <code>constraint</code> property. * * <p> * The following formulas are always true * for a <code>Constraints</code> object (here WEST and <code>x</code> are synonyms, as are and NORTH and <code>y</code>): * * <pre> * EAST = WEST + WIDTH * SOUTH = NORTH + HEIGHT * HORIZONTAL_CENTER = WEST + WIDTH/2 * VERTICAL_CENTER = NORTH + HEIGHT/2 * ABSOLUTE_BASELINE = NORTH + RELATIVE_BASELINE* * </pre> * <p> * For example, if you have specified the WIDTH and WEST (X) location * the EAST is calculated as WEST + WIDTH. If you instead specified * the WIDTH and EAST locations the WEST (X) location is then calculated * as EAST - WIDTH. * <p> * [RELATIVE_BASELINE is a private constraint that is set automatically when * the SpringLayout.Constraints(Component) constuctor is called or when * a constraints object is registered with a SpringLayout object.] * <p> * <b>Note</b>: In this document, * operators represent methods * in the <code>Spring</code> class. * For example, "a + b" is equal to * <code>Spring.sum(a, b)</code>, * and "a - b" is equal to * <code>Spring.sum(a, Spring.minus(b))</code>. * See the * {@link Spring <code>Spring</code> API documentation} * for further details * of spring arithmetic. * * <p> * * Because a <code>Constraints</code> object's properties -- * representing its edges, size, and location -- can all be set * independently and yet are interrelated, * a <code>Constraints</code> object can become <em>over-constrained</em>. * For example, if the <code>WEST</code>, <code>WIDTH</code> and * <code>EAST</code> edges are all set, steps must be taken to ensure that * the first of the formulas above holds. To do this, the * <code>Constraints</code> * object throws away the <em>least recently set</em> * constraint so as to make the formulas hold. * @since 1.4 */ public static class Constraints { private Spring x; private Spring y; private Spring width; private Spring height; private Spring east; private Spring south; private Spring horizontalCenter; private Spring verticalCenter; private Spring baseline; private List<String> horizontalHistory = new ArrayList<String>(2); private List<String> verticalHistory = new ArrayList<String>(2); // Used for baseline calculations private Component c; /** * Creates an empty <code>Constraints</code> object. */ public Constraints() { } /** * Creates a <code>Constraints</code> object with the * specified values for its * <code>x</code> and <code>y</code> properties. * The <code>height</code> and <code>width</code> springs * have <code>null</code> values. * * @param x the spring controlling the component's <em>x</em> value * @param y the spring controlling the component's <em>y</em> value */ public Constraints(Spring x, Spring y) { setX(x); setY(y); } /** * Creates a <code>Constraints</code> object with the * specified values for its * <code>x</code>, <code>y</code>, <code>width</code>, * and <code>height</code> properties. * Note: If the <code>SpringLayout</code> class * encounters <code>null</code> values in the * <code>Constraints</code> object of a given component, * it replaces them with suitable defaults. * * @param x the spring value for the <code>x</code> property * @param y the spring value for the <code>y</code> property * @param width the spring value for the <code>width</code> property * @param height the spring value for the <code>height</code> property */ public Constraints(Spring x, Spring y, Spring width, Spring height) { setX(x); setY(y); setWidth(width); setHeight(height); } /** * Creates a <code>Constraints</code> object with * suitable <code>x</code>, <code>y</code>, <code>width</code> and * <code>height</code> springs for component, <code>c</code>. * The <code>x</code> and <code>y</code> springs are constant * springs initialised with the component's location at * the time this method is called. The <code>width</code> and * <code>height</code> springs are special springs, created by * the <code>Spring.width()</code> and <code>Spring.height()</code> * methods, which track the size characteristics of the component * when they change. * * @param c the component whose characteristics will be reflected by this Constraints object * @throws NullPointerException if <code>c</code> is null. * @since 1.5 */ public Constraints(Component c) { this.c = c; setX(Spring.constant(c.getX())); setY(Spring.constant(c.getY())); setWidth(Spring.width(c)); setHeight(Spring.height(c)); } private void pushConstraint(String name, Spring value, boolean horizontal) { boolean valid = true; List<String> history = horizontal ? horizontalHistory : verticalHistory; if (history.contains(name)) { history.remove(name); valid = false; } else if (history.size() == 2 && value != null) { history.remove(0); valid = false; } if (value != null) { history.add(name); } if (!valid) { String[] all = horizontal ? ALL_HORIZONTAL : ALL_VERTICAL; for (String s : all) { if (!history.contains(s)) { setConstraint(s, null); } } } } private Spring sum(Spring s1, Spring s2) { return (s1 == null || s2 == null) ? null : Spring.sum(s1, s2); } private Spring difference(Spring s1, Spring s2) { return (s1 == null || s2 == null) ? null : Spring.difference(s1, s2); } private Spring scale(Spring s, float factor) { return (s == null) ? null : Spring.scale(s, factor); } private int getBaselineFromHeight(int height) { if (height < 0) { // Bad Scott, Bad Scott! return -c.getBaseline(c.getPreferredSize().width, -height); } return c.getBaseline(c.getPreferredSize().width, height); } private int getHeightFromBaseLine(int baseline) { Dimension prefSize = c.getPreferredSize(); int prefHeight = prefSize.height; int prefBaseline = c.getBaseline(prefSize.width, prefHeight); if (prefBaseline == baseline) { // If prefBaseline < 0, then no baseline, assume preferred // height. // If prefBaseline == baseline, then specified baseline // matches preferred baseline, return preferred height return prefHeight; } // Valid baseline switch(c.getBaselineResizeBehavior()) { case CONSTANT_DESCENT: return prefHeight + (baseline - prefBaseline); case CENTER_OFFSET: return prefHeight + 2 * (baseline - prefBaseline); case CONSTANT_ASCENT: // Component baseline and specified baseline will NEVER // match, fall through to default default: // OTHER // No way to map from baseline to height. } return Integer.MIN_VALUE; } private Spring heightToRelativeBaseline(Spring s) { return new Spring.SpringMap(s) { protected int map(int i) { return getBaselineFromHeight(i); } protected int inv(int i) { return getHeightFromBaseLine(i); } }; } private Spring relativeBaselineToHeight(Spring s) { return new Spring.SpringMap(s) { protected int map(int i) { return getHeightFromBaseLine(i); } protected int inv(int i) { return getBaselineFromHeight(i); } }; } private boolean defined(List history, String s1, String s2) { return history.contains(s1) && history.contains(s2); }