001: /*
002: * Copyright (c) 2002-2004 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 as required by
044: * the {@link FormLayout}. The conversion of sizes that are not based on pixel
045: * is delegated to an implementation of {@link UnitConverter}. The conversion
046: * methods require the layout container as parameter to read its current font
047: * and resolution.
048: *
049: * @author Karsten Lentzsch
050: * @version $Revision: 1.2 $
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; measures
102: * preferred sizes when asked for the preferred size and minimum sizes when
103: * 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 deserialized
110: * 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
135: * value and unit in string representation
136: * @param horizontal
137: * true for horizontal, false for vertical
138: * @return a <code>ConstantSize</code> for the given value and unit
139: */
140: public static ConstantSize constant(String encodedValueAndUnit,
141: boolean horizontal) {
142: return ConstantSize.valueOf(encodedValueAndUnit, horizontal);
143: }
144:
145: /**
146: * Returns an instance of <code>Size</code> for the specified value in
147: * horizontal dialog units.
148: *
149: * @param value
150: * size value in horizontal dialog units
151: * @return the associated <code>ConstantSize</code>
152: */
153: public static ConstantSize dluX(int value) {
154: return ConstantSize.dluX(value);
155: }
156:
157: /**
158: * Returns an instance of <code>Size</code> for the specified value in
159: * vertical dialog units.
160: *
161: * @param value
162: * size value in vertical dialog units
163: * @return the associated <code>ConstantSize</code>
164: */
165: public static ConstantSize dluY(int value) {
166: return ConstantSize.dluY(value);
167: }
168:
169: /**
170: * Creates and returns an instance of <code>Size</code> for the specified
171: * pixel value.
172: *
173: * @param value
174: * value in pixel
175: * @return the associated <code>ConstantSize</code>
176: */
177: public static ConstantSize pixel(int value) {
178: return new ConstantSize(value, ConstantSize.PIXEL);
179: }
180:
181: /**
182: * Creates and returns a <code>BoundedSize</code> for the given basis
183: * using the specified lower and upper bounds.
184: *
185: * @param basis
186: * the base size
187: * @param lowerBound
188: * the lower bound size
189: * @param upperBound
190: * the upper bound size
191: * @return a <code>BoundedSize</code> for the given basis and bounds
192: * @throws NullPointerException
193: * if basis is null
194: */
195: public static Size bounded(Size basis, Size lowerBound,
196: Size upperBound) {
197: return new BoundedSize(basis, lowerBound, upperBound);
198: }
199:
200: // Unit Conversion ******************************************************
201:
202: /**
203: * Converts Inches and returns pixels using the specified resolution.
204: *
205: * @param in
206: * the Inches
207: * @param component
208: * the component that provides the graphics object
209: * @return the given Inches as pixels
210: */
211: public static int inchAsPixel(double in, Component component) {
212: return in == 0d ? 0 : getUnitConverter().inchAsPixel(in,
213: component);
214: }
215:
216: /**
217: * Converts Millimeters and returns pixels using the resolution of the given
218: * component's graphics object.
219: *
220: * @param mm
221: * Millimeters
222: * @param component
223: * the component that provides the graphics object
224: * @return the given Millimeters as pixels
225: */
226: public static int millimeterAsPixel(double mm, Component component) {
227: return mm == 0d ? 0 : getUnitConverter().millimeterAsPixel(mm,
228: component);
229: }
230:
231: /**
232: * Converts Centimeters and returns pixels using the resolution of the given
233: * component's graphics object.
234: *
235: * @param cm
236: * Centimeters
237: * @param component
238: * the component that provides the graphics object
239: * @return the given Centimeters as pixels
240: */
241: public static int centimeterAsPixel(double cm, Component component) {
242: return cm == 0d ? 0 : getUnitConverter().centimeterAsPixel(cm,
243: component);
244: }
245:
246: /**
247: * Converts DTP Points and returns pixels using the resolution of the given
248: * component's graphics object.
249: *
250: * @param pt
251: * DTP Points
252: * @param component
253: * the component that provides the graphics object
254: * @return the given Points as pixels
255: */
256: public static int pointAsPixel(int pt, Component component) {
257: return pt == 0 ? 0 : getUnitConverter().pointAsPixel(pt,
258: component);
259: }
260:
261: /**
262: * Converts horizontal dialog units and returns pixels. Honors the
263: * resolution, dialog font size, platform, and l&f.
264: *
265: * @param dluX
266: * the horizontal dialog units
267: * @param component
268: * the component that provides the graphics object
269: * @return the given horizontal dialog units as pixels
270: */
271: public static int dialogUnitXAsPixel(int dluX, Component component) {
272: return dluX == 0 ? 0 : getUnitConverter().dialogUnitXAsPixel(
273: dluX, component);
274: }
275:
276: /**
277: * Converts vertical dialog units and returns pixels. Honors the resolution,
278: * dialog font size, platform, and l&f.
279: *
280: * @param dluY
281: * the vertical dialog units
282: * @param component
283: * the component that provides the graphics object
284: * @return the given vertical dialog units as pixels
285: */
286: public static int dialogUnitYAsPixel(int dluY, Component component) {
287: return dluY == 0 ? 0 : getUnitConverter().dialogUnitYAsPixel(
288: dluY, component);
289: }
290:
291: // Accessing the Unit Converter *******************************************
292:
293: /**
294: * Returns the current {@link UnitConverter}. If it has not been
295: * initialized before it will get an instance of
296: * {@link DefaultUnitConverter}.
297: *
298: * @return the current <code>UnitConverter</code>
299: */
300: public static UnitConverter getUnitConverter() {
301: if (unitConverter == null) {
302: unitConverter = DefaultUnitConverter.getInstance();
303: }
304: return unitConverter;
305: }
306:
307: /**
308: * Sets a new {@link UnitConverter} that will be used to convert
309: * font-dependent sizes to pixel sizes.
310: *
311: * @param newUnitConverter
312: * the unit converter to be set
313: */
314: public static void setUnitConverter(UnitConverter newUnitConverter) {
315: unitConverter = newUnitConverter;
316: }
317:
318: // Helper Class *********************************************************
319:
320: /**
321: * An ordinal-based serializable typesafe enumeration that implements the
322: * {@link Size} interface for the component sizes:
323: * <em>min, pref, default</em>.
324: */
325: static final class ComponentSize implements Size, Serializable {
326:
327: private final transient String name;
328:
329: private ComponentSize(String name) {
330: this .name = name;
331: }
332:
333: /**
334: * Returns an instance of <code>ComponentSize</code> that corresponds
335: * to the specified string.
336: *
337: * @param str
338: * the encoded component size
339: * @return the corresponding ComponentSize or null if none matches
340: */
341: static ComponentSize valueOf(String str) {
342: if (str.equals("m") || str.equals("min"))
343: return MINIMUM;
344: if (str.equals("p") || str.equals("pref"))
345: return PREFERRED;
346: if (str.equals("d") || str.equals("default"))
347: return DEFAULT;
348: else
349: return null;
350: }
351:
352: /**
353: * Computes the maximum size for the given list of components, using
354: * this form spec and the specified measure.
355: * <p>
356: * Invoked by FormLayout to determine the size of one of my elements
357: *
358: * @param container
359: * the layout container
360: * @param components
361: * the list of components to measure
362: * @param minMeasure
363: * the measure used to determine the minimum size
364: * @param prefMeasure
365: * the measure used to determine the preferred size
366: * @param defaultMeasure
367: * the measure used to determine the default size
368: * @return the maximum size in pixels for the given list of components
369: */
370: public int maximumSize(Container container, List components,
371: FormLayout.Measure minMeasure,
372: FormLayout.Measure prefMeasure,
373: FormLayout.Measure defaultMeasure) {
374:
375: FormLayout.Measure measure = this == MINIMUM ? minMeasure
376: : (this == PREFERRED ? prefMeasure : defaultMeasure);
377: int maximum = 0;
378: for (Iterator i = components.iterator(); i.hasNext();) {
379: Component c = (Component) i.next();
380: maximum = Math.max(maximum, measure.sizeOf(c));
381: }
382: return maximum;
383: }
384:
385: public String toString() {
386: return name.substring(0, 1);
387: }
388:
389: // Serialization *****************************************************
390:
391: private static int nextOrdinal = 0;
392:
393: private final int ordinal = nextOrdinal++;
394:
395: private Object readResolve() {
396: return VALUES[ordinal]; // Canonicalize
397: }
398:
399: }
400:
401: }
|