/*
* JYearChooser.java - A bean for choosing a year
* Copyright (C) 2004 Kai Toedter
* [email protected]
* 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.myapp.util.swing.datechooser;
/**
* JYearChooser is a bean for choosing a year.
*
* @author Kai Toedter
* @version 1.2
*/
@SuppressWarnings("serial") public class JYearChooser extends JSpinField { protected JDayChooser dayChooser; protected int startYear; protected int endYear;
/**
* Sets the year. This is a bound property.
*
* @param y
* the new year
*
* @see #getYear
*/ public void setYear(int y) { int oldYear = getValue(); super.setValue(y, true, false);
if (dayChooser != null) {
dayChooser.setYear(value);
}
/**
* Sets the year value.
*
* @param value
* the year value
*/ public void setValue(int value) {
setYear(value);
}
/**
* Returns the year.
*
* @return the year
*/ public int getYear() { return super.getValue();
}
/**
* Convenience method set a day chooser that might be updated directly.
*
* @param dayChooser
* the day chooser
*/ public void setDayChooser(JDayChooser dayChooser) { this.dayChooser = dayChooser;
}
/**
* Returns "JYearChooser".
*
* @return the name value
*/ public String getName() { return "JYearChooser";
}
/**
* Returns the endy ear.
*
* @return the end year
*/ public int getEndYear() { return getMaximum();
}
/**
* Sets the end ear.
*
* @param endYear
* the end year
*/ public void setEndYear(int endYear) {
setMaximum(endYear);
}
/**
* Returns the start year.
*
* @return the start year.
*/ public int getStartYear() { return getMinimum();
}
/**
* Sets the start year.
*
* @param startYear
* the start year
*/ public void setStartYear(int startYear) {
setMinimum(startYear);
}
/**
* Creates a JFrame with a JYearChooser inside and can be used for testing.
*
* @param s
* command line arguments
*/ static public void main(String[] s) {
JFrame frame = new JFrame("JYearChooser");
frame.getContentPane().add(new JYearChooser());
frame.pack();
frame.setVisible(true);
}
}
/*
* JSpinField.java - A spin field using a JSpinner (JDK 1.4)
* Copyright (C) 2004 Kai Toedter
* [email protected]
* 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.myapp.util.swing.datechooser;
/**
* JSpinField2 is a numeric field with 2 spin buttons to increase or decrease
* the value. It has the same interface as the "old" JSpinField but uses a
* JSpinner internally (since J2SE SDK 1.4) rather than a scrollbar for
* emulating the spin buttons.
*
* @author Kai Toedter
* @version 1.2
*/
@SuppressWarnings("serial") class JSpinField extends JPanel implements ChangeListener,
CaretListener, ActionListener { protected JSpinner spinner;
/** the text (number) field */ protected JTextField textField; protected int min; protected int max; protected int value; protected Color darkGreen;
/**
* JSpinField constructor with given minimum and maximum vaues..
* @param min
* @param max
*/ public JSpinField(int min, int max) { super(); this.min = min; if (max < min)
max = min; this.max = max;
value = 0; if (value < min)
value = min; if (value > max)
value = max;
darkGreen = new Color(0, 150, 0);
setLayout(new BorderLayout());
textField = new JTextField();
textField.addCaretListener(this);
textField.addActionListener(this);
textField.setHorizontalAlignment(SwingConstants.RIGHT);
textField.setBorder(BorderFactory.createEmptyBorder());
textField.setText(Integer.toString(value));
spinner = new JSpinner();
spinner.setEditor(textField);
spinner.addChangeListener(this);
add(spinner, BorderLayout.CENTER);
}
public void adjustWidthToMaximumValue() {
JTextField testTextField = new JTextField(Integer.toString(max)); int width = testTextField.getPreferredSize().width; int height = testTextField.getPreferredSize().height;
textField.setPreferredSize(new Dimension(width, height));
textField.revalidate();
}
/**
* Is invoked when the spinner model changes
*
* @param e
* the ChangeEvent
*/ public void stateChanged(ChangeEvent e) {
SpinnerNumberModel model = (SpinnerNumberModel) spinner.getModel(); int val = model.getNumber().intValue();
setValue(val);
}
/**
* Sets the value attribute of the JSpinField object.
*
* @param newValue
* The new value
* @param updateTextField
* true if text field should be updated
* @param firePropertyChange bleh
*/ protected void setValue(int newValue, boolean updateTextField, boolean firePropertyChange) { int oldValue = value;
if (newValue < min) {
value = min;
} else if (newValue > max) {
value = max;
} else {
value = newValue;
}
if (updateTextField) {
textField.setText(Integer.toString(value));
textField.setForeground(Color.black);
}
if (firePropertyChange) {
firePropertyChange("value", oldValue, value);
}
}
/**
* Sets the value. This is a bound property.
*
* @param newValue
* the new value
*
* @see #getValue
*/ public void setValue(int newValue) {
setValue(newValue, true, true);
spinner.setValue(new Integer(value));
}
/**
* Returns the value.
*
* @return the value value
*/ public int getValue() { return value;
}
/**
* Sets the minimum value.
*
* @param newMinimum
* the new minimum value
*
* @see #getMinimum
*/ public void setMinimum(int newMinimum) {
min = newMinimum;
}
/**
* Returns the minimum value.
*
* @return the minimum value
*/ public int getMinimum() { return min;
}
/**
* Sets the maximum value and adjusts the preferred width.
*
* @param newMaximum
* the new maximum value
*
* @see #getMaximum
*/ public void setMaximum(int newMaximum) {
max = newMaximum;
}
/**
* Sets the horizontal alignment of the displayed value.
*
* @param alignment
* the horizontal alignment
*/ public void setHorizontalAlignment(int alignment) {
textField.setHorizontalAlignment(alignment);
}
/**
* Returns the maximum value.
*
* @return the maximum value
*/ public int getMaximum() { return max;
}
/**
* Sets the font property.
*
* @param font
* the new font
*/ public void setFont(Font font) { if (textField != null) {
textField.setFont(font);
}
}
/**
* After any user input, the value of the textfield is proofed. Depending on
* being an integer, the value is colored green or red.
*
* @param e
* Description of the Parameter
*/ public void caretUpdate(CaretEvent e) { try { int testValue = Integer.valueOf(textField.getText()).intValue();
if ((testValue >= min) && (testValue <= max)) {
textField.setForeground(darkGreen);
setValue(testValue, false, true);
} else {
textField.setForeground(Color.red);
}
} catch (Exception ex) { if (ex instanceof NumberFormatException) {
textField.setForeground(Color.red);
}
// Ignore all other exceptions, e.g. illegal state exception
}
textField.repaint();
}
/**
* After any user input, the value of the textfield is proofed. Depending on
* being an integer, the value is colored green or red. If the textfield is
* green, the enter key is accepted and the new value is set.
*
* @param e
* Description of the Parameter
*/ public void actionPerformed(ActionEvent e) { if (textField.getForeground().equals(darkGreen)) {
setValue(Integer.valueOf(textField.getText()).intValue());
}
}
/**
* Enable or disable the JSpinField.
*
* @param enabled
* The new enabled value
*/ public void setEnabled(boolean enabled) { super.setEnabled(enabled);
textField.setEnabled(enabled);
spinner.setEnabled(enabled);
}
/**
* Returns the year chooser's spinner (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() { return spinner;
}
/**
* Returns "JSpinField".
*
* @return the name value
*/ public String getName() { return "JSpinField";
}
/**
* Creates a JFrame with a JSpinField inside and can be used for testing.
*
* @param s
* The command line arguments
*/ public static void main(String[] s) {
JFrame frame = new JFrame("JSpinField2");
frame.getContentPane().add(new JSpinField());
frame.pack();
frame.setVisible(true);
}
}
/**
* JCalendar is a bean for choosing a day.
*
* @author Kai Toedter
* @version 1.2.1
*/
@SuppressWarnings("serial") class JDayChooser extends JPanel implements ActionListener, KeyListener,
FocusListener { protected JButton[] days; protected JButton[] weeks; protected JButton selectedDay; protected JPanel weekPanel; protected JPanel dayPanel; protected int day; protected Color oldDayBackgroundColor; protected Color selectedColor; protected Color sundayForeground; protected Color weekdayForeground; protected Color decorationBackgroundColor; protected String[] dayNames; protected Calendar calendar; protected Calendar today; protected Locale locale; protected boolean initialized; protected boolean weekOfYearVisible; protected boolean decorationBackgroundVisible = true; protected boolean decorationBordersVisible; private boolean alwaysFireDayProperty;
/**
* JDayChooser constructor.
*
* @param weekOfYearVisible
* true, if the weeks of a year shall be shown
*/ public JDayChooser(boolean weekOfYearVisible) {
setBackground(Color.blue); this.weekOfYearVisible = weekOfYearVisible;
locale = Locale.getDefault();
days = new JButton[49];
selectedDay = null;
calendar = Calendar.getInstance(locale);
today = (Calendar) calendar.clone();
setLayout(new BorderLayout());
dayPanel = new JPanel();
dayPanel.setLayout(new GridLayout(7, 7));
sundayForeground = new Color(164, 0, 0);
weekdayForeground = new Color(0, 90, 164);
// decorationBackgroundColor = new Color(194, 211, 252);
// decorationBackgroundColor = new Color(206, 219, 246);
decorationBackgroundColor = new Color(210, 228, 238);
for (int y = 0; y < 7; y++) { for (int x = 0; x < 7; x++) { int index = x + (7 * y);
if (y == 0) {
// Create a button that doesn't react on clicks or focus
// changes.
// Thanks to Thomas Schaefer for the focus hint :)
days[index] = new JButton() { public void addMouseListener(MouseListener l) {
}
if (weekOfYearVisible) {
add(weekPanel, BorderLayout.WEST);
}
initialized = true;
}
/**
* Initilizes the locale specific names for the days of the week.
*/ protected void init() {
JButton testButton = new JButton();
oldDayBackgroundColor = testButton.getBackground();
selectedColor = new Color(160, 160, 160);
Date date = calendar.getTime();
calendar = Calendar.getInstance(locale);
calendar.setTime(date);
drawDayNames();
drawDays();
}
/**
* Draws the day names of the day columnes.
*/ private void drawDayNames() { int firstDayOfWeek = calendar.getFirstDayOfWeek();
DateFormatSymbols dateFormatSymbols = new DateFormatSymbols(locale);
dayNames = dateFormatSymbols.getShortWeekdays();
int dayi = firstDayOfWeek;
for (int i = 0; i < 7; i++) {
days[i].setText(dayNames[dayi]);
/**
* Initializes both day names and weeks of the year.
*/ protected void initDecorations() { for (int x = 0; x < 7; x++) {
days[x].setContentAreaFilled(decorationBackgroundVisible);
days[x].setBorderPainted(decorationBordersVisible);
weeks[x].setContentAreaFilled(decorationBackgroundVisible);
weeks[x].setBorderPainted(decorationBordersVisible);
}
}
/**
* Hides and shows the week buttons.
*/ protected void drawWeeks() {
Calendar tmpCalendar = (Calendar) calendar.clone();
for (int i = 1; i < 7; i++) {
tmpCalendar.set(Calendar.DAY_OF_MONTH, (i * 7) - 6);
int week = tmpCalendar.get(Calendar.WEEK_OF_YEAR);
String buttonText = Integer.toString(week);
if (week < 10) {
buttonText = "0" + buttonText;
}
weeks[i].setText(buttonText);
if ((i == 5) || (i == 6)) {
weeks[i].setVisible(days[i * 7].isVisible());
}
}
}
/**
* Hides and shows the day buttons.
*/ protected void drawDays() {
Calendar tmpCalendar = (Calendar) calendar.clone(); int firstDayOfWeek = tmpCalendar.getFirstDayOfWeek();
tmpCalendar.set(Calendar.DAY_OF_MONTH, 1);
int firstDay = tmpCalendar.get(Calendar.DAY_OF_WEEK) - firstDayOfWeek;
if (firstDay < 0) {
firstDay += 7;
}
int i;
for (i = 0; i < firstDay; i++) {
days[i + 7].setVisible(false);
days[i + 7].setText("");
}
tmpCalendar.add(Calendar.MONTH, 1);
Date firstDayInNextMonth = tmpCalendar.getTime();
tmpCalendar.add(Calendar.MONTH, -1);
Date dayi = tmpCalendar.getTime(); int n = 0;
Color foregroundColor = getForeground();
while (dayi.before(firstDayInNextMonth)) {
days[i + n + 7].setText(Integer.toString(n + 1));
days[i + n + 7].setVisible(true);
if ((tmpCalendar.get(Calendar.DAY_OF_YEAR) == today
.get(Calendar.DAY_OF_YEAR))
&& (tmpCalendar.get(Calendar.YEAR) == today
.get(Calendar.YEAR))) {
days[i + n + 7].setForeground(sundayForeground);
} else {
days[i + n + 7].setForeground(foregroundColor);
}
if ((n + 1) == this.day) {
days[i + n + 7].setBackground(selectedColor);
selectedDay = days[i + n + 7];
} else {
days[i + n + 7].setBackground(oldDayBackgroundColor);
}
/**
* this is needed for JDateChooser.
*
* @param alwaysFire
* true, if day property shall be fired every time a day is
* chosen.
*/ public void setAlwaysFireDayProperty(boolean alwaysFire) {
alwaysFireDayProperty = alwaysFire;
}
/**
* Returns the selected day.
*
* @return the day value
*
* @see #setDay
*/ public int getDay() { return day;
}
/**
* Sets a specific month. This is needed for correct graphical
* representation of the days.
*
* @param month
* the new month
*/ public void setMonth(int month) {
calendar.set(Calendar.MONTH, month);
// Since the day does not change,
// don't fire a day property change, even if alwaysFireDayProperty is
// true :) boolean storedMode = alwaysFireDayProperty;
alwaysFireDayProperty = false;
setDay(day);
alwaysFireDayProperty = storedMode;
drawDays();
drawWeeks();
}
/**
* Sets a specific year. This is needed for correct graphical representation
* of the days.
*
* @param year
* the new year
*/ public void setYear(int year) {
calendar.set(Calendar.YEAR, year);
drawDays();
drawWeeks();
}
/**
* Sets a specific calendar. This is needed for correct graphical
* representation of the days.
*
* @param calendar
* the new calendar
*/ public void setCalendar(Calendar calendar) { this.calendar = calendar;
drawDays();
}
/**
* Sets the font property.
*
* @param font
* the new font
*/ public void setFont(Font font) { if (days != null) { for (int i = 0; i < 49; i++) {
days[i].setFont(font);
}
}
}
/**
* Sets the foregroundColor color.
*
* @param foreground
* the new foregroundColor
*/ public void setForeground(Color foreground) { super.setForeground(foreground);
if (days != null) { for (int i = 7; i < 49; i++) {
days[i].setForeground(foreground);
}
drawDays();
}
}
/**
* Returns "JDayChooser".
*
* @return the name value
*/ public String getName() { return "JDayChooser";
}
/**
* JDayChooser is the ActionListener for all day buttons.
*
* @param e
* the ActionEvent
*/ public void actionPerformed(ActionEvent e) {
JButton button = (JButton) e.getSource();
String buttonText = button.getText(); int dayi = new Integer(buttonText).intValue();
setDay(dayi);
}
/**
* JDayChooser is the FocusListener for all day buttons. (Added by Thomas
* Schaefer)
*
* @param e
* the FocusEvent
*/
/*
* Code below commented out by Mark Brown on 24 Aug 2004. This code breaks
* the JDateChooser code by triggering the actionPerformed method on the
* next day button. This causes the date chosen to always be incremented by
* one day.
*/ public void focusGained(FocusEvent e) {
// JButton button = (JButton) e.getSource();
// String buttonText = button.getText();
//
// if ((buttonText != null) && !buttonText.equals("") &&
// !e.isTemporary()) {
// actionPerformed(new ActionEvent(e.getSource(), 0, null));
// }
}
/**
* Does nothing.
*
* @param e
* the FocusEvent
*/ public void focusLost(FocusEvent e) {
}
/**
* JDayChooser is the KeyListener for all day buttons. (Added by Thomas
* Schaefer and modified by Austin Moore)
*
* @param e
* the KeyEvent
*/ public void keyPressed(KeyEvent e) { int offset = (e.getKeyCode() == KeyEvent.VK_UP) ? (-7) : ((e
.getKeyCode() == KeyEvent.VK_DOWN) ? (+7)
: ((e.getKeyCode() == KeyEvent.VK_LEFT) ? (-1) : ((e
.getKeyCode() == KeyEvent.VK_RIGHT) ? (+1) : 0)));
/**
* Does nothing.
*
* @param e
* the KeyEvent
*/ public void keyTyped(KeyEvent e) {
}
/**
* Does nothing.
*
* @param e
* the KeyEvent
*/ public void keyReleased(KeyEvent e) {
}
/**
* Enable or disable the JDayChooser.
*
* @param enabled
* The new enabled value
*/ public void setEnabled(boolean enabled) { super.setEnabled(enabled);
for (short i = 0; i < days.length; i++) { if (days[i] != null) {
days[i].setEnabled(enabled);
}
}
for (short i = 0; i < weeks.length; i++) { if (weeks[i] != null) {
weeks[i].setEnabled(enabled);
}
}
}
/**
* In some Countries it is often usefull to know in which week of the year a
* date is.
*
* @return boolean true, if the weeks of the year is shown
*/ public boolean isWeekOfYearVisible() { return weekOfYearVisible;
}
/**
* In some Countries it is often usefull to know in which week of the year a
* date is.
*
* @param weekOfYearVisible
* true, if the weeks of the year shall be shown
*/ public void setWeekOfYearVisible(boolean weekOfYearVisible) { if (weekOfYearVisible == this.weekOfYearVisible) { return;
} else if (weekOfYearVisible) {
add(weekPanel, BorderLayout.WEST);
} else {
remove(weekPanel);
}
/**
* Returns the day panel.
*
* @return the day panel
*/ public JPanel getDayPanel() { return dayPanel;
}
/**
* Returns the color of the decoration (day names and weeks).
*
* @return the color of the decoration (day names and weeks).
*/ public Color getDecorationBackgroundColor() { return decorationBackgroundColor;
}
/**
* Sets the background of days and weeks of year buttons.
*
* @param decorationBackgroundColor
* The background to set
*/ public void setDecorationBackgroundColor(Color decorationBackgroundColor) { this.decorationBackgroundColor = decorationBackgroundColor;
if (days != null) { for (int i = 0; i < 7; i++) {
days[i].setBackground(decorationBackgroundColor);
}
}
if (weeks != null) { for (int i = 0; i < 7; i++) {
weeks[i].setBackground(decorationBackgroundColor);
}
}
}
/**
* Returns the Sunday foreground.
*
* @return Color the Sunday foreground.
*/ public Color getSundayForeground() { return sundayForeground;
}
/**
* Returns the weekday foreground.
*
* @return Color the weekday foreground.
*/ public Color getWeekdayForeground() { return weekdayForeground;
}
/**
* Sets the Sunday foreground.
*
* @param sundayForeground
* The sundayForeground to set
*/ public void setSundayForeground(Color sundayForeground) { this.sundayForeground = sundayForeground;
drawDayNames();
drawDays();
}
/**
* Sets the weekday foreground.
*
* @param weekdayForeground
* The weekdayForeground to set
*/ public void setWeekdayForeground(Color weekdayForeground) { this.weekdayForeground = weekdayForeground;
drawDayNames();
drawDays();
}
/**
* Requests that the selected day also have the focus.
*/ public void setFocus() { if (selectedDay != null) { this.selectedDay.requestFocus();
}
}
/**
* The decoration background is the background color of the day titles and
* the weeks of the year.
*
* @return Returns true, if the decoration background is painted.
*/ public boolean isDecorationBackgroundVisible() { return decorationBackgroundVisible;
}
/**
* The decoration background is the background color of the day titles and
* the weeks of the year.
*
* @param decorationBackgroundVisible
* true, if the decoration background shall be painted.
*/ public void setDecorationBackgroundVisible( boolean decorationBackgroundVisible) { this.decorationBackgroundVisible = decorationBackgroundVisible;
initDecorations();
}
/**
* The decoration border is the button border of the day titles and the
* weeks of the year.
*
* @return Returns true, if the decoration border is painted.
*/ public boolean isDecorationBordersVisible() { return decorationBordersVisible;
}
/**
* The decoration border is the button border of the day titles and the
* weeks of the year.
*
* @param decorationBordersVisible
* true, if the decoration border shall be painted.
*/ public void setDecorationBordersVisible(boolean decorationBordersVisible) { this.decorationBordersVisible = decorationBordersVisible;
initDecorations();
}
/**
* Creates a JFrame with a JDayChooser inside and can be used for testing.
*
* @param s
* The command line arguments
*/ public static void main(String[] s) {
JFrame frame = new JFrame("JDayChooser");
frame.getContentPane().add(new JDayChooser());
frame.pack();
frame.setVisible(true);
}
}