001: /*
002: * Copyright 2000,2005 wingS development team.
003: *
004: * This file is part of wingS (http://wingsframework.org).
005: *
006: * wingS is free software; you can redistribute it and/or modify
007: * it under the terms of the GNU Lesser General Public License
008: * as published by the Free Software Foundation; either version 2.1
009: * of the License, or (at your option) any later version.
010: *
011: * Please see COPYING for the complete licence.
012: */
013: package org.wings;
014:
015: import org.apache.commons.logging.Log;
016: import org.apache.commons.logging.LogFactory;
017:
018: import java.io.Serializable;
019: import java.text.DecimalFormat;
020: import java.text.ParsePosition;
021:
022: /**
023: * Holds preferred component sizes (dimensions).
024: * <p/>
025: * Web browsers support different notations for sizes. Absolute pixel values,
026: * realtive percentages (of the available viewport) and
027: * special CSS values as 'inherit' and 'auto' (Default).
028: * This class if capable of handling all these cases.
029: */
030: public class SDimension implements Serializable {
031:
032: /**
033: * String constant for CSS dimension 'auto'.
034: * This is the default width used by wings as well as by CSS capable browsers.
035: */
036: public final static String AUTO = "auto";
037:
038: /**
039: * String for CSS dimension 'inherit'.
040: * With this value the preferred size is inherited by the surrounding element.
041: */
042: public final static String INHERIT = "inherit";
043:
044: /**
045: * Integer constant for CSS dimension 'auto'.
046: * This is the default width used by wings as well as by CSS capable browsers.
047: */
048: public final static int AUTO_INT = -1;
049:
050: /**
051: * Integer constant for CSS dimension 'inherit'.
052: * With this value the preferred size is inherited by the surrounding element.
053: */
054: public final static int INHERIT_INT = -2;
055:
056: /**
057: * Immutable SDimension constants for a component taking up the full available width.
058: */
059: public static final SDimension FULLWIDTH = new ImmutableSDimension(
060: "100%", null);
061: /**
062: * Immutable SDimension constants for a component taking up the full available height.
063: */
064: public static final SDimension FULLHEIGHT = new ImmutableSDimension(
065: null, "100%");
066: /**
067: * Immutable SDimension constants for a component taking up the full available area.
068: */
069: public static final SDimension FULLAREA = new ImmutableSDimension(
070: "100%", "100%");
071: /**
072: * Immutable SDimension constants for a component taking up normal space
073: */
074: public static final SDimension AUTOAREA = new ImmutableSDimension(
075: AUTO, AUTO);
076:
077: private final transient static Log log = LogFactory
078: .getLog(SDimension.class);
079:
080: private int widthInt = AUTO_INT;
081: private int heightInt = AUTO_INT;
082: private String widthUnit;
083: private String heightUnit;
084:
085: public SDimension() {
086: }
087:
088: public SDimension(String width, String height) {
089: setWidth(width);
090: setHeight(height);
091: }
092:
093: /**
094: * Construct a new dimension with absolute values.
095: * The value is interpreted as absolute pixel values.
096: *
097: * @param width the preferred width in pixel. Use -1 for AUTO.
098: * @param height the preferred height in pixel. Use -1 for AUTO.
099: * @see #setSize(int,int)
100: */
101: public SDimension(int width, int height) {
102: setSize(width, height);
103: }
104:
105: /**
106: * Construct a new dimension with absolute values.
107: * The value is interpreted as absolute pixel values.
108: *
109: * @param width the preferred width in pixel. You may pass <code>null</code>.
110: * @param height the preferred height in pixel. You may pass <code>null</code>.
111: * @see #setSize(int,int)
112: */
113: public SDimension(Integer width, Integer height) {
114: setSize(width != null ? width.intValue() : AUTO_INT,
115: height != null ? height.intValue() : AUTO_INT);
116: }
117:
118: /**
119: * Sets the preferred width via an string. Expects an dimension/unit compount i.e.
120: * "120px" or "80%" but will assume px by default.
121: * @param width A preferred witdth.
122: */
123: public void setWidth(String width) {
124: this .widthInt = extractNumericValue(width);
125: this .widthUnit = extractUnit(width);
126: }
127:
128: /**
129: * Sets the preferred height via an string. Expects an dimension/unit compount i.e.
130: * "120px" or "80%" but will assume px by default.
131: * @param height A preferred height.
132: */
133: public void setHeight(String height) {
134: this .heightInt = extractNumericValue(height);
135: this .heightUnit = extractUnit(height);
136: }
137:
138: /**
139: * Set width in pixel.
140: * This appends "px" to the integer value.
141: *
142: * @param width if -1 set {@link SDimension#widthInt} to <code>null</code>
143: */
144: public void setWidth(int width) {
145: widthInt = width;
146: widthUnit = width < 0 ? null : "px";
147: }
148:
149: /**
150: * Set height in pixel.
151: * This appends "px" to the integer value.
152: *
153: * @param height if -1 set {@link SDimension#heightInt} to <code>null</code>
154: */
155: public void setHeight(int height) {
156: heightInt = height;
157: heightUnit = height < 0 ? null : "px";
158: }
159:
160: /**
161: * @return The preferred width i.e. like <code>120px</code> or <code>80%</code> or <code>auto</code>
162: */
163: public String getWidth() {
164: return toString(widthInt, widthUnit);
165: }
166:
167: /**
168: * @return The preferred height i.e. like <code>120px</code> or <code>80%</code> or <code>auto</code>
169: */
170: public String getHeight() {
171: return toString(heightInt, heightUnit);
172: }
173:
174: /**
175: * Get just the width as number without trailing
176: * unit.
177: */
178: public int getWidthInt() {
179: return widthInt;
180: }
181:
182: /**
183: * Get just the height as number without trailing
184: * unit.
185: */
186: public int getHeightInt() {
187: return heightInt;
188: }
189:
190: /**
191: * @return The unit of the current width. Returns <code>null</code> for {@link #AUTO} and {@link #INHERIT}.
192: * Otherwise always returns a non-null value!
193: */
194: public String getWidthUnit() {
195: return widthInt < 0 ? null : (((widthUnit != null && widthUnit
196: .length() > 0) ? widthUnit : "px"));
197: }
198:
199: /**
200: * @return The unit of the current height. Returns <code>null</code> for {@link #AUTO} and {@link #INHERIT}.
201: * Otherwise always returns a non-null value!
202: */
203: public String getHeightUnit() {
204: return heightInt < 0 ? null
205: : (((heightUnit != null && heightUnit.length() > 0) ? heightUnit
206: : "px"));
207: }
208:
209: /**
210: * Set the size of this Dimension object to the specified width and height
211: * and append "px" to both values.
212: *
213: * @see #setHeight(int)
214: * @see #setWidth(int)
215: */
216: public void setSize(int width, int height) {
217: setWidth(width);
218: setHeight(height);
219: }
220:
221: public String toString() {
222: return "width: " + getWidth() + "; height: " + getHeight();
223: }
224:
225: /**
226: * Extract number from string.
227: *
228: * @return extracted integer. f.e.: "120px" becomes 120
229: */
230: protected int getIntValue(String sizeString) {
231: if (sizeString == null) {
232: return AUTO_INT;
233: }
234: if (sizeString.trim().equalsIgnoreCase(AUTO)) {
235: return AUTO_INT;
236: }
237: if (sizeString.trim().equalsIgnoreCase(INHERIT)) {
238: return INHERIT_INT;
239: }
240: try {
241: return new DecimalFormat().parse(sizeString,
242: new ParsePosition(0)).intValue();
243: } catch (Exception e) {
244: log.warn("Can not parse [" + sizeString + "]", e);
245: }
246: return AUTO_INT;
247: }
248:
249: protected String toString(int size, String unit) {
250: if (size == INHERIT_INT) {
251: return INHERIT;
252: } else if (size < 0) {
253: return AUTO;
254: } else if (unit != null && unit.length() > 0) {
255: return Integer.toString(size) + unit;
256: } else {
257: // default: assume px
258: return Integer.toString(size) + "px";
259: }
260: }
261:
262: /**
263: * Extract number from string.
264: *
265: * @return extracted integer. f.e.: "120px" becomes 120 or {@link #AUTO_INT} if <code>null</code>
266: */
267: protected int extractNumericValue(String value) {
268: if (value == null || value.equalsIgnoreCase(AUTO)) {
269: return AUTO_INT;
270: } else if (value.equalsIgnoreCase(INHERIT)) {
271: return INHERIT_INT;
272: } else {
273: try {
274: return new DecimalFormat().parse(value,
275: new ParsePosition(0)).intValue();
276: } catch (Exception e) {
277: return AUTO_INT;
278: }
279: }
280: }
281:
282: /**
283: * Tries to extract unit from passed string. I.e. returtn "px" if you pass "120px".
284: *
285: * @param value A compound number/unit string. May be <code>null</code>
286: * @return The unit or <code>null</code> if not possible.
287: */
288: private String extractUnit(String value) {
289: if (value == null) {
290: return null;
291: } else {
292: ParsePosition position = new ParsePosition(0);
293: try {
294: new DecimalFormat().parse(value, position).intValue();
295: return value.substring(position.getIndex()).trim();
296: } catch (Exception e) {
297: return null;
298: }
299: }
300: }
301:
302: private final static class ImmutableSDimension extends SDimension {
303: public ImmutableSDimension(String width, String height) {
304: super (width, height);
305: }
306: }
307:
308: public boolean equals(Object o) {
309: if (this == o) {
310: return true;
311: }
312: if (!(o instanceof SDimension)) {
313: return false;
314: }
315:
316: final SDimension sDimension = (SDimension) o;
317:
318: if (heightInt != sDimension.heightInt
319: || widthInt != sDimension.widthInt) {
320: return false;
321: }
322: if (heightUnit != null ? !heightUnit
323: .equals(sDimension.heightUnit)
324: : sDimension.heightUnit != null) {
325: return false;
326: }
327: if (widthUnit != null ? !widthUnit.equals(sDimension.widthUnit)
328: : sDimension.widthUnit != null) {
329: return false;
330: }
331:
332: return true;
333: }
334:
335: public int hashCode() {
336: return widthInt;
337: }
338:
339: }
|