/*
* JMonthChooser.java - A bean for choosing a month
* Copyright (C) 2004 Kai Toedter
* kai@toedter.com
* www.toedter.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package com.toedter.calendar;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.text.DateFormatSymbols;
import java.util.Calendar;
import java.util.Locale;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
/**
* JMonthChooser is a bean for choosing a month.
*
* @author Kai Toedter
* @version $LastChangedRevision: 100 $
* @version $LastChangedDate: 2006-06-04 14:36:06 +0200 (So, 04 Jun 2006) $
*/
public class JMonthChooser extends JPanel implements ItemListener,
ChangeListener
{
private static final long serialVersionUID = -2028361332231218527L;
/** true, if the month chooser has a spinner component */
protected boolean hasSpinner;
private Locale locale;
private int month;
private int oldSpinnerValue = 0;
// needed for comparison
private JDayChooser dayChooser;
private JYearChooser yearChooser;
private JComboBox comboBox;
private JSpinner spinner;
private String[] monthNames = new String[] {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
private boolean initialized;
private boolean localInitialize;
/**
* Default JMonthChooser constructor.
*/
public JMonthChooser()
{
this (true);
}
/**
* JMonthChooser constructor with month spinner parameter.
*
* @param hasSpinner
* true, if the month chooser should have a spinner component
*/
public JMonthChooser(boolean hasSpinner)
{
super ();
setName ("JMonthChooser");
this.hasSpinner = hasSpinner;
setLayout (new BorderLayout ());
comboBox = new JComboBox ();
comboBox.addItemListener (this);
comboBox.setBackground (new Color (246, 245, 245));
// comboBox.addPopupMenuListener(this);
locale = Locale.getDefault ();
initNames ();
if (hasSpinner)
{
spinner = new JSpinner ()
{
private static final long serialVersionUID = 1L;
private JTextField textField = new JTextField ();
public Dimension getPreferredSize()
{
Dimension size = super.getPreferredSize ();
return new Dimension (size.width, textField.getPreferredSize ().height);
}
};
spinner.addChangeListener (this);
spinner.setEditor (comboBox);
comboBox.setBorder (new EmptyBorder (0, 0, 0, 0));
updateUI ();
add (spinner, BorderLayout.WEST);
}
else
{
add (comboBox, BorderLayout.WEST);
}
setOpaque (false);
initialized = true;
setMonth (Calendar.getInstance ().get (Calendar.MONTH), true);
}
/**
* Set the month names with the given month names list.
*
* @param monthNames The new month names to be set.
*/
public void setMonthNames(String[] monthNames)
{
this.monthNames = monthNames;
initNames ();
}
/**
* Initializes the locale specific month names.
*/
public void initNames()
{
localInitialize = true;
if (comboBox.getItemCount () == 12)
{
comboBox.removeAllItems ();
}
for (int i = 0; i < 12; i++)
{
comboBox.addItem (monthNames[i]);
}
localInitialize = false;
comboBox.setSelectedIndex (month);
}
/**
* Is invoked if the state of the spnner changes.
*
* @param e
* the change event.
*/
public void stateChanged(ChangeEvent e)
{
SpinnerNumberModel model = (SpinnerNumberModel) ((JSpinner) e.getSource ()).getModel ();
int value = model.getNumber ().intValue ();
boolean increase = (value > oldSpinnerValue) ? true : false;
oldSpinnerValue = value;
int month = getMonth ();
if (increase)
{
month += 1;
if (month == 12)
{
month = 0;
if (yearChooser != null)
{
int year = yearChooser.getYear ();
year += 1;
yearChooser.setYear (year);
}
}
}
else
{
month -= 1;
if (month == -1)
{
month = 11;
if (yearChooser != null)
{
int year = yearChooser.getYear ();
year -= 1;
yearChooser.setYear (year);
}
}
}
setMonth (month, true);
}
/**
* The ItemListener for the months.
*
* @param e
* the item event
*/
public void itemStateChanged(ItemEvent e)
{
if (e.getStateChange () == ItemEvent.SELECTED)
{
int index = comboBox.getSelectedIndex ();
if ((index >= 0) && (index != month))
{
setMonth (index, false);
}
}
}
/**
* Sets the month attribute of the JMonthChooser object. Fires a property
* change "month".
*
* @param newMonth
* the new month value
* @param select
* true, if the month should be selcted in the combo box.
*/
private void setMonth(int newMonth, boolean select)
{
if (!initialized || localInitialize)
{
return;
}
int oldMonth = month;
month = newMonth;
if (select)
{
comboBox.setSelectedIndex (month);
}
if (dayChooser != null)
{
dayChooser.setMonth (month);
}
firePropertyChange ("month", oldMonth, month);
}
/**
* Sets the month. This is a bound property. Value are valid between 0
* (January) and 11 (December). A value < 0 will be treated as 0, a value >
* 11 will be treated as 11.
*
* @param newMonth
* the new month value
*
* @see #getMonth
*/
public void setMonth(int newMonth)
{
if (newMonth < 0)
{
yearChooser.setYear (yearChooser.getYear () - 1);
setMonth (11, true);
}
else if (newMonth > 11)
{
yearChooser.setYear (yearChooser.getYear () + 1);
setMonth (0, true);
}
else
{
setMonth (newMonth, true);
}
}
/**
* Returns the month.
*
* @return the month value
*/
public int getMonth()
{
return month;
}
/**
* Convenience method set a day chooser.
*
* @param dayChooser
* the day chooser
*/
public void setDayChooser(JDayChooser dayChooser)
{
this.dayChooser = dayChooser;
}
/**
* Convenience method set a year chooser. If set, the spin for the month
* buttons will spin the year as well
*
* @param yearChooser
* the new yearChooser value
*/
public void setYearChooser(JYearChooser yearChooser)
{
this.yearChooser = yearChooser;
}
/**
* Returns the locale.
*
* @return the locale value
*
* @see #setLocale
*/
public Locale getLocale()
{
return locale;
}
/**
* Set the locale and initializes the new month names.
*
* @param l
* the new locale value
*
* @see #getLocale
*/
public void setLocale(Locale l)
{
if (!initialized)
{
super.setLocale (l);
}
else
{
locale = l;
initNames ();
}
}
/**
* Enable or disable the JMonthChooser.
*
* @param enabled
* the new enabled value
*/
public void setEnabled(boolean enabled)
{
super.setEnabled (enabled);
comboBox.setEnabled (enabled);
if (spinner != null)
{
spinner.setEnabled (enabled);
}
}
/**
* Returns the month chooser's comboBox text area (which allow the focus to
* be set to it).
*
* @return the combo box
*/
public JComboBox getComboBoxObj()
{
return comboBox;
}
/**
* Returns the month chooser's comboBox text area (which allow the focus to
* be set to it).
*
* @return the combo box
*/
public Component getComboBox()
{
return comboBox;
}
/**
* Returns the month chooser's comboBox bar (which allow the focus to be set
* to it).
*
* @return Component the spinner or null, if the month chooser has no
* spinner
*/
public Component getSpinner()
{
// Returns <null> if there is no spinner.
return spinner;
}
/**
* Returns the type of spinner the month chooser is using.
*
* @return true, if the month chooser has a spinner
*/
public boolean hasSpinner()
{
return hasSpinner;
}
/**
* Sets the font for this component.
*
* @param font the desired <code>Font</code> for this component
*/
public void setFont(Font font)
{
if (comboBox != null)
{
comboBox.setFont (font);
}
super.setFont (font);
}
/**
* Updates the UI.
*
* @see javax.swing.JPanel#updateUI()
*/
public void updateUI()
{
final JSpinner testSpinner = new JSpinner ();
if (spinner != null)
{
if ("Windows".equals (UIManager.getLookAndFeel ().getID ()))
{
spinner.setBorder (testSpinner.getBorder ());
}
else
{
spinner.setBorder (new EmptyBorder (0, 0, 0, 0));
}
}
}
}