View Javadoc

1   /*
2    *  File: DateChooser.java 
3    *  Copyright (c) 2004-2007  Peter Kliem (Peter.Kliem@jaret.de)
4    *  A commercial license is available, see http://www.jaret.de.
5    *
6    * All rights reserved. This program and the accompanying materials
7    * are made available under the terms of the Common Public License v1.0
8    * which accompanies this distribution, and is available at
9    * http://www.eclipse.org/legal/cpl-v10.html
10   */
11  package de.jaret.util.ui.datechooser;
12  
13  import java.text.DateFormat;
14  import java.text.ParseException;
15  import java.util.ArrayList;
16  import java.util.Calendar;
17  import java.util.Date;
18  import java.util.GregorianCalendar;
19  import java.util.List;
20  import java.util.Locale;
21  
22  import org.eclipse.swt.SWT;
23  import org.eclipse.swt.events.DisposeEvent;
24  import org.eclipse.swt.events.DisposeListener;
25  import org.eclipse.swt.events.FocusEvent;
26  import org.eclipse.swt.events.FocusListener;
27  import org.eclipse.swt.events.KeyAdapter;
28  import org.eclipse.swt.events.KeyEvent;
29  import org.eclipse.swt.events.SelectionAdapter;
30  import org.eclipse.swt.events.SelectionEvent;
31  import org.eclipse.swt.events.ShellAdapter;
32  import org.eclipse.swt.events.ShellEvent;
33  import org.eclipse.swt.graphics.Color;
34  import org.eclipse.swt.graphics.Point;
35  import org.eclipse.swt.layout.FillLayout;
36  import org.eclipse.swt.layout.GridData;
37  import org.eclipse.swt.layout.GridLayout;
38  import org.eclipse.swt.widgets.Button;
39  import org.eclipse.swt.widgets.Composite;
40  import org.eclipse.swt.widgets.Display;
41  import org.eclipse.swt.widgets.Event;
42  import org.eclipse.swt.widgets.Listener;
43  import org.eclipse.swt.widgets.Shell;
44  import org.eclipse.swt.widgets.Text;
45  
46  import de.jaret.util.date.JaretDate;
47  import de.jaret.util.date.holidayenumerator.HolidayEnumerator;
48  
49  /***
50   * A date field with an attached datechooser in a combobox style. The date chooser used is
51   * 
52   * @see de.jaret.swt.util.datechooser.DateChooserPanel. The popup is displayed using a shell. The creation of the shell
53   * and the chooserpanel is lazy. The control offers three strategies for dealing with unparsable input in the textfield:
54   * KEEP_AND_MARK: keep the unparsable input, do not modify the date value and mark the field. This is the default
55   * behaviour allowing the user to step back and correct the input without slowing down the input process.
56   * RESET_TO_LASTVALID: reset the input to the last valid date entered or given RESET_TO_NULL: reset the value to null
57   * 
58   * The DateFieldCombo features
59   * <ul>
60   * <li>selectable locale which is used for the determination of the first day of the week and the weekday/months
61   * abbreviations</li>
62   * <li>display of week of the year selectable</li>
63   * <li>keyboard control (cursor keys navigate in the day panel, SHIFT-Cursor-left/right navigate month, ESC cancels, t
64   * sets the date to the current date), ctrl-space will open dropdown, RETURN selects</li>
65   * <li>roll fields in the edited field with cursor up/down (if a FieldIdentfier is supplied)</li>
66   * <li>mousewheel on textfieled. roll field if field identifier is set and feature is enabled (default:true)</li>
67   * <li>mousewheel on panel. roll day; use shift+wheel to roll months</li>
68   * <li>optional a
69   * @see de.jaret.util.date.HolidayEnumerator can be set for highlighting holidays in the day panel</li>
70   * <li>can be wired with a time chooser to keep date and time in sync</li>
71   * </ul>
72   * 
73   * @author Peter Kliem
74   * @version $Id: DateChooser.java 871 2009-08-17 20:35:34Z kliem $
75   */
76  public class DateChooser extends Composite implements FocusListener, IDateChooserListener {
77      /*** Invalid input behaviour: keep the textual input and mark the field. */
78      public static final int KEEP_AND_MARK = 0;
79  
80      /*** Invalid input behaviour: reset the date to the last valid input. */
81      public static final int RESET_TO_LASTVALID = 1;
82  
83      /*** Invalid input behaviour: reset the date to <code>null</code>. */
84      public static final int RESET_TO_NULL = 2;
85  
86      /*** Color used to mark invalid input. */
87      public static final Color MARKER_COLOR = Display.getCurrent().getSystemColor(SWT.COLOR_RED);
88  
89      /*** divisor for the mousewheel ticks. */
90      protected static final int MOUSEWHEEL_DIVISOR = 3;
91  
92      /*** behaviour on invalid input. */
93      protected int _invalidInputBehaviour = KEEP_AND_MARK;
94  
95      /*** if true: editable. */
96      protected boolean _editable = true;
97  
98      /*** if true: enabled. */
99      private boolean _enabled = true;
100 
101     /*** if true: select all in textfield on focus gain. */
102     private boolean _selectAllOnFocusGained = true;
103 
104     /***
105      * If true mousewheel will roll in the textfield.
106      */
107     private boolean _textfieldMouseWheelEnable = true;
108 
109     /*** listener list of interestedlisteners. */
110     protected List<IDateChooserListener> _listenerList;
111 
112     /*** the date value manipulated by the control. */
113     protected Date _date = new Date();
114 
115     /*** dateformat used to format the date in the textfield. */
116     protected DateFormat _dateformat;
117 
118     /*** locale used by the control. */
119     protected Locale _locale;
120 
121     /*** text field widgets used. */
122     protected Text _textField;
123 
124     /*** dropdown button. */
125     protected Button _dropdownButton;
126 
127     /*** shell for the drop down. */
128     protected Shell _dropDownShell;
129 
130     /*** dropped state. */
131     protected boolean _dropped = false;
132 
133     /*** flag regeistering that drop down is about to happen. */
134     boolean _goingToDropDown = false;
135 
136     /*** DateChooserPanel in the dropdown. */
137     protected DateChooserPanel _chooserPanel;
138 
139     /*** Enumerator for identifying holidays. */
140     protected HolidayEnumerator _holidayEnumerator;
141 
142     /*** Provier for additional day information. */
143     protected IAdditionalDayInformationProvider _dayInformationProvider;
144 
145     /*** FieldIdentifier used for field rolling. */
146     protected IFieldIdentifier _fieldIdentifier;
147 
148     /*** initial bg color of the textfield. */
149     private Color _textfieldBGColor;
150 
151     /*** flag to help keeping focus listeners happy. */
152     private boolean _hasFocus = false;
153 
154     /*** timechooser to sync time of the handled date with. */
155     protected TimeChooser _timeChooser;
156 
157     /*** true if th einput is valid. */
158     protected boolean _hasValidInput = true;
159     
160     /***
161      * Constructor for the datefieldcombo.
162      * 
163      * @param parent Composite parent
164      * @param style style
165      * @param locale locale to be used
166      */
167     public DateChooser(Composite parent, int style, Locale locale) {
168         super(parent, style);
169         _locale = locale;
170         _dateformat = DateFormat.getDateInstance(DateFormat.MEDIUM, _locale);
171         _dateformat.setLenient(false);
172         createControls();
173         updateTextField(_date);
174 
175         addDisposeListener(new DisposeListener() {
176             public void widgetDisposed(DisposeEvent e) {
177                 onDispose();
178             }
179         });
180 
181     }
182 
183     /***
184      * Constructor using the default locale.
185      * 
186      * @param parent Composite parent
187      * @param style style
188      */
189     public DateChooser(Composite parent, int style) {
190         this(parent, style, Locale.getDefault());
191     }
192 
193     /***
194      * Retrieve the used dateformat.
195      * 
196      * @return the dateformat used to format and parse the date.
197      */
198     public DateFormat getDateFormat() {
199         return _dateformat;
200     }
201 
202     /***
203      * Set the dateformat used to parse and format the date in the text field. Default is the MEDIUM style DateInstance
204      * for the given locale.
205      * 
206      * @param dateformat dateformat to use.
207      */
208     public void setDateFormat(DateFormat dateformat) {
209         _dateformat = dateformat;
210         updateTextField(_date);
211     }
212 
213     /***
214      * create the controls (a text field and the drop down button).
215      */
216     private void createControls() {
217         GridLayout gridLayout = new GridLayout();
218         gridLayout.numColumns = 2;
219         gridLayout.horizontalSpacing = 0;
220         gridLayout.verticalSpacing = 0;
221         gridLayout.marginHeight = 0;
222         gridLayout.marginWidth = 0;
223         setLayout(gridLayout);
224 
225         _textField = new Text(this, SWT.BORDER | SWT.RIGHT);
226         GridData gd = new GridData(GridData.FILL_HORIZONTAL);
227         _textField.setLayoutData(gd);
228         // add this as Focuslistener to parse the date when loosing focus
229         _textField.addFocusListener(this);
230         // save the bg color for resetting mark
231         _textfieldBGColor = _textField.getBackground();
232 
233         // KeyListener to toggle drop down on ctrl-space
234         _textField.addKeyListener(new KeyAdapter() {
235             public void keyPressed(KeyEvent keyEvent) {
236                 if ((keyEvent.stateMask & SWT.CTRL) != 0 && keyEvent.keyCode == 32) {
237                     setDropped(!isDropped());
238                     keyEvent.doit = false;
239                 } else if (keyEvent.keyCode == SWT.CR) {
240                     // cr to leave the field
241                     _textField.traverse(SWT.TRAVERSE_TAB_NEXT);
242                 } else if (keyEvent.keyCode == SWT.ARROW_UP) {
243                     rollField(1);
244                     keyEvent.doit = false;
245                 } else if (keyEvent.keyCode == SWT.ARROW_DOWN) {
246                     rollField(-1);
247                     keyEvent.doit = false;
248                 }
249             }
250         });
251 
252         // mousewheel rolling of fields
253         Listener listener = new Listener() {
254 
255             public void handleEvent(Event event) {
256                 switch (event.type) {
257                 case SWT.MouseWheel:
258                     int count = -event.count / MOUSEWHEEL_DIVISOR;
259                     if (_textfieldMouseWheelEnable) {
260                         rollField(count);
261                     }
262                     break;
263                 default:
264                     throw new RuntimeException("unsupported event");
265 
266                 }
267             }
268         };
269 
270         addListener(SWT.MouseWheel, listener);
271 
272         _dropdownButton = new Button(this, SWT.ARROW | SWT.DOWN); // | (style & SWT.FLAT)
273         gd = new GridData();
274         _dropdownButton.setLayoutData(gd);
275         // SelectionListener for the dropdown button toggles dropdown state
276         _dropdownButton.addSelectionListener(new SelectionAdapter() {
277             public void widgetSelected(SelectionEvent arg0) {
278                 setDropped(!isDropped());
279             }
280         });
281 
282     }
283 
284     /***
285      * dispose has to take care of some additional disposals.
286      */
287     public void onDispose() {
288         if (_dropDownShell != null) {
289             _dropDownShell.dispose();
290         }
291     }
292 
293     /***
294      * Roll the field (if identifiable) by the given delta.
295      * 
296      * @param delta delta to roll the field
297      */
298     private void rollField(int delta) {
299         if (_fieldIdentifier != null) {
300             if (validateInput()) {
301                 // proceed only if the current input is valid
302                 int caretpos = _textField.getCaretPosition();
303                 int field = _fieldIdentifier.getField(_textField.getText(), caretpos);
304                 if (field != -1) {
305                     Calendar cal = new GregorianCalendar(_locale);
306                     cal.setTime(_date);
307                     cal.roll(field, delta);
308                     setDate(cal.getTime());
309                 }
310             }
311         }
312     }
313 
314     /***
315      * Check whether the drop down is dropped down.
316      * 
317      * @return true if the dropdow is dropped down
318      */
319     public boolean isDropped() {
320         return _dropped;
321     }
322 
323     /***
324      * Set the state of the dropdown.
325      * 
326      * @param dropped if true the dropdowbn will be displayed.
327      */
328     public void setDropped(boolean dropped) {
329         if (dropped != _dropped) {
330             _dropped = dropped;
331             if (_dropped && _editable && _enabled) {
332                 if (_dropDownShell == null) {
333                     _dropDownShell = createDropDown();
334                 }
335 
336                 _goingToDropDown = true;
337 
338                 _chooserPanel.setDate(getDate());
339                 Point size = _dropdownButton.getSize();
340                 Point dispLocation = toDisplay(_dropdownButton.getLocation());
341                 Point dropDownSize = _dropDownShell.computeSize(SWT.DEFAULT, SWT.DEFAULT);
342                 int dsWidth = dropDownSize.x;
343                 int dsHeight = dropDownSize.y;
344                 int locx = dispLocation.x + size.x - dsWidth;
345                 int locy = dispLocation.y + size.y + 3;
346                 // corrections if the display would not be complete
347                 // x
348                 // minX might be negative on multi-screen systems
349                 int minX = Display.getCurrent().getClientArea().x;
350                 if (locx < minX) {
351                        locx = minX;
352                 } else if (locx + dsWidth > Display.getCurrent().getBounds().width) {
353                        locx = Display.getCurrent().getBounds().width - dsWidth;
354                 }
355                 // On multi-screen systems ensure that the complete
356                 // DropDownShell is being displayed on one screen.
357                 // Prefer the right screen, because the dropdown-Button is on
358                 // the right of the widget.
359                 if (locx < 0 && locx > -dsWidth) {
360                        locx = 0;
361                 }
362 
363                 // y
364                 if (locy + dsHeight > Display.getCurrent().getBounds().height) {
365                     locy = dispLocation.y - dsHeight - 3;
366                 }
367 
368                 _dropDownShell.setLocation(locx, locy);
369                 _dropDownShell.setSize(dsWidth, dsHeight);
370                 _dropDownShell.pack();
371                 _dropDownShell.layout(true);
372 
373                 _dropDownShell.setVisible(true);
374                 _dropDownShell.setActive();
375                 _chooserPanel.forceFocus();
376                 resetMark(); // in case of an invalid input reset the amrk since the input continues
377             } else if (_dropDownShell != null) {
378                 _dropDownShell.setVisible(false);
379                 _goingToDropDown = false;
380                 _textField.setFocus();
381             }
382         }
383 
384     }
385 
386     /***
387      * Create the dropdown shell and the chooser panel.
388      * 
389      * @return the created Shell
390      */
391     private Shell createDropDown() {
392         Shell dropDown = new Shell(getShell(), SWT.NO_TRIM | SWT.BORDER);
393         dropDown.setLayout(new FillLayout());
394         _chooserPanel = new DateChooserPanel(dropDown, SWT.NULL | SWT.BORDER, false, true, _locale);
395         _chooserPanel.setDate(getDate());
396         _chooserPanel.addDateChooserListener(this);
397         _chooserPanel.setHolidayEnumerator(_holidayEnumerator);
398         _chooserPanel.setAdditionalDayInformationProvider(_dayInformationProvider);
399         _chooserPanel.setBackground(getBackground());
400 
401         _chooserPanel.addFocusListener(this);
402         /*
403          * The dropdown should be hidden if the focus gets assigned to any other component. This is accomplished by
404          * using a ShellListener and hide the dropdown on deactivation. The drawback of this mechanism is that the mouse
405          * event of the deactivation will get lost. This seems to be acceptable.
406          */
407         dropDown.addShellListener(new ShellAdapter() {
408             public void shellDeactivated(ShellEvent event) {
409                 setDropped(false);
410             }
411         });
412         return dropDown;
413     }
414 
415     /***
416      * Get the time part of a set time cchooder and set it to the date.
417      * 
418      * @param date date to correct
419      * @return corrected date (if a time choser is set)
420      */
421     private Date correctTime(Date date) {
422         if (_timeChooser != null) {
423             JaretDate d = new JaretDate(date);
424             JaretDate time = new JaretDate(_timeChooser.getDateInternal());
425             d.setHours(time.getHours());
426             d.setMinutes(time.getMinutes());
427             date = d.getDate();
428         }
429         return date;
430     }
431 
432     /***
433      * Retrieve the current selected date. Corrects the time from a time chooser if set.
434      * 
435      * @return Returns the date.
436      */
437     public Date getDate() {
438         _date = correctTime(_date);
439         return _date;
440     }
441 
442     /***
443      * Retrieve the current date without syncing with a time chooser.
444      * 
445      * @return current selected date
446      */
447     protected Date getDateInternal() {
448         return _date;
449     }
450 
451     /***
452      * Set the date.
453      * 
454      * @param date The date to set.
455      */
456     public void setDate(Date date) {
457         _date = date;
458         updateTextField(_date);
459     }
460 
461     /***
462      * Update the text in the textfield.
463      * 
464      * @param date date to update the field with
465      */
466     private void updateTextField(Date date) {
467         if (date != null) {
468             int caretpos = _textField.getCaretPosition(); // save caretpos
469             _textField.setText(_dateformat.format(date));
470             _textField.setSelection(caretpos, caretpos); // restore caretpos
471         } else {
472             _textField.setText("");
473         }
474     }
475 
476     /***
477      * Set the input in the textfield direct.
478      * 
479      * @param text new text of the textfield
480      */
481     public void setText(String text) {
482         _textField.setText(text);
483     }
484 
485     /***
486      * Select the text fields contents.
487      * 
488      */
489     public void selectAll() {
490         _textField.selectAll();
491     }
492 
493     /***
494      * Set the selection on the textfield.
495      * 
496      * @param pos position
497      */
498     public void setSelection(int pos) {
499         _textField.setSelection(pos);
500     }
501 
502     /***
503      * Clear selection on the textfield.
504      */
505     public void clearSelection() {
506         _textField.clearSelection();
507     }
508 
509     /***
510      * Cut operation of the textfield.
511      */
512     public void cut() {
513         _textField.cut();
514     }
515 
516     /***
517      * Copy operation of the textfield.
518      */
519     public void copy() {
520         _textField.copy();
521     }
522 
523     /***
524      * Paste operation of the textfield.
525      */
526     public void paste() {
527         _textField.paste();
528     }
529 
530     /***
531      * {@inheritDoc} The textfield will get the focus.
532      */
533     public boolean setFocus() {
534         super.setFocus();
535         return _textField.setFocus();
536     }
537 
538     /***
539      * {@inheritDoc} The textfield will get the focus.
540      */
541     public boolean forceFocus() {
542         return _textField.forceFocus();
543     }
544 
545     /***
546      * Access to the embedded textfield widget.
547      * 
548      * @return the textfield
549      */
550     public Text getTextField() {
551         return _textField;
552     }
553 
554     /***
555      * Retrieve he holiday enumerator used.
556      * 
557      * @return the holiday enumerator
558      */
559     public HolidayEnumerator getHolidayEnumerator() {
560         return _holidayEnumerator;
561     }
562 
563     /***
564      * Set a HolidayEnumerator for marking holidays in the day panel. A value of <code>null</code> is valid indicating
565      * no HolidayEnumerator to be used.
566      * 
567      * @param holidayEnumerator HolidayEnumerator to be used.
568      */
569     public void setHolidayEnumerator(HolidayEnumerator holidayEnumerator) {
570         _holidayEnumerator = holidayEnumerator;
571         if (_chooserPanel != null) {
572             _chooserPanel.setHolidayEnumerator(_holidayEnumerator);
573         }
574     }
575 
576     /***
577      * Retrieve the additional information provider.
578      * 
579      * @return the additional information provider
580      */
581     public IAdditionalDayInformationProvider getAdditionalDayInformationProvider() {
582         return _dayInformationProvider;
583     }
584 
585     /***
586      * Set an additional information provider for days.
587      * 
588      * @param dayInformationProvider the information provider
589      */
590     public void setAdditionalDayInformationProvider(IAdditionalDayInformationProvider dayInformationProvider) {
591         _dayInformationProvider = dayInformationProvider;
592         if (_chooserPanel != null) {
593             _chooserPanel.setAdditionalDayInformationProvider(dayInformationProvider);
594         }
595     }
596 
597     // DateChooserListener
598     /***
599      * {@inheritDoc} If a date has been chosen in the panel, close dropdaown, selection finished.
600      */
601     public void dateChosen(Date date) {
602         setDate(_chooserPanel.getDate());
603         setDropped(false);
604         fireDateChosen(correctTime(date));
605     }
606 
607     /***
608      * {@inheritDoc} Propagate cancelling.
609      */
610     public void choosingCanceled() {
611         updateTextField(_date);
612         setDropped(false);
613         fireChoosingCanceled();
614     }
615 
616     /***
617      * {@inheritDoc} Do an update on the textfield.
618      */
619     public void dateIntermediateChange(Date date) {
620         updateTextField(date);
621         fireIntermediateChange(correctTime(date));
622     }
623   
624     /***
625      * {@inheritDoc} Do nothing.
626      */
627     public void inputInvalid() {
628         // nothing to do: the panel will never fire an invalid event
629     }
630 
631     // End of DateChooser Listener
632 
633     // FocusListener
634     /***
635      * {@inheritDoc} On gaining focus on the textfield, select its content. If the datechooser does not already own the
636      * focus, notify other listeners.
637      */
638     public void focusGained(FocusEvent evt) {
639         // on gaining focus select the textfield contents if configured
640         if (evt.widget.equals(_textField) && _selectAllOnFocusGained) {
641             _textField.selectAll();
642         }
643         if (!_hasFocus) {
644             _hasFocus = true;
645             super.notifyListeners(SWT.FocusIn, new Event());
646         }
647     }
648 
649     /***
650      * {@inheritDoc} On loosing focus validate the input and check whether the focus will be going to the dropdown. In
651      * latter case do not notify other listeners.
652      */
653     public void focusLost(FocusEvent evt) {
654         // on loosing focus parse the text entered
655         validateInput();
656 
657         // check whether the click occured over the dropdown button and deduce this will not modify
658         // the focus state
659         if (Display.getCurrent().getCursorControl() == _dropdownButton) {
660             _goingToDropDown = true;
661         }
662 
663         if (_hasFocus && !_goingToDropDown) {
664             _hasFocus = false;
665             super.notifyListeners(SWT.FocusOut, new Event());
666         }
667 
668     }
669 
670     // End of FocusListener
671     /***
672      * Validate the input currently present in the textfield. Resets a mark if set and handles input behaviour for
673      * invalid inputs.
674      * 
675      * @return true if valid
676      */
677     public boolean validateInput() {
678         boolean valid = false;
679         String text = _textField.getText();
680         Date date = null;
681         try {
682             date = _dateformat.parse(text);
683             valid = true;
684         } catch (ParseException e) {
685             // nothing to do here
686         }
687         if (date != null) {
688             // parsing successful
689             setDate(date);
690             resetMark(); // in case a mark has been set
691             // fireDateChosen(date);
692         } else {
693             switch (_invalidInputBehaviour) {
694             case KEEP_AND_MARK:
695                 setMark();
696                 break;
697             case RESET_TO_LASTVALID:
698                 updateTextField(_date);
699                 break;
700             case RESET_TO_NULL:
701                 setDate(null);
702                 break;
703 
704             default:
705                 throw new RuntimeException("Invalid InputBehaviour set");
706             }
707         }
708         if (!valid && _hasValidInput) {
709             _hasValidInput = valid;
710             fireInputInvalid();
711         }
712         _hasValidInput = valid;
713         return valid;
714     }
715 
716     /***
717      * Reset the background color of the textfield.
718      */
719     private void resetMark() {
720         _textField.setBackground(_textfieldBGColor);
721     }
722 
723     /***
724      * Set the background color of the textfield to the marker color.
725      * 
726      */
727     private void setMark() {
728         _textField.setBackground(MARKER_COLOR);
729     }
730 
731     /***
732      * @return Returns the invalidInputBehaviour.
733      */
734     public int getInvalidInputBehaviour() {
735         return _invalidInputBehaviour;
736     }
737 
738     /***
739      * @param invalidInputBehaviour The invalidInputBehaviour to set.
740      */
741     public void setInvalidInputBehaviour(int invalidInputBehaviour) {
742         _invalidInputBehaviour = invalidInputBehaviour;
743     }
744 
745     /***
746      * @return Returns the editable state.
747      */
748     public boolean isEditable() {
749         return _editable;
750     }
751 
752     /***
753      * Set the editable state. If set to false the textfiled be set to editable(false) and the dropdown will be
754      * disabled.
755      * 
756      * @param editable The editable state to be set.
757      */
758     public void setEditable(boolean editable) {
759         _editable = editable;
760         _textField.setEditable(editable);
761         setDropped(false);
762     }
763 
764     /***
765      * @return the enabled state of the widget.
766      */
767     public boolean isEnabled() {
768         return _enabled;
769     }
770 
771     /***
772      * Set the enabled state of the widget.
773      * 
774      * @param enabled the enabled state to set
775      */
776     public void setEnabled(boolean enabled) {
777         super.setEnabled(enabled);
778         _enabled = enabled;
779         _textField.setEnabled(enabled);
780         _dropdownButton.setEnabled(enabled);
781         setDropped(false);
782     }
783 
784     /***
785      * Set the onClick property of the date chooser panel.
786      * 
787      * @param oneClick if set to true a single click will selct the date.
788      */
789     public void setOneClickSelection(boolean oneClick) {
790         // chooser panel need not to be instantiated by now
791         if (_dropDownShell == null) {
792             _dropDownShell = createDropDown();
793         }
794         _chooserPanel.setOneClickSelection(oneClick);
795     }
796 
797     /***
798      * Get the oneClick property of the date chooser panel.
799      * 
800      * @return true if a single click will select the date
801      */
802     public boolean isOneClickSelection() {
803         // chooser panel needs not to be instantiated by now
804         if (_dropDownShell == null) {
805             _dropDownShell = createDropDown();
806         }
807         return _chooserPanel.isOneClickSelection();
808     }
809 
810     /***
811      * Return the chooser panel used by the DateChooser.
812      * 
813      * @return DateChooserPanel used by the date chooser.
814      */
815     public DateChooserPanel getDateChooserPanel() {
816         // chooser panel need not to be instantiated by now
817         if (_dropDownShell == null) {
818             _dropDownShell = createDropDown();
819         }
820         return _chooserPanel;
821     }
822 
823     /***
824      * Add a DateChooserListener to be informed about changes.
825      * 
826      * @param listener the DateChooserListener to be added
827      */
828     public void addDateChooserListener(IDateChooserListener listener) {
829         if (_listenerList == null) {
830             _listenerList = new ArrayList<IDateChooserListener>();
831         }
832         _listenerList.add(listener);
833     }
834 
835     /***
836      * Remove a DateChooserListener.
837      * 
838      * @param listener the DateChooserListener to be removed
839      */
840     public void remDateChooserListener(IDateChooserListener listener) {
841         if (_listenerList == null) {
842             return;
843         }
844         _listenerList.remove(listener);
845     }
846 
847     /***
848      * Inform listeners that a date has been chosen.
849      * 
850      * @param date chosen date
851      */
852     protected void fireDateChosen(Date date) {
853         if (_listenerList != null) {
854             for (IDateChooserListener listener : _listenerList) {
855                 listener.dateChosen(date);
856             }
857         }
858     }
859 
860     /***
861      * Inform listeners about an intermediate change of the date.
862      * 
863      * @param date current date
864      */
865     protected void fireIntermediateChange(Date date) {
866         if (_listenerList != null) {
867             for (IDateChooserListener listener : _listenerList) {
868                 listener.dateIntermediateChange(date);
869             }
870         }
871     }
872 
873     /***
874      * Inform listeners that the choosing has been cancelled.
875      */
876     protected void fireChoosingCanceled() {
877         if (_listenerList != null) {
878             for (IDateChooserListener listener : _listenerList) {
879                 listener.choosingCanceled();
880             }
881         }
882     }
883 
884     /***
885      * Inform listeners that the current input has become invalid.
886      */
887     protected void fireInputInvalid() {
888         if (_listenerList != null) {
889             for (IDateChooserListener listener : _listenerList) {
890                 listener.inputInvalid();
891             }
892         }
893     }
894 
895     /***
896      * @return Returns the selectAllOnFocusGained.
897      */
898     public boolean isSelectAllOnFocusGained() {
899         return _selectAllOnFocusGained;
900     }
901 
902     /***
903      * @param selectAllOnFocusGained The selectAllOnFocusGained to set.
904      */
905     public void setSelectAllOnFocusGained(boolean selectAllOnFocusGained) {
906         _selectAllOnFocusGained = selectAllOnFocusGained;
907     }
908 
909     /***
910      * @return Returns the fieldIdentifier.
911      */
912     public IFieldIdentifier getFieldIdentifier() {
913         return _fieldIdentifier;
914     }
915 
916     /***
917      * @param fieldIdentifier The fieldIdentifier to set.
918      */
919     public void setFieldIdentifier(IFieldIdentifier fieldIdentifier) {
920         _fieldIdentifier = fieldIdentifier;
921     }
922 
923     /***
924      * Retrieve state of mousewheel support on textfield.
925      * 
926      * @return true if enabled
927      */
928     public boolean isTextfieldMouseWheelEnable() {
929         return _textfieldMouseWheelEnable;
930     }
931 
932     /***
933      * Enable/Disable mousewheel for rolling on text field. Default is true.
934      * 
935      * @param mouseWheelEnable true for enable
936      */
937     public void setTextfieldMouseWheelEnable(boolean mouseWheelEnable) {
938         _textfieldMouseWheelEnable = mouseWheelEnable;
939     }
940 
941     /***
942      * Get the timechooser set for time synchronization.
943      * 
944      * @return timechooser or <code>null</code>
945      */
946     public TimeChooser getTimeChooser() {
947         return _timeChooser;
948     }
949 
950     /***
951      * Set a timechoser to synchronize the time of the chosen date with.
952      * 
953      * @param timeChooser time chooser
954      */
955     public void setTimeChooser(TimeChooser timeChooser) {
956         _timeChooser = timeChooser;
957     }
958 
959 }