001 /*
002 * This file is part of McIDAS-V
003 *
004 * Copyright 2007-2013
005 * Space Science and Engineering Center (SSEC)
006 * University of Wisconsin - Madison
007 * 1225 W. Dayton Street, Madison, WI 53706, USA
008 * https://www.ssec.wisc.edu/mcidas
009 *
010 * All Rights Reserved
011 *
012 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
013 * some McIDAS-V source code is based on IDV and VisAD source code.
014 *
015 * McIDAS-V is free software; you can redistribute it and/or modify
016 * it under the terms of the GNU Lesser Public License as published by
017 * the Free Software Foundation; either version 3 of the License, or
018 * (at your option) any later version.
019 *
020 * McIDAS-V is distributed in the hope that it will be useful,
021 * but WITHOUT ANY WARRANTY; without even the implied warranty of
022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
023 * GNU Lesser Public License for more details.
024 *
025 * You should have received a copy of the GNU Lesser Public License
026 * along with this program. If not, see http://www.gnu.org/licenses.
027 */
028 package edu.wisc.ssec.mcidasv.data.dateChooser;
029
030 import java.awt.BorderLayout;
031 import java.awt.Component;
032 import java.awt.Dimension;
033 import java.awt.Font;
034 import java.awt.event.ItemEvent;
035 import java.awt.event.ItemListener;
036 import java.text.DateFormatSymbols;
037 import java.util.Calendar;
038 import java.util.Locale;
039
040 import javax.swing.JComboBox;
041 import javax.swing.JFrame;
042 import javax.swing.JPanel;
043 import javax.swing.JSpinner;
044 import javax.swing.JTextField;
045 import javax.swing.SpinnerNumberModel;
046 import javax.swing.UIManager;
047 import javax.swing.border.EmptyBorder;
048 import javax.swing.event.ChangeEvent;
049 import javax.swing.event.ChangeListener;
050
051 /**
052 * JMonthChooser is a bean for choosing a month.
053 *
054 * @author Kai Toedter
055 * @version $LastChangedRevision: 100 $
056 * @version $LastChangedDate: 2006-06-04 14:36:06 +0200 (So, 04 Jun 2006) $
057 */
058 public class JMonthChooser extends JPanel implements ItemListener,
059 ChangeListener {
060 private static final long serialVersionUID = -2028361332231218527L;
061
062 /** true, if the month chooser has a spinner component */
063 protected boolean hasSpinner;
064
065 private Locale locale;
066
067 private int month;
068
069 private int oldSpinnerValue = 0;
070
071 // needed for comparison
072 private JDayChooser dayChooser;
073
074 private JYearChooser yearChooser;
075
076 private JComboBox comboBox;
077
078 private JSpinner spinner;
079
080 private boolean initialized;
081
082 private boolean localInitialize;
083
084 /**
085 * Default JMonthChooser constructor.
086 */
087 public JMonthChooser() {
088 this(true);
089 }
090
091 /**
092 * JMonthChooser constructor with month spinner parameter.
093 *
094 * @param hasSpinner
095 * true, if the month chooser should have a spinner component
096 */
097 public JMonthChooser(boolean hasSpinner) {
098 super();
099 setName("JMonthChooser");
100 this.hasSpinner = hasSpinner;
101
102 setLayout(new BorderLayout());
103
104 comboBox = new JComboBox();
105 comboBox.addItemListener(this);
106
107 // comboBox.addPopupMenuListener(this);
108 locale = Locale.getDefault();
109 initNames();
110
111 if (hasSpinner) {
112 spinner = new JSpinner() {
113 private static final long serialVersionUID = 1L;
114
115 private JTextField textField = new JTextField();
116
117 public Dimension getPreferredSize() {
118 Dimension size = super.getPreferredSize();
119 return new Dimension(size.width, textField
120 .getPreferredSize().height);
121 }
122 };
123 spinner.addChangeListener(this);
124 spinner.setEditor(comboBox);
125 comboBox.setBorder(new EmptyBorder(0, 0, 0, 0));
126 updateUI();
127
128 add(spinner, BorderLayout.WEST);
129 } else {
130 add(comboBox, BorderLayout.WEST);
131 }
132
133 initialized = true;
134 setMonth(Calendar.getInstance().get(Calendar.MONTH));
135 }
136
137 /**
138 * Initializes the locale specific month names.
139 */
140 public void initNames() {
141 localInitialize = true;
142
143 DateFormatSymbols dateFormatSymbols = new DateFormatSymbols(locale);
144 String[] monthNames = dateFormatSymbols.getMonths();
145
146 if (comboBox.getItemCount() == 12) {
147 comboBox.removeAllItems();
148 }
149
150 for (int i = 0; i < 12; i++) {
151 comboBox.addItem(monthNames[i]);
152 }
153
154 localInitialize = false;
155 comboBox.setSelectedIndex(month);
156 }
157
158 /**
159 * Is invoked if the state of the spnner changes.
160 *
161 * @param e
162 * the change event.
163 */
164 public void stateChanged(ChangeEvent e) {
165 SpinnerNumberModel model = (SpinnerNumberModel) ((JSpinner) e
166 .getSource()).getModel();
167 int value = model.getNumber().intValue();
168 boolean increase = (value > oldSpinnerValue) ? true : false;
169 oldSpinnerValue = value;
170
171 int month = getMonth();
172
173 if (increase) {
174 month += 1;
175
176 if (month == 12) {
177 month = 0;
178
179 if (yearChooser != null) {
180 int year = yearChooser.getYear();
181 year += 1;
182 yearChooser.setYear(year);
183 }
184 }
185 } else {
186 month -= 1;
187
188 if (month == -1) {
189 month = 11;
190
191 if (yearChooser != null) {
192 int year = yearChooser.getYear();
193 year -= 1;
194 yearChooser.setYear(year);
195 }
196 }
197 }
198
199 setMonth(month);
200 }
201
202 /**
203 * The ItemListener for the months.
204 *
205 * @param e
206 * the item event
207 */
208 public void itemStateChanged(ItemEvent e) {
209 if (e.getStateChange() == ItemEvent.SELECTED) {
210 int index = comboBox.getSelectedIndex();
211
212 if ((index >= 0) && (index != month)) {
213 setMonth(index, false);
214 }
215 }
216 }
217
218 /**
219 * Sets the month attribute of the JMonthChooser object. Fires a property
220 * change "month".
221 *
222 * @param newMonth
223 * the new month value
224 * @param select
225 * true, if the month should be selcted in the combo box.
226 */
227 private void setMonth(int newMonth, boolean select) {
228 if (!initialized || localInitialize) {
229 return;
230 }
231
232 int oldMonth = month;
233 month = newMonth;
234
235 if (select) {
236 comboBox.setSelectedIndex(month);
237 }
238
239 if (dayChooser != null) {
240 dayChooser.setMonth(month);
241 }
242
243 firePropertyChange("month", oldMonth, month);
244 }
245
246 /**
247 * Sets the month. This is a bound property. Valuse are valid between 0
248 * (January) and 11 (December). A value < 0 will be treated as 0, a value >
249 * 11 will be treated as 11.
250 *
251 * @param newMonth
252 * the new month value
253 *
254 * @see #getMonth
255 */
256 public void setMonth(int newMonth) {
257 if (newMonth < 0 || newMonth == Integer.MIN_VALUE) {
258 setMonth(0, true);
259 } else if (newMonth > 11) {
260 setMonth(11, true);
261 } else {
262 setMonth(newMonth, true);
263 }
264 }
265
266 /**
267 * Returns the month.
268 *
269 * @return the month value
270 */
271 public int getMonth() {
272 return month;
273 }
274
275 /**
276 * Convenience method set a day chooser.
277 *
278 * @param dayChooser
279 * the day chooser
280 */
281 public void setDayChooser(JDayChooser dayChooser) {
282 this.dayChooser = dayChooser;
283 }
284
285 /**
286 * Convenience method set a year chooser. If set, the spin for the month
287 * buttons will spin the year as well
288 *
289 * @param yearChooser
290 * the new yearChooser value
291 */
292 public void setYearChooser(JYearChooser yearChooser) {
293 this.yearChooser = yearChooser;
294 }
295
296 /**
297 * Returns the locale.
298 *
299 * @return the locale value
300 *
301 * @see #setLocale
302 */
303 public Locale getLocale() {
304 return locale;
305 }
306
307 /**
308 * Set the locale and initializes the new month names.
309 *
310 * @param l
311 * the new locale value
312 *
313 * @see #getLocale
314 */
315 public void setLocale(Locale l) {
316 if (!initialized) {
317 super.setLocale(l);
318 } else {
319 locale = l;
320 initNames();
321 }
322 }
323
324 /**
325 * Enable or disable the JMonthChooser.
326 *
327 * @param enabled
328 * the new enabled value
329 */
330 public void setEnabled(boolean enabled) {
331 super.setEnabled(enabled);
332 comboBox.setEnabled(enabled);
333
334 if (spinner != null) {
335 spinner.setEnabled(enabled);
336 }
337 }
338
339 /**
340 * Returns the month chooser's comboBox text area (which allow the focus to
341 * be set to it).
342 *
343 * @return the combo box
344 */
345 public Component getComboBox() {
346 return this.comboBox;
347 }
348
349 /**
350 * Returns the month chooser's comboBox bar (which allow the focus to be set
351 * to it).
352 *
353 * @return Component the spinner or null, if the month chooser has no
354 * spinner
355 */
356 public Component getSpinner() {
357 // Returns <null> if there is no spinner.
358 return spinner;
359 }
360
361 /**
362 * Returns the type of spinner the month chooser is using.
363 *
364 * @return true, if the month chooser has a spinner
365 */
366 public boolean hasSpinner() {
367 return hasSpinner;
368 }
369
370 /**
371 * Sets the font for this component.
372 *
373 * @param font the desired <code>Font</code> for this component
374 */
375 public void setFont(Font font) {
376 if (comboBox != null) {
377 comboBox.setFont(font);
378 }
379 super.setFont(font);
380 }
381
382 /**
383 * Updates the UI.
384 *
385 * @see javax.swing.JPanel#updateUI()
386 */
387 public void updateUI() {
388 final JSpinner testSpinner = new JSpinner();
389 if (spinner != null) {
390 if ("Windows".equals(UIManager.getLookAndFeel().getID())) {
391 spinner.setBorder(testSpinner.getBorder());
392 } else {
393 spinner.setBorder(new EmptyBorder(0, 0, 0, 0));
394 }
395 }
396 }
397
398 /**
399 * Creates a JFrame with a JMonthChooser inside and can be used for testing.
400 *
401 * @param s
402 * The command line arguments
403 */
404 public static void main(String[] s) {
405 JFrame frame = new JFrame("MonthChooser");
406 frame.getContentPane().add(new JMonthChooser());
407 frame.pack();
408 frame.setVisible(true);
409 }
410 }