KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jdesktop > swing > JXDatePicker


1 /*
2  * $Id: JXDatePicker.java,v 1.6 2004/09/24 23:54:31 dmouse Exp $
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7 package org.jdesktop.swing;
8
9 import java.awt.*;
10 import java.awt.event.*;
11 import java.text.ParseException JavaDoc;
12 import java.text.SimpleDateFormat JavaDoc;
13 import java.util.Date JavaDoc;
14 import javax.swing.*;
15 import javax.swing.JFormattedTextField.AbstractFormatterFactory;
16 import javax.swing.border.*;
17 import org.jdesktop.swing.calendar.*;
18
19 /**
20  * A component that combines a button, an editable field and a JXMonthView
21  * component. The user can select a date from the calendar component, which
22  * appears when the button is pressed. The selection from the calendar
23  * component will be displayed in editable field. Values may also be modified
24  * manually by entering a date into the editable field using one of the
25  * supported date formats.
26  *
27  * @author Joshua Outwater
28  */

29 public class JXDatePicker extends JComponent {
30     /** The editable date field that displays the date */
31     protected JFormattedTextField _dateField;
32     /**
33      * Popup that displays the month view with controls for
34      * traversing/selecting dates.
35      */

36     protected JXDatePickerPopup _popup;
37     private JButton _popupButton;
38     private int _popupButtonWidth = 20;
39     private JXMonthView _monthView;
40     private Handler _handler;
41     private String JavaDoc _actionCommand = "selectionChanged";
42
43     /**
44      * Create a new date picker using the current date as the initial
45      * selection.
46      */

47     public JXDatePicker() {
48         this(System.currentTimeMillis());
49     }
50
51     /**
52      * Create a new date picker using the specified time as the initial
53      * seleciton.
54      *
55      * @param millis initial time in milliseconds
56      */

57     public JXDatePicker(long millis) {
58         _dateField = new JFormattedTextField(
59             new JXDatePickerFormatterFactory());
60         _dateField.setName("dateField");
61         _dateField.setBorder(null);
62
63         _handler = new Handler();
64         _popupButton = new JButton();
65         _popupButton.setName("popupButton");
66         _popupButton.setRolloverEnabled(false);
67         _popupButton.addMouseListener(_handler);
68         _popupButton.addMouseMotionListener(_handler);
69
70         KeyStroke enterKey =
71             KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false);
72
73         InputMap inputMap = _dateField.getInputMap(JComponent.WHEN_FOCUSED);
74         inputMap.put(enterKey, "COMMIT_EDIT");
75
76         ActionMap actionMap = _dateField.getActionMap();
77         actionMap.put("COMMIT_EDIT", new CommitEditAction());
78
79         KeyStroke spaceKey =
80             KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, false);
81
82         inputMap = _popupButton.getInputMap(JComponent.WHEN_FOCUSED);
83         inputMap.put(spaceKey, "TOGGLE_POPUP");
84
85         actionMap = _popupButton.getActionMap();
86         actionMap.put("TOGGLE_POPUP", new TogglePopupAction());
87
88         add(_dateField);
89         add(_popupButton);
90
91         updateUI();
92
93         _dateField.setValue(new Date JavaDoc(millis));
94     }
95
96     /**
97      * Resets the UI property to a value from the current look and feel.
98      */

99     public void updateUI() {
100         int cols = UIManager.getInt("JXDatePicker.numColumns");
101         if (cols == -1) {
102             cols = 10;
103         }
104         _dateField.setColumns(cols);
105
106         String JavaDoc str = UIManager.getString("JXDatePicker.arrowDown.tooltip");
107         if (str == null) {
108             str = "Show Calendar";
109         }
110         _popupButton.setToolTipText(str);
111
112         Icon icon = UIManager.getIcon("JXDatePicker.arrowDown.image");
113         if (icon == null) {
114             icon = new ImageIcon(getClass().getResource(
115                     "/toolbarButtonGraphics/navigation/Down24.gif"));
116         }
117         _popupButton.setIcon(icon);
118
119         Border border = UIManager.getBorder("JXDatePicker.border");
120         if (border == null) {
121             border = BorderFactory.createCompoundBorder(
122                     LineBorder.createGrayLineBorder(),
123                     BorderFactory.createEmptyBorder(3, 3, 3, 3));
124         }
125         _dateField.setBorder(border);
126     }
127
128     /**
129      * Set the currently selected date.
130      *
131      * @param date date
132      */

