| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to you 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 org.apache.pivot.wtk; |
| |
| import java.util.Locale; |
| |
| import org.apache.pivot.collections.Dictionary; |
| import org.apache.pivot.json.JSON; |
| import org.apache.pivot.json.JSONSerializer; |
| import org.apache.pivot.serialization.SerializationException; |
| import org.apache.pivot.util.CalendarDate; |
| import org.apache.pivot.util.Filter; |
| import org.apache.pivot.util.ListenerList; |
| |
| /** |
| * Component that allows the user to select a date. |
| */ |
| public class Calendar extends Container { |
| /** |
| * Translates between calendar date and context data during data binding. |
| */ |
| public interface SelectedDateBindMapping { |
| /** |
| * Converts a context value to a calendar date. |
| * |
| * @param value The value retrieved from the bound object. |
| * @return The value converted to a calendar date. |
| */ |
| public CalendarDate toDate(Object value); |
| |
| /** |
| * Converts a calendar date to a context value. |
| * |
| * @param calendarDate The current calendar date value from the component. |
| * @return The converted object value suitable for persistence in the bound object. |
| */ |
| public Object valueOf(CalendarDate calendarDate); |
| } |
| |
| private static class CalendarListenerList extends WTKListenerList<CalendarListener> implements |
| CalendarListener { |
| @Override |
| public void yearChanged(Calendar calendar, int previousYear) { |
| for (CalendarListener listener : this) { |
| listener.yearChanged(calendar, previousYear); |
| } |
| } |
| |
| @Override |
| public void monthChanged(Calendar calendar, int previousMonth) { |
| for (CalendarListener listener : this) { |
| listener.monthChanged(calendar, previousMonth); |
| } |
| } |
| |
| @Override |
| public void localeChanged(Calendar calendar, Locale previousLocale) { |
| for (CalendarListener listener : this) { |
| listener.localeChanged(calendar, previousLocale); |
| } |
| } |
| |
| @Override |
| public void disabledDateFilterChanged(Calendar calendar, |
| Filter<CalendarDate> previousDisabledDateFilter) { |
| for (CalendarListener listener : this) { |
| listener.disabledDateFilterChanged(calendar, previousDisabledDateFilter); |
| } |
| } |
| } |
| |
| private static class CalendarSelectionListenerList extends |
| WTKListenerList<CalendarSelectionListener> implements CalendarSelectionListener { |
| |
| @Override |
| public void selectedDateChanged(Calendar calendar, CalendarDate previousSelectedDate) { |
| for (CalendarSelectionListener listener : this) { |
| listener.selectedDateChanged(calendar, previousSelectedDate); |
| } |
| } |
| } |
| |
| private static class CalendarBindingListenerList extends |
| WTKListenerList<CalendarBindingListener> implements CalendarBindingListener { |
| @Override |
| public void selectedDateKeyChanged(Calendar calendar, String previousSelectedDateKey) { |
| for (CalendarBindingListener listener : this) { |
| listener.selectedDateKeyChanged(calendar, previousSelectedDateKey); |
| } |
| } |
| |
| @Override |
| public void selectedDateBindTypeChanged(Calendar calendar, |
| BindType previousSelectedDateBindType) { |
| for (CalendarBindingListener listener : this) { |
| listener.selectedDateBindTypeChanged(calendar, previousSelectedDateBindType); |
| } |
| } |
| |
| @Override |
| public void selectedDateBindMappingChanged(Calendar calendar, |
| SelectedDateBindMapping previousSelectedDateBindMapping) { |
| for (CalendarBindingListener listener : this) { |
| listener.selectedDateBindMappingChanged(calendar, previousSelectedDateBindMapping); |
| } |
| } |
| } |
| |
| private int year; |
| private int month; |
| |
| private CalendarDate selectedDate = null; |
| private Locale locale = Locale.getDefault(); |
| private Filter<CalendarDate> disabledDateFilter = null; |
| |
| private String selectedDateKey = null; |
| private BindType selectedDateBindType = BindType.BOTH; |
| private SelectedDateBindMapping selectedDateBindMapping = null; |
| |
| private CalendarListenerList calendarListeners = new CalendarListenerList(); |
| private CalendarSelectionListenerList calendarSelectionListeners = new CalendarSelectionListenerList(); |
| private CalendarBindingListenerList calendarBindingListeners = new CalendarBindingListenerList(); |
| |
| public static final String LANGUAGE_KEY = "language"; |
| public static final String COUNTRY_KEY = "country"; |
| public static final String VARIANT_KEY = "variant"; |
| |
| public Calendar() { |
| this(new CalendarDate()); |
| } |
| |
| private Calendar(CalendarDate calendarDate) { |
| this(calendarDate.year, calendarDate.month); |
| } |
| |
| public Calendar(int year, int month) { |
| this.year = year; |
| this.month = month; |
| |
| installSkin(Calendar.class); |
| } |
| |
| /** |
| * Gets the year to which this calendar is currently set. |
| * |
| * @return The current year value. |
| */ |
| public int getYear() { |
| return year; |
| } |
| |
| /** |
| * Sets this calendar's year. |
| * |
| * @param year The new year to set this calendar to. |
| */ |
| public void setYear(int year) { |
| int previousYear = this.year; |
| |
| if (previousYear != year) { |
| this.year = year; |
| calendarListeners.yearChanged(this, previousYear); |
| } |
| } |
| |
| /** |
| * Gets the month to which this calendar is currently set. |
| * |
| * @return The current month value. |
| */ |
| public int getMonth() { |
| return month; |
| } |
| |
| /** |
| * Sets this calendar's month. |
| * |
| * @param month The new month value to set this calendar to. |
| */ |
| public void setMonth(int month) { |
| int previousMonth = this.month; |
| |
| if (previousMonth != month) { |
| this.month = month; |
| calendarListeners.monthChanged(this, previousMonth); |
| } |
| } |
| |
| /** |
| * @return The currently selected date, or <tt>null</tt> if no date is |
| * selected. |
| */ |
| public CalendarDate getSelectedDate() { |
| return selectedDate; |
| } |
| |
| /** |
| * Sets the currently selected date. |
| * |
| * @param selectedDate The selected date, or <tt>null</tt> to specify no |
| * selection |
| */ |
| public void setSelectedDate(CalendarDate selectedDate) { |
| CalendarDate previousSelectedDate = this.selectedDate; |
| |
| if (previousSelectedDate != selectedDate) { |
| this.selectedDate = selectedDate; |
| calendarSelectionListeners.selectedDateChanged(this, previousSelectedDate); |
| } |
| } |
| |
| /** |
| * Sets the selected date to the date represented by the specified date |
| * string. The date string must be in the <tt>ISO 8601</tt> "calendar date" |
| * format, which is <tt>[YYYY]-[MM]-[DD]</tt>. |
| * |
| * @param selectedDate A string in the form of <tt>[YYYY]-[MM]-[DD]</tt> |
| * (e.g. 2008-07-23) |
| * @throws IllegalArgumentException if the given date is {@code null}. |
| */ |
| public final void setSelectedDate(String selectedDate) { |
| if (selectedDate == null) { |
| throw new IllegalArgumentException("selectedDate is null."); |
| } |
| |
| setSelectedDate(CalendarDate.decode(selectedDate)); |
| } |
| |
| /** |
| * @return The locale used to present calendar data. |
| */ |
| public Locale getLocale() { |
| return locale; |
| } |
| |
| /** |
| * Sets the locale used to present calendar data. |
| * |
| * @param locale The new locale for this calendar. |
| * @throws IllegalArgumentException if the locale argument is {@code null}. |
| */ |
| public void setLocale(Locale locale) { |
| if (locale == null) { |
| throw new IllegalArgumentException("locale is null."); |
| } |
| |
| Locale previousLocale = this.locale; |
| if (previousLocale != locale) { |
| this.locale = locale; |
| calendarListeners.localeChanged(this, previousLocale); |
| } |
| } |
| |
| /** |
| * Sets the locale used to present calendar data. |
| * |
| * @param locale An dictionary containing values for language, country, and |
| * variant. Country and variant are optional but the must adhere to the |
| * following rules: <ul> <li>If variant is specified, language and country |
| * are required;</li> <li>Otherwise, if country is specified, language is |
| * required;</li> <li>Otherwise, language is required.</li> </ul> |
| * @throws IllegalArgumentException if the given locale dictionary is {@code null}. |
| */ |
| public void setLocale(Dictionary<String, ?> locale) { |
| if (locale == null) { |
| throw new IllegalArgumentException("locale is null."); |
| } |
| |
| String language = (String) locale.get(LANGUAGE_KEY); |
| String country = (String) locale.get(COUNTRY_KEY); |
| String variant = (String) locale.get(VARIANT_KEY); |
| |
| if (variant != null) { |
| setLocale(new Locale(language, country, variant)); |
| } else if (country != null) { |
| setLocale(new Locale(language, country)); |
| } else { |
| setLocale(new Locale(language)); |
| } |
| } |
| |
| /** |
| * Sets the locale used to present calendar data. |
| * |
| * @param locale A JSON map containing values for language, country, and |
| * variant. |
| * @throws IllegalArgumentException if the locale string is {@code null} |
| * or if it cannot be parsed successfully. |
| * @see #setLocale(Dictionary) |
| */ |
| public void setLocale(String locale) { |
| if (locale == null) { |
| throw new IllegalArgumentException("locale is null."); |
| } |
| |
| try { |
| setLocale(JSONSerializer.parseMap(locale)); |
| } catch (SerializationException exception) { |
| throw new IllegalArgumentException(exception); |
| } |
| } |
| |
| public Filter<CalendarDate> getDisabledDateFilter() { |
| return disabledDateFilter; |
| } |
| |
| public void setDisabledDateFilter(Filter<CalendarDate> disabledDateFilter) { |
| Filter<CalendarDate> previousDisabledDateFilter = this.disabledDateFilter; |
| |
| if (previousDisabledDateFilter != disabledDateFilter) { |
| this.disabledDateFilter = disabledDateFilter; |
| calendarListeners.disabledDateFilterChanged(this, previousDisabledDateFilter); |
| } |
| } |
| |
| /** |
| * Gets the data binding key that is set on this calendar. |
| * |
| * @return The current value of the selected date binding key. |
| */ |
| public String getSelectedDateKey() { |
| return selectedDateKey; |
| } |
| |
| /** |
| * Sets this calendar's data binding key. |
| * |
| * @param selectedDateKey The new key to use for binding to the selected date. |
| */ |
| public void setSelectedDateKey(String selectedDateKey) { |
| String previousSelectedDateKey = this.selectedDateKey; |
| |
| if (selectedDateKey != previousSelectedDateKey) { |
| this.selectedDateKey = selectedDateKey; |
| calendarBindingListeners.selectedDateKeyChanged(this, previousSelectedDateKey); |
| } |
| } |
| |
| public BindType getSelectedDateBindType() { |
| return selectedDateBindType; |
| } |
| |
| public void setSelectedDateBindType(BindType selectedDateBindType) { |
| if (selectedDateBindType == null) { |
| throw new IllegalArgumentException(); |
| } |
| |
| BindType previousSelectedDateBindType = this.selectedDateBindType; |
| |
| if (previousSelectedDateBindType != selectedDateBindType) { |
| this.selectedDateBindType = selectedDateBindType; |
| calendarBindingListeners.selectedDateBindTypeChanged(this, previousSelectedDateBindType); |
| } |
| } |
| |
| public SelectedDateBindMapping getSelectedDateBindMapping() { |
| return selectedDateBindMapping; |
| } |
| |
| public void setSelectedDateBindMapping(SelectedDateBindMapping selectedDateBindMapping) { |
| SelectedDateBindMapping previousSelectedDateBindMapping = this.selectedDateBindMapping; |
| |
| if (previousSelectedDateBindMapping != selectedDateBindMapping) { |
| this.selectedDateBindMapping = selectedDateBindMapping; |
| calendarBindingListeners.selectedDateBindMappingChanged(this, |
| previousSelectedDateBindMapping); |
| } |
| } |
| |
| @Override |
| public void load(Object context) { |
| if (selectedDateKey != null && JSON.containsKey(context, selectedDateKey) |
| && selectedDateBindType != BindType.STORE) { |
| Object value = JSON.get(context, selectedDateKey); |
| |
| CalendarDate selectedDateLocal = null; |
| |
| if (value instanceof CalendarDate) { |
| selectedDateLocal = (CalendarDate) value; |
| } else if (selectedDateBindMapping == null) { |
| if (value != null) { |
| selectedDateLocal = CalendarDate.decode(value.toString()); |
| } |
| } else { |
| selectedDateLocal = selectedDateBindMapping.toDate(value); |
| } |
| |
| setSelectedDate(selectedDateLocal); |
| } |
| } |
| |
| @Override |
| public void store(Object context) { |
| if (selectedDateKey != null && selectedDateBindType != BindType.LOAD) { |
| JSON.put(context, selectedDateKey, (selectedDateBindMapping == null) ? selectedDate |
| : selectedDateBindMapping.valueOf(selectedDate)); |
| } |
| } |
| |
| @Override |
| public void clear() { |
| if (selectedDateKey != null) { |
| setSelectedDate((CalendarDate) null); |
| } |
| } |
| |
| /** |
| * @return The calendar listener list. |
| */ |
| public ListenerList<CalendarListener> getCalendarListeners() { |
| return calendarListeners; |
| } |
| |
| /** |
| * @return The calendar selection listener list. |
| */ |
| public ListenerList<CalendarSelectionListener> getCalendarSelectionListeners() { |
| return calendarSelectionListeners; |
| } |
| |
| /** |
| * @return The calendar binding listener list. |
| */ |
| public ListenerList<CalendarBindingListener> getCalendarBindingListeners() { |
| return calendarBindingListeners; |
| } |
| } |