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