From: http://code.google.com/p/gwt-datepicker/
License: GNU Lesser public license!
package com.rntsoft.gwt.client;
import com.google.gwt.i18n.client.*;
import com.google.gwt.user.client.*;
import com.google.gwt.user.client.ui.*;
import com.google.gwt.core.client.*;
import java.util.Date;
/**
* Main class of the DatePicker. It extends the TextBox widget and manages a Date object.
* When it is clicked, it opens a PopupCalendar on which we can select a new date.
* Example of use :
*
* DatePicker datePicker = new DatePicker();
* RootPanel.get().add(datePicker);
*
* You can specify a theme (see the CSS file DatePickerStyle.css) and
* the date to initialize the date picker.
* Enjoy xD
* @author Nicolas Wetzel (nicolas.wetzel@zenika.com)
* @author Jean-Philippe Dournel
*/
class DatePicker extends TextBox {
private PopupCalendar popup;
private Date date;
private DateTimeFormat dateFormatter;
{
dateFormatter = DateUtil.getDateTimeFormat();
popup = new PopupCalendar(this);
}
/**
* Default constructor. It creates a DatePicker which shows the current
* month.
*/
public DatePicker() {
super();
setText("");
sinkEvents(Event.ONCHANGE | Event.ONKEYPRESS);
}
/**
* Create a DatePicker which show a specific Date.
* @param date Date to show
*/
public DatePicker(Date date) {
this();
this.date = date;
synchronizeFromDate();
}
/**
* Create a DatePicker which uses a specific theme.
* @param theme Theme name
*/
public DatePicker(String theme) {
this();
setTheme(theme);
}
/**
* Create a DatePicker which specifics date and theme.
* @param date Date to show
* @param theme Theme name
*/
public DatePicker(Date date, String theme) {
this();
this.date = date;
synchronizeFromDate();
setTheme(theme);
}
/**
* Return the Date contained in the DatePicker.
* @return The Date
*/
public Date getDate() {
return date;
}
/**
* Set the Date of the datePicker and synchronize it with the display.
* @param value
*/
public void setDate(Date value) {
this.date = value;
synchronizeFromDate();
}
/**
* Return the theme name.
* @return Theme name
*/
public String getTheme() {
return popup.getTheme();
}
/**
* Set the theme name.
* @param theme Theme name
*/
public void setTheme(String theme) {
popup.setTheme(theme);
}
public void onBrowserEvent(Event event) {
switch (DOM.eventGetType(event)) {
case Event.ONCLICK:
showPopup();
break;
case Event.ONBLUR:
popup.hidePopupCalendar();
break;
case Event.ONCHANGE:
parseDate();
break;
case Event.ONKEYPRESS:
if (DOM.eventGetKeyCode(event) == 13) {
parseDate();
showPopup();
break;
}
}
}
/**
* Display the date in the DatePicker.
*/
public void synchronizeFromDate() {
this.setText(dateFormatter.format(this.date));
}
/**
* Display the PopupCalendar.
*/
private void showPopup() {
if (this.date != null) {
popup.setDisplayedMonth(this.date);
}
popup.setPopupPosition(this.getAbsoluteLeft()+150, this.getAbsoluteTop());
popup.displayMonth();
}
/**
* Parse the date entered in the DatePicker.
*/
private void parseDate() {
date = dateFormatter.parse(getText());
synchronizeFromDate();
}
}
/**
* Popup used by the datePicker. It represents a calendar and allows the user to
* select a date. It is localizable thanks to the DateTimerFormat class(GWT
* class) and the DateLocale class.
*
* @author Nicolas Wetzel (nicolas.wetzel@zenika.com)
* @author Jean-Philippe Dournel
*/
class PopupCalendar extends PopupPanel {
private boolean leave;
private String theme;
private final DatePicker datePicker;
private DateTimeFormat dayNameFormat;
private DateTimeFormat monthFormat;
private DateTimeFormat dayNumberFormat;
private Label currentMonth;
private Grid daysGrid;
private Date displayedMonth;
{
this.leave = true;
this.theme = "blue";
this.dayNameFormat = DateTimeFormat.getFormat("E");
this.monthFormat = DateTimeFormat.getFormat("MMMM yyyy");
this.dayNumberFormat = DateTimeFormat.getFormat("d");
this.daysGrid = new Grid(7, 7);
}
/**
* Create a calendar popup. You have to call the displayMonth method to
* display the the popup.
*
* @param datePicker
* The date picker on which the popup is attached
*/
public PopupCalendar(DatePicker datePicker) {
super(true);
this.datePicker = datePicker;
this.setStyleName(theme + "-date-picker");
VerticalPanel panel = new VerticalPanel();
this.add(panel);
sinkEvents(Event.ONBLUR);
drawMonthLine(panel);
drawWeekLine(panel);
drawDayGrid(panel);
}
/**
* Return the month displayed by the PopupCalendar.
* @return a Date pointing to the month
*/
public Date getDisplayedMonth() {
return displayedMonth;
}
/**
* Set the month which is display by the PopupCalendar.
* @param displayedMonth The Date to display
*/
public void setDisplayedMonth(Date displayedMonth) {
this.displayedMonth = displayedMonth;
}
/**
* Return the theme used by the PopupCalendar.
* @return Name of the theme
*/
public String getTheme() {
return this.theme;
}
/**
* Set the theme used by the PopupCalendar.
* @param theme Name of the theme
*/
public void setTheme(String theme) {
this.theme = theme;
this.setStyleName(theme + "-date-picker");
}
/**
* Refresh the PopupCalendar and show it.
*/
public void displayMonth() {
if (this.displayedMonth == null) {
if (datePicker.getDate() != null)
this.displayedMonth = datePicker.getDate();
else {
this.displayedMonth = new Date();
}
}
this.drawLabelMoisAnnee();
this.drawDaysGridContent(this.displayedMonth);
show();
}
/**
* This method is destined to be used by the DatePicker in case of focus lost.
* It creates a delay before the popup hides to allows the popup to catch
* a click and eventually update the Date of the DatePicker.
*/
public void hidePopupCalendar() {
DeferredCommand.addCommand(new Command() {
public void execute() {
Timer t = new Timer() {
public void run() {
if (leave) {
hide();
} else {
leave = true;
}
}
};
t.schedule(300);
}
});
}
/**
* Draw the monthLine with contains navigations buttons (change the month
* and the year) and displayed the displayed month.
*
* @param panel
* The panel contained in the popup
*/
private void drawMonthLine(Panel panel) {
Grid monthLine = new Grid(1, 5);
monthLine.setStyleName(theme + "-" + "month-line");
HTMLTable.CellFormatter monthCellFormatter = monthLine.getCellFormatter();
Label previousYear = new Label("?);
previousYear.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
leave = false;
PopupCalendar.this.changeMonth(-12);
}
});
monthLine.setWidget(0, 0, previousYear);
Label previousMonth = new Label("?);
previousMonth.addClickListener(new ClickListener() {
public void onClick(com.google.gwt.user.client.ui.Widget sender) {
leave = false;
PopupCalendar.this.changeMonth(-1);
};
});
monthLine.setWidget(0, 1, previousMonth);
monthCellFormatter.setWidth(0, 2, "60%");
currentMonth = new Label();
currentMonth.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
leave = false;
}
});
monthLine.setWidget(0, 2, currentMonth);
Label nextMonth = new Label("?);
nextMonth.addClickListener(new ClickListener() {
public void onClick(com.google.gwt.user.client.ui.Widget sender) {
leave = false;
PopupCalendar.this.changeMonth(1);
};
});
monthLine.setWidget(0, 3, nextMonth);
Label nextYear = new Label("?);
nextYear.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
leave = false;
PopupCalendar.this.changeMonth(12);
}
});
monthLine.setWidget(0, 4, nextYear);
panel.add(monthLine);
}
/**
* Draw the week line which displays first letter of week days. example : S
* M T ....etc
*
* @param panel
* The panel contained in the popup
*/
private void drawWeekLine(Panel panel) {
Grid weekLine = new Grid(1, 7);
weekLine.setStyleName(theme + "-" + "week-line");
Date weekFirstday = DateUtil.getWeekFirstDay();
for (int i = 0; i < 7; i++) {
weekLine.setText(0, i, dayNameFormat.format(
DateUtil.addDays(weekFirstday, i)).substring(0, 1)
.toUpperCase());
}
panel.add(weekLine);
}
/**
* Display the grid which contains the days. When a day is clicked, it
* updates the Date contained in the DatePicker.
* @param panel
* The panel contained in the popup
*/
private void drawDayGrid(Panel panel) {
this.daysGrid.addTableListener(new TableListener() {
public void onCellClicked(SourcesTableEvents sender, int row,
int cell) {
Date selectedDay = DateUtil.addDays(
getDaysGridOrigin(displayedMonth), row * 7 + cell);
datePicker.setDate(selectedDay);
datePicker.synchronizeFromDate();
PopupCalendar.this.hide();
leave = true;
};
});
daysGrid.setStyleName(theme + "-" + "day-grid");
panel.add(daysGrid);
}
/**
* Update the Label which shows the displayed month (in the month line).
*/
private void drawLabelMoisAnnee() {
currentMonth
.setText(monthFormat.format(this.displayedMonth).toLowerCase());
}
/**
* Draw the days into the days grid. Days drawn are the days of the displayed month
* and few days after and before the displayed month.
* @param displayedMonth Date of the displayed month
*/
private void drawDaysGridContent(Date displayedMonth) {
HTMLTable.CellFormatter cfJours = daysGrid.getCellFormatter();
Date cursor = this.getDaysGridOrigin(displayedMonth);
for (int i = 0; i < 7; i++) {
for (int j = 0; j < 7; j++) {
daysGrid.setText(i, j, dayNumberFormat.format(cursor));
cfJours.removeStyleName(i, j, theme + "-" + "selected");
cfJours.removeStyleName(i, j, theme + "-"
+ "current-month-selected");
cfJours.removeStyleName(i, j, theme + "-" + "other-day");
cfJours.removeStyleName(i, j, theme + "-"
+ "current-month-other-day");
cfJours.removeStyleName(i, j, theme + "-" + "week-end");
cfJours.removeStyleName(i, j, theme + "-"
+ "current-month-week-end");
if (datePicker.getDate() != null
&& DateUtil.areEquals(datePicker.getDate(), cursor))
if (displayedMonth.getMonth() == cursor.getMonth())
cfJours.addStyleName(i, j, theme + "-"
+ "current-month-selected");
else
cfJours.addStyleName(i, j, theme + "-" + "selected");
else if (DateUtil.isInWeekEnd(cursor))
if (displayedMonth.getMonth() == cursor.getMonth())
cfJours.addStyleName(i, j, theme + "-"
+ "current-month-week-end");
else
cfJours.addStyleName(i, j, theme + "-" + "week-end");
else if (displayedMonth.getMonth() == cursor.getMonth())
cfJours.addStyleName(i, j, theme + "-"
+ "current-month-other-day");
else
cfJours.addStyleName(i, j, theme + "-" + "other-day");
cursor = DateUtil.addDays(cursor, 1);
}
}
}
/**
* Change the displayed month.
* @param i Number of month to add to the displayed month
*/
protected void changeMonth(int i) {
this.displayedMonth = DateUtil.addMonths(this.displayedMonth, i);
this.displayMonth();
}
/**
* Return the first day to display. If the month first day is after the 5th
* day of the week, it return the first day of the week. Else, it returns
* the first day of the week before.
*
* @param displayedMonth
* @return The first day to display in the grid
*/
private Date getDaysGridOrigin(Date displayedMonth) {
int currentYear = displayedMonth.getYear();
int currentMonth = displayedMonth.getMonth();
HTMLTable.CellFormatter cfJours = daysGrid.getCellFormatter();
Date monthFirstDay = new Date(currentYear, currentMonth, 1);
int indice = DateUtil.getWeekDayIndex(monthFirstDay);
Date origineTableau;
if (indice > 4) {
origineTableau = DateUtil.getWeekFirstDay(monthFirstDay);
} else {
origineTableau = DateUtil.getWeekFirstDay(DateUtil.addDays(
monthFirstDay, -7));
}
return origineTableau;
}
}
/**
* Utility class which ease the use of Date classes with the DatePicker.
*
* @author Nicolas Wetzel (nicolas.wetzel@zenika.com)
* @author Jean-Philippe Dournel
*
*/
class DateUtil {
/**
* Add days to the Date object.
*
* @param date
* The Date to modify
* @param days
* Number of day to add
* @return The modified Date object
*/
public static Date addDays(Date date, int days) {
return new Date(date.getYear(), date.getMonth(), date.getDate() + days);
}
/**
* Add months to the Date object.
*
* @param date
* The Date to modify
* @param months
* Number of month to add
* @return The modified Date object
*/
public static Date addMonths(Date date, int months) {
return new Date(date.getYear(), date.getMonth() + months, date
.getDate());
}
/**
* Test if two Date objects represent the same day. It tests if the days,
* the months and the years are equals.
*
* @param date1
* First Date
* @param date2
* Second Date
* @return true if the days are the same
*/
public static boolean areEquals(Date date1, Date date2) {
return date1.getDate() == date2.getDate()
&& date1.getMonth() == date2.getMonth()
&& date1.getYear() == date2.getYear();
}
/**
* Return a Date object with represents the first day of a month contained
* in another Date object.
*
* @param date The Date containing the month
* @return The first day of the month
*/
public static Date getMonthFirstDay(Date date) {
Date current = date;
while (current.getDate() != 1) {
current = new Date(current.getYear(), current.getMonth(), current
.getDate() - 1);
}
return current;
}
/**
* Returns the place of the day in the week.
* Example : sunday = 0, monday = 1 ....
* Depends on the locale.
* @param day The day
* @return The place of the day
*/
public static int getWeekDayIndex(Date day) {
DateLocale locale = (DateLocale) GWT.create(DateLocale.class);
int[] daysOrder = locale.getDAY_ORDER();
int dayIndex = day.getDay();
for (int i = 0; i < 7; i++) {
if (dayIndex == daysOrder[i]) {
return i;
}
}
return -1;
}
/**
* Returns the first day of the current week.
* @return Date pointing to the first day
*/
public static Date getWeekFirstDay() {
return getWeekFirstDay(new Date());
}
/**
* Returns the first day of the week containing a Date object.
* @param date The Date
* @return The Date pointing to the first day
*/
public static Date getWeekFirstDay(Date date) {
Date current = date;
DateLocale local = (DateLocale) GWT.create(DateLocale.class);
int firstDay = local.getDAY_ORDER()[0];
while (current.getDay() != firstDay) {
current = new Date(current.getYear(), current.getMonth(), current
.getDate() - 1);
}
return current;
}
/**
* Test if a day is a weekend day.
* @param day The Date to test
* @return true if the Date is a weekend day
*/
public static boolean isInWeekEnd(Date day) {
int dayIndex = day.getDay();
return (dayIndex == 0 | dayIndex == 6) ? true : false;
}
/**
* Get the DateTimeFormat corresponding to the locale.
* @return DateTimeFormat
*/
public static DateTimeFormat getDateTimeFormat() {
DateLocale locale = (DateLocale) GWT.create(DateLocale.class);
DateTimeFormat format = locale.getDateTimeFormat();
return format;
}
}
/**
* This interface is used to extend the localization property
* of the DateTimeFormat of GWT. It adds the support of the days order
* which is not the same in all countries.
* It uses the Localizable interface. See GWT documentation for more detail.
* @author Jean-Philippe Dournel
*
*/
interface DateLocale extends Localizable{
/**
* Returns an array containing the order of days in the week.
* For a week starting by the monday, it'll return {1,2,3,4,5,6,0}.
* @return Array of days index
*/
public int[] getDAY_ORDER();
/**
* Return the DateTimeFormat corresponding to the date pattern used in
* the country. For example : "dd/MM/yyyy" in France and "MM/dd/yyyy" in the US.
* @return DateTimeFormat
*/
public DateTimeFormat getDateTimeFormat();
}
/**
* DateLocale implementation for US.
* @author Jean-Philippe Dournel
*
*/
class DateLocale_ implements DateLocale {
public int[] DAYS_ORDER = { 0, 1, 2, 3, 4, 5, 6 };
public int[] getDAY_ORDER() {
return DAYS_ORDER;
}
public DateTimeFormat getDateTimeFormat() {
DateTimeFormat format = DateTimeFormat.getFormat("MM/dd/yyyy");
return format;
}
}
/**
* DateLocale implementation for UK.
* @author Jean-Philippe Dournel
*
*/
class DateLocale_en_GB implements DateLocale {
public int[] DAYS_ORDER = { 1, 2, 3, 4, 5, 6, 0 };
public int[] getDAY_ORDER() {
return DAYS_ORDER;
}
public DateTimeFormat getDateTimeFormat() {
DateTimeFormat format = DateTimeFormat.getFormat("dd/MM/yyyy");
return format;
}
}
/**
* DateLocale implementation for french-speaking Canada.
* @author Jean-Philippe Dournel
*
*/
class DateLocale_fr_CA implements DateLocale {
public int[] DAYS_ORDER = { 0, 1, 2, 3, 4, 5, 6 };
public int[] getDAY_ORDER() {
return DAYS_ORDER;
}
public DateTimeFormat getDateTimeFormat() {
DateTimeFormat format = DateTimeFormat.getFormat("dd/MM/yyyy");
return format;
}
}
/**
* DateLocale implementation for France.
* @author Jean-Philippe Dournel
*
*/
class DateLocale_fr implements DateLocale {
public int[] DAYS_ORDER = { 1, 2, 3, 4, 5, 6, 0 };
public int[] getDAY_ORDER() {
return DAYS_ORDER;
}
public DateTimeFormat getDateTimeFormat() {
DateTimeFormat format = DateTimeFormat.getFormat("dd/MM/yyyy");
return format;
}
}
public class GWTClient implements EntryPoint{
public void onModuleLoad() {
DatePicker datePicker = new DatePicker("blue");
RootPanel.get().add(datePicker);
}
}
GWT-calendar2.zip( 7 k)