com.google.gwt.user.datepicker.client.DefaultCalendarView Maven / Gradle / Ivy
/*
* Copyright 2008 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 com.google.gwt.user.datepicker.client;
import com.google.gwt.aria.client.Roles;
import com.google.gwt.aria.client.SelectedValue;
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
import com.google.gwt.user.datepicker.client.DefaultCalendarView.CellGrid.DateCell;
import java.util.Date;
/**
* Simple calendar view. Not extensible as we wish to evolve it freely over
* time.
*/
@SuppressWarnings(/* Date manipulation required */{"deprecation"})
public final class DefaultCalendarView extends CalendarView {
/**
* Cell grid.
*/
// Javac bug requires that date be fully specified here.
class CellGrid extends CellGridImpl {
/**
* A cell representing a date.
*/
class DateCell extends Cell {
private String cellStyle;
private String dateStyle;
DateCell(boolean isWeekend) {
super(new Date());
cellStyle = css().day();
if (isWeekend) {
cellStyle += " " + css().dayIsWeekend();
}
getElement().setTabIndex(isFiller() ? -1 : 0);
setAriaSelected(false);
}
@Override
public void addStyleName(String styleName) {
if (dateStyle.indexOf(" " + styleName + " ") == -1) {
dateStyle += styleName + " ";
}
updateStyle();
}
public boolean isFiller() {
return !getModel().isInCurrentMonth(getValue());
}
@Override
public void onHighlighted(boolean highlighted) {
setHighlightedDate(getValue());
updateStyle();
}
@Override
public void onSelected(boolean selected) {
if (selected) {
getDatePicker().setValue(getValue(), true);
if (isFiller()) {
getDatePicker().setCurrentMonth(getValue());
}
}
updateStyle();
}
@Override
public void removeStyleName(String styleName) {
dateStyle = dateStyle.replace(" " + styleName + " ", " ");
updateStyle();
}
public void setAriaSelected(boolean value) {
Roles.getGridcellRole().setAriaSelectedState(getElement(), SelectedValue.of(value));
}
@Override
public void updateStyle() {
String accum = dateStyle;
if (isHighlighted()) {
accum += " " + css().dayIsHighlighted();
if (isHighlighted() && isSelected()) {
accum += " " + css().dayIsValueAndHighlighted();
}
}
if (!isEnabled()) {
accum += " " + css().dayIsDisabled();
}
setStyleName(accum);
}
void update(Date current) {
setEnabled(true);
getValue().setTime(current.getTime());
String value = getModel().formatDayOfMonth(getValue());
setText(value);
dateStyle = cellStyle;
if (isFiller()) {
getElement().setTabIndex(-1);
dateStyle += " " + css().dayIsFiller();
} else {
getElement().setTabIndex(0);
String extraStyle = getDatePicker().getStyleOfDate(current);
if (extraStyle != null) {
dateStyle += " " + extraStyle;
}
}
// We want to certify that all date styles have " " before and after
// them for ease of adding to and replacing them.
dateStyle += " ";
updateStyle();
}
private void setText(String value) {
getElement().setInnerText(value);
}
}
CellGrid() {
resize(CalendarModel.WEEKS_IN_MONTH + 1, CalendarModel.DAYS_IN_WEEK);
}
@Override
protected void onSelected(Cell lastSelected, Cell cell) {
}
}
private CellGrid grid = new CellGrid();
private Date firstDisplayed;
private Date lastDisplayed = new Date();
private DateCell ariaSelectedCell;
/**
* Constructor.
*/
public DefaultCalendarView() {
}
@Override
public void addStyleToDate(String styleName, Date date) {
assert getDatePicker().isDateVisible(date) : "You tried to add style " + styleName + " to "
+ date + ". The calendar is currently showing " + getFirstDate()
+ " to " + getLastDate();
getCell(date).addStyleName(styleName);
}
@Override
public Date getFirstDate() {
return firstDisplayed;
}
@Override
public Date getLastDate() {
return lastDisplayed;
}
@Override
public boolean isDateEnabled(Date d) {
return getCell(d).isEnabled();
}
@Override
public void refresh() {
firstDisplayed = getModel().getCurrentFirstDayOfFirstWeek();
if (firstDisplayed.getDate() == 1) {
// show one empty week if date is Monday is the first in month.
addDays(firstDisplayed, -7);
}
lastDisplayed.setTime(firstDisplayed.getTime());
for (int i = 0; i < grid.getNumCells(); i++) {
if (i != 0) {
addDays(lastDisplayed, 1);
}
DateCell cell = (DateCell) grid.getCell(i);
cell.update(lastDisplayed);
}
setAriaSelectedCell(null);
}
private static void addDays(Date date, int days) {
CalendarUtil.addDaysToDate(date, days);
if (date.getHours() != 0) {
// We hit DST transition, try reseting back so follow up days continue showing midnight:
date.setHours(0);
}
}
@Override
public void removeStyleFromDate(String styleName, Date date) {
getCell(date).removeStyleName(styleName);
}
@Override
public void setAriaSelectedCell(Date date) {
if (ariaSelectedCell != null) {
ariaSelectedCell.setAriaSelected(false);
}
DateCell newSelectedCell = date != null ? getCell(date) : null;
if (newSelectedCell != null) {
newSelectedCell.setAriaSelected(true);
}
ariaSelectedCell = newSelectedCell;
}
@Override
public void setEnabledOnDate(boolean enabled, Date date) {
getCell(date).setEnabled(enabled);
}
@Override
public void setup() {
// Preparation
CellFormatter formatter = grid.getCellFormatter();
int weekendStartColumn = -1;
int weekendEndColumn = -1;
// Set up the day labels.
for (int i = 0; i < CalendarModel.DAYS_IN_WEEK; i++) {
int shift = CalendarUtil.getStartingDayOfWeek();
int dayIdx = i + shift < CalendarModel.DAYS_IN_WEEK ? i + shift : i
+ shift - CalendarModel.DAYS_IN_WEEK;
grid.setText(0, i, getModel().formatDayOfWeek(dayIdx));
if (CalendarUtil.isWeekend(dayIdx)) {
formatter.setStyleName(0, i, css().weekendLabel());
if (weekendStartColumn == -1) {
weekendStartColumn = i;
} else {
weekendEndColumn = i;
}
} else {
formatter.setStyleName(0, i, css().weekdayLabel());
}
}
// Set up the calendar grid.
for (int row = 1; row <= CalendarModel.WEEKS_IN_MONTH; row++) {
for (int column = 0; column < CalendarModel.DAYS_IN_WEEK; column++) {
DateCell cell = grid.new DateCell(column == weekendStartColumn
|| column == weekendEndColumn);
grid.setWidget(row, column, cell);
}
}
initWidget(grid);
grid.setStyleName(css().days());
}
private DateCell getCell(Date d) {
int index = CalendarUtil.getDaysBetween(firstDisplayed, d);
if (index < 0 || grid.getNumCells() <= index) {
return null;
}
DateCell cell = (DateCell) grid.getCell(index);
if (cell.getValue().getDate() != d.getDate()) {
throw new IllegalStateException(d + " cannot be associated with cell "
+ cell + " as it has date " + cell.getValue());
}
return cell;
}
}