import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.border.Border;
import at.atc.ows.client.api.unsorted.PopupButton;
import at.atc.ows.client.api.unsorted.gui.layouts.RasterLayout;
public class DateSelectButton extends PopupButton {
private int month;
private int year;
private JLabel selectedLabel;
private DateSelectButtonModel model;
public DateSelectButton() {
this(new DefaultDateSelectButtonModel());
}
public DateSelectButton(DateSelectButtonModel model) {
super(new ImageIcon(DateSelectButton.class.getResource("dateSelectButtonIcon.png")));
this.model = model;
JPopupMenu popup = getPopup();
popup.setLayout(new BorderLayout());
}
protected void pressed() {
long currentDate = loadCurrentDate(model.getDateString());
initDate(currentDate);
buildGui();
super.pressed();
}
private void initDate(long currentDate) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(currentDate);
calendar.setTimeZone(model.getTimeZone());
calendar.setFirstDayOfWeek(Calendar.MONDAY);
month = calendar.get(Calendar.MONTH);
year = calendar.get(Calendar.YEAR);
}
private void buildGui() {
JPopupMenu popup = getPopup();
popup.removeAll();
popup.add(buildHeadPanel(), BorderLayout.NORTH);
popup.add(buildCalendarPanel(), BorderLayout.CENTER);
popup.revalidate();
}
private JPanel buildHeadPanel() {
JPanel headPanel = new JPanel();
headPanel.setLayout(new BoxLayout(headPanel, BoxLayout.X_AXIS));
headPanel.add(Box.createRigidArea(new Dimension(10, 0)));
final JLabel previouseMonthLabel = new JLabel("<<");
previouseMonthLabel.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(model.getTimeZone());
calendar.setFirstDayOfWeek(Calendar.MONDAY);
calendar.set(Calendar.MONTH, month - 1);
calendar.set(Calendar.YEAR, year);
month = calendar.get(Calendar.MONTH);
year = calendar.get(Calendar.YEAR);
buildGui();
}
public void mouseExited(MouseEvent e) {
previouseMonthLabel.setForeground(Color.BLACK);
}
public void mouseEntered(MouseEvent e) {
previouseMonthLabel.setForeground(Color.RED);
}
});
headPanel.add(previouseMonthLabel);
headPanel.add(Box.createHorizontalGlue());
JLabel monthNameLabel = new JLabel(model.getMonthName(month) + ", " + year);
headPanel.add(monthNameLabel);
headPanel.add(Box.createHorizontalGlue());
final JLabel nextMonthLabel = new JLabel(">>");
nextMonthLabel.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(model.getTimeZone());
calendar.setFirstDayOfWeek(Calendar.MONDAY);
calendar.set(Calendar.MONTH, month + 1);
calendar.set(Calendar.YEAR, year);
month = calendar.get(Calendar.MONTH);
year = calendar.get(Calendar.YEAR);
buildGui();
}
public void mouseExited(MouseEvent e) {
nextMonthLabel.setForeground(Color.BLACK);
}
public void mouseEntered(MouseEvent e) {
nextMonthLabel.setForeground(Color.RED);
}
});
headPanel.add(nextMonthLabel);
headPanel.add(Box.createRigidArea(new Dimension(10, 0)));
return(headPanel);
}
private JPanel buildCalendarPanel() {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.DAY_OF_MONTH, 1);
calendar.set(Calendar.MONTH, month);
calendar.set(Calendar.YEAR, year);
calendar.setTimeZone(model.getTimeZone());
calendar.setFirstDayOfWeek(Calendar.MONDAY);
int currentWeekday = calendar.get(Calendar.DAY_OF_WEEK);
int daysInMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
if(currentWeekday == Calendar.SUNDAY) {
currentWeekday = 6;
}
else {
currentWeekday-= 2;
}
JPanel calendarPanel = new JPanel(new RasterLayout(6 + 1, 7, 5, 5));
for(int i = 0, size = model.getWeekdayCount(); i < size; i++) {
String s = model.getWeekdayName(i);
JLabel label = new JLabel(s);
label.setHorizontalAlignment(JLabel.CENTER);
if(i != 0 && i%6 == 0) {
label.setForeground(Color.RED);
}
calendarPanel.add(label, new Point(i, 0));
}
for(int i = 0; i < daysInMonth + currentWeekday; i++) {
if(i >= currentWeekday) {
JLabel label = createDayLabel((byte) (i + 1 - currentWeekday));
if((i + 1)%7 == 0) {
label.setForeground(Color.RED);
}
int x = i;
int y = x / 7;
calendarPanel.add(label, new Point(x - y * 7, y + 1));
}
}
return(calendarPanel);
}
private long loadCurrentDate(String currentDateStringFromModel)
{
if(currentDateStringFromModel == null || currentDateStringFromModel.trim().length() == 0) {
return(new Date().getTime());
}
else {
SimpleDateFormat sdf = new SimpleDateFormat(model.getDateFormatterString());
sdf.setTimeZone(model.getTimeZone());
try {
return(sdf.parse(currentDateStringFromModel).getTime());
}
catch (ParseException e) {
loadCurrentDate(null);
}
}
return(-1);
}
private JLabel createDayLabel(final byte day) {
final JLabel label = new JLabel(String.valueOf(day));
label.setHorizontalAlignment(JLabel.CENTER);
final Border titledBorder = BorderFactory.createTitledBorder((String)null);
Insets insets = titledBorder.getBorderInsets(label);
final Border defaultBorder = BorderFactory.createEmptyBorder(insets.top, insets.left, insets.bottom, insets.right);
label.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e)
{
if(selectedLabel != null && selectedLabel != label) {
selectedLabel.setBorder(defaultBorder);
}
selectedLabel = label;
updateModel(day);
}
public void mouseEntered(MouseEvent e) {
label.setBorder(titledBorder);
}
public void mouseExited(MouseEvent e) {
if(selectedLabel == null || selectedLabel != label) {
label.setBorder(defaultBorder);
}
}
});
label.setBorder(defaultBorder);
return(label);
}
private void updateModel(byte day) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.DAY_OF_MONTH, day);
calendar.set(Calendar.MONTH, month);
calendar.set(Calendar.YEAR, year);
calendar.setTimeZone(model.getTimeZone());
calendar.setFirstDayOfWeek(Calendar.MONDAY);
Date selectedTime = calendar.getTime();
SimpleDateFormat sdf = new SimpleDateFormat(model.getDateFormatterString());
String s = sdf.format(selectedTime);
model.setDateString(s);
}
public static class DefaultDateSelectButtonModel implements DateSelectButtonModel {
private static final String DEFAULT_DATE_FORMATTER_STRING = "dd.MM.yyyy";
private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("GMT+1");
private static final String[] DEFAULT_MONTH_NAMES = {
"January",
"February",
"März",
"April",
"Mai",
"Juni",
"Juli",
"August",
"September",
"Oktober",
"November",
"Dezember"
};
private static final String[] DEFAULT_WEEKDAY_NAMES = {
"M", "D", "M", "D", "F", "S", "S"
};
private String dateString;
public DefaultDateSelectButtonModel() {
dateString = getCurrentDateString();
}
private String getCurrentDateString() {
return(new SimpleDateFormat(getDateFormatterString()).format(new Date()));
}
public void setDateString(String dateString) {
this.dateString = dateString;
}
public String getDateString() {
return(this.dateString);
}
public TimeZone getTimeZone() {
return(DEFAULT_TIMEZONE);
}
public String getMonthName(int month) {
return(DEFAULT_MONTH_NAMES[month]);
}
public String getWeekdayName(int weekdayId) {
return(DEFAULT_WEEKDAY_NAMES[weekdayId]);
}
public int getWeekdayCount() {
return(DEFAULT_WEEKDAY_NAMES.length);
}
public String getDateFormatterString() {
return(DEFAULT_DATE_FORMATTER_STRING);
}
}
public static interface DateSelectButtonModel {
void setDateString(String dateString);
String getDateFormatterString();
String getWeekdayName(int weekdayId);
int getWeekdayCount();
String getMonthName(int month);
TimeZone getTimeZone();
String getDateString();
}
}