001: /* Datebox.java
002:
003: {{IS_NOTE
004: Purpose:
005:
006: Description:
007:
008: History:
009: Tue Jun 28 13:41:01 2005, Created by tomyeh
010: }}IS_NOTE
011:
012: Copyright (C) 2005 Potix Corporation. All Rights Reserved.
013:
014: {{IS_RIGHT
015: This program is distributed under GPL Version 2.0 in the hope that
016: it will be useful, but WITHOUT ANY WARRANTY.
017: }}IS_RIGHT
018: */
019: package org.zkoss.zul;
020:
021: import java.util.Map;
022: import java.util.HashMap;
023: import java.util.Date;
024: import java.util.TimeZone;
025: import java.util.GregorianCalendar;
026: import java.text.DateFormat;
027: import java.text.SimpleDateFormat;
028: import java.text.ParseException;
029:
030: import org.zkoss.lang.Objects;
031: import org.zkoss.util.Locales;
032: import org.zkoss.util.TimeZones;
033: import org.zkoss.xml.HTMLs;
034:
035: import org.zkoss.zk.ui.UiException;
036: import org.zkoss.zk.ui.WrongValueException;
037: import org.zkoss.zk.au.out.AuInvoke;
038:
039: import org.zkoss.zul.mesg.MZul;
040: import org.zkoss.zul.impl.FormatInputElement;
041:
042: /**
043: * An edit box for holding a date.
044: *
045: * <p>Default {@link #getSclass}: datebox.
046: *
047: * <p>The default format ({@link #getFormat}) depends on JVM's setting
048: * and the current user's locale. That is,
049: * <code>DateFormat.getDateInstance(DateFormat,DEFAULT, Locales.getCurrent).</code>
050: * You might override {@link #getDefaultFormat} to provide your own default
051: * format.
052: *
053: * @author tomyeh
054: */
055: public class Datebox extends FormatInputElement {
056: private static final String DEFAULT_IMAGE = "~./zul/img/caldrbtn.gif";
057: private String _img;
058: private TimeZone _tzone;
059: private boolean _lenient = true;
060: private boolean _compact, _btnVisible = true;
061:
062: public Datebox() {
063: setFormat(getDefaultFormat());
064: setSclass("datebox");
065: setCols(11);
066: _compact = "zh".equals(Locales.getCurrent().getLanguage());
067: }
068:
069: public Datebox(Date date) throws WrongValueException {
070: this ();
071: setValue(date);
072: }
073:
074: /** Returns the default format, which is used when contructing
075: * a datebox.
076: * <p>The default format ({@link #getFormat}) depends on JVM's setting
077: * and the current user's locale. That is,
078: * <code>DateFormat.getDateInstance(DateFormat,DEFAULT, Locales.getCurrent).</code>
079: *
080: * <p>You might override this method to provide your own default format.
081: */
082: protected String getDefaultFormat() {
083: final DateFormat df = DateFormat.getDateInstance(
084: DateFormat.DEFAULT, Locales.getCurrent());
085: if (df instanceof SimpleDateFormat) {
086: final String fmt = ((SimpleDateFormat) df).toPattern();
087: if (fmt != null && !"M/d/yy h:mm a".equals(fmt))
088: return fmt; //note: JVM use "M/d/yy h:mm a" if not found!
089: }
090: return "yyyy/MM/dd";
091: }
092:
093: /** Returns whether or not date/time parsing is to be lenient.
094: *
095: * <p>With lenient parsing, the parser may use heuristics to interpret
096: * inputs that do not precisely match this object's format.
097: * With strict parsing, inputs must match this object's format.
098: */
099: public boolean isLenient() {
100: return _lenient;
101: }
102:
103: /** Returns whether or not date/time parsing is to be lenient.
104: * <p>Default: true.
105: *
106: * <p>With lenient parsing, the parser may use heuristics to interpret
107: * inputs that do not precisely match this object's format.
108: * With strict parsing, inputs must match this object's format.
109: */
110: public void setLenient(boolean lenient) {
111: if (_lenient != lenient) {
112: _lenient = lenient;
113: smartUpdate("z.lenient", _lenient);
114: }
115: }
116:
117: /** Returns whether to use a compact layout.
118: * <p>Default: true if zh_TW or zh_CN; false otherwise.
119: */
120: public boolean isCompact() {
121: return _compact;
122: }
123:
124: /** Sets whether to use a compact layout.
125: */
126: public void setCompact(boolean compact) {
127: if (_compact != compact) {
128: _compact = compact;
129: invalidate();
130: }
131: }
132:
133: /** Returns whether the button (on the right of the textbox) is visible.
134: * <p>Default: true.
135: * @since 2.4.1
136: */
137: public boolean isButtonVisible() {
138: return _btnVisible;
139: }
140:
141: /** Sets whether the button (on the right of the textbox) is visible.
142: * @since 2.4.1
143: */
144: public void setButtonVisible(boolean visible) {
145: if (_btnVisible != visible) {
146: _btnVisible = visible;
147: smartUpdate("z.btnVisi", visible);
148: }
149: }
150:
151: /** Returns the URI of the button image.
152: * @since 3.0.0
153: */
154: public String getImage() {
155: return _img != null ? _img : DEFAULT_IMAGE;
156: }
157:
158: /** Sets the URI of the button image.
159: *
160: * @param img the URI of the button image. If null or empty, the default
161: * URI is used.
162: * @since 3.0.0
163: */
164: public void setImage(String img) {
165: if (img != null
166: && (img.length() == 0 || DEFAULT_IMAGE.equals(img)))
167: img = null;
168: if (!Objects.equals(_img, img)) {
169: _img = img;
170: invalidate();
171: }
172: }
173:
174: /** Returns the value (in Date), might be null unless
175: * a constraint stops it.
176: * @exception WrongValueException if user entered a wrong value
177: */
178: public Date getValue() throws WrongValueException {
179: return (Date) getTargetValue();
180: }
181:
182: /** Sets the value (in Date).
183: * @exception WrongValueException if value is wrong
184: */
185: public void setValue(Date value) throws WrongValueException {
186: validate(value);
187: setRawValue(value);
188: }
189:
190: public void setFormat(String format) throws WrongValueException {
191: if (format == null || format.length() == 0)
192: format = getDefaultFormat();
193: super .setFormat(format);
194: }
195:
196: /** Returns the time zone that this date box belongs to, or null if
197: * the default time zone is used.
198: * <p>The default time zone is determined by {@link TimeZones#getCurrent}.
199: */
200: public TimeZone getTimeZone() {
201: return _tzone;
202: }
203:
204: /** Sets the time zone that this date box belongs to, or null if
205: * the default time zone is used.
206: * <p>The default time zone is determined by {@link TimeZones#getCurrent}.
207: */
208: public void setTimeZone(TimeZone tzone) {
209: _tzone = tzone;
210: }
211:
212: /** Drops down or closes the calendar to select a date.
213: *
214: * @since 3.0.1
215: * @see #open
216: * @see #close
217: */
218: public void setOpen(boolean open) {
219: if (open)
220: open();
221: else
222: close();
223: }
224:
225: /** Drops down the calendar to select a date.
226: * The same as setOpen(true).
227: *
228: * @since 3.0.1
229: */
230: public void open() {
231: response("dropdn", new AuInvoke(this , "dropdn", true));
232: }
233:
234: /** Closes the calendar if it was dropped down.
235: * The same as setOpen(false).
236: *
237: * @since 3.0.1
238: */
239: public void close() {
240: response("dropdn", new AuInvoke(this , "dropdn", false));
241: }
242:
243: //-- super --//
244: public void setConstraint(String constr) {
245: setConstraint(new SimpleDateConstraint(constr));
246: }
247:
248: protected Object coerceFromString(String value)
249: throws WrongValueException {
250: if (value == null || value.length() == 0)
251: return null;
252:
253: final String fmt = getFormat();
254: final DateFormat df = getDateFormat(fmt);
255: df.setLenient(_lenient);
256: final Date date;
257: try {
258: date = df.parse(value);
259: } catch (ParseException ex) {
260: throw showCustomError(new WrongValueException(this ,
261: MZul.DATE_REQUIRED, new Object[] { value, fmt }));
262: }
263: return date;
264: }
265:
266: protected String coerceToString(Object value) {
267: final DateFormat df = getDateFormat(getFormat());
268: return value != null ? df.format((Date) value) : "";
269: }
270:
271: /** Returns the date format of the specified format
272: *
273: * <p>Default: it uses SimpleDateFormat to format the date.
274: *
275: * @param fmt the pattern.
276: */
277: protected DateFormat getDateFormat(String fmt) {
278: final DateFormat df = new SimpleDateFormat(fmt, Locales
279: .getCurrent());
280: final TimeZone tz = _tzone != null ? _tzone : TimeZones
281: .getCurrent();
282: df.setTimeZone(tz);
283: return df;
284: }
285:
286: public String getOuterAttrs() {
287: final StringBuffer sb = new StringBuffer(80).append(super
288: .getOuterAttrs());
289: if (getConstraint() instanceof SimpleDateConstraint) {
290: final SimpleDateConstraint st = (SimpleDateConstraint) getConstraint();
291: Date d = st.getBeginDate();
292: if (d != null)
293: HTMLs.appendAttribute(sb, "z.bd", d.getTime() / 1000);
294: d = st.getEndDate();
295: if (d != null)
296: HTMLs.appendAttribute(sb, "z.ed", d.getTime() / 1000);
297: }
298: if (!_lenient)
299: sb.append(" z.lenient=\"false\"");
300: if (_compact)
301: sb.append(" z.compact=\"true\"");
302: return sb.toString();
303: }
304:
305: public String getInnerAttrs() {
306: final String attrs = super .getInnerAttrs();
307: final String style = getInnerStyle();
308: return style.length() > 0 ? attrs + " style=\"" + style + '"'
309: : attrs;
310: }
311:
312: private String getInnerStyle() {
313: final StringBuffer sb = new StringBuffer(32).append(HTMLs
314: .getTextRelevantStyle(getRealStyle()));
315: HTMLs.appendStyle(sb, "width", getWidth());
316: HTMLs.appendStyle(sb, "height", getHeight());
317: return sb.toString();
318: }
319:
320: /** Returns RS_NO_WIDTH|RS_NO_HEIGHT.
321: */
322: protected int getRealStyleFlags() {
323: return super.getRealStyleFlags() | RS_NO_WIDTH | RS_NO_HEIGHT;
324: }
325: }
|