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 }