View Javadoc
1   /*******************************************************************************
2    * JDateButton: Java Swing Date Button
3    * Copyright 2012,2014 Tony Washer
4    *
5    * Licensed under the Apache License, Version 2.0 (the "License");
6    * you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   * ------------------------------------------------------------
17   * SubVersion Revision Information:
18   * $URL: https://svn.code.sf.net/p/jdatebutton/code/tags/v2.1.0-b3/jdatebutton-swing/src/main/java/net/sourceforge/jdatebutton/swing/JDateButton.java $
19   * $Revision: 34 $
20   * $Author: tonywasher $
21   * $Date: 2015-12-01 16:21:13 +0000 (Tue, 01 Dec 2015) $
22   ******************************************************************************/
23  package net.sourceforge.jdatebutton.swing;
24  
25  import java.awt.Dimension;
26  import java.awt.Insets;
27  import java.awt.Point;
28  import java.awt.event.ActionEvent;
29  import java.awt.event.ActionListener;
30  import java.time.LocalDate;
31  import java.util.Locale;
32  
33  import javax.swing.JButton;
34  
35  import net.sourceforge.jdatebutton.JDateBaseButton;
36  import net.sourceforge.jdatebutton.JDateFormatter;
37  
38  /**
39   * <p>
40   * Provides a button which displays the currently selected {@link LocalDate}.
41   * <p>
42   * When clicked the button displays a mode-less {@link JDateDialog} enabling date selection This
43   * dialog will be closed if focus is lost or escape is pressed
44   * <p>
45   * An underlying {@link JDateConfig} is used to control locale, format and select-able range, and to
46   * directly set the selected date. Changes to the selected date are reported via a
47   * {@link java.beans.PropertyChangeEvent} for the {@link #PROPERTY_DATE} property, and may be
48   * monitored by attaching a {@link java.beans.PropertyChangeListener}
49   * @author Tony Washer
50   */
51  public class JDateButton
52          extends JButton
53          implements JDateBaseButton {
54      /**
55       * Serial Id.
56       */
57      private static final long serialVersionUID = 7110911129423423705L;
58  
59      /**
60       * Name of the Date property.
61       */
62      public static final String PROPERTY_DATE = "SelectedDate";
63  
64      /**
65       * Preferred Width.
66       */
67      public static final int PREFERRED_WIDTH = 100;
68  
69      /**
70       * Preferred Height.
71       */
72      public static final int PREFERRED_HEIGHT = 25;
73  
74      /**
75       * The Underlying Date Configuration.
76       */
77      private final transient JDateConfig theConfig;
78  
79      /**
80       * The dialog.
81       */
82      private final JDateDialog theDialog;
83  
84      /**
85       * Constructor.
86       */
87      public JDateButton() {
88          /* Create a button with a standard configuration */
89          this(new JDateConfig());
90      }
91  
92      /**
93       * Constructor.
94       * @param pFormatter the Date formatter
95       */
96      public JDateButton(final JDateFormatter pFormatter) {
97          /* Create a button with a standard configuration */
98          this(new JDateConfig(pFormatter));
99      }
100 
101     /**
102      * Constructor for extension classes.
103      * @param pConfig the configuration to use
104      */
105     public JDateButton(final JDateConfig pConfig) {
106         /* Store configuration and create the Dialog */
107         theConfig = pConfig;
108 
109         /* Create the dialog */
110         theDialog = new JDateDialog(this, theConfig);
111 
112         /* Register this button as the configuration owner */
113         theConfig.setOwner(this);
114 
115         /* Configure the button */
116         addActionListener(new ButtonListener());
117         setMargin(new Insets(1, 1, 1, 1));
118         setPreferredSize(new Dimension(PREFERRED_WIDTH, PREFERRED_HEIGHT));
119     }
120 
121     @Override
122     public JDateConfig getDateConfig() {
123         return theConfig;
124     }
125 
126     /**
127      * Obtain the dialog.
128      * @return the dialog
129      */
130     public JDateDialog getDialog() {
131         return theDialog;
132     }
133 
134     /**
135      * Obtain SelectedDate.
136      * @return the selected date
137      */
138     public LocalDate getSelectedDate() {
139         return theConfig.getSelectedDate();
140     }
141 
142     /**
143      * Set SelectedDate.
144      * @param pDate the selected date
145      */
146     public void setSelectedDate(final LocalDate pDate) {
147         theConfig.setSelectedDate(pDate);
148     }
149 
150     @Override
151     public void setLocale(final Locale pLocale) {
152         /* Record the locale */
153         theConfig.setLocale(pLocale);
154 
155         /* Pass the call onwards */
156         super.setLocale(pLocale);
157     }
158 
159     /**
160      * Set the date format.
161      * @param pFormat the format string
162      */
163     public void setFormat(final String pFormat) {
164         theConfig.setFormat(pFormat);
165     }
166 
167     /**
168      * Set formatter.
169      * @param pFormatter the formatter
170      */
171     public void setFormatter(final JDateFormatter pFormatter) {
172         theConfig.setFormatter(pFormatter);
173     }
174 
175     /**
176      * Set the earliest date. This is the earliest date that may be selected. If the configured
177      * latest date is earlier than this date, it will be set to this date to ensure a valid range.
178      * @param pEarliest the Earliest select-able date (or null if unlimited)
179      */
180     public void setEarliestDate(final LocalDate pEarliest) {
181         theConfig.setEarliestDate(pEarliest);
182     }
183 
184     /**
185      * Set the latest date. This is the latest date that may be selected. If the configured earliest
186      * date is later than this date, it will be set to this date to ensure a valid range.
187      * @param pLatest the Latest select-able date (or null if unlimited)
188      */
189     public void setLatestDate(final LocalDate pLatest) {
190         theConfig.setLatestDate(pLatest);
191     }
192 
193     /**
194      * Allow null date selection. If this flag is set an additional button will be displayed
195      * allowing the user to explicitly select no date, thus setting the SelectedDate to null.
196      * @param pAllowNullDateSelection true/false
197      */
198     public void setAllowNullDateSelection(final boolean pAllowNullDateSelection) {
199         theConfig.setAllowNullDateSelection(pAllowNullDateSelection);
200     }
201 
202     @Override
203     public void refreshText() {
204         setText(theConfig.formatDate(theConfig.getSelectedDate()));
205     }
206 
207     /**
208      * Fire date property change.
209      * @param pOldValue the old value
210      * @param pNewValue the new value
211      */
212     protected void fireDatePropertyChange(final LocalDate pOldValue,
213                                           final LocalDate pNewValue) {
214         /* Fire the property change */
215         firePropertyChange(PROPERTY_DATE, pOldValue, pNewValue);
216     }
217 
218     @Override
219     public void reBuildNames() {
220         theDialog.doBuildNames();
221     }
222 
223     /**
224      * Listener class.
225      */
226     private final class ButtonListener
227             implements ActionListener {
228         @Override
229         public void actionPerformed(final ActionEvent e) {
230             /* Position the dialog just below the button */
231             Point myLoc = getLocationOnScreen();
232             theDialog.setLocation(myLoc.x, myLoc.y
233                                            + getHeight());
234 
235             /* Show the dialog */
236             theDialog.setVisible(true);
237         }
238     }
239 }