001: /*--------------------------------------------------------------------------*
002: | Copyright (C) 2006 Christopher Kohlhaas |
003: | |
004: | This program is free software; you can redistribute it and/or modify |
005: | it under the terms of the GNU General Public License as published by the |
006: | Free Software Foundation. A copy of the license has been included with |
007: | these distribution in the COPYING file, if not go to www.fsf.org |
008: | |
009: | As a special exception, you are granted the permissions to link this |
010: | program with every library, which license fulfills the Open Source |
011: | Definition as published by the Open Source Initiative (OSI). |
012: *--------------------------------------------------------------------------*/
013:
014: package org.rapla.components.calendar;
015:
016: import javax.swing.*;
017: import javax.swing.event.*;
018: import java.awt.*;
019: import java.util.*;
020:
021: /** This is another ComboBox-like calendar component.
022: * It is localizable and it uses swing-components.
023: * <p>The combobox editor is a {@link DateField}. If the ComboBox-Button
024: * is pressed, a CalendarMenu will drop down.</p>
025: * @see CalendarMenu
026: * @see DateField
027: * @author Christopher Kohlhaas
028: */
029: public final class RaplaCalendar extends RaplaComboBox {
030: private static final long serialVersionUID = 1L;
031:
032: protected DateField m_dateField;
033: protected CalendarMenu m_calendarMenu;
034: Collection m_listenerList = new ArrayList();
035: protected DateModel m_model;
036: private Date m_lastDate;
037: DateRenderer m_dateRenderer;
038:
039: /** Create a new Calendar with the default locale. The calendarmenu
040: will be accessible via a drop-down-box */
041: public RaplaCalendar() {
042: this (Locale.getDefault());
043: }
044:
045: /** Create a new Calendar with the specified locale and the
046: default timeZone. The calendarmenu will be accessible via a
047: drop-down-box */
048: public RaplaCalendar(Locale locale) {
049: this (locale, TimeZone.getDefault(), true);
050: }
051:
052: /** @deprecated replaced with #RaplaCalendar(Locale,TimeZone,boolean)*/
053: public RaplaCalendar(Locale locale, boolean isDropDown) {
054: this (locale, TimeZone.getDefault(), isDropDown);
055: }
056:
057: /** Create a new Calendar with the specified locale and timezone. The calendarmenu
058: will be accessible via a drop-down-box */
059: public RaplaCalendar(Locale locale, TimeZone timeZone) {
060: this (locale, timeZone, true);
061: }
062:
063: /** Create a new Calendar with the specified locale and timezone. The
064: isDropDown flag specifies if the calendarmenu should be
065: accessible via a drop-down-box. Alternatively you can get the
066: calendarmenu with getPopupComponent().
067: */
068: public RaplaCalendar(Locale locale, TimeZone timeZone,
069: boolean isDropDown) {
070: super (isDropDown, new DateField(locale, timeZone));
071: m_model = new DateModel(locale, timeZone);
072: m_dateField = (DateField) m_editorComponent;
073: Listener listener = new Listener();
074: m_dateField.addChangeListener(listener);
075: m_model.addDateChangeListener(listener);
076: m_lastDate = m_model.getDate();
077: setDateRenderer(new WeekendHighlightRenderer());
078: }
079:
080: class Listener implements ChangeListener, DateChangeListener {
081: // Implementation of ChangeListener
082: public void stateChanged(ChangeEvent evt) {
083: validateEditor();
084: }
085:
086: // Implementation of DateChangeListener
087: public void dateChanged(DateChangeEvent evt) {
088: closePopup();
089: if (needSync())
090: m_dateField.setDate(evt.getDate());
091: if (m_lastDate == null || !m_lastDate.equals(evt.getDate()))
092: fireDateChange(evt.getDate());
093: m_lastDate = evt.getDate();
094: }
095: }
096:
097: public void setTimeZone(TimeZone timeZone) {
098: m_model.setTimeZone(timeZone);
099: if (m_calendarMenu != null)
100: m_calendarMenu.setTimeZone(timeZone);
101: m_dateField.setTimeZone(timeZone);
102: }
103:
104: public TimeZone getTimeZone() {
105: return m_model.getTimeZone();
106: }
107:
108: /* Use this to get the CalendarMenu Component. The calendar menu will be created lazily.*/
109: public JComponent getPopupComponent() {
110: if (m_calendarMenu == null) {
111: m_calendarMenu = new CalendarMenu(m_model);
112: m_calendarMenu.setFont(getFont());
113: // #TODO Property change listener for TimeZone
114: m_calendarMenu.getDaySelection().setDateRenderer(
115: m_dateRenderer);
116: javax.swing.ToolTipManager
117: .sharedInstance()
118: .registerComponent(m_calendarMenu.getDaySelection());
119: }
120: return m_calendarMenu;
121: }
122:
123: public void setFont(Font font) {
124: super .setFont(font);
125: // Method called during super-constructor?
126: if (m_calendarMenu == null || font == null)
127: return;
128: m_calendarMenu.setFont(font);
129: }
130:
131: /** Selects the date relative to the given timezone.
132: * The hour,minute,second and millisecond values will be ignored.
133: */
134: public void setDate(Date date) {
135: m_model.setDate(date);
136: }
137:
138: /** Parse the returned date with a calendar-object set to the
139: * correct time-zone to get the date,month and year. The
140: * hour,minute,second and millisecond values should be ignored.
141: * @return the selected date
142: * @see #getYear
143: * @see #getMonth
144: * @see #getDay
145: */
146: public Date getDate() {
147: return m_model.getDate();
148: }
149:
150: /** selects the specified day, month and year.
151: @see #setDate(Date date)*/
152: public void select(int day, int month, int year) {
153: m_model.setDate(day, month, year);
154: }
155:
156: /** you can choose, if you want to highlight the weekends. Default is true.
157: If flag is set to true a new WeekendHighlightRenderer will be installed.
158: If flag is set to false the DateRenderer will be uninstalled.
159: @deprecated use setDateRenderer(new WeekendHighlightRenderer()) instead.
160: */
161: public void setHighlightWeekend(boolean bHighlight) {
162: if (bHighlight)
163: setDateRenderer(new WeekendHighlightRenderer());
164: else
165: setDateRenderer(null);
166: }
167:
168: /** sets the DateRenderer for the calendar */
169: public void setDateRenderer(DateRenderer dateRenderer) {
170: m_dateRenderer = dateRenderer;
171: if (m_calendarMenu != null) {
172: m_calendarMenu.getDaySelection().setDateRenderer(
173: m_dateRenderer);
174: }
175: m_dateField.setDateRenderer(m_dateRenderer);
176: }
177:
178: /** you can choose, if weekdays should be displayed in the right corner of the DateField.
179: Default is true. This method simply calls setWeekdaysVisble on the DateField Component.
180: If a DateRender is installed the weekday will be rendered with the DateRenderer.
181: This includes a tooltip that shows up on the DateRenderer.
182: @see DateField
183: */
184: public void setWeekdaysVisibleInDateField(boolean bVisible) {
185: m_dateField.setWeekdaysVisible(bVisible);
186: }
187:
188: /** @return the selected year (relative to the given TimeZone)
189: @see #getDate
190: @see #getMonth
191: @see #getDay
192: */
193: public int getYear() {
194: return m_model.getYear();
195: }
196:
197: /** @return the selected month (relative to the given TimeZone)
198: @see #getDate
199: @see #getYear
200: @see #getDay
201: */
202: public int getMonth() {
203: return m_model.getMonth();
204: }
205:
206: /** @return the selected day (relative to the given TimeZone)
207: @see #getDate
208: @see #getYear
209: @see #getMonth
210: */
211: public int getDay() {
212: return m_model.getDay();
213: }
214:
215: /** registers new DateChangeListener for this component.
216: * A DateChangeEvent will be fired to every registered DateChangeListener
217: * when the a different date is selected.
218: * @see DateChangeListener
219: * @see DateChangeEvent
220: */
221: public void addDateChangeListener(DateChangeListener listener) {
222: m_listenerList.add(listener);
223: }
224:
225: /** removes a listener from this component.*/
226: public void removeDateChangeListener(DateChangeListener listener) {
227: m_listenerList.remove(listener);
228: }
229:
230: public DateChangeListener[] getDateChangeListeners() {
231: return (DateChangeListener[]) m_listenerList
232: .toArray(new DateChangeListener[] {});
233: }
234:
235: /** A DateChangeEvent will be fired to every registered DateChangeListener
236: * when the a different date is selected.
237: */
238: protected void fireDateChange(Date date) {
239: if (m_listenerList.size() == 0)
240: return;
241: DateChangeListener[] listeners = getDateChangeListeners();
242: DateChangeEvent evt = new DateChangeEvent(this , date);
243: for (int i = 0; i < listeners.length; i++) {
244: listeners[i].dateChanged(evt);
245: }
246: }
247:
248: protected void showPopup() {
249: validateEditor();
250: super .showPopup();
251: }
252:
253: /** test if we need to synchronize the dateModel and the dateField*/
254: private boolean needSync() {
255: return (m_dateField.getDate() != null && !m_model
256: .sameDate(m_dateField.getDate()));
257: }
258:
259: protected void validateEditor() {
260: if (needSync())
261: m_model.setDate(m_dateField.getDate());
262: }
263:
264: }
|