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     */
021    package org.jdesktop.swingx.calendar;
022    
023    import java.util.Calendar;
024    import java.util.Date;
025    import java.util.Locale;
026    import java.util.SortedSet;
027    import java.util.TimeZone;
028    
029    import 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     */
038    public 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    }