/* * Copyright 2005 Wicket Stuff * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.googlecode.wicketwebbeans.datepicker; import java.io.IOException; import java.io.InputStream; import java.io.Serializable; import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.Properties; import org.apache.wicket.ResourceReference; import org.apache.wicket.markup.html.resources.CompressedResourceReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * The settings of the date picker component. Use this to customize the * datepicker (e.g. the icon, locale, format, etc). * * @author Eelco Hillenius */ public class DatePickerSettings implements Serializable { /** all date formats. */ private static Properties dateformats = new Properties(); /** locale to language map. */ private static final Map<String, String> localeToLanguageReference = new HashMap<String, String>(); /** log. */ private static final Logger log = LoggerFactory.getLogger(DatePickerSettings.class); private static final long serialVersionUID = 1L; static { // fill our default map. Note that new Locale("en", "","").getLanguage() // is to avoid future breaks because of the instable standard // (read about this in Locale.getLanguage() localeToLanguageReference.put(new Locale("af", "", "").toString(), "lang/calendar-af.js"); localeToLanguageReference.put(new Locale("al", "", "").toString(), "lang/calendar-al.js"); localeToLanguageReference.put(new Locale("br", "", "").toString(), "lang/calendar-br.js"); localeToLanguageReference.put(new Locale("cs", "", "").toString(), "lang/calendar-cs-utf8.js"); localeToLanguageReference.put(new Locale("da", "", "").toString(), "lang/calendar-da-utf8.js"); localeToLanguageReference.put(new Locale("de", "", "").toString(), "lang/calendar-de.js"); localeToLanguageReference.put(new Locale("el", "", "").toString(), "lang/calendar-el.js"); localeToLanguageReference.put(new Locale("en", "", "").toString(), "lang/calendar-en.js"); localeToLanguageReference.put(new Locale("en", "ZA", "").toString(), "lang/calendar-en_ZA.js"); localeToLanguageReference.put(new Locale("es", "", "").toString(), "lang/calendar-es-utf8.js"); localeToLanguageReference.put(new Locale("es", "AR", "").toString(), "lang/calendar-es_AR.js"); localeToLanguageReference.put(new Locale("eu", "", "").toString(), "lang/calendar-eu.js"); localeToLanguageReference.put(new Locale("fi", "", "").toString(), "lang/calendar-fi.js"); localeToLanguageReference.put(new Locale("fr", "", "").toString(), "lang/calendar-fr-utf8.js"); localeToLanguageReference.put(new Locale("he", "", "").toString(), "lang/calendar-he-utf8.js"); localeToLanguageReference.put(new Locale("hr", "", "").toString(), "lang/calendar-hr-utf8.js"); localeToLanguageReference.put(new Locale("hu", "", "").toString(), "lang/calendar-hu-utf8.js"); localeToLanguageReference.put(new Locale("it", "", "").toString(), "lang/calendar-it-utf8.js"); localeToLanguageReference.put(new Locale("ko", "", "").toString(), "lang/calendar-ko-utf8.js"); localeToLanguageReference.put(new Locale("lt", "", "").toString(), "lang/calendar-lt-utf8.js"); localeToLanguageReference.put(new Locale("lv", "", "").toString(), "lang/calendar-lv-utf8.js"); localeToLanguageReference.put(new Locale("nl", "", "").toString(), "lang/calendar-nl.js"); localeToLanguageReference.put(new Locale("no", "", "").toString(), "lang/calendar-no-utf8.js"); localeToLanguageReference.put(new Locale("pl", "", "").toString(), "lang/calendar-pl-utf8.js"); localeToLanguageReference.put(new Locale("pt", "", "").toString(), "lang/calendar-pt.js"); localeToLanguageReference.put(new Locale("ro", "", "").toString(), "lang/calendar-ro-utf8.js"); localeToLanguageReference.put(new Locale("ru", "", "").toString(), "lang/calendar-ru-utf8.js"); localeToLanguageReference.put(new Locale("si", "", "").toString(), "lang/calendar-si-utf8.js"); localeToLanguageReference.put(new Locale("sk", "", "").toString(), "lang/calendar-sk-utf8.js"); localeToLanguageReference.put(new Locale("sr", "", "").toString(), "lang/calendar-sr-utf8.js"); localeToLanguageReference.put(new Locale("sv", "", "").toString(), "lang/calendar-sv-utf8.js"); localeToLanguageReference.put(new Locale("tr", "", "").toString(), "lang/calendar-tr-utf8.js"); localeToLanguageReference.put(new Locale("zh", "", "").toString(), "lang/calendar-zh-utf8.js"); localeToLanguageReference.put(new Locale("zh", "TW", "").toString(), "lang/calendar-zh_TW-utf8.js"); } static { InputStream resourceAsStream = null; try { resourceAsStream = DatePickerSettings.class .getResourceAsStream("dateformats.properties"); dateformats.load(resourceAsStream); } catch (IOException e) { log.error(e.getMessage(), e); throw new RuntimeException(e); } finally { try { if (resourceAsStream != null) { resourceAsStream.close(); } } catch (IOException ex) { // ignore } } } /** * Gets the language. * * @param currentLocale * the current locale * @return language */ public static ResourceReference getLanguageFromMap(Locale currentLocale) { // try to get the reference from our default mapping // first try the language and country String ref = localeToLanguageReference.get(currentLocale.toString()); if (ref != null) { return new CompressedResourceReference(DatePickerSettings.class, ref); } // now try only the language ref = localeToLanguageReference.get(currentLocale.getLanguage()); if (ref != null) { return new CompressedResourceReference(DatePickerSettings.class, ref); } // we didn't find a mapping; just return English return new CompressedResourceReference(DatePickerSettings.class, "lang/calendar-en.js"); } /** * Alignment of the calendar, relative to the reference element. The * reference element is dynamically chosen like this: if a displayArea is * specified then it will be the reference element. Otherwise, the input * field is the reference element. * <p> * Align may contain one or two characters. The first character dictates the * vertical alignment, relative to the element, and the second character * dictates the horizontal alignment. If the second character is missing it * will be assumed "l" (the left margin of the calendar will be at the same * horizontal position as the left margin of the element). The characters * given for the align parameters are case sensitive. This function only * makes sense when the calendar is in popup mode. After computing the * position it uses Calendar.showAt to display the calendar there. * </p> * <p> * <strong>Vertical alignment</strong> The first character in ``align'' can * take one of the following values: * <ul> * <li>T -- completely above the reference element (bottom margin of the * calendar aligned to the top margin of the element). </li> * <li>t -- above the element but may overlap it (bottom margin of the * calendar aligned to the bottom margin of the element). </li> * <li>c -- the calendar displays vertically centered to the reference * element. It might overlap it (that depends on the horizontal alignment). * </li> * <li>b -- below the element but may overlap it (top margin of the * calendar aligned to the top margin of the element). </li> * <li>B -- completely below the element (top margin of the calendar * aligned to the bottom margin of the element). </li> * </ul> * </p> * <p> * <strong>Horizontal alignment</strong> The second character in ``align'' * can take one of the following values: * <ul> * <li>L -- completely to the left of the reference element (right margin * of the calendar aligned to the left margin of the element). </li> * <li>l -- to the left of the element but may overlap it (left margin of * the calendar aligned to the left margin of the element). </li> * <li>c -- horizontally centered to the element. Might overlap it, * depending on the vertical alignment. </li> * <li>r -- to the right of the element but may overlap it (right margin of * the calendar aligned to the right margin of the element). </li> * <li>R -- completely to the right of the element (left margin of the * calendar aligned to the right margin of the element). </li> * </ul> * </p> */ private String align = null; /** * Set this to ``false'' if you want the calendar to update the field only * when closed (by default it updates the field at each date change, even if * the calendar is not closed). */ private boolean electric = true; /** * Specifies which day is to be displayed as the first day of week. Possible * values are 0 to 6; 0 means Sunday, 1 means Monday, ..., 6 means Saturday. * The end user can easily change this too, by clicking on the day name in * the calendar header. */ private int firstDay = -1; /** the button icon. */ private ResourceReference icon = null; /** * The format string that will be used to enter the date in the input field. * This format will be honored even if the input field is hidden. Use * Javascript notation, like '%m/%d/%Y'. */ private String ifFormat = null; /** the language. */ private ResourceReference language = null; /** * Wether the calendar is in ``single-click mode'' or ``double-click mode''. * If true (the default) the calendar will be created in single-click mode. */ private boolean mode = true; /** * If set to ``true'' then days belonging to months overlapping with the * currently displayed month will also be displayed in the calendar (but in * a ``faded-out'' color). */ private boolean showOthers = false; /** * If this is set to true then the calendar will also allow time selection. */ private boolean showsTime = false; /** the style. */ private ResourceReference style = null; /** * Set this to ``12'' or ``24'' to configure the way that the calendar will * display time. */ private String timeFormat = null; /** * If ``true'' then the calendar will display week numbers. */ private boolean weekNumbers = true; private ISelectCallback onSelect; private ISelectCallback onClose; private ISelectCallback onUpdate; /** * Construct. */ public DatePickerSettings() { } /** * Gets the align. * * @return align */ public String getAlign() { return align; } /** * Gets the firstDay. * * @return firstDay */ public int getFirstDay() { return firstDay; } /** * Gets the icon. * * @return icon */ public ResourceReference getIcon() { if (icon == null) { icon = newButtonIconRed(); } return icon; } /** * Gets the format string that will be used to enter the date in the input * field based on the provided locale. Should return Javascript notation, * like '%m/%d/%Y'. * * @param locale * The locale * @return The date format */ public String getIfFormat(Locale locale) { // when it was set explicitly, return that if (ifFormat != null) { return ifFormat; } // else, get it from our map - might be null, but our calling // function can handle that return dateformats.getProperty(locale.toString()); } /** * Gets the language. * * @param currentLocale * the current locale * @return language */ public ResourceReference getLanguage(Locale currentLocale) { // if the language was set explicitly, return that if (language != null) { return language; } return getLanguageFromMap(currentLocale); } /** * Gets the style. * * @return style */ public ResourceReference getStyle() { if (style == null) { style = newStyleAqua(); } return style; } /** * Gets the timeFormat. * * @return timeFormat */ public String getTimeFormat() { return timeFormat; } /** * Gets the electric. * * @return electric */ public boolean isElectric() { return electric; } /** * Gets the mode. * * @return mode */ public boolean isMode() { return mode; } /** * Gets the showOthers. * * @return showOthers */ public boolean isShowOthers() { return showOthers; } /** * Gets the showsTime. * * @return showsTime */ public boolean isShowsTime() { return showsTime; } /** * Gets the weekNumbers. * * @return weekNumbers */ public boolean isWeekNumbers() { return weekNumbers; } /** * create a button icon. * * @return a button icon. */ public final ResourceReference newButtonIconBlue() { return new CompressedResourceReference(DatePickerSettings.class, "calendar_icon_3.gif"); } /** * create a button icon. * * @return a button icon. */ public final ResourceReference newButtonIconPlain() { return new CompressedResourceReference(DatePickerSettings.class, "calendar_icon_2.gif"); } /** * create a button icon. * * @return a button icon. */ public final ResourceReference newButtonIconRed() { return new CompressedResourceReference(DatePickerSettings.class, "calendar_icon_1.gif"); } /** * Create a style * * @return a style */ public final ResourceReference newStyleAqua() { return new CompressedResourceReference(DatePickerSettings.class, "style/aqua/theme.css"); } /** * Create a style * * @return a style */ public final ResourceReference newStyleBlue() { return new CompressedResourceReference(DatePickerSettings.class, "style/calendar-blue2.css"); } /** * Create a style * * @return a style */ public final ResourceReference newStyleGreen() { return new CompressedResourceReference(DatePickerSettings.class, "style/calendar-green.css"); } /** * Create a style * * @return a style */ public final ResourceReference newStyleSummer() { return new CompressedResourceReference(DatePickerSettings.class, "style/calendar-brown.css"); } /** * Create a style * * @return a style */ public final ResourceReference newStyleSystem() { return new CompressedResourceReference(DatePickerSettings.class, "style/calendar-system.css"); } /** * Create a style * * @return a style */ public final ResourceReference newStyleTas() { return new CompressedResourceReference(DatePickerSettings.class, "style/calendar-tas.css"); } /** * Create a style * * @return a style */ public final ResourceReference newStyleWin2k1() { return new CompressedResourceReference(DatePickerSettings.class, "style/calendar-win2k-1.css"); } /** * Create a style * * @return a style */ public final ResourceReference newStyleWin2k2() { return new CompressedResourceReference(DatePickerSettings.class, "style/calendar-win2k-2.css"); } /** * Create a style * * @return a style */ public final ResourceReference newStyleWin2kCold1() { return new CompressedResourceReference(DatePickerSettings.class, "style/calendar-win2k-cold-1.css"); } /** * Create a style * * @return a style */ public final ResourceReference newStyleWin2kCold2() { return new CompressedResourceReference(DatePickerSettings.class, "style/calendar-win2k-cold-2.css"); } /** * Create a style * * @return a style */ public final ResourceReference newStyleWinter() { return new CompressedResourceReference(DatePickerSettings.class, "style/calendar-blue.css"); } /** * Sets the align. * * @param align * align */ public void setAlign(String align) { this.align = align; } /** * Sets the electric. * * @param electric * electric */ public void setElectric(boolean electric) { this.electric = electric; } /** * Sets the firstDay. * * @param firstDay * firstDay */ public void setFirstDay(int firstDay) { this.firstDay = firstDay; } /** * Sets the icon. * * @param icon * icon */ public void setIcon(ResourceReference icon) { this.icon = icon; } /** * Sets the format string that will be used to enter the date in the input * field. This format will be honored even if the input field is hidden. Use * Javascript notation, like '%m/%d/%Y'. * <p> * Note: setting this field to a non-null value, overrides the lookup using * dateformats.properties. To remove the override, pass null. * </p> * * @param ifFormat * the data format * * @deprecated The format is extracted from the java datefomatter format * string */ public void setIfFormat(String ifFormat) { this.ifFormat = ifFormat; } /** * Sets the language. * * @param language * language */ public void setLanguage(ResourceReference language) { this.language = language; } /** * Sets the mode. * * @param mode * mode */ public void setMode(boolean mode) { this.mode = mode; } /** * Set an onClose callback. * * @see ISelectCallback * @param onClose * The onClose callback to use. */ public void setOnClose(ISelectCallback onClose) { this.onClose = onClose; } /** * Set an onSelect callback. * * @see ISelectCallback * @param onSelect * The onSelect callback to use. */ public void setOnSelect(ISelectCallback onSelect) { this.onSelect = onSelect; } /** * Set an onUpdate callback. * * @see ISelectCallback * @param onUpdate * The onUpdate callback to use. */ public void setOnUpdate(ISelectCallback onUpdate) { this.onUpdate = onUpdate; } /** * Sets the showOthers. * * @param showOthers * showOthers */ public void setShowOthers(boolean showOthers) { this.showOthers = showOthers; } /** * Sets the showsTime. * * @param showsTime * showsTime * * @deprecated The format is extracted from the java datefomatter format * string */ public void setShowsTime(boolean showsTime) { this.showsTime = showsTime; } /** * Sets the style. * * @param style * style */ public void setStyle(ResourceReference style) { this.style = style; } /** * Sets the timeFormat. * * @param timeFormat * timeFormat * * @deprecated The format is extracted from the java datefomatter format * string */ public void setTimeFormat(String timeFormat) { this.timeFormat = timeFormat; } /** * Sets the weekNumbers. * * @param weekNumbers * weekNumbers */ public void setWeekNumbers(boolean weekNumbers) { this.weekNumbers = weekNumbers; } /** * Return the properties as a script. * * @param locale * the current locale * @param format * @return the properties as a script */ public String toScript(Locale locale, String format) { if (format != null) { boolean showTime = false; String timeFormat = "24"; char prev = 0; StringBuffer sb = new StringBuffer(); for (int i = 0; i < format.length(); i++) { char ch = format.charAt(i); if (ch == 'd') { if (prev != 'd') { sb.append("%d"); } prev = ch; } else if (ch == 'M') { if (prev != 'M') { sb.append("%m"); } prev = ch; } else if (ch == 'y') { if (prev != 'y') { sb.append("%Y"); } prev = ch; } else if (ch == 'H') { showTime = true; if (prev != 'H') { sb.append("%H"); } prev = ch; } else if (ch == 'h') { timeFormat = "12"; showTime = true; if (prev != 'h') { sb.append("%I"); } prev = ch; } else if (ch == 'm') { showTime = true; if (prev != 'm') { sb.append("%M"); } prev = ch; } else if (ch == 's') { showTime = true; if (prev != 's') { sb.append("%S"); } prev = ch; } else if (ch == 'a') { if (prev != 'a') { sb.append("%P"); } prev = ch; } else if ("GwWDFEkKSzZ".indexOf(ch) != -1) { prev = 0; } else if (prev != 0) { sb.append(ch); } } setIfFormat(sb.toString().trim()); setShowsTime(showTime); setTimeFormat(timeFormat); } StringBuffer b = new StringBuffer(); // create the script that represents these properties. Only create // entries for // values that are different from the default value (save a bit // bandwith) if (!isMode()) { b.append("\n\tmode : false,"); } if (getFirstDay() != -1) { b.append("\n\tfirstDay : ").append(getFirstDay()).append(","); } if (!isWeekNumbers()) { b.append("\n\tweekNumbers : false,"); } if (getAlign() != null) { b.append("\n\talign : ").append(getAlign()).append(","); } if (isShowsTime()) { b.append("\n\tshowsTime : true,"); } if (getTimeFormat() != null) { b.append("\n\ttimeFormat : ").append(getTimeFormat()).append(","); } if (!isElectric()) { b.append("\n\telectric : false,"); } if (isShowOthers()) { b.append("\n\tshowOthers : true,"); } // append date format String ifFormat = getIfFormat(locale); if (ifFormat != null) { b.append("\n\t\tifFormat : \"").append(ifFormat).append("\""); } return b.toString(); } ISelectCallback getOnClose() { return onClose; } ISelectCallback getOnSelect() { return onSelect; } ISelectCallback getOnUpdate() { return onUpdate; } }