133     public void setDate(Date JavaDoc date) {
134         _dateField.setValue(date);
135     }
136
137     /**
138      * Set the currently selected date.
139      *
140      * @param millis milliseconds
141      */

142     public void setDateInMillis(long millis) {
143         _dateField.setValue(new Date JavaDoc(millis));
144     }
145
146     /**
147      * Returns the currently selected date.
148      *
149      * @return Date
150      */

151     public Date JavaDoc getDate() {
152         return (Date JavaDoc)_dateField.getValue();
153     }
154
155     /**
156      * Returns the currently selected date in milliseconds.
157      *
158      * @return the date in milliseconds
159      */

160     public long getDateInMillis() {
161         return ((Date JavaDoc)_dateField.getValue()).getTime();
162     }
163
164     /**
165      * Returns the formatted text field used to edit the date selection.
166      *
167      * @return the formatted text field
168      */

169     public JFormattedTextField getEditor() {
170         return _dateField;
171     }
172
173     /**
174      * Return the AbstractFormatterFactory for this instance of the
175      * JXDatePicker.
176      *
177      * @return the AbstractFormatterFactory
178      */

179     public AbstractFormatterFactory getDateFormatterFactory() {
180         return _dateField.getFormatterFactory();
181     }
182
183     /**
184      * Set the AbstractFormatterFactory to be used by this instance of the
185      * JXDatePicker.
186      *
187      * @param dateFormatterFactory the AbstractFormatterFactory
188      */

189     public void setDateFormatterFactory(
190             AbstractFormatterFactory dateFormatterFactory) {
191         _dateField.setFormatterFactory(dateFormatterFactory);
192     }
193
194     /**
195      * Returns true if the current value being edited is valid.
196      *
197      * @return true if the current value being edited is valid.
198      */

199     public boolean isEditValid() {
200         return _dateField.isEditValid();
201     }
202
203     /**
204      * Forces the current value to be taken from the AbstractFormatter and
205      * set as the current value. This has no effect if there is no current
206      * AbstractFormatter installed.
207      */

208     public void commitEdit() throws ParseException JavaDoc {
209         _dateField.commitEdit();
210     }
211
212     /**
213      * Enables or disables the date picker and all its subcomponents.
214      *
215      * @param value true to enable, false to disable
216      */

217     public void setEnabled(boolean value) {
218         if (isEnabled() == value) {
219             return;
220         }
221
222         super.setEnabled(value);
223         _dateField.setEnabled(value);
224         _popupButton.setEnabled(value);
225     }
226
227     /**
228      * Returns the string currently used to identiy fired ActionEvents.
229      *
230      * @return String The string used for identifying ActionEvents.
231      */

232     public String JavaDoc getActionCommand() {
233         return _actionCommand;
234     }
235
236     /**
237      * Sets the string used to identify fired ActionEvents.
238      *
239      * @param actionCommand The string used for identifying ActionEvents.
240      */

241     public void setActionCommand(String JavaDoc actionCommand) {
242         _actionCommand = actionCommand;
243     }
244
245     /**
246      * Adds an ActionListener.
247      * <p>
248      * The ActionListener will receive an ActionEvent when a selection has
249      * been made.
250      *
251      * @param l The ActionListener that is to be notified
252      */

253     public void addActionListener(ActionListener l) {
254         listenerList.add(ActionListener.class, l);
255     }
256
257     /**
258      * Removes an ActionListener.
259      *
260      * @param l The action listener to remove.
261      */

262     public void removeActionListener(ActionListener l) {
263         listenerList.remove(ActionListener.class, l);
264     }
265
266     /**
267      * Fires an ActionEvent to all listeners.
268      */

