1
|
/*
* Copyright 2007 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.litesoft.GWT.forms.client.components.nonpublic.datepicker;
import java.util.*;
import org.litesoft.GWT.forms.client.components.nonpublic.datepicker.impl.*;
import com.google.gwt.user.client.ui.*;
/**
* DatePicker widget displays a small Gregorian calendar dates to select
* a date by the user.
*
* <p>It has following features:
*
* <ul>
* <li>Fully internationalized by default locale</li>
* <li>Optional display of dates form the adjacent dates months</li>
* <li>Add a special formatting for a given day</li>
* <li>Select any date as the start date and month.
* Today's date is the default selection and the default displayed month.</li>
* </ul>
* </p>
* <p>CSS hooks:
<table border="1" bordercolor="#000000" cellpadding="3" cellspacing="0">
<tbody>
<tr>
<td style="FONT-WEIGHT:bold">
Style name<br/>
</td>
<td style="FONT-WEIGHT:bold">
Widget region affected<br/>
</td>
</tr>
<tr>
<td>
.goog-date-picker<br/>
</td>
<td>
Entire widget<br/>
</td>
</tr>
<tr>
<td>
.goog-date-picker .grid<br/>
</td>
<td>
Grid in the DatePicker.
This includes week names and the date numbers.<br/>
</td>
</tr>
<tr>
<td>
.goog-date-picker .title<br/>
</td>
<td>
Month and Year titles on the top<br/>
</td>
</tr>
<tr>
<td>
.goog-date-picker .control<br/>
</td>
<td>
Month and year increment and decrement buttons<br/>
</td>
</tr>
<tr>
<td>
.goog-date-picker .control-menu<br/>
</td>
<td>
Month and year list available by clicking on them<br/>
</td>
</tr>
<tr>
<td>
.goog-date-picker .control-block<br/>
</td>
<td>
The block of month/year display with its
increment decrement controls<br/>
</td>
</tr>
<tr>
<td>
.goog-date-picker .control-pane<br/>
</td>
<td>
Top area containing month and year controls<br/>
</td>
</tr>
<tr>
<td>
.goog-date-picker .control-today<br/>
</td>
<td>
Clickable today button<br/>
</td>
</tr>
<tr>
<td>
.goog-date-picker .weekday<br/>
</td>
<td>
Any date<br/>
</td>
</tr>
<tr>
<td>
.goog-date-picker .week-names<br/>
</td>
<td>
Weekday names<br/>
</td>
</tr>
<tr>
<td>
.goog-date-picker .week-numbers<br/>
</td>
<td>
Week of the year number<br/>
</td>
</tr>
<tr>
<td>
.goog-date-picker .weekend-start<br/>
</td>
<td>
Weekend startdate<br/>
</td>
</tr>
<tr>
<td>
.goog-date-picker .weekend-end<br/>
</td>
<td>
Weekend end date<br/>
</td>
</tr>
<tr>
<td>
.goog-date-picker .today<br/>
</td>
<td>
Special formatting for today
</td>
</tr>
<tr>
<td>
.goog-date-picker .selected<br/>
</td>
<td>
Special formatting for the selected date<br/>
</td>
</tr>
<tr>
<td>
.goog-date-picker .other-month
</td>
<td>
Opacity reducing formatting for the adjacent months<br/>
</td>
</tr>
</tbody>
</table>
</p>
* <p>Following are the incomplete features.
* Some components of these features exist.
* However, they do not function completely.
* <ul>
* <li>Optional display week numbers</li>
* </ul>
* </p>
* <p>Desired features
* <ul>
* <li>Disable calendar functions beyond an end date.
* This is useful when document archives. Default today.</li>
* <li>Disable calendar functions beyond an start date.
* This is useful for reservation systems. Default today.</li>
* <li>Disable calendar functions on a specific date.
* This is useful for reservation systems.</li>
* <li>Right to Left layout depending on the page layout.</li>
* </ul>
* </p>
*/
@Deprecated
public class DatePicker extends DialogBox
implements ClickListener, ChangeListener, SourcesChangeEvents {
private static final String STYLE_DATE_PICKER = "goog-date-picker";
private static final String STYLE_GRID = "grid";
private static final String STYLE_CONTROL = "control";
private static final String STYLE_CONTROL_BLOCK = "control-block";
private static final String STYLE_CONTROL_PANE = "control-pane";
private static final String STYLE_CONTROL_MENU = "control-menu";
private static final String STYLE_CONTROL_TODAY = "control-today";
private static final String STYLE_TITLE = "title";
private static final String STYLE_WEEK_NAMES = "week-names";
private static final String STYLE_WEEK_NUMBERS = "numbers";
private static final String STYLE_WEEKDAY = "weekday";
private static final String STYLE_WEEKEND_START = "weekend-start";
private static final String STYLE_WEEKEND_END = "weekend-end";
private static final String STYLE_OTHER_MONTHS = "other-month";
private static final String STYLE_TODAY = "today";
private static final String STYLE_SELECTED = "selected";
// Unique numbers representing various actions available in the controls.
private static final int ACTION_PREV_MONTH = 0;
private static final int ACTION_SET_MONTH = 1;
private static final int ACTION_NEXT_MONTH = 2;
private static final int ACTION_PREV_YEAR = 3;
private static final int ACTION_SET_YEAR = 4;
private static final int ACTION_NEXT_YEAR = 5;
private static final int ACTION_TODAY = 6;
private static final int ACTION_CLOSE = 7;
// Unique numbers representing formating actions.
private static final int FORMAT_ACTION_REMOVE = 0;
private static final int FORMAT_ACTION_ADD = 1;
private LocaleCalendarUtils dateTable;
private ChangeListenerCollection changeListeners
= new ChangeListenerCollection();
private HorizontalPanel control = new HorizontalPanel();
private FlexTable grid;
// menu based action
private int weekOfYearOffset = 0;
private boolean showYearMonthListing = true;
private boolean showTodayButton = false;
private int monthAction;
private int yearAction;
private DatePickerCell today;
private final VerticalPanel panel = new VerticalPanel();
private int prevMonthSize;
private int prevMonthDays;
private int currMonthSize;
private int nextMonthDays;
private int gridStart;
/**
* Constructor of the DatePicker class.
*
*/
public DatePicker() {
super(true); // hide dialogue box when clicked outside
dateTable = new LocaleCalendarUtils(false);
dateTable.specialDate(LocaleCalendarUtils.TODAY).setTag(STYLE_TODAY);
dateTable.specialDate(LocaleCalendarUtils.SELECTED).setTag(STYLE_SELECTED);
grid = new FlexTable();
grid.setWidth("100%");
grid.setStyleName(STYLE_GRID);
panel.addStyleName(STYLE_DATE_PICKER);
panel.setHorizontalAlignment(VerticalPanel.ALIGN_CENTER);
drawControlPane();
panel.add(control);
// grid operations
addDaysOfWeek();
initialGrid();
gridUpdate();
panel.add(grid);
// today label
today = dateTable.todayCell();
today.setValue(ACTION_TODAY);
today.addStyleName(STYLE_CONTROL_TODAY);
today.addClickListener(this);
enableTodayButton();
super.setWidget(panel);
}
/**
* Public method complete ClickListner interface. This adds a listener to the
* listeners for Change events. Namely, a date clicked by the user.
*
* @param listener - listener for events
*/
public void addChangeListener(ChangeListener listener) {
changeListeners.add(listener);
}
/**
* Public method onChange which is fired when user clicks on the
* list menu in the widget.
* @param sender - widget on which user clicked.
*
*/
public void onChange(Widget sender) {
if (sender instanceof ListBox) {
ListBox list = (ListBox)sender;
String val = list.getValue(list.getSelectedIndex());
int ival = Integer.valueOf( val ).intValue();
if (list == dateTable.monthNames()) {
action(monthAction, ival);
} else {
action(yearAction, ival);
}
changeListeners.fireChange(this);
}
}
/**
* Public method onClick which is fired when user clicks on the widget.
* @param sender - widget on which user clicked.
*
*/
public void onClick(Widget sender) {
if (sender instanceof DatePickerCell) {
DatePickerCell cell = (DatePickerCell)sender;
int type = cell.type();
int value = cell.value();
if (type == LocaleCalendarUtils.TYPE_CONTROL) {
action(value);
} else {
formatSpecialDates(FORMAT_ACTION_REMOVE);
dateTable.selectedDate(type, value);
if (type == LocaleCalendarUtils.TYPE_CURR_MONTH) {
formatSpecialDates(FORMAT_ACTION_ADD);
} else {
gridUpdate();
}
}
changeListeners.fireChange(this);
}
}
/**
* Public method removeChangeListener() removes a element from the list of
* listeners which will get fired on an widget change event. Example for
* listener change event is user click on a date.
*
* @param listener - listener for widget change events
*
*/
public void removeChangeListener(ChangeListener listener) {
changeListeners.remove(listener);
}
/**
* Public method to get the value of the user selected date for the
* DatePicker object.
*
* @return Date - value of the selected date
*/
public Date selectedDate() {
return dateTable;
}
/**
* Public method to set the default day and date of the widget.
* Date picker for the given month and year will be displayed.
* The given date will be marked as the selected date.
*
* @param date - Java Date value to be set
*/
public void setFullDate(Date date) {
formatSpecialDates(FORMAT_ACTION_REMOVE);
dateTable.setFullDate(date);
gridUpdate();
}
/**
* Public method to set a given special formatting for the given date.
*
* @param date - Date to be formatted specially
* @param style - CSS style to be used
*/
public void setSpecialDate(Date date, String style) {
DatePickerDate specialDay = dateTable.addSpecialDay(date);
specialDay.setTag(style);
formatSpecialDates(FORMAT_ACTION_ADD);
}
/**
* Public method to enable or disable displaying the trailing
* and leading dates from previous and next months.
*
* @param show - A boolean indicating whether to show or not
*
*/
public void showAdjacentMonths(boolean show) {
dateTable.enableAdjacentMonths(show);
gridUpdate();
}
/**
* Public method to display the listing of adjacent months and years by
* clicking on the month or year in the title.
*
* @param show - A boolean indicating whether to show or not
*
*/
public void showTodayButton(boolean show) {
this.showTodayButton = show;
enableTodayButton();
}
/**
* Public method to enable or disable displaying the week number of the year.
* (implementation not completed)
*
* @param show - A boolean indicating whether to show or not
*
*/
public void showWeekOfYear(boolean show) {
this.weekOfYearOffset = show ? 1 : 0;
gridUpdate();
}
/**
* Public method to display the listing of adjacent months and years by
* clicking on the month or year in the title.
*
* @param show - A boolean indicating whether to show or not
*
*/
public void showYearMonthListing(boolean show) {
this.showYearMonthListing = show;
drawControlPane();
}
private void action(int actionNum, int arg) {
formatSpecialDates(FORMAT_ACTION_REMOVE);
switch(actionNum) {
case ACTION_SET_MONTH:
dateTable.setMonth(arg);
break;
case ACTION_SET_YEAR:
dateTable.setYear(arg);
break;
}
gridUpdate();
}
private void action(int actionNum) {
if (actionNum == ACTION_CLOSE) {
this.hide();
} else {
formatSpecialDates(FORMAT_ACTION_REMOVE);
switch(actionNum) {
case ACTION_PREV_MONTH:
dateTable.addMonths(-1);
break;
case ACTION_NEXT_MONTH:
dateTable.addMonths(1);
break;
case ACTION_PREV_YEAR:
dateTable.addMonths(-12);
break;
case ACTION_NEXT_YEAR:
dateTable.addMonths(12);
break;
case ACTION_TODAY:
dateTable.setToday();
break;
}
gridUpdate();
}
}
private void addDaysOfWeek() {
String[] dayOfWeekNames = LocaleCalendarUtils.dayOfWeekNames();
for (int col = 0; col < 7; col++) {
int dayOfWeek = (col + dateTable.weekStart()) % 7;
grid.setText(0, col + weekOfYearOffset, dayOfWeekNames[dayOfWeek]);
grid.getCellFormatter().setStyleName(0, col + weekOfYearOffset,
STYLE_WEEK_NAMES);
}
}
private void addWeekOfYear() {
String[] weekOfYear = dateTable.weekOfYear();
for (int row = 0; row < 7; row++) {
grid.setText(row + 1, 0, weekOfYear[row]);
grid.getCellFormatter().addStyleName(row + 1, 0, STYLE_WEEK_NUMBERS);
}
}
private void colFormat(int tableRow,
int tableCol,
int weekendStart,
int weekendEnd,
DatePickerCell w) {
String style;
if (tableCol == (weekendStart + weekOfYearOffset)) {
style = STYLE_WEEKEND_START;
} else if (tableCol == (weekendEnd + weekOfYearOffset)) {
style = STYLE_WEEKEND_END;
} else {
style = STYLE_WEEKDAY;
}
w.setStyleName(style);
grid.getCellFormatter().addStyleName(tableRow, tableCol, style);
}
private void dateFormat(int diffFromMonthStart, String style, int action) {
if ( diffFromMonthStart < -prevMonthDays
|| diffFromMonthStart >= currMonthSize + nextMonthDays ) {
return;
}
int i = diffFromMonthStart + prevMonthDays + gridStart;
int row = i / 7;
int col = i % 7;
int tableRow = row + 1;
int tableCol = col + weekOfYearOffset;
switch(action) {
case FORMAT_ACTION_REMOVE:
grid.getCellFormatter().removeStyleName(tableRow, tableCol, style);
grid.getWidget(tableRow, tableCol).removeStyleName(style);
break;
case FORMAT_ACTION_ADD:
grid.getCellFormatter().addStyleName(tableRow, tableCol, style);
grid.getWidget(tableRow, tableCol).addStyleName(style);
break;
}
}
private void drawControlPane() {
control.clear();
control.setWidth("100%");
control.setHorizontalAlignment(HorizontalPanel.ALIGN_CENTER);
control.addStyleName(STYLE_CONTROL_PANE);
Widget yearControl = drawControls(dateTable.yearNames(),
dateTable.yearName(),
ACTION_PREV_YEAR,
ACTION_NEXT_YEAR,
ACTION_SET_YEAR );
Widget monthControl = drawControls(dateTable.monthNames(),
dateTable.monthName(),
ACTION_PREV_MONTH,
ACTION_NEXT_MONTH,
ACTION_SET_MONTH );
if (dateTable.isYearBeforeMonth()) {
control.add(yearControl);
control.add(monthControl);
} else {
control.add(monthControl);
control.add(yearControl);
}
}
private Widget drawControls( ListBox names, Label name,
int prev, int next, int set ) {
HorizontalPanel hp = new HorizontalPanel();
hp.setHorizontalAlignment(HorizontalPanel.ALIGN_CENTER);
hp.addStyleName(STYLE_CONTROL_BLOCK);
if (names == dateTable.monthNames()) {
monthAction = set;
} else {
yearAction = set;
}
// move left
if (!showYearMonthListing || set == ACTION_SET_MONTH) {
DatePickerCell left = new DatePickerCell("\u00ab"); // \u00ab is <<
left.setType(LocaleCalendarUtils.TYPE_CONTROL);
left.setValue(prev);
left.addStyleName(STYLE_CONTROL);
left.addClickListener(this);
hp.add(left);
}
// Need list box or not
if (showYearMonthListing) {
names.setVisibleItemCount(1);
names.addStyleName(STYLE_CONTROL_MENU);
names.addChangeListener(this);
hp.add(names);
} else {
name.addStyleName(STYLE_TITLE);
hp.add(name);
}
// move right
if (!showYearMonthListing || set == ACTION_SET_MONTH) {
DatePickerCell right = new DatePickerCell("\u00bb"); // \u00ab is >>
right.setType(LocaleCalendarUtils.TYPE_CONTROL);
right.setValue(next);
right.addStyleName(STYLE_CONTROL);
right.addClickListener(this);
hp.add(right);
}
return hp;
}
private void enableTodayButton () {
if (showTodayButton) {
panel.add(today);
} else {
panel.remove(today);
}
}
private void formatSpecialDates(int action) {
int numSpecialDays = dateTable.numSpecialDays();
for (int i = 0; i < numSpecialDays; i++) {
DatePickerDate date = dateTable.specialDate(i);
dateFormat(date.dayDiff(), date.tag(), action);
}
}
private void gridUpdate() {
DatePickerCell[] dayOfMonthNames = dateTable.dayOfMonthNames();
DatePickerCell[] dayOfMonthNamesPrev = dateTable.dayOfMonthNamesPrev();
DatePickerCell[] dayOfMonthNamesNext = dateTable.dayOfMonthNamesNext();
prevMonthSize = dateTable.prevMonthSize();
prevMonthDays = dateTable.prevMonthDays();
currMonthSize = dateTable.currMonthSize();
nextMonthDays = dateTable.nextMonthDays();
gridStart = dateTable.gridStart();
int weekendStart = dateTable.weekendStart();
int weekendEnd = dateTable.weekendEnd();
if (weekOfYearOffset > 0) {
addWeekOfYear();
}
int rowCount = grid.getRowCount();
for (int i = rowCount - 1; i > 0; i--) { // 0th row is the week names
grid.removeRow(i);
}
for (int i = 0; i < prevMonthDays; i++) {
int row = i / 7;
int col = i % 7;
int tableRow = row + 1;
int tableCol = col + weekOfYearOffset;
int dayOfMonth = prevMonthSize - prevMonthDays + i; // 0 based
colFormat(tableRow, tableCol,
weekendStart, weekendEnd,
dayOfMonthNamesPrev[dayOfMonth]);
grid.setWidget(tableRow, tableCol, dayOfMonthNamesPrev[dayOfMonth]);
grid.getCellFormatter().addStyleName(tableRow, tableCol,
STYLE_OTHER_MONTHS);
}
for (int i = 0; i < currMonthSize; i++) {
int row = (gridStart + prevMonthDays + i) / 7;
int col = (gridStart + prevMonthDays + i) % 7;
int tableRow = row + 1;
int tableCol = col + weekOfYearOffset;
colFormat(tableRow, tableCol, weekendStart, weekendEnd,
dayOfMonthNames[i]);
grid.setWidget(tableRow, tableCol, dayOfMonthNames[i]);
}
for (int i = 0; i < nextMonthDays; i++) {
int row = (currMonthSize + prevMonthDays + i) / 7;
int col = (currMonthSize + prevMonthDays + i) % 7;
int tableRow = row + 1;
int tableCol = col + weekOfYearOffset;
colFormat(tableRow, tableCol, weekendStart, weekendEnd,
dayOfMonthNamesNext[i]);
grid.setWidget(tableRow, tableCol, dayOfMonthNamesNext[i]);
grid.getCellFormatter().addStyleName(tableRow, tableCol,
STYLE_OTHER_MONTHS);
}
formatSpecialDates(FORMAT_ACTION_ADD);
}
private void initialGrid() {
DatePickerCell[] dayOfMonthNamesPrev = dateTable.dayOfMonthNamesPrev();
DatePickerCell[] dayOfMonthNamesNext = dateTable.dayOfMonthNamesNext();
DatePickerCell[] dayOfMonthNames = dateTable.dayOfMonthNames();
for (int i = 0; i < 31; i++) {
dayOfMonthNamesPrev[i].addClickListener(this);
dayOfMonthNamesNext[i].addClickListener(this);
dayOfMonthNames[i].addClickListener(this);
}
}
}
|