001: /* ***** BEGIN LICENSE BLOCK *****
002: * Version: MPL 1.1
003: * The contents of this file are subject to the Mozilla Public License Version
004: * 1.1 (the "License"); you may not use this file except in compliance with
005: * the License. You may obtain a copy of the License at
006: * http://www.mozilla.org/MPL/
007: *
008: * Software distributed under the License is distributed on an "AS IS" basis,
009: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
010: * for the specific language governing rights and limitations under the
011: * License.
012: *
013: * The Original Code is Riot.
014: *
015: * The Initial Developer of the Original Code is
016: * Neteye GmbH.
017: * Portions created by the Initial Developer are Copyright (C) 2006
018: * the Initial Developer. All Rights Reserved.
019: *
020: * Contributor(s):
021: * Felix Gnass [fgnass at neteye dot de]
022: *
023: * ***** END LICENSE BLOCK ***** */
024: package org.riotfamily.forms.element;
025:
026: import java.net.URL;
027: import java.text.DateFormat;
028: import java.text.ParseException;
029: import java.text.SimpleDateFormat;
030: import java.util.Date;
031: import java.util.regex.Matcher;
032: import java.util.regex.Pattern;
033:
034: import org.riotfamily.common.util.FormatUtils;
035: import org.riotfamily.forms.DHTMLElement;
036: import org.riotfamily.forms.ErrorUtils;
037: import org.riotfamily.forms.MessageUtils;
038: import org.riotfamily.forms.TemplateUtils;
039: import org.riotfamily.forms.resource.FormResource;
040: import org.riotfamily.forms.resource.ResourceElement;
041: import org.riotfamily.forms.resource.ScriptResource;
042: import org.riotfamily.forms.resource.StylesheetResource;
043: import org.springframework.beans.propertyeditors.CustomDateEditor;
044: import org.springframework.util.StringUtils;
045:
046: /**
047: * A DHTML calendar widget.
048: * http://www.dynarch.com/projects/calendar/
049: */
050: public class Calendar extends AbstractTextElement implements
051: ResourceElement, DHTMLElement {
052:
053: /**
054: * Rules to translate {@link SimpleDateFormat SimpleDateFormat patterns}
055: * to the syntax used by the JavaScript calendar widget.
056: * */
057: private static String[] conversions = new String[] { "'(.)", "$1",
058: "%", "%%", "(?<!%)MMMM", "%B", "(?<!%)MMM", "%b",
059: "(?<!%)MM?", "%m", "(?<!%)dd", "%d", "(?<!%)d", "%e",
060: "(?<!%)yyyy", "%Y", "(?<!%)yy", "%y", "(?<!%)hh", "%I",
061: "(?<!%)h", "%i", "(?<!%)HH", "%H", "(?<!%)H", "%h",
062: "(?<!%)mm?", "%M", "(?<!%)ss?", "%S", "(?<!%)EE?", "%a",
063: "(?<!%)w", "%W", "(?<!%)a", "%P" };
064:
065: /** List of compiled conversion patterns */
066: private static Pattern[] patterns;
067:
068: static {
069: patterns = new Pattern[conversions.length / 2];
070: for (int i = 0; i < patterns.length; i++) {
071: patterns[i] = Pattern.compile(conversions[i * 2]);
072: }
073: }
074:
075: private String formatPattern = "yyyy-MM-dd";
076:
077: private String formatKey;
078:
079: private String defaultValue;
080:
081: private String jsFormatPattern;
082:
083: private DateFormat dateFormat;
084:
085: private ScriptResource resource;
086:
087: public Calendar() {
088: setStyleClass("text calendar-input");
089: }
090:
091: public String getFormatPattern() {
092: return formatPattern;
093: }
094:
095: /**
096: * Sets the format pattern to use.
097: * @see SimpleDateFormat
098: */
099: public void setFormatPattern(String formatPattern) {
100: this .formatPattern = formatPattern;
101: }
102:
103: public String getJsFormatPattern() {
104: return jsFormatPattern;
105: }
106:
107: /**
108: * Sets a message-key that is used to look-up the actual format pattern.
109: */
110: public void setFormatKey(String formatKey) {
111: this .formatKey = formatKey;
112: }
113:
114: public void setDefaultValue(String defaultValue) {
115: this .defaultValue = defaultValue;
116: }
117:
118: protected void afterFormSet() {
119: if (formatKey != null) {
120: formatPattern = MessageUtils.getMessage(this , formatKey);
121: }
122: jsFormatPattern = formatPattern;
123: for (int i = 0; i < patterns.length; i++) {
124: Matcher matcher = patterns[i].matcher(jsFormatPattern);
125: jsFormatPattern = matcher
126: .replaceAll(conversions[i * 2 + 1]);
127: }
128: dateFormat = new SimpleDateFormat(formatPattern);
129: setPropertyEditor(new CustomDateEditor(dateFormat, false));
130: }
131:
132: public boolean isShowTime() {
133: return formatPattern != null
134: && (formatPattern.indexOf('H') != -1 || formatPattern
135: .indexOf('h') != -1);
136: }
137:
138: public void setValue(Object value) {
139: if (value == null && defaultValue != null) {
140: value = getDefaultDate();
141: }
142: super .setValue(value);
143: }
144:
145: public void validate() {
146: super .validate();
147: if (StringUtils.hasText(getText())) {
148: try {
149: dateFormat.parse(getText());
150: } catch (ParseException e) {
151: ErrorUtils.reject(this ,
152: "error.calendar.invalidDateFormat");
153: }
154: }
155: }
156:
157: protected void afterFormContextSet() {
158: String lang = getFormContext().getLocale().getLanguage()
159: .toLowerCase();
160: URL languageScript = getClass().getResource(
161: "/org/riotfamily/resources/jscalendar/lang/calendar-"
162: + lang + ".js");
163:
164: if (languageScript == null) {
165: lang = "en";
166: }
167:
168: resource = new ScriptResource("jscalendar/calendar-setup.js",
169: "Calendar.setup", new FormResource[] {
170: new ScriptResource("jscalendar/lang/calendar-"
171: + lang + ".js", "Calendar._DN",
172: new ScriptResource(
173: "jscalendar/calendar.js",
174: "Calendar")),
175: new StylesheetResource(
176: "jscalendar/calendar.css") });
177: }
178:
179: public FormResource getResource() {
180: return resource;
181: }
182:
183: public String getInitScript() {
184: return TemplateUtils.getInitScript(this );
185: }
186:
187: protected Date getDefaultDate() {
188: Date date = FormatUtils.parseDate(defaultValue);
189: if (date == null) {
190: try {
191: date = dateFormat.parse(defaultValue);
192: } catch (ParseException e) {
193: }
194: }
195: return date;
196: }
197: }
|