269     protected void fireActionPerformed() {
270         Object JavaDoc[] listeners = listenerList.getListenerList();
271         ActionEvent e = null;
272         for (int i = listeners.length - 2; i >= 0; i -=2) {
273             if (listeners[i] == ActionListener.class) {
274                 if (e == null) {
275                     e = new ActionEvent(JXDatePicker.this,
276                             ActionEvent.ACTION_PERFORMED,
277                             _actionCommand);
278                 }
279                 ((ActionListener)listeners[i + 1]).actionPerformed(e);
280             }
281         }
282     }
283
284     /**
285      * {@inheritDoc}
286      */

287     public void doLayout() {
288         int width = getWidth();
289         int height = getHeight();
290
291         Insets insets = getInsets();
292         _dateField.setBounds(insets.left,
293                 insets.bottom,
294                 width - _popupButtonWidth,
295                 height);
296         _popupButton.setBounds(width - _popupButtonWidth + insets.left,
297                 insets.bottom,
298                 _popupButtonWidth,
299                 height);
300     }
301
302     /**
303      * {@inheritDoc}
304      */

305     public Dimension getMinimumSize() {
306         return getPreferredSize();
307     }
308
309     /**
310      * {@inheritDoc}
311      */

312     public Dimension getPreferredSize() {
313         Dimension dim = _dateField.getPreferredSize();
314         dim.width += _popupButton.getPreferredSize().width;
315         Insets insets = getInsets();
316         dim.width += insets.left + insets.right;
317         dim.height += insets.top + insets.bottom;
318         return dim;
319     }
320
321     /**
322      * Action used to commit the current value in the JFormattedTextField.
323      * This action is used by the keyboard bindings.
324      */

325     private class TogglePopupAction extends AbstractAction {
326         public TogglePopupAction() {
327             super("TogglePopup");
328         }
329
330         public void actionPerformed(ActionEvent ev) {
331             _handler.toggleShowPopup();
332         }
333     }
334
335     /**
336      * Action used to commit the current value in the JFormattedTextField.
337      * This action is used by the keyboard bindings.
338      */

339     private class CommitEditAction extends AbstractAction {
340         public CommitEditAction() {
341             super("CommitEditPopup");
342         }
343
344         public void actionPerformed(ActionEvent ev) {
345             try {
346                 // Commit the current value.
347
_dateField.commitEdit();
348
349                 // Reformat the value according to the formatter.
350
_dateField.setValue(_dateField.getValue());
351                 fireActionPerformed();
352             } catch (java.text.ParseException JavaDoc ex) {
353             }
354         }
355     }
356
357     private class Handler implements MouseListener, MouseMotionListener {
358         private boolean _forwardReleaseEvent = false;
359
360         public void mouseClicked(MouseEvent ev) {
361         }
362
363         public void mousePressed(MouseEvent ev) {
364             if (!isEnabled()) {
365                 return;
366             }
367
368             if (_dateField.isEditValid()) {
369                 try {
370                     _dateField.commitEdit();
371                 } catch (java.text.ParseException JavaDoc ex) {
372                 }
373             }
374             toggleShowPopup();
375         }
376
377         public void mouseReleased(MouseEvent ev) {
378             // Retarget mouse event to the month view.
379
if (_forwardReleaseEvent) {
380                 ev = SwingUtilities.convertMouseEvent(_popupButton, ev,
381                         _monthView);
382                 _monthView.dispatchEvent(ev);
383                 _forwardReleaseEvent = false;
384             }
385         }
386
387         public void mouseEntered(MouseEvent ev) {
388         }
389
390         public void mouseExited(MouseEvent ev) {
391         }
392
393         public void mouseDragged(MouseEvent ev) {
394             _forwardReleaseEvent = true;
395
396             if (!_popup.isShowing()) {
397                 return;
398             }
399
400             // Retarget mouse event to the month view.
401
ev = SwingUtilities.convertMouseEvent(_popupButton, ev, _monthView);
402             _monthView.dispatchEvent(ev);
403         }
404
405         public void mouseMoved(MouseEvent ev) {
406         }
407
408         public void toggleShowPopup() {
409             if (_popup == null) {
410                 _popup = new JXDatePickerPopup();
411             }
412             if (!_popup.isVisible()) {
413                 if (_dateField.getValue() == null) {
414                     _dateField.setValue(new Date JavaDoc(System.currentTimeMillis()));
415                 }
416                 DateSpan span =
417                         new DateSpan((java.util.Date JavaDoc)_dateField.getValue(),
418                                 (java.util.Date JavaDoc)_dateField.getValue());
419                 _monthView.setSelectedDateSpan(span);
420                 _monthView.ensureDateVisible(
421                         ((Date JavaDoc)_dateField.getValue()).getTime());
422                 Point loc = _dateField.getLocationOnScreen();
423                 _popup.show(JXDatePicker.this,
424                         0, JXDatePicker.this.getHeight());
425             } else {
426                 _popup.setVisible(false);
427             }
428         }
429     }
430
431     /**
432      * Popup component that shows a JXMonthView component along with controlling
433      * buttons to allow traversal of the months. Upon selection of a date the
434      * popup will automatically hide itself and enter the selection into the
435      * editable field of the JXDatePicker.
436      */

