/*
* Beanfabrics Framework Copyright (C) by Michael Karneim, beanfabrics.org
* Use is subject to license terms. See license.txt.
*/
package org.beanfabrics.swing.goodies.calendar;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.Serializable;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.JButton;
import javax.swing.JPopupMenu;
import javax.swing.text.JTextComponent;
/**
* CalendarButton provides a simple mechanism for the user to bind a date chooser popup to a text component. Whenever
* the button is pressed a popup appears below a specified text component, and displays a CalenderBean control.
* <P>
* example:<BR>
*
* <PRE>
* JTextField dateField = new JTextField("14.01.1971 ");
* CalendarButton dateButton = new CalendarButton();
* dateButton.setText("...");
* dateButton.setTextComponent(dateField);
* dateButton.setPreferredSize(new Dimension(20, dateField.getPreferredSize().height));
* JFrame frame = new JFrame();
* frame.getContentPane().setLayout(new FlowLayout(0));
* frame.getContentPane().add(dateField);
* frame.getContentPane().add(dateButton);
* frame.pack();
* frame.setVisible(true);
* </PRE>
*
* @author Michael Karneim
*/
@SuppressWarnings("serial")
public class CalendarButton extends JButton implements ActionListener {
private JTextComponent textComponent;
private JPopupMenu popup = null;
private static final SimpleDateFormat format = new SimpleDateFormat("dd.MM.yyyy");
private CalendarChooser calendarBean;
private int numberOfPreviousVisibleMonths = 0;
private int numberOfSubsequentVisibleMonths = 0;
/**
* Creates an instance of CalenderBean
*/
public CalendarButton() {
this.addActionListener(this);
this.setEnabled(this.textComponent != null ? this.textComponent.isEditable() : false);
}
/**
* Implements the ActionListener interface. This method is called whenever the button is pressed.
*/
public void actionPerformed(ActionEvent e) {
if (textComponent == null)
return;
if (e.getSource() == this) {
JPopupMenu p = this.getPopupMenu();
String dateString = this.textComponent.getText();
try {
Date date = CalendarButton.format.parse(dateString);
this.getCalendarBean().setSelectedDate(date);
} catch (ParseException ex) {
this.getCalendarBean().setMonth(new Date());
this.getCalendarBean().setSelectedDate((Date) null);
}
p.show(textComponent, 0, textComponent.getSize().height);
} else if (e.getSource() == this.getCalendarBean()) {
JPopupMenu p = this.getPopupMenu();
p.setVisible(false);
Date date = this.getCalendarBean().getSelectedDate();
if (date == null) {
this.textComponent.setText("");
} else {
String dateString = format.format(date);
this.textComponent.setText(dateString);
}
}
}
private final PropertyChangeListener enableStateListener = new MyPropertyChangeListener();
private class MyPropertyChangeListener implements PropertyChangeListener, Serializable {
public void propertyChange(PropertyChangeEvent evt) {
if (!(evt.getSource() == textComponent))
return;
boolean newValue = ((Boolean) evt.getNewValue()).booleanValue();
setEnabled(newValue);
}
};
/**
* Sets the reference to the text component, the calender button should work with. From this text component the
* calendar button will get the date string to put into the date chooser popup on button click. Below this text
* component the date chooser popup will be displayed. Into this text component the selected date will be inserted
* from the date chooser component.
*
* @param newTextComponent
* the text component the button will work with
*/
public void setTextComponent(javax.swing.text.JTextComponent newTextComponent) {
javax.swing.text.JTextComponent oldTextComponent = textComponent;
if (this.textComponent != null)
this.textComponent.removePropertyChangeListener("editable", enableStateListener);
textComponent = newTextComponent;
if (this.textComponent != null) {
this.textComponent.addPropertyChangeListener("editable", enableStateListener);
this.setEnabled(this.textComponent.isEditable());
}
firePropertyChange("textComponent", oldTextComponent, newTextComponent);
}
/**
* Returns the text component that is bound to this button for displaying the date.
*
* @return the text component that is bound to this button for displaying the date
*/
public JTextComponent getTextComponent() {
return textComponent;
}
/**
* Returns the popup menu with the date chooser control.
*
* @return the popup menu with the date chooser control
*/
protected JPopupMenu getPopupMenu() {
if (this.popup == null) {
this.popup = new JPopupMenu();
this.popup.add(this.getCalendarBean());
}
return this.popup;
}
/**
* Defines the pattern that has to be used to transform a String to a Date instance and vice versa. The default is
* "dd.mm.yyyy".
*
* @param pattern
* the format pattern
*/
public void setDatePattern(String pattern) {
String oldPattern = CalendarButton.format.toPattern();
CalendarButton.format.applyPattern(pattern);
firePropertyChange("datePattern", oldPattern, pattern);
}
/**
* Returns the pattern that has to be used to transform a String to a Date instance and vice versa.
*
* @return the pattern that has to be used to transform a String to a Date instance and vice versa
*/
public String getDatePattern() {
return CalendarButton.format.toPattern();
}
/**
* Sets the CalendarBean instance that has to be used in the popup.
* <P>
* Note:<BR>
* This method offers an easy way to customize the look and feel of the date chooser popup. Be carefull not to use
* one single calendar bean in more calendar buttons.
*
* @param newCalendarBean
* the CalendarBean instance that has to be used in the popup
*/
public void setCalendarBean(CalendarChooser newCalendarBean) {
CalendarChooser oldCalendarBean = calendarBean;
if (oldCalendarBean != null) {
oldCalendarBean.removeActionListener(this);
}
this.calendarBean = newCalendarBean;
this.calendarBean.addActionListener(this);
firePropertyChange("calendarBean", oldCalendarBean, newCalendarBean);
}
/**
* Returns the CalendarBean instance that is used in the popup.
*
* @return the CalendarBean instance that is used in the popup
*/
public CalendarChooser getCalendarBean() {
if (this.calendarBean == null) {
this.calendarBean = new CalendarChooser();
this.calendarBean.setNumberOfPreviousVisibleMonths(numberOfPreviousVisibleMonths);
this.calendarBean.setNumberOfSubsequentVisibleMonths(numberOfSubsequentVisibleMonths);
this.calendarBean.addActionListener(this);
}
return this.calendarBean;
}
public int getNumberOfPreviousVisibleMonths() {
return numberOfPreviousVisibleMonths;
}
public void setNumberOfPreviousVisibleMonths(int numberOfPreviousVisibleMonths) {
this.numberOfPreviousVisibleMonths = numberOfPreviousVisibleMonths;
}
public int getNumberOfSubsequentVisibleMonths() {
return numberOfSubsequentVisibleMonths;
}
public void setNumberOfSubsequentVisibleMonths(int numberOfSubsequentVisibleMonths) {
this.numberOfSubsequentVisibleMonths = numberOfSubsequentVisibleMonths;
}
}