001: /*
002: * XCalendar.java
003: *
004: * Created on 9. Juni 2006, 12:37
005: *
006: * To change this template, choose Tools | Template Manager
007: * and open the template in the editor.
008: */
009:
010: package org.wingx;
011:
012: import java.awt.event.ActionEvent;
013: import java.awt.event.ActionListener;
014: import java.text.DateFormat;
015: import java.text.Format;
016: import java.text.SimpleDateFormat;
017: import java.util.Date;
018: import java.util.GregorianCalendar;
019: import java.util.TimeZone;
020: import org.wings.LowLevelEventListener;
021: import org.wings.SContainer;
022: import org.wings.SDimension;
023: import org.wings.SFormattedTextField;
024: import org.wings.SIcon;
025: import org.wings.SResourceIcon;
026: import org.wings.event.SDocumentEvent;
027: import org.wings.event.SDocumentListener;
028: import org.wings.text.SDefaultFormatterFactory;
029: import org.wings.text.SAbstractFormatter;
030: import org.wings.text.SDateFormatter;
031: import org.wings.text.SInternationalFormatter;
032: import org.wingx.plaf.css.CalendarCG;
033:
034: /**
035: * @author <a href="mailto:e.habicht@thiesen.com">Erik Habicht</a>
036: */
037: public class XCalendar extends SContainer implements
038: LowLevelEventListener, SDocumentListener {
039:
040: /**
041: * The <code>XCalendar</code> default <code>SIcon</code> for editing.
042: */
043: public static final SIcon DEFAULT_EDIT_ICON = new SResourceIcon(
044: "org/wingx/calendar/calbu.gif");
045:
046: /**
047: * The current <code>XCalendar</code>'s icon to choose a new date.
048: */
049: private SIcon editIcon = DEFAULT_EDIT_ICON;
050:
051: /**
052: * The current <code>SFormattedTextField</code>.
053: */
054: private SFormattedTextField fTextField;
055:
056: /**
057: * The current <code>TimeZone</code>
058: */
059: private TimeZone timeZone = TimeZone.getDefault();
060:
061: private ActionListener actionListener = null;
062:
063: private ActionListener getActionListener() {
064: if (actionListener == null) {
065: actionListener = new ActionListener() {
066: public void actionPerformed(ActionEvent e) {
067: fireActionEvents();
068: }
069: };
070: }
071: return actionListener;
072: }
073:
074: /**
075: * @see LowLevelEventListener#isEpochCheckEnabled()
076: */
077: protected boolean epochCheckEnabled = true;
078:
079: /**
080: * Set the look and feel delegate for this component
081: *
082: * @see org.wings.SComponent#setCG
083: * @param cg the component's cg
084: */
085: public void setCG(org.wingx.plaf.CalendarCG cg) {
086: super .setCG(cg);
087: }
088:
089: /**
090: * Creates a <code>XCalendar</code> with the current Date and a default <code>SDateFormatter</code>.
091: */
092: public XCalendar() {
093: this (new SDateFormatter());
094: }
095:
096: /**
097: * Creates a <code>XCalendar</code> with the current Date and the specified <code>SDateFormatter</code>
098: * instance.
099: * @param formatter <code>SDateFormatter</code> to use for formatting.
100: */
101: public XCalendar(SDateFormatter formatter) {
102: this (new GregorianCalendar().getTime(), formatter);
103: }
104:
105: /**
106: * Creates a <code>XCalendar</code> with the given Date and the specified <code>SDateFormatter</code>
107: * instance.
108: * @param date Date
109: * @param formatter <code>SDateFormatter</code> to use for formatting.
110: */
111: public XCalendar(Date date, SDateFormatter formatter) {
112: add(getFormattedTextField());
113: setFormatter(formatter);
114: setDate(date);
115: }
116:
117: /**
118: * Sets the <code>XCalendar</code>'s default <code>SIcon</code>.
119: * @param icon the icon used as the default image.
120: * @deprecated Use <code>editIcon</code> instead
121: */
122: public void setIcon(SIcon icon) {
123: this .editIcon = icon;
124: }
125:
126: /**
127: * Returns the default <code>SIcon</code>.
128: * @return the default <code>SIcon</code>
129: * @deprecated Use <code>editIcon</code> instead
130: */
131: public SIcon getIcon() {
132: return this .editIcon;
133: }
134:
135: /**
136: * Sets the icon to use for calling the date picker.
137: * @param icon the icon used as the trigger icon to start the date picker.
138: */
139: public void setEditIcon(SIcon icon) {
140: this .editIcon = icon;
141: }
142:
143: /**
144: * Returns the current <code>SIcon</code> to start the date picker.
145: * @return the default <code>SIcon</code>
146: */
147: public SIcon getEditIcon() {
148: return this .editIcon;
149: }
150:
151: /**
152: * The current icon to use for clearing the input/ date.
153: * @return The current icon to use for clearing the input/ date.
154: * @deprecated Returns now the DEFAULT_EDIT_ICON
155: */
156: public SIcon getClearIcon() {
157: return DEFAULT_EDIT_ICON;
158: }
159:
160: /**
161: * The icon to use for clearing the input/ date.
162: * @param clearIcon The new icon to use for clearing the input/ date.
163: * @deprecated
164: */
165: public void setClearIcon(SIcon clearIcon) {
166: }
167:
168: /**
169: * Defines if the user should be able to select also null values.
170: * <p><b>NOTE:</b> He can always do this manually. Default is <code>false</code>
171: * @return <code>true</code> if the user has an clear icon to define a null date
172: * @deprecated
173: */
174: public boolean isNullable() {
175: return false;
176: }
177:
178: /**
179: * Defines if the user has an clear icon to reset the picked date to <code>null</code>.
180: * @param nullable <code>true</code> if the user should be able to clear the date.
181: * @deprecated
182: */
183: public void setNullable(boolean nullable) {
184: }
185:
186: /**
187: * Sets the current <code>SDateFormatter</code>.
188: * @param formatter <code>SDateFormatter</code> to use for formatting
189: */
190: public void setFormatter(SDateFormatter formatter) {
191: getFormattedTextField().setFormatterFactory(
192: new SDefaultFormatterFactory(formatter));
193: }
194:
195: /**
196: * Sets the current <code>TimeZone</code>.
197: * @param timeZone <code>TimeZone</code>
198: */
199: public void setTimeZone(TimeZone timeZone) {
200: this .timeZone = timeZone;
201: if (timeZone != null) {
202: SAbstractFormatter aFormatter = getFormattedTextField()
203: .getFormatter();
204: if (aFormatter != null
205: && aFormatter instanceof SInternationalFormatter) {
206: SInternationalFormatter iFormatter = (SInternationalFormatter) aFormatter;
207: Format format = iFormatter.getFormat();
208: if (format != null && format instanceof DateFormat) {
209: ((DateFormat) format).setTimeZone(timeZone);
210: }
211: }
212: }
213: }
214:
215: /**
216: * Returns the current <code>TimeZone</code>.
217: * @return <code>TimeZone</code>
218: */
219: public TimeZone getTimeZone() {
220: return this .timeZone;
221: }
222:
223: /**
224: * Returns the current <code>Date</code>.
225: * @return the current <code>Date</code>
226: */
227: public Date getDate() {
228: return (Date) getFormattedTextField().getValue();
229: }
230:
231: /**
232: * Sets the current <code>Date</code>.
233: * @param date the current <code>Date</code>
234: */
235: public void setDate(Date date) {
236: getFormattedTextField().removeDocumentListener(this );
237: getFormattedTextField().setValue(date);
238: getFormattedTextField().addDocumentListener(this );
239: if (isUpdatePossible() && date != null)
240: update(((CalendarCG) getCG()).getHiddenUpdate(this , date));
241: else
242: reload();
243: }
244:
245: /**
246: * Set the preferred size of the component
247: * @param dimension <code>SDimension</code>
248: */
249: public void setPreferredSize(SDimension dimension) {
250: super .setPreferredSize(dimension);
251: getFormattedTextField()
252: .setPreferredSize(
253: dimension != null
254: && dimension.getWidth() != null ? SDimension.FULLWIDTH
255: : null);
256: }
257:
258: /**
259: * Fire an <code>ActionEvent</code> at each registered listener.
260: *
261: * @param event supplied <code>ActionEvent</code>
262: */
263: protected void fireActionPerformed(ActionEvent event) {
264: // Guaranteed to return a non-null array
265: Object[] listeners = getListenerList();
266: ActionEvent e = null;
267: // Process the listeners last to first, notifying
268: // those that are interested in this event
269: for (int i = listeners.length - 2; i >= 0; i -= 2) {
270: if (listeners[i] == ActionListener.class) {
271: if (e == null) {
272: e = new ActionEvent(XCalendar.this ,
273: ActionEvent.ACTION_PERFORMED, "", event
274: .getWhen(), event.getModifiers());
275: }
276: ((ActionListener) listeners[i + 1]).actionPerformed(e);
277: }
278: }
279: }
280:
281: private void fireActionEvents() {
282: fireActionPerformed(new ActionEvent(this ,
283: ActionEvent.ACTION_PERFORMED, ""));
284: }
285:
286: /**
287: * Adds an action listener to the <code>XCalendar</code>
288: *
289: * @param listener the ActionListener to be added
290: */
291: public void addActionListener(ActionListener listener) {
292: addEventListener(ActionListener.class, listener);
293: if (getActionListeners().length > 0
294: && getFormattedTextField().getActionListeners().length == 0) {
295: getFormattedTextField().addActionListener(
296: getActionListener());
297: }
298: }
299:
300: /**
301: * Removes the supplied Listener from the listener list
302: * @param listener ActionListener
303: */
304: public void removeActionListener(ActionListener listener) {
305: removeEventListener(ActionListener.class, listener);
306: if (getActionListeners().length == 0) {
307: getFormattedTextField().removeActionListener(
308: getActionListener());
309: }
310: }
311:
312: /**
313: * Returns an array of all the <code>ActionListener</code>s added
314: * to this AbstractButton with addActionListener().
315: *
316: * @return all of the <code>ActionListener</code>s added or an empty
317: * array if no listeners have been added
318: */
319: public ActionListener[] getActionListeners() {
320: return (ActionListener[]) (getListeners(ActionListener.class));
321: }
322:
323: /**
324: * Returns the current <code>SFormattedTextField</code>.
325: * @return the current <code>SFormattedTextField</code>
326: */
327: public SFormattedTextField getFormattedTextField() {
328: if (fTextField == null) {
329: fTextField = new SFormattedTextField();
330: fTextField.getDocument().addDocumentListener(this );
331: }
332: return fTextField;
333: }
334:
335: public void setFocusTraversalIndex(int index) {
336: super .setFocusTraversalIndex(index);
337: getFormattedTextField().setFocusTraversalIndex(index);
338: }
339:
340: /**
341: * #####################
342: * # SDocumentListener #
343: * #####################
344: */
345: /**
346: * @see SDocumentListener#insertUpdate()
347: */
348: public void insertUpdate(SDocumentEvent e) {
349: }
350:
351: /**
352: * @see SDocumentListener#removeUpdate()
353: */
354: public void removeUpdate(SDocumentEvent e) {
355: }
356:
357: /**
358: * @see SDocumentListener#changedUpdate()
359: */
360: public void changedUpdate(SDocumentEvent e) {
361: setDate((Date) getFormattedTextField().getValue());
362: }
363:
364: /**
365: * #########################
366: * # LowLevelEventListener #
367: * #########################
368: */
369:
370: /**
371: * @see LowLevelEventListener#isEpochCheckEnabled()
372: */
373: public boolean isEpochCheckEnabled() {
374: return epochCheckEnabled;
375: }
376:
377: /**
378: * @see LowLevelEventListener#setEpochCheckEnabled()
379: */
380: public void setEpochCheckEnabled(boolean epochCheckEnabled) {
381: this .epochCheckEnabled = epochCheckEnabled;
382: }
383:
384: /**
385: * @see LowLevelEventListener#fireIntermediateEvents()
386: */
387: public void fireIntermediateEvents() {
388: }
389:
390: /**
391: * @see LowLevelEventListener#processLowLevelEvent(String action, String[] values)
392: */
393: public void processLowLevelEvent(String action, String[] values) {
394: processKeyEvents(values);
395: if (action.endsWith("_keystroke"))
396: return;
397:
398: SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");
399: dateFormat.setTimeZone(getTimeZone());
400:
401: try {
402: setDate(dateFormat.parse(values[0]));
403: } catch (Exception e) {
404: getFormattedTextField()
405: .processLowLevelEvent(action, values);
406: }
407:
408: fireActionEvents();
409:
410: }
411:
412: }
|