437     private class JXDatePickerPopup extends JPopupMenu
438             implements ActionListener {
439         private JButton _nextButton;
440         private JButton _previousButton;
441         private JButton _todayButton;
442
443         public JXDatePickerPopup() {
444             _monthView = new JXMonthView();
445             _monthView.setActionCommand("MONTH_VIEW");
446             _monthView.addActionListener(this);
447
448             JPanel panel = new JPanel(new FlowLayout());
449             Icon icon = UIManager.getIcon("JXMonthView.monthUp.image");
450             if (icon == null) {
451                 icon = new ImageIcon(getClass().getResource(
452                         "/toolbarButtonGraphics/navigation/Up24.gif"));
453             }
454             _previousButton = new JButton(icon);
455             _previousButton.setActionCommand("PREVIOUS_MONTH");
456             _previousButton.addActionListener(this);
457
458             icon = UIManager.getIcon("JXMonthView.monthDown.image");
459             if (icon == null) {
460                 icon = new ImageIcon(getClass().getResource(
461                         "/toolbarButtonGraphics/navigation/Down24.gif"));
462             }
463             _nextButton = new JButton(icon);
464             _nextButton.setActionCommand("NEXT_MONTH");
465             _nextButton.addActionListener(this);
466
467             icon = UIManager.getIcon("JXMonthView.monthCurrent.image");
468             if (icon == null) {
469                 icon = new ImageIcon(getClass().getResource(
470                         "/toolbarButtonGraphics/media/Stop24.gif"));
471             }
472             _todayButton = new JButton(icon);
473             _todayButton.setActionCommand("TODAY");
474             _todayButton.addActionListener(this);
475
476             setLayout(new BorderLayout());
477             add(_monthView, BorderLayout.CENTER);
478
479             panel.add(_previousButton);
480             panel.add(_todayButton);
481             panel.add(_nextButton);
482             add(panel, BorderLayout.NORTH);
483         }
484
485         public void actionPerformed(ActionEvent ev) {
486             String JavaDoc command = ev.getActionCommand();
487             if ("MONTH_VIEW" == command) {
488                 DateSpan span = _monthView.getSelectedDateSpan();
489                 _dateField.setValue(span.getStartAsDate());
490                 _popup.setVisible(false);
491                 fireActionPerformed();
492             } else if ("PREVIOUS_MONTH" == command) {
493                 _monthView.setFirstDisplayedDate(DateUtils.getPreviousMonth(
494                               _monthView.getFirstDisplayedDate()));
495             } else if ("NEXT_MONTH" == command) {
496                 _monthView.setFirstDisplayedDate(DateUtils.getNextMonth(
497                                    _monthView.getFirstDisplayedDate()));
498             } else if ("TODAY" == command) {
499                 DateSpan span = new DateSpan(System.currentTimeMillis(),
500                     System.currentTimeMillis());
501                 _monthView.ensureDateVisible(span.getStart());
502             }
503         }
504     }
505 }
506
Popular Tags