001/*
002 * $Id: DateSelectionModel.java 3100 2008-10-14 22:33:10Z rah003 $
003 *
004 * Copyright 2006 Sun Microsystems, Inc., 4150 Network Circle,
005 * Santa Clara, California 95054, U.S.A. All rights reserved.
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015 * Lesser General Public License for more details.
016 *
017 * You should have received a copy of the GNU Lesser General Public
018 * License along with this library; if not, write to the Free Software
019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
020 */
021package org.jdesktop.swingx.calendar;
022
023import java.util.Calendar;
024import java.util.Date;
025import java.util.Locale;
026import java.util.SortedSet;
027import java.util.TimeZone;
028
029import org.jdesktop.swingx.event.DateSelectionListener;
030
031
032/**
033 * The Model used by calendar components. It controls the Calendar to use and 
034 * keeps selection-related state.
035 * 
036 * @author Joshua Outwater
037 */
038public interface DateSelectionModel {
039    public static enum SelectionMode {
040        /**
041         * Mode that allows for selection of a single day.
042         */
043        SINGLE_SELECTION,
044        /**
045         * Mode that allows for selecting of multiple consecutive days.
046         */
047        SINGLE_INTERVAL_SELECTION,
048        /**
049         * Mode that allows for selecting disjoint days.
050         */
051        MULTIPLE_INTERVAL_SELECTION
052    }
053
054//---------------------- mode    
055    /**
056     * Get the selection mode.
057     *
058     * @return return the current selection mode
059     */
060    public SelectionMode getSelectionMode();
061
062    /**
063     * Set the selection mode.
064     *
065     * @param mode new selection mode
066     */
067    public void setSelectionMode(final SelectionMode mode);
068
069    
070//-------------------- calendar    
071    /**
072     * Returns a clone of the calendar used by this model. It's date is unspecified.
073     * 
074     * @return a clone of the calendar used by this model.
075     */
076    public Calendar getCalendar();
077    
078    /**
079     * Gets what the first day of the week is; e.g.,
080     * <code>Calendar.SUNDAY</code> in the U.S., <code>Calendar.MONDAY</code>
081     * in France.  This is needed when the model selection mode is 
082     * <code>WEEK_INTERVAL_SELECTION</code>.
083     * 
084     * PENDING JW: move week-interval selection from JXMonthView into the model.
085     *
086     * @return int The first day of the week.
087     * @see #setFirstDayOfWeek(int)
088     */
089    public int getFirstDayOfWeek();
090
091    /**
092     * Sets what the first day of the week is. E.g.,
093     * <code>Calendar.SUNDAY</code> in US, <code>Calendar.MONDAY</code>
094     * in France. Fires a DateSelectionEvent of type CALENDAR_CHANGED, if the
095     * value is different from the old. <p>
096     * 
097     * The default value depends on the Calendar's default.
098     * 
099     * PENDING JW: actually, it's a bound property. Use a propertyChangeListener?
100     *
101     * @param firstDayOfWeek The first day of the week.
102     * @see #getFirstDayOfWeek()
103     * @see java.util.Calendar
104     */
105    public void setFirstDayOfWeek(final int firstDayOfWeek);
106
107    
108    /**
109     * Gets the minimal number of days in the first week of the year.
110     *
111     * @return int the minimal number of days in the first week of the year.
112     */
113    public int getMinimalDaysInFirstWeek();
114
115    /**
116     * Sets the minimal number of days in the first week of the year.
117     * Fires a DateSelectionEvent of type CALENDAR_CHANGED, if the
118     * value is different from the old.
119     * 
120     * The default value depends on the Calendar's default.
121     * 
122     * PENDING JW: actually, it's a bound property. Use a propertyChangeListener?
123     *
124     * @param minimalDays the minimal number of days in the first week of the year.
125     * @see #getMinimalDaysInFirstWeek()
126     * @see java.util.Calendar
127     */
128    public void setMinimalDaysInFirstWeek(final int minimalDays);
129
130    /**
131     * Returns the TimeZone of this model.
132     * 
133     * @return the TimeZone of this model.
134     * @see #setTimeZone(TimeZone)
135     */
136    public TimeZone getTimeZone();
137    
138
139    /**
140     * Sets the TimeZone of this model. Fires a DateSelectionEvent of type 
141     * CALENDAR_CHANGED if the new value is different from the old.
142     * 
143     * The default value depends on the Calendar's default.
144     * 
145     * PENDING JW: actually, it's a bound property. Use a propertyChangeListener?
146     * 
147     * @param timeZone the TimeZone to use in this model, must not be null.
148     * @see #getTimeZone()
149     */
150    public void setTimeZone(TimeZone timeZone);
151    
152    /**
153     * Returns the Locale of this model's calendar.
154     * @return the Locale of this model's calendar.
155     */
156    public Locale getLocale();
157
158    /**
159     * Sets the Locale of this model's calendar. Fires a DateSelectionEvent of type 
160     * CALENDAR_CHANGED if the new value is different from the old. <p>
161     * 
162     * The default value is Locale.default(). <p>
163     * 
164     * PENDING JW: fall back to JComponent.getDefaultLocale instead? We use this
165     *   with components anyway? <p>
166     * PENDING JW: actually, it's a bound property. Use a propertyChangeListener?
167     * 
168     * @param locale the Locale to use. If null, the default Locale is used.
169     */
170    public void setLocale(Locale locale);
171    
172    //-------------------- selection 
173    
174    /**
175     * Adds the specified selection interval to the selection model.
176     *
177     * @param startDate interval start date, must not be null
178     * @param endDate   interval end date >= start date, must not be null
179     * @throws NullPointerException if any of the dates is null
180     */
181    public void addSelectionInterval(Date startDate, Date endDate);
182
183    /**
184     * Sest the specified selection interval to the selection model.
185     *
186     * @param startDate interval start date, must not be null
187     * @param endDate   interval end date >= start date, must not be null
188     * @throws NullPointerException if any of the dates is null
189     */
190    public void setSelectionInterval(Date startDate, Date endDate);
191
192    /**
193     * Removes the specifed selection interval from the selection model. If
194     * the selection is changed by this method, it fires a DateSelectionEvent
195     * of type DATES_REMOVED.
196     *
197     * @param startDate interval start date, must not be null
198     * @param endDate   interval end date >= start date, must not be null
199     * @throws NullPointerException if any of the dates is null
200     */
201    public void removeSelectionInterval(Date startDate, Date endDate);
202
203    /**
204     * Clears any selection from the selection model. Fires an Event of 
205     * type SELECTION_CLEARED if there had been a selection, does nothing
206     * otherwise.
207     */
208    public void clearSelection();
209
210    /**
211     * Returns the current selection.
212     *
213     * @return sorted set of selected dates, guaranteed to be never null.
214     */
215    public SortedSet<Date> getSelection();
216
217    /**
218     * Returns the earliest date in the selection or null if the selection is empty.
219     * 
220     * @return the earliest date in the selection, or null if isSelectionEmpty.
221     * 
222     * @see #getLastSelectionDate()
223     * @see #getSelection()
224     * @see #isSelectionEmpty()
225     */
226    public Date getFirstSelectionDate();
227
228    /**
229     * Returns the latest date in the selection or null if the selection is empty.
230     * 
231     * @return the lastest date in the selection, or null if isSelectionEmpty.
232     * 
233     * @see #getFirstSelectionDate()
234     * @see #getSelection()
235     * @see #isSelectionEmpty()
236     */
237    public Date getLastSelectionDate();
238
239
240    /**
241     * Returns true if the date specified is selected, false otherwise. <p>
242     * 
243     * Note: it is up to implementations to define the exact notion of selected.
244     * It does not imply the exact date as given is contained the set returned from 
245     * getSelection().
246     * 
247     * @param date date to check for selection, must not be null
248     * @return true if the date is selected, false otherwise
249     * @throws NullPointerException if the date is null
250     */
251    public boolean isSelected(final Date date);
252
253    /**
254     * Returns a normalized Date as used by the implementation, if any. F.i.
255     * DaySelectionModel returns the start of the day in the model's calendar.
256     * If no normalization is applied, a clone of the Date itself is returned.
257     * The given Date is never changed.
258     * <p>
259     * 
260     * The overall contract:
261     * 
262     * <pre><code>
263     * if ((date != null) &amp;&amp; isSelectable(date)) {
264     *     setSelectionInterval(date, date);
265     *     assertEquals(getNormalized(date), getFirstSelectionDate();
266     * }
267     * </code></pre>
268     * 
269     * 
270     * @return the date as it would be normalized before used in the model, 
271     *    must not be null.
272     * @throws NullPointerException if given date is null.
273     */
274    public Date getNormalizedDate(Date date);
275    
276    /**
277     * Returns true if the selection is empty, false otherwise.
278     *
279     * @return true if the selection is empty, false otherwise
280     */
281    public boolean isSelectionEmpty();
282
283
284    /**
285     * Returns a <code>SortedSet</code> of <code>Date</codes>s that are unselectable.
286     *
287     * @return sorted set of dates
288     */
289    public SortedSet<Date> getUnselectableDates();
290
291    /**
292     * Sets a collection of dates which are not selectable.<p>
293     * 
294     * Note: it is up to implementations to define the exact notion of unselectableDate.
295     * It does not imply the only the exact date as given is unselectable, it might
296     * have a period like "all dates on the same day".
297     * 
298     * PENDING JW: any collection would do - why insist on a SortedSet?
299     *
300     * @param unselectableDates dates that are unselectable, must not be null and 
301     *   must not contain null dates.
302     */
303    public void setUnselectableDates(SortedSet<Date> unselectableDates);
304
305    /**
306     * Returns true is the specified date is unselectable.
307     *
308     * @param unselectableDate the date to check for unselectability, must not be null.
309     * @return true is the date is unselectable, false otherwise
310     */
311    public boolean isUnselectableDate(Date unselectableDate);
312
313    /**
314     * Return the upper bound date that is allowed to be selected for this
315     * model.
316     *
317     * @return upper bound date or null if not set
318     */
319    public Date getUpperBound();
320
321    /**
322     * Set the upper bound date that is allowed to be selected for this model.
323     *
324     * @param upperBound upper bound
325     */
326    public void setUpperBound(final Date upperBound);
327
328    /**
329     * Return the lower bound date that is allowed to be selected for this
330     * model.
331     *
332     * @return lower bound date or null if not set
333     */
334    public Date getLowerBound();
335
336    /**
337     * Set the lower bound date that is allowed to be selected for this model.
338     *
339     * @param lowerBound lower bound date or null if not set
340     */
341    public void setLowerBound(final Date lowerBound);
342
343    /**
344     * Set the property to mark upcoming selections as intermediate/
345     * final. This will fire a event of type adjusting_start/stop.
346     * 
347     * The default value is false.
348     * 
349     * Note: Client code marking as intermediate must take care of
350     * finalizing again.
351     * 
352     * @param adjusting a flag to turn the adjusting property on/off.
353     */
354    public void setAdjusting(boolean adjusting);
355
356    /**
357     * Returns the property to decide whether the selection is 
358     * intermediate or final.
359     * 
360     * @return the adjusting property.
361     */
362    public boolean isAdjusting();
363
364    /**
365     * Add the specified listener to this model.
366     *
367     * @param listener listener to add to this model
368     */
369    public void addDateSelectionListener(DateSelectionListener listener);
370
371    /**
372     * Remove the specified listener to this model.
373     *
374     * @param listener listener to remove from this model
375     */
376    public void removeDateSelectionListener(DateSelectionListener listener);
377
378}