package open.dolphin.client;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collection;
import java.util.GregorianCalendar;
import java.util.HashMap;
import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;
import open.dolphin.infomodel.SimpleDate;
/**
* LiteCalendarPanel
*
* @author Kazushi Minagawa
*/
public final class LiteCalendarPanel extends JPanel implements PropertyChangeListener {
public static final String SELECTED_DATE_PROP = "selectedDateProp";
public static final String MARK_LIST_PROP = "markListProp";
// 表示のデフォルト設定
private static final int TITLE_ALIGN = SwingConstants.CENTER;
private static final int TITLE_FONT_SIZE = 14;
private static final Font TITLE_FONT = new Font("Dialog", Font.PLAIN, TITLE_FONT_SIZE);
private static final Font CALENDAR_FONT = new Font("Dialog", Font.PLAIN, ClientContext.getInt("calendar.font.size"));
private static final Font OUTOF_MONTH_FONT = new Font("Dialog", Font.PLAIN, ClientContext.getInt("calendar.font.size.outOfMonth"));
// カレンダテーブル
private int relativeMonth;
private int year;
private int month;
private CalendarTableModel tableModel;
private JTable table;
private PropertyChangeSupport boundSupport;
private Object selectedDate;
private JLabel titleLabel;
private SimpleDate today;
private SimpleDate[] acceptRange;
private HashMap eventColorTable;
// 表示用の属性
private Color titleFore = ClientContext.getColor("color.calendar.title.fore");
private Color titleBack = ClientContext.getColor("color.calendar.title.back");
private int titleAlign = TITLE_ALIGN;
private Font titleFont = TITLE_FONT;
private int cellWidth = ClientContext.getInt("calendar.cell.width");
private int cellHeight = ClientContext.getInt("calendar.cell.height");
private int autoResizeMode = JTable.AUTO_RESIZE_OFF;
private boolean cellSelectionEnabled = true;
private Color sundayFore = ClientContext.getColor("color.SUNDAY_FORE");
private Color saturdayFore = ClientContext.getColor("color.SATURDAY_FORE");
private Color weekdayFore = ClientContext.getColor("color.WEEKDAY_FORE");
private Color outOfMothFore = ClientContext.getColor("color.OUTOFMONTH_FORE");
private Color calendarBack = ClientContext.getColor("color.CALENDAR_BACK");
private Color todayBack = ClientContext.getColor("color.TODAY_BACK");
private Color birthdayBack = ClientContext.getColor("color.BIRTHDAY_BACK");
private Font calendarFont = CALENDAR_FONT;
private Font outOfMonthFont = OUTOF_MONTH_FONT;
public LiteCalendarPanel() {
super();
}
public LiteCalendarPanel(int n) {
this(n, true);
}
public LiteCalendarPanel(int n, boolean addTitle) {
// 作成するカレンダの当月を起点とする相対月数(n ケ月前/後)
relativeMonth = n;
GregorianCalendar gc = new GregorianCalendar();
gc.clear(Calendar.MILLISECOND);
gc.clear(Calendar.SECOND);
gc.clear(Calendar.MINUTE);
gc.clear(Calendar.HOUR_OF_DAY);
gc.add(Calendar.MONTH, relativeMonth);
year = gc.get(Calendar.YEAR);
month = gc.get(Calendar.MONTH);
tableModel = new CalendarTableModel(year, month);
table = new JTable(tableModel);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
//masuda^
// カラムのドラッグ・リサイズを不許可
table.getTableHeader().setResizingAllowed(false);
table.getTableHeader().setReorderingAllowed(false);
//masuda$
setAutoResizeMode(autoResizeMode);
table.setBackground(calendarBack);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
setCellSelectionEnabled(cellSelectionEnabled);
setCellWidth(cellWidth);
setCellHeight(cellHeight);
// Replace DefaultRender
DateRenderer dateRenderer = new DateRenderer();
dateRenderer.setHorizontalAlignment(SwingConstants.CENTER);
table.setDefaultRenderer(java.lang.Object.class, dateRenderer);
// ヘッダー センタリング
((JLabel)table.getTableHeader().getDefaultRenderer()).setHorizontalAlignment(SwingConstants.CENTER);
// MouseAdapter
table.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() != 1) {
return;
}
Point p = e.getPoint();
int row = table.rowAtPoint(p);
int col = table.columnAtPoint(p);
if (row != -1 && col != -1) {
Object o = tableModel.getDate(row, col);
setSelectedDate(o);
}
}
});
//minagawa^ I18N
// StringBuilder buf = new StringBuilder();
// buf.append(year);
// buf.append(ClientContext.getString("calendar.title.year"));
// buf.append(month + 1);
// buf.append(ClientContext.getString("calendar.title.month"));
// setTitleLabel(new JLabel(buf.toString()));
String fmt = ClientContext.getString("calendar.title.yearMonth");
SimpleDateFormat sdf = new SimpleDateFormat(fmt);
String dateString = sdf.format(gc.getTime());
setTitleLabel(new JLabel(dateString));
//minagawa$
setTitleAlign(titleAlign);
setTitleFont(titleFont);
setTitleFore(titleFore);
setTitleBack(titleBack);
getTitleLabel().setOpaque(true);
this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
if (addTitle) {
this.add(getTitleLabel());
}
this.add(table.getTableHeader());
this.add(table);
this.setBorder(BorderFactory.createEtchedBorder());
boundSupport = new PropertyChangeSupport(this);
}
public int getYear() {
return year;
}
public int getMonth() {
return month;
}
@Override
public void addPropertyChangeListener(String prop, PropertyChangeListener l) {
if (boundSupport == null) {
boundSupport = new PropertyChangeSupport(this);
}
boundSupport.addPropertyChangeListener(prop, l);
}
@Override
public void removePropertyChangeListener(String prop,
PropertyChangeListener l) {
if (boundSupport == null) {
boundSupport = new PropertyChangeSupport(this);
}
boundSupport.removePropertyChangeListener(prop, l);
}
@Override
public void propertyChange(PropertyChangeEvent e) {
String prop = e.getPropertyName();
if (prop.equals(MARK_LIST_PROP)) {
Collection list = (Collection) e.getNewValue();
tableModel.setMarkDates(list);
}
}
/**
* 選択された日を通知する。
* @param o
*/
public void setSelectedDate(Object o) {
Object old = selectedDate;
selectedDate = o;
if (selectedDate instanceof String) {
SimpleDate sd = new SimpleDate(getYear(), getMonth(), Integer.parseInt((String) selectedDate));
selectedDate = sd;
}
SimpleDate test = (SimpleDate)selectedDate;
boolean notify = true;
if (this.acceptRange!=null && this.acceptRange[0]!=null) {
// after [0]
notify = notify && (test.compareTo(this.acceptRange[0])>=0);
}
if (this.acceptRange!=null && this.acceptRange[1]!=null) {
// before [1]
notify = notify && (test.compareTo(this.acceptRange[1])<=0);
}
if (notify) {
boundSupport.firePropertyChange(SELECTED_DATE_PROP, old, selectedDate);
}
}
public JTable getTable() {
return table;
}
public CalendarTableModel getTableModel() {
return tableModel;
}
public int getRelativeMonth() {
return relativeMonth;
}
public SimpleDate getFirstDate() {
return tableModel.getFirstDate();
}
public SimpleDate getLastDate() {
return tableModel.getLastDate();
}
public HashMap getEventColorTable() {
return eventColorTable;
}
public void setEventColorTable(HashMap ht) {
eventColorTable = ht;
}
/**
* @param titleFore
* The titleFore to set.
*/
public void setTitleFore(Color titleFore) {
this.titleFore = titleFore;
getTitleLabel().setForeground(titleFore);
}
/**
* @return Returns the titleFore.
*/
public Color getTitleFore() {
return titleFore;
}
/**
* @param titleBack
* The titleBack to set.
*/
private void setTitleBack(Color titleBack) {
this.titleBack = titleBack;
getTitleLabel().setBackground(titleBack);
}
/**
* @param titleAlign
* The titleAlign to set.
*/
private void setTitleAlign(int titleAlign) {
this.titleAlign = titleAlign;
getTitleLabel().setHorizontalAlignment(titleAlign);
}
/**
* @param titleFont
* The titleFont to set.
*/
private void setTitleFont(Font titleFont) {
this.titleFont = titleFont;
getTitleLabel().setFont(titleFont);
}
/**
* @param cellWidth
* The cellWidth to set.
*/
public void setCellWidth(int cellWidth) {
this.cellWidth = cellWidth;
TableColumn column;
for (int i = 0; i < 7; i++) {
column = table.getColumnModel().getColumn(i);
column.setPreferredWidth(cellWidth);
}
}
/**
* @return Returns the cellWidth.
*/
public int getCellWidth() {
return cellWidth;
}
/**
* @param cellHeight
* The cellHeight to set.
*/
public void setCellHeight(int cellHeight) {
this.cellHeight = cellHeight;
table.setRowHeight(cellHeight);
}
/**
* @return Returns the cellHeight.
*/
public int getCellHeight() {
return cellHeight;
}
/**
* @param mode
*/
public void setAutoResizeMode(int mode) {
this.autoResizeMode = mode;
}
/**
* @return Returns the autoResize.
*/
public int getAutoResizeMode() {
return autoResizeMode;
}
/**
* @param cellSelectionEnabled
* The cellSelectionEnabled to set.
*/
public void setCellSelectionEnabled(boolean cellSelectionEnabled) {
this.cellSelectionEnabled = cellSelectionEnabled;
}
/**
* @return Returns the cellSelectionEnabled.
*/
public boolean isCellSelectionEnabled() {
return cellSelectionEnabled;
}
/**
* @param sundayFore
* The sundayFore to set.
*/
public void setSundayFore(Color sundayFore) {
this.sundayFore = sundayFore;
}
/**
* @return Returns the sundayFore.
*/
public Color getSundayFore() {
return sundayFore;
}
/**
* @param saturdayFore
* The saturdayFore to set.
*/
public void setSaturdayFore(Color saturdayFore) {
this.saturdayFore = saturdayFore;
}
/**
* @return Returns the saturdayFore.
*/
public Color getSaturdayFore() {
return saturdayFore;
}
/**
* @param weekdayFore
* The weekdayFore to set.
*/
public void setWeekdayFore(Color weekdayFore) {
this.weekdayFore = weekdayFore;
}
/**
* @return Returns the weekdayFore.
*/
public Color getWeekdayFore() {
return weekdayFore;
}
/**
* @param outOfMothFore
* The outOfMothFore to set.
*/
public void setOutOfMothFore(Color outOfMothFore) {
this.outOfMothFore = outOfMothFore;
}
/**
* @return Returns the outOfMothFore.
*/
public Color getOutOfMothFore() {
return outOfMothFore;
}
/**
* @param calendarBack
* The calendarBack to set.
*/
public void setCalendarBack(Color calendarBack) {
this.calendarBack = calendarBack;
}
/**
* @return Returns the calendarBack.
*/
public Color getCalendarBack() {
return calendarBack;
}
/**
* @param todayBack
* The todayBack to set.
*/
public void setTodayBack(Color todayBack) {
this.todayBack = todayBack;
}
/**
* @return Returns the todayBack.
*/
public Color getTodayBack() {
return todayBack;
}
/**
* @param birthdayBack
* The birthdayBack to set.
*/
public void setBirthdayBack(Color birthdayBack) {
this.birthdayBack = birthdayBack;
}
/**
* @return Returns the birthdayBack.
*/
public Color getBirthdayBack() {
return birthdayBack;
}
/**
* @param calendarFont
* The calendarFont to set.
*/
public void setCalendarFont(Font calendarFont) {
this.calendarFont = calendarFont;
}
/**
* @return Returns the calendarFont.
*/
public Font getCalendarFont() {
return calendarFont;
}
/**
* @param outOfMonthFont
* The outOfMonthFont to set.
*/
public void setOutOfMonthFont(Font outOfMonthFont) {
this.outOfMonthFont = outOfMonthFont;
}
/**
* @return Returns the outOfMonthFont.
*/
public Font getOutOfMonthFont() {
return outOfMonthFont;
}
public void setToday(SimpleDate today) {
this.today = today;
}
public void setAcceptRange(SimpleDate[] range) {
this.acceptRange = range;
}
/**
* @param titleLabel
* The titleLabel to set.
*/
public void setTitleLabel(JLabel titleLabel) {
this.titleLabel = titleLabel;
}
/**
* @return Returns the titleLabel.
*/
public JLabel getTitleLabel() {
return titleLabel;
}
/**
* Custom table cell renderer for the carendar panel.
*/
protected class DateRenderer extends DefaultTableCellRenderer {
private static final long serialVersionUID = 5817292848730765481L;
public DateRenderer() {
super();
this.setOpaque(true);
this.setHorizontalAlignment(SwingConstants.CENTER);
}
@Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean isFocused, int row,
int col) {
Component compo = super.getTableCellRendererComponent(table, value,
isSelected, isFocused, row, col);
if (compo != null && value != null) {
// 日を書く
String day = null;
Color color = null;
if (value instanceof SimpleDate) {
day = ((SimpleDate) value).toString();
if (today != null
&& today.compareTo((SimpleDate) value) == 0) {
// color = todayBack;
color = (Color) eventColorTable.get("TODAY");
} else {
color = (Color) eventColorTable
.get(((SimpleDate) value).getEventCode());
// color = Color.black;
}
} else if (value instanceof String) {
day = (String) value;
if (today != null
&& today.equalDate(year, month, Integer
.parseInt(day))) {
// color = todayBack;
color = (Color) eventColorTable.get("TODAY");
} else {
color = getCalendarBack();
}
}
((JLabel) compo).setText(day);
if (!isAccept(row, col)) {
this.setForeground(Color.LIGHT_GRAY);
}
// 曜日によって ForeColor を変える
else if (col == 0) {
this.setForeground(getSundayFore());
} else if (col == 6) {
this.setForeground(getSaturdayFore());
} else {
this.setForeground(getWeekdayFore());
}
// このカレンダ月内の日かどうかでフォントを変える
if (tableModel.isOutOfMonth(row, col)) {
this.setFont(getOutOfMonthFont());
this.setBackground(getCalendarBack());
} else {
this.setFont(getCalendarFont());
this.setBackground(color);
}
}
return compo;
}
}
private boolean isAccept(int row, int col) {
// 制限がない場合はOK
if (this.acceptRange==null) {
return true;
}
boolean ok = true;
SimpleDate test = tableModel.getDate(row, col);
// 比較できな場合もOK
if (!(test instanceof SimpleDate)) {
return ok;
}
// 有効開始日がある場合-> testが有効開始日以降
if (this.acceptRange[0]!=null) {
ok = ok && (test.compareTo(this.acceptRange[0])>=0);
}
// 有効終了日がある場合 -> testが有効開始日以前
if (this.acceptRange[1]!=null) {
ok = ok && (test.compareTo(this.acceptRange[1])<=0);
}
return ok;
}
}