001: /*
002: * Copyright (c) 2002-2007 JGoodies Karsten Lentzsch. All Rights Reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * o Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * o Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * o Neither the name of JGoodies Karsten Lentzsch nor the names of
015: * its contributors may be used to endorse or promote products derived
016: * from this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
020: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
021: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
022: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
025: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
026: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
027: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030:
031: package com.jgoodies.forms.layout;
032:
033: import java.awt.Component;
034: import java.awt.Container;
035: import java.io.Serializable;
036: import java.util.Iterator;
037: import java.util.List;
038:
039: import com.jgoodies.forms.util.DefaultUnitConverter;
040: import com.jgoodies.forms.util.UnitConverter;
041:
042: /**
043: * Consists only of static methods that create and convert sizes
044: * as required by the FormLayout. The conversion of sizes
045: * that are not based on pixel is delegated to an implementation
046: * of {@link UnitConverter}. The conversion methods require the
047: * layout container as parameter to read its current font and resolution.
048: *
049: * @author Karsten Lentzsch
050: * @version $Revision: 1.5 $
051: *
052: * @see Size
053: * @see UnitConverter
054: * @see DefaultUnitConverter
055: */
056: public final class Sizes {
057:
058: // Common Constant Sizes ************************************************
059:
060: public static final ConstantSize ZERO = pixel(0);
061:
062: public static final ConstantSize DLUX1 = dluX(1);
063: public static final ConstantSize DLUX2 = dluX(2);
064: public static final ConstantSize DLUX3 = dluX(3);
065: public static final ConstantSize DLUX4 = dluX(4);
066: public static final ConstantSize DLUX5 = dluX(5);
067: public static final ConstantSize DLUX6 = dluX(6);
068: public static final ConstantSize DLUX7 = dluX(7);
069: public static final ConstantSize DLUX8 = dluX(8);
070: public static final ConstantSize DLUX9 = dluX(9);
071: public static final ConstantSize DLUX11 = dluX(11);
072: public static final ConstantSize DLUX14 = dluX(14);
073:
074: public static final ConstantSize DLUY1 = dluY(1);
075: public static final ConstantSize DLUY2 = dluY(2);
076: public static final ConstantSize DLUY3 = dluY(3);
077: public static final ConstantSize DLUY4 = dluY(4);
078: public static final ConstantSize DLUY5 = dluY(5);
079: public static final ConstantSize DLUY6 = dluY(6);
080: public static final ConstantSize DLUY7 = dluY(7);
081: public static final ConstantSize DLUY8 = dluY(8);
082: public static final ConstantSize DLUY9 = dluY(9);
083: public static final ConstantSize DLUY11 = dluY(11);
084: public static final ConstantSize DLUY14 = dluY(14);
085:
086: // Static Component Sizes ***********************************************
087:
088: /**
089: * Use the maximum of all component minimum sizes as column or row size.
090: */
091: public static final ComponentSize MINIMUM = new ComponentSize(
092: "minimum");
093:
094: /**
095: * Use the maximum of all component preferred sizes as column or row size.
096: */
097: public static final ComponentSize PREFERRED = new ComponentSize(
098: "preferred");
099:
100: /**
101: * Use the maximum of all component sizes as column or row size;
102: * measures preferred sizes when asked for the preferred size
103: * and minimum sizes when asked for the minimum size.
104: */
105: public static final ComponentSize DEFAULT = new ComponentSize(
106: "default");
107:
108: /**
109: * An array of all enumeration values used to canonicalize
110: * deserialized component sizes.
111: */
112: private static final ComponentSize[] VALUES = { MINIMUM, PREFERRED,
113: DEFAULT };
114:
115: // Singleton State *******************************************************
116:
117: /**
118: * Holds the current converter that maps non-pixel sizes to pixels.
119: */
120: private static UnitConverter unitConverter;
121:
122: // Instance Creation ******************************************************
123:
124: private Sizes() {
125: // Suppresses default constructor, ensuring non-instantiability.
126: }
127:
128: // Creation of Size Instances *********************************************
129:
130: /**
131: * Creates and returns an instance of <code>ConstantSize</code> from the
132: * given encoded size and unit description.
133: *
134: * @param encodedValueAndUnit value and unit in string representation
135: * @param horizontal true for horizontal, false for vertical
136: * @return a <code>ConstantSize</code> for the given value and unit
137: */
138: public static ConstantSize constant(String encodedValueAndUnit,
139: boolean horizontal) {
140: return ConstantSize.valueOf(encodedValueAndUnit, horizontal);
141: }
142:
143: /**
144: * Creates and returns a ConstantSize for the specified value
145: * in horizontal dialog units.
146: *
147: * @param value size value in horizontal dialog units
148: * @return the associated <code>ConstantSize</code>
149: */
150: public static ConstantSize dluX(int value) {
151: return ConstantSize.dluX(value);
152: }
153:
154: /**
155: * Creates and returns a ConstantSize for the specified value
156: * in vertical dialog units.
157: *
158: * @param value size value in vertical dialog units
159: * @return the associated <code>ConstantSize</code>
160: */
161: public static ConstantSize dluY(int value) {
162: return ConstantSize.dluY(value);
163: }
164:
165: /**
166: * Creates and returns a ConstantSize
167: * for the specified pixel value.
168: *
169: * @param value value in pixel
170: * @return the associated <code>ConstantSize</code>
171: */
172: public static ConstantSize pixel(int value) {
173: return new ConstantSize(value, ConstantSize.PIXEL);
174: }
175:
176: /**
177: * Creates and returns a BoundedSize for the given basis
178: * using the specified lower and upper bounds.
179: *
180: * @param basis the base size
181: * @param lowerBound the lower bound size
182: * @param upperBound the upper bound size
183: * @return a <code>BoundedSize</code> for the given basis and bounds
184: * @throws NullPointerException if basis is null
185: */
186: public static Size bounded(Size basis, Size lowerBound,
187: Size upperBound) {
188: return new BoundedSize(basis, lowerBound, upperBound);
189: }
190:
191: // Unit Conversion ******************************************************
192:
193: /**
194: * Converts Inches and returns pixels using the specified resolution.
195: *
196: * @param in the Inches
197: * @param component the component that provides the graphics object
198: * @return the given Inches as pixels
199: */
200: public static int inchAsPixel(double in, Component component) {
201: return in == 0d ? 0 : getUnitConverter().inchAsPixel(in,
202: component);
203: }
204:
205: /**
206: * Converts Millimeters and returns pixels using the resolution of the
207: * given component's graphics object.
208: *
209: * @param mm Millimeters
210: * @param component the component that provides the graphics object
211: * @return the given Millimeters as pixels
212: */
213: public static int millimeterAsPixel(double mm, Component component) {
214: return mm == 0d ? 0 : getUnitConverter().millimeterAsPixel(mm,
215: component);
216: }
217:
218: /**
219: * Converts Centimeters and returns pixels using the resolution of the
220: * given component's graphics object.
221: *
222: * @param cm Centimeters
223: * @param component the component that provides the graphics object
224: * @return the given Centimeters as pixels
225: */
226: public static int centimeterAsPixel(double cm, Component component) {
227: return cm == 0d ? 0 : getUnitConverter().centimeterAsPixel(cm,
228: component);
229: }
230:
231: /**
232: * Converts DTP Points and returns pixels using the resolution of the
233: * given component's graphics object.
234: *
235: * @param pt DTP Points
236: * @param component the component that provides the graphics object
237: * @return the given Points as pixels
238: */
239: public static int pointAsPixel(int pt, Component component) {
240: return pt == 0 ? 0 : getUnitConverter().pointAsPixel(pt,
241: component);
242: }
243:
244: /**
245: * Converts horizontal dialog units and returns pixels.
246: * Honors the resolution, dialog font size, platform, and l&f.
247: *
248: * @param dluX the horizontal dialog units
249: * @param component the component that provides the graphics object
250: * @return the given horizontal dialog units as pixels
251: */
252: public static int dialogUnitXAsPixel(int dluX, Component component) {
253: return dluX == 0 ? 0 : getUnitConverter().dialogUnitXAsPixel(
254: dluX, component);
255: }
256:
257: /**
258: * Converts vertical dialog units and returns pixels.
259: * Honors the resolution, dialog font size, platform, and l&f.
260: *
261: * @param dluY the vertical dialog units
262: * @param component the component that provides the graphics object
263: * @return the given vertical dialog units as pixels
264: */
265: public static int dialogUnitYAsPixel(int dluY, Component component) {
266: return dluY == 0 ? 0 : getUnitConverter().dialogUnitYAsPixel(
267: dluY, component);
268: }
269:
270: // Accessing the Unit Converter *******************************************
271:
272: /**
273: * Returns the current {@link UnitConverter}. If it has not been initialized
274: * before it will get an instance of {@link DefaultUnitConverter}.
275: *
276: * @return the current <code>UnitConverter</code>
277: */
278: public static UnitConverter getUnitConverter() {
279: if (unitConverter == null) {
280: unitConverter = DefaultUnitConverter.getInstance();
281: }
282: return unitConverter;
283: }
284:
285: /**
286: * Sets a new UnitConverter that will be used to convert
287: * font-dependent sizes to pixel sizes.
288: *
289: * @param newUnitConverter the unit converter to be set
290: */
291: public static void setUnitConverter(UnitConverter newUnitConverter) {
292: unitConverter = newUnitConverter;
293: }
294:
295: // Helper Class *********************************************************
296:
297: /**
298: * An ordinal-based serializable typesafe enumeration that implements
299: * the {@link Size} interface for the component sizes:
300: * <em>min, pref, default</em>.
301: */
302: static final class ComponentSize implements Size, Serializable {
303:
304: private final transient String name;
305:
306: private ComponentSize(String name) {
307: this .name = name;
308: }
309:
310: /**
311: * Returns an instance of <code>ComponentSize</code> that corresponds
312: * to the specified string.
313: * @param str the encoded component size
314: * @return the corresponding ComponentSize or null if none matches
315: */
316: static ComponentSize valueOf(String str) {
317: if (str.equals("m") || str.equals("min"))
318: return MINIMUM;
319: if (str.equals("p") || str.equals("pref"))
320: return PREFERRED;
321: if (str.equals("d") || str.equals("default"))
322: return DEFAULT;
323: return null;
324: }
325:
326: /**
327: * Computes the maximum size for the given list of components, using
328: * this form spec and the specified measure.
329: * <p>
330: * Invoked by FormLayout to determine the size of one of my elements
331: *
332: * @param container the layout container
333: * @param components the list of components to measure
334: * @param minMeasure the measure used to determine the minimum size
335: * @param prefMeasure the measure used to determine the preferred size
336: * @param defaultMeasure the measure used to determine the default size
337: * @return the maximum size in pixels for the given list of components
338: */
339: public int maximumSize(Container container, List components,
340: FormLayout.Measure minMeasure,
341: FormLayout.Measure prefMeasure,
342: FormLayout.Measure defaultMeasure) {
343:
344: FormLayout.Measure measure = this == MINIMUM ? minMeasure
345: : (this == PREFERRED ? prefMeasure : defaultMeasure);
346: int maximum = 0;
347: for (Iterator i = components.iterator(); i.hasNext();) {
348: Component c = (Component) i.next();
349: maximum = Math.max(maximum, measure.sizeOf(c));
350: }
351: return maximum;
352: }
353:
354: /**
355: * Describes if this Size can be compressed, if container space gets scarce.
356: * Used by the FormLayout size computations in <code>#compressedSizes</code>
357: * to check whether a column or row can be compressed or not.<p>
358: *
359: * The DEFAULT ComponentSize is compressible, MINIMUM and PREFERRED
360: * are incompressible.
361: *
362: * @return <code>true</code> for the DEFAULT size,
363: * <code>false</code> otherwise
364: *
365: * @since 1.1
366: */
367: public boolean compressible() {
368: return this == DEFAULT;
369: }
370:
371: public String toString() {
372: return name.substring(0, 1);
373: }
374:
375: // Serialization *****************************************************
376:
377: private static int nextOrdinal = 0;
378:
379: private final int ordinal = nextOrdinal++;
380:
381: private Object readResolve() {
382: return VALUES[ordinal]; // Canonicalize
383: }
384:
385: }
386:
387: }
|