diff options
author | Artur Signell <artur@vaadin.com> | 2016-08-30 14:18:12 +0300 |
---|---|---|
committer | Artur Signell <artur@vaadin.com> | 2016-08-30 17:19:35 +0300 |
commit | a23bf9481cedb7f981a5ff95f6acc19a7c46ffd2 (patch) | |
tree | d53b3b569d50e9ccfcb60de5b07a642f7845e3c1 | |
parent | b31a71ae635d431c258d387a90bacb27d62a6bbf (diff) | |
download | vaadin-framework-a23bf9481cedb7f981a5ff95f6acc19a7c46ffd2.tar.gz vaadin-framework-a23bf9481cedb7f981a5ff95f6acc19a7c46ffd2.zip |
Move and duplicate client side and state to compatibility package
* DateField
* PopupDateField
* InlineDateField
Change-Id: I7d6c0253435dcdf424b7914d025e81af504be11d
57 files changed, 3962 insertions, 58 deletions
diff --git a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VCalendarPanel.java b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VCalendarPanel.java new file mode 100644 index 0000000000..782cd1ca44 --- /dev/null +++ b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VCalendarPanel.java @@ -0,0 +1,2267 @@ +/* + * Copyright 2000-2016 Vaadin Ltd. + * + * 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.vaadin.v7.client.ui; + +import java.util.Date; +import java.util.Iterator; + +import com.google.gwt.aria.client.Roles; +import com.google.gwt.aria.client.SelectedValue; +import com.google.gwt.dom.client.Element; +import com.google.gwt.dom.client.NativeEvent; +import com.google.gwt.dom.client.Node; +import com.google.gwt.event.dom.client.BlurEvent; +import com.google.gwt.event.dom.client.BlurHandler; +import com.google.gwt.event.dom.client.ChangeEvent; +import com.google.gwt.event.dom.client.ChangeHandler; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.event.dom.client.DomEvent; +import com.google.gwt.event.dom.client.FocusEvent; +import com.google.gwt.event.dom.client.FocusHandler; +import com.google.gwt.event.dom.client.KeyCodes; +import com.google.gwt.event.dom.client.KeyDownEvent; +import com.google.gwt.event.dom.client.KeyDownHandler; +import com.google.gwt.event.dom.client.KeyPressEvent; +import com.google.gwt.event.dom.client.KeyPressHandler; +import com.google.gwt.event.dom.client.MouseDownEvent; +import com.google.gwt.event.dom.client.MouseDownHandler; +import com.google.gwt.event.dom.client.MouseOutEvent; +import com.google.gwt.event.dom.client.MouseOutHandler; +import com.google.gwt.event.dom.client.MouseUpEvent; +import com.google.gwt.event.dom.client.MouseUpHandler; +import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.Timer; +import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.FlexTable; +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.InlineHTML; +import com.google.gwt.user.client.ui.ListBox; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.client.BrowserInfo; +import com.vaadin.client.DateTimeService; +import com.vaadin.client.VConsole; +import com.vaadin.client.WidgetUtil; +import com.vaadin.client.ui.FocusableFlexTable; +import com.vaadin.client.ui.SubPartAware; +import com.vaadin.shared.ui.datefield.Resolution; +import com.vaadin.shared.util.SharedUtil; +import com.vaadin.v7.client.ui.VPopupCalendar; + +@SuppressWarnings("deprecation") +public class VCalendarPanel extends FocusableFlexTable implements + KeyDownHandler, KeyPressHandler, MouseOutHandler, MouseDownHandler, + MouseUpHandler, BlurHandler, FocusHandler, SubPartAware { + + public interface SubmitListener { + + /** + * Called when calendar user triggers a submitting operation in calendar + * panel. Eg. clicking on day or hitting enter. + */ + void onSubmit(); + + /** + * On eg. ESC key. + */ + void onCancel(); + } + + /** + * Blur listener that listens to blur event from the panel + */ + public interface FocusOutListener { + /** + * @return true if the calendar panel is not used after focus moves out + */ + boolean onFocusOut(DomEvent<?> event); + } + + /** + * FocusChangeListener is notified when the panel changes its _focused_ + * value. + */ + public interface FocusChangeListener { + void focusChanged(Date focusedDate); + } + + /** + * Dispatches an event when the panel when time is changed + */ + public interface TimeChangeListener { + + void changed(int hour, int min, int sec, int msec); + } + + /** + * Represents a Date button in the calendar + */ + private class VEventButton extends Button { + public VEventButton() { + addMouseDownHandler(VCalendarPanel.this); + addMouseOutHandler(VCalendarPanel.this); + addMouseUpHandler(VCalendarPanel.this); + } + } + + private static final String CN_FOCUSED = "focused"; + + private static final String CN_TODAY = "today"; + + private static final String CN_SELECTED = "selected"; + + private static final String CN_OFFMONTH = "offmonth"; + + private static final String CN_OUTSIDE_RANGE = "outside-range"; + + /** + * Represents a click handler for when a user selects a value by using the + * mouse + */ + private ClickHandler dayClickHandler = new ClickHandler() { + /* + * (non-Javadoc) + * + * @see + * com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt + * .event.dom.client.ClickEvent) + */ + @Override + public void onClick(ClickEvent event) { + if (!isEnabled() || isReadonly()) { + return; + } + + Date newDate = ((Day) event.getSource()).getDate(); + if (!isDateInsideRange(newDate, Resolution.DAY)) { + return; + } + if (newDate.getMonth() != displayedMonth.getMonth() + || newDate.getYear() != displayedMonth.getYear()) { + // If an off-month date was clicked, we must change the + // displayed month and re-render the calendar (#8931) + displayedMonth.setMonth(newDate.getMonth()); + displayedMonth.setYear(newDate.getYear()); + renderCalendar(); + } + focusDay(newDate); + selectFocused(); + onSubmit(); + } + }; + + private VEventButton prevYear; + + private VEventButton nextYear; + + private VEventButton prevMonth; + + private VEventButton nextMonth; + + private VTime time; + + private FlexTable days = new FlexTable(); + + private Resolution resolution = Resolution.YEAR; + + private Timer mouseTimer; + + private Date value; + + private DateTimeService dateTimeService; + + private boolean showISOWeekNumbers; + + private FocusedDate displayedMonth; + + private FocusedDate focusedDate; + + private Day selectedDay; + + private Day focusedDay; + + private FocusOutListener focusOutListener; + + private SubmitListener submitListener; + + private FocusChangeListener focusChangeListener; + + private TimeChangeListener timeChangeListener; + + private boolean hasFocus = false; + + private VDateField parent; + + private boolean initialRenderDone = false; + + public VCalendarPanel() { + getElement().setId(DOM.createUniqueId()); + setStyleName(VDateField.CLASSNAME + "-calendarpanel"); + Roles.getGridRole().set(getElement()); + + /* + * Firefox auto-repeat works correctly only if we use a key press + * handler, other browsers handle it correctly when using a key down + * handler + */ + if (BrowserInfo.get().isGecko()) { + addKeyPressHandler(this); + } else { + addKeyDownHandler(this); + } + addFocusHandler(this); + addBlurHandler(this); + } + + public void setParentField(VDateField parent) { + this.parent = parent; + } + + /** + * Sets the focus to given date in the current view. Used when moving in the + * calendar with the keyboard. + * + * @param date + * A Date representing the day of month to be focused. Must be + * one of the days currently visible. + */ + private void focusDay(Date date) { + // Only used when calender body is present + if (resolution.getCalendarField() > Resolution.MONTH + .getCalendarField()) { + if (focusedDay != null) { + focusedDay.removeStyleDependentName(CN_FOCUSED); + } + + if (date != null && focusedDate != null) { + focusedDate.setTime(date.getTime()); + int rowCount = days.getRowCount(); + for (int i = 0; i < rowCount; i++) { + int cellCount = days.getCellCount(i); + for (int j = 0; j < cellCount; j++) { + Widget widget = days.getWidget(i, j); + if (widget != null && widget instanceof Day) { + Day curday = (Day) widget; + if (curday.getDate().equals(date)) { + curday.addStyleDependentName(CN_FOCUSED); + focusedDay = curday; + return; + } + } + } + } + } + } + } + + /** + * Sets the selection highlight to a given day in the current view + * + * @param date + * A Date representing the day of month to be selected. Must be + * one of the days currently visible. + * + */ + private void selectDate(Date date) { + if (selectedDay != null) { + selectedDay.removeStyleDependentName(CN_SELECTED); + Roles.getGridcellRole() + .removeAriaSelectedState(selectedDay.getElement()); + } + + int rowCount = days.getRowCount(); + for (int i = 0; i < rowCount; i++) { + int cellCount = days.getCellCount(i); + for (int j = 0; j < cellCount; j++) { + Widget widget = days.getWidget(i, j); + if (widget != null && widget instanceof Day) { + Day curday = (Day) widget; + if (curday.getDate().equals(date)) { + curday.addStyleDependentName(CN_SELECTED); + selectedDay = curday; + Roles.getGridcellRole().setAriaSelectedState( + selectedDay.getElement(), SelectedValue.TRUE); + return; + } + } + } + } + } + + /** + * Updates year, month, day from focusedDate to value + */ + private void selectFocused() { + if (focusedDate != null && isDateInsideRange(focusedDate, resolution)) { + if (value == null) { + // No previously selected value (set to null on server side). + // Create a new date using current date and time + value = new Date(); + } + /* + * #5594 set Date (day) to 1 in order to prevent any kind of + * wrapping of months when later setting the month. (e.g. 31 -> + * month with 30 days -> wraps to the 1st of the following month, + * e.g. 31st of May -> 31st of April = 1st of May) + */ + value.setDate(1); + if (value.getYear() != focusedDate.getYear()) { + value.setYear(focusedDate.getYear()); + } + if (value.getMonth() != focusedDate.getMonth()) { + value.setMonth(focusedDate.getMonth()); + } + if (value.getDate() != focusedDate.getDate()) { + } + // We always need to set the date, even if it hasn't changed, since + // it was forced to 1 above. + value.setDate(focusedDate.getDate()); + + selectDate(focusedDate); + } else { + VConsole.log("Trying to select a the focused date which is NULL!"); + } + } + + protected boolean onValueChange() { + return false; + } + + public Resolution getResolution() { + return resolution; + } + + public void setResolution(Resolution resolution) { + this.resolution = resolution; + if (time != null) { + time.removeFromParent(); + time = null; + } + } + + private boolean isReadonly() { + return parent.isReadonly(); + } + + private boolean isEnabled() { + return parent.isEnabled(); + } + + @Override + public void setStyleName(String style) { + super.setStyleName(style); + if (initialRenderDone) { + // Dynamic updates to the stylename needs to render the calendar to + // update the inner element stylenames + renderCalendar(); + } + } + + @Override + public void setStylePrimaryName(String style) { + super.setStylePrimaryName(style); + if (initialRenderDone) { + // Dynamic updates to the stylename needs to render the calendar to + // update the inner element stylenames + renderCalendar(); + } + } + + private void clearCalendarBody(boolean remove) { + if (!remove) { + // Leave the cells in place but clear their contents + + // This has the side effect of ensuring that the calendar always + // contain 7 rows. + for (int row = 1; row < 7; row++) { + for (int col = 0; col < 8; col++) { + days.setHTML(row, col, " "); + } + } + } else if (getRowCount() > 1) { + removeRow(1); + days.clear(); + } + } + + /** + * Builds the top buttons and current month and year header. + * + * @param needsMonth + * Should the month buttons be visible? + */ + private void buildCalendarHeader(boolean needsMonth) { + + getRowFormatter().addStyleName(0, + parent.getStylePrimaryName() + "-calendarpanel-header"); + + if (prevMonth == null && needsMonth) { + prevMonth = new VEventButton(); + prevMonth.setHTML("‹"); + prevMonth.setStyleName("v-button-prevmonth"); + + prevMonth.setTabIndex(-1); + + nextMonth = new VEventButton(); + nextMonth.setHTML("›"); + nextMonth.setStyleName("v-button-nextmonth"); + + nextMonth.setTabIndex(-1); + + setWidget(0, 3, nextMonth); + setWidget(0, 1, prevMonth); + } else if (prevMonth != null && !needsMonth) { + // Remove month traverse buttons + remove(prevMonth); + remove(nextMonth); + prevMonth = null; + nextMonth = null; + } + + if (prevYear == null) { + + prevYear = new VEventButton(); + prevYear.setHTML("«"); + prevYear.setStyleName("v-button-prevyear"); + + prevYear.setTabIndex(-1); + nextYear = new VEventButton(); + nextYear.setHTML("»"); + nextYear.setStyleName("v-button-nextyear"); + + nextYear.setTabIndex(-1); + setWidget(0, 0, prevYear); + setWidget(0, 4, nextYear); + } + + updateControlButtonRangeStyles(needsMonth); + + final String monthName = needsMonth + ? getDateTimeService().getMonth(displayedMonth.getMonth()) : ""; + final int year = displayedMonth.getYear() + 1900; + + getFlexCellFormatter().setStyleName(0, 2, + parent.getStylePrimaryName() + "-calendarpanel-month"); + getFlexCellFormatter().setStyleName(0, 0, + parent.getStylePrimaryName() + "-calendarpanel-prevyear"); + getFlexCellFormatter().setStyleName(0, 4, + parent.getStylePrimaryName() + "-calendarpanel-nextyear"); + getFlexCellFormatter().setStyleName(0, 3, + parent.getStylePrimaryName() + "-calendarpanel-nextmonth"); + getFlexCellFormatter().setStyleName(0, 1, + parent.getStylePrimaryName() + "-calendarpanel-prevmonth"); + + setHTML(0, 2, + "<span class=\"" + parent.getStylePrimaryName() + + "-calendarpanel-month\">" + monthName + " " + year + + "</span>"); + } + + private void updateControlButtonRangeStyles(boolean needsMonth) { + + if (focusedDate == null) { + return; + } + + if (needsMonth) { + Date prevMonthDate = (Date) focusedDate.clone(); + removeOneMonth(prevMonthDate); + + if (!isDateInsideRange(prevMonthDate, Resolution.MONTH)) { + prevMonth.addStyleName(CN_OUTSIDE_RANGE); + } else { + prevMonth.removeStyleName(CN_OUTSIDE_RANGE); + } + Date nextMonthDate = (Date) focusedDate.clone(); + addOneMonth(nextMonthDate); + if (!isDateInsideRange(nextMonthDate, Resolution.MONTH)) { + nextMonth.addStyleName(CN_OUTSIDE_RANGE); + } else { + nextMonth.removeStyleName(CN_OUTSIDE_RANGE); + } + } + + Date prevYearDate = (Date) focusedDate.clone(); + prevYearDate.setYear(prevYearDate.getYear() - 1); + if (!isDateInsideRange(prevYearDate, Resolution.YEAR)) { + prevYear.addStyleName(CN_OUTSIDE_RANGE); + } else { + prevYear.removeStyleName(CN_OUTSIDE_RANGE); + } + + Date nextYearDate = (Date) focusedDate.clone(); + nextYearDate.setYear(nextYearDate.getYear() + 1); + if (!isDateInsideRange(nextYearDate, Resolution.YEAR)) { + nextYear.addStyleName(CN_OUTSIDE_RANGE); + } else { + nextYear.removeStyleName(CN_OUTSIDE_RANGE); + } + + } + + private DateTimeService getDateTimeService() { + return dateTimeService; + } + + public void setDateTimeService(DateTimeService dateTimeService) { + this.dateTimeService = dateTimeService; + } + + /** + * Returns whether ISO 8601 week numbers should be shown in the value + * selector or not. ISO 8601 defines that a week always starts with a Monday + * so the week numbers are only shown if this is the case. + * + * @return true if week number should be shown, false otherwise + */ + public boolean isShowISOWeekNumbers() { + return showISOWeekNumbers; + } + + public void setShowISOWeekNumbers(boolean showISOWeekNumbers) { + this.showISOWeekNumbers = showISOWeekNumbers; + } + + /** + * Checks inclusively whether a date is inside a range of dates or not. + * + * @param date + * @return + */ + private boolean isDateInsideRange(Date date, Resolution minResolution) { + assert (date != null); + + return isAcceptedByRangeEnd(date, minResolution) + && isAcceptedByRangeStart(date, minResolution); + } + + /** + * Accepts dates greater than or equal to rangeStart, depending on the + * resolution. If the resolution is set to DAY, the range will compare on a + * day-basis. If the resolution is set to YEAR, only years are compared. So + * even if the range is set to one millisecond in next year, also next year + * will be included. + * + * @param date + * @param minResolution + * @return + */ + private boolean isAcceptedByRangeStart(Date date, + Resolution minResolution) { + assert (date != null); + + // rangeStart == null means that we accept all values below rangeEnd + if (rangeStart == null) { + return true; + } + + Date valueDuplicate = (Date) date.clone(); + Date rangeStartDuplicate = (Date) rangeStart.clone(); + + if (minResolution == Resolution.YEAR) { + return valueDuplicate.getYear() >= rangeStartDuplicate.getYear(); + } + if (minResolution == Resolution.MONTH) { + valueDuplicate = clearDateBelowMonth(valueDuplicate); + rangeStartDuplicate = clearDateBelowMonth(rangeStartDuplicate); + } else { + valueDuplicate = clearDateBelowDay(valueDuplicate); + rangeStartDuplicate = clearDateBelowDay(rangeStartDuplicate); + } + + return !rangeStartDuplicate.after(valueDuplicate); + } + + /** + * Accepts dates earlier than or equal to rangeStart, depending on the + * resolution. If the resolution is set to DAY, the range will compare on a + * day-basis. If the resolution is set to YEAR, only years are compared. So + * even if the range is set to one millisecond in next year, also next year + * will be included. + * + * @param date + * @param minResolution + * @return + */ + private boolean isAcceptedByRangeEnd(Date date, Resolution minResolution) { + assert (date != null); + + // rangeEnd == null means that we accept all values above rangeStart + if (rangeEnd == null) { + return true; + } + + Date valueDuplicate = (Date) date.clone(); + Date rangeEndDuplicate = (Date) rangeEnd.clone(); + + if (minResolution == Resolution.YEAR) { + return valueDuplicate.getYear() <= rangeEndDuplicate.getYear(); + } + if (minResolution == Resolution.MONTH) { + valueDuplicate = clearDateBelowMonth(valueDuplicate); + rangeEndDuplicate = clearDateBelowMonth(rangeEndDuplicate); + } else { + valueDuplicate = clearDateBelowDay(valueDuplicate); + rangeEndDuplicate = clearDateBelowDay(rangeEndDuplicate); + } + + return !rangeEndDuplicate.before(valueDuplicate); + + } + + private static Date clearDateBelowMonth(Date date) { + date.setDate(1); + return clearDateBelowDay(date); + } + + private static Date clearDateBelowDay(Date date) { + date.setHours(0); + date.setMinutes(0); + date.setSeconds(0); + // Clearing milliseconds + long time = date.getTime() / 1000; + date = new Date(time * 1000); + return date; + } + + /** + * Builds the day and time selectors of the calendar. + */ + private void buildCalendarBody() { + + final int weekColumn = 0; + final int firstWeekdayColumn = 1; + final int headerRow = 0; + + setWidget(1, 0, days); + setCellPadding(0); + setCellSpacing(0); + getFlexCellFormatter().setColSpan(1, 0, 5); + getFlexCellFormatter().setStyleName(1, 0, + parent.getStylePrimaryName() + "-calendarpanel-body"); + + days.getFlexCellFormatter().setStyleName(headerRow, weekColumn, + "v-week"); + days.setHTML(headerRow, weekColumn, "<strong></strong>"); + // Hide the week column if week numbers are not to be displayed. + days.getFlexCellFormatter().setVisible(headerRow, weekColumn, + isShowISOWeekNumbers()); + + days.getRowFormatter().setStyleName(headerRow, + parent.getStylePrimaryName() + "-calendarpanel-weekdays"); + + if (isShowISOWeekNumbers()) { + days.getFlexCellFormatter().setStyleName(headerRow, weekColumn, + "v-first"); + days.getFlexCellFormatter().setStyleName(headerRow, + firstWeekdayColumn, ""); + days.getRowFormatter().addStyleName(headerRow, + parent.getStylePrimaryName() + + "-calendarpanel-weeknumbers"); + } else { + days.getFlexCellFormatter().setStyleName(headerRow, weekColumn, ""); + days.getFlexCellFormatter().setStyleName(headerRow, + firstWeekdayColumn, "v-first"); + } + + days.getFlexCellFormatter().setStyleName(headerRow, + firstWeekdayColumn + 6, "v-last"); + + // Print weekday names + final int firstDay = getDateTimeService().getFirstDayOfWeek(); + for (int i = 0; i < 7; i++) { + int day = i + firstDay; + if (day > 6) { + day = 0; + } + if (getResolution().getCalendarField() > Resolution.MONTH + .getCalendarField()) { + days.setHTML(headerRow, firstWeekdayColumn + i, "<strong>" + + getDateTimeService().getShortDay(day) + "</strong>"); + } else { + days.setHTML(headerRow, firstWeekdayColumn + i, ""); + } + + Roles.getColumnheaderRole().set(days.getCellFormatter() + .getElement(headerRow, firstWeekdayColumn + i)); + } + + // Zero out hours, minutes, seconds, and milliseconds to compare dates + // without time part + final Date tmp = new Date(); + final Date today = new Date(tmp.getYear(), tmp.getMonth(), + tmp.getDate()); + + final Date selectedDate = value == null ? null + : new Date(value.getYear(), value.getMonth(), value.getDate()); + + final int startWeekDay = getDateTimeService() + .getStartWeekDay(displayedMonth); + final Date curr = (Date) displayedMonth.clone(); + // Start from the first day of the week that at least partially belongs + // to the current month + curr.setDate(1 - startWeekDay); + + // No month has more than 6 weeks so 6 is a safe maximum for rows. + for (int weekOfMonth = 1; weekOfMonth < 7; weekOfMonth++) { + for (int dayOfWeek = 0; dayOfWeek < 7; dayOfWeek++) { + + // Actually write the day of month + Date dayDate = (Date) curr.clone(); + Day day = new Day(dayDate); + + day.setStyleName( + parent.getStylePrimaryName() + "-calendarpanel-day"); + + if (!isDateInsideRange(dayDate, Resolution.DAY)) { + day.addStyleDependentName(CN_OUTSIDE_RANGE); + } + + if (curr.equals(selectedDate)) { + day.addStyleDependentName(CN_SELECTED); + Roles.getGridcellRole().setAriaSelectedState( + day.getElement(), SelectedValue.TRUE); + selectedDay = day; + } + if (curr.equals(today)) { + day.addStyleDependentName(CN_TODAY); + } + if (curr.equals(focusedDate)) { + focusedDay = day; + if (hasFocus) { + day.addStyleDependentName(CN_FOCUSED); + } + } + if (curr.getMonth() != displayedMonth.getMonth()) { + day.addStyleDependentName(CN_OFFMONTH); + } + + days.setWidget(weekOfMonth, firstWeekdayColumn + dayOfWeek, + day); + Roles.getGridcellRole().set(days.getCellFormatter().getElement( + weekOfMonth, firstWeekdayColumn + dayOfWeek)); + + // ISO week numbers if requested + days.getCellFormatter().setVisible(weekOfMonth, weekColumn, + isShowISOWeekNumbers()); + + if (isShowISOWeekNumbers()) { + final String baseCssClass = parent.getStylePrimaryName() + + "-calendarpanel-weeknumber"; + String weekCssClass = baseCssClass; + + int weekNumber = DateTimeService.getISOWeekNumber(curr); + + days.setHTML(weekOfMonth, 0, "<span class=\"" + weekCssClass + + "\"" + ">" + weekNumber + "</span>"); + } + curr.setDate(curr.getDate() + 1); + } + } + } + + /** + * Do we need the time selector + * + * @return True if it is required + */ + private boolean isTimeSelectorNeeded() { + return getResolution().getCalendarField() > Resolution.DAY + .getCalendarField(); + } + + /** + * Updates the calendar and text field with the selected dates. + */ + public void renderCalendar() { + renderCalendar(true); + } + + /** + * For internal use only. May be removed or replaced in the future. + * + * Updates the calendar and text field with the selected dates. + * + * @param updateDate + * The value false prevents setting the selected date of the + * calendar based on focusedDate. That can be used when only the + * resolution of the calendar is changed and no date has been + * selected. + */ + public void renderCalendar(boolean updateDate) { + + super.setStylePrimaryName( + parent.getStylePrimaryName() + "-calendarpanel"); + + if (focusedDate == null) { + Date now = new Date(); + // focusedDate must have zero hours, mins, secs, millisecs + focusedDate = new FocusedDate(now.getYear(), now.getMonth(), + now.getDate()); + displayedMonth = new FocusedDate(now.getYear(), now.getMonth(), 1); + } + + if (updateDate && getResolution().getCalendarField() <= Resolution.MONTH + .getCalendarField() && focusChangeListener != null) { + focusChangeListener.focusChanged(new Date(focusedDate.getTime())); + } + + final boolean needsMonth = getResolution() + .getCalendarField() > Resolution.YEAR.getCalendarField(); + boolean needsBody = getResolution().getCalendarField() >= Resolution.DAY + .getCalendarField(); + buildCalendarHeader(needsMonth); + clearCalendarBody(!needsBody); + if (needsBody) { + buildCalendarBody(); + } + + if (isTimeSelectorNeeded()) { + time = new VTime(); + setWidget(2, 0, time); + getFlexCellFormatter().setColSpan(2, 0, 5); + getFlexCellFormatter().setStyleName(2, 0, + parent.getStylePrimaryName() + "-calendarpanel-time"); + } else if (time != null) { + remove(time); + } + + initialRenderDone = true; + } + + /** + * Moves the focus forward the given number of days. + */ + private void focusNextDay(int days) { + if (focusedDate == null) { + return; + } + + Date focusCopy = ((Date) focusedDate.clone()); + focusCopy.setDate(focusedDate.getDate() + days); + if (!isDateInsideRange(focusCopy, resolution)) { + // If not inside allowed range, then do not move anything + return; + } + + int oldMonth = focusedDate.getMonth(); + int oldYear = focusedDate.getYear(); + focusedDate.setDate(focusedDate.getDate() + days); + + if (focusedDate.getMonth() == oldMonth + && focusedDate.getYear() == oldYear) { + // Month did not change, only move the selection + focusDay(focusedDate); + } else { + + // If the month changed we need to re-render the calendar + displayedMonth.setMonth(focusedDate.getMonth()); + displayedMonth.setYear(focusedDate.getYear()); + renderCalendar(); + } + } + + /** + * Moves the focus backward the given number of days. + */ + private void focusPreviousDay(int days) { + focusNextDay(-days); + } + + /** + * Selects the next month + */ + private void focusNextMonth() { + + if (focusedDate == null) { + return; + } + // Trying to request next month + Date requestedNextMonthDate = (Date) focusedDate.clone(); + addOneMonth(requestedNextMonthDate); + + if (!isDateInsideRange(requestedNextMonthDate, Resolution.MONTH)) { + return; + } + + // Now also checking whether the day is inside the range or not. If not + // inside, + // correct it + if (!isDateInsideRange(requestedNextMonthDate, Resolution.DAY)) { + requestedNextMonthDate = adjustDateToFitInsideRange( + requestedNextMonthDate); + } + + focusedDate.setTime(requestedNextMonthDate.getTime()); + displayedMonth.setMonth(displayedMonth.getMonth() + 1); + + renderCalendar(); + } + + private static void addOneMonth(Date date) { + int currentMonth = date.getMonth(); + int requestedMonth = (currentMonth + 1) % 12; + + date.setMonth(date.getMonth() + 1); + + /* + * If the selected value was e.g. 31.3 the new value would be 31.4 but + * this value is invalid so the new value will be 1.5. This is taken + * care of by decreasing the value until we have the correct month. + */ + while (date.getMonth() != requestedMonth) { + date.setDate(date.getDate() - 1); + } + } + + private static void removeOneMonth(Date date) { + int currentMonth = date.getMonth(); + + date.setMonth(date.getMonth() - 1); + + /* + * If the selected value was e.g. 31.12 the new value would be 31.11 but + * this value is invalid so the new value will be 1.12. This is taken + * care of by decreasing the value until we have the correct month. + */ + while (date.getMonth() == currentMonth) { + date.setDate(date.getDate() - 1); + } + } + + /** + * Selects the previous month + */ + private void focusPreviousMonth() { + + if (focusedDate == null) { + return; + } + Date requestedPreviousMonthDate = (Date) focusedDate.clone(); + removeOneMonth(requestedPreviousMonthDate); + + if (!isDateInsideRange(requestedPreviousMonthDate, Resolution.MONTH)) { + return; + } + + if (!isDateInsideRange(requestedPreviousMonthDate, Resolution.DAY)) { + requestedPreviousMonthDate = adjustDateToFitInsideRange( + requestedPreviousMonthDate); + } + focusedDate.setTime(requestedPreviousMonthDate.getTime()); + displayedMonth.setMonth(displayedMonth.getMonth() - 1); + + renderCalendar(); + } + + /** + * Selects the previous year + */ + private void focusPreviousYear(int years) { + + if (focusedDate == null) { + return; + } + Date previousYearDate = (Date) focusedDate.clone(); + previousYearDate.setYear(previousYearDate.getYear() - years); + // Do not focus if not inside range + if (!isDateInsideRange(previousYearDate, Resolution.YEAR)) { + return; + } + // If we remove one year, but have to roll back a bit, fit it + // into the calendar. Also the months have to be changed + if (!isDateInsideRange(previousYearDate, Resolution.DAY)) { + previousYearDate = adjustDateToFitInsideRange(previousYearDate); + + focusedDate.setYear(previousYearDate.getYear()); + focusedDate.setMonth(previousYearDate.getMonth()); + focusedDate.setDate(previousYearDate.getDate()); + displayedMonth.setYear(previousYearDate.getYear()); + displayedMonth.setMonth(previousYearDate.getMonth()); + } else { + + int currentMonth = focusedDate.getMonth(); + focusedDate.setYear(focusedDate.getYear() - years); + displayedMonth.setYear(displayedMonth.getYear() - years); + /* + * If the focused date was a leap day (Feb 29), the new date becomes + * Mar 1 if the new year is not also a leap year. Set it to Feb 28 + * instead. + */ + if (focusedDate.getMonth() != currentMonth) { + focusedDate.setDate(0); + } + } + + renderCalendar(); + } + + /** + * Selects the next year + */ + private void focusNextYear(int years) { + + if (focusedDate == null) { + return; + } + Date nextYearDate = (Date) focusedDate.clone(); + nextYearDate.setYear(nextYearDate.getYear() + years); + // Do not focus if not inside range + if (!isDateInsideRange(nextYearDate, Resolution.YEAR)) { + return; + } + // If we add one year, but have to roll back a bit, fit it + // into the calendar. Also the months have to be changed + if (!isDateInsideRange(nextYearDate, Resolution.DAY)) { + nextYearDate = adjustDateToFitInsideRange(nextYearDate); + + focusedDate.setYear(nextYearDate.getYear()); + focusedDate.setMonth(nextYearDate.getMonth()); + focusedDate.setDate(nextYearDate.getDate()); + displayedMonth.setYear(nextYearDate.getYear()); + displayedMonth.setMonth(nextYearDate.getMonth()); + } else { + + int currentMonth = focusedDate.getMonth(); + focusedDate.setYear(focusedDate.getYear() + years); + displayedMonth.setYear(displayedMonth.getYear() + years); + /* + * If the focused date was a leap day (Feb 29), the new date becomes + * Mar 1 if the new year is not also a leap year. Set it to Feb 28 + * instead. + */ + if (focusedDate.getMonth() != currentMonth) { + focusedDate.setDate(0); + } + } + + renderCalendar(); + } + + /** + * Handles a user click on the component + * + * @param sender + * The component that was clicked + * @param updateVariable + * Should the value field be updated + * + */ + private void processClickEvent(Widget sender) { + if (!isEnabled() || isReadonly()) { + return; + } + if (sender == prevYear) { + focusPreviousYear(1); + } else if (sender == nextYear) { + focusNextYear(1); + } else if (sender == prevMonth) { + focusPreviousMonth(); + } else if (sender == nextMonth) { + focusNextMonth(); + } + } + + /* + * (non-Javadoc) + * + * @see + * com.google.gwt.event.dom.client.KeyDownHandler#onKeyDown(com.google.gwt + * .event.dom.client.KeyDownEvent) + */ + @Override + public void onKeyDown(KeyDownEvent event) { + handleKeyPress(event); + } + + /* + * (non-Javadoc) + * + * @see + * com.google.gwt.event.dom.client.KeyPressHandler#onKeyPress(com.google + * .gwt.event.dom.client.KeyPressEvent) + */ + @Override + public void onKeyPress(KeyPressEvent event) { + handleKeyPress(event); + } + + /** + * Handles the keypress from both the onKeyPress event and the onKeyDown + * event + * + * @param event + * The keydown/keypress event + */ + private void handleKeyPress(DomEvent<?> event) { + // Special handling for events from time ListBoxes. + if (time != null && time.getElement().isOrHasChild( + (Node) event.getNativeEvent().getEventTarget().cast())) { + int nativeKeyCode = event.getNativeEvent().getKeyCode(); + if (nativeKeyCode == getSelectKey()) { + onSubmit(); // submit if enter key hit down on listboxes + event.preventDefault(); + event.stopPropagation(); + } + if (nativeKeyCode == getCloseKey()) { + onCancel(); // cancel if ESC key hit down on listboxes + event.preventDefault(); + event.stopPropagation(); + } + return; + } + + // Check tabs + int keycode = event.getNativeEvent().getKeyCode(); + if (keycode == KeyCodes.KEY_TAB + && event.getNativeEvent().getShiftKey()) { + if (onTabOut(event)) { + return; + } + } + + // Handle the navigation + if (handleNavigation(keycode, + event.getNativeEvent().getCtrlKey() + || event.getNativeEvent().getMetaKey(), + event.getNativeEvent().getShiftKey())) { + event.preventDefault(); + } + + } + + /** + * Notifies submit-listeners of a submit event + */ + private void onSubmit() { + if (getSubmitListener() != null) { + getSubmitListener().onSubmit(); + } + } + + /** + * Notifies submit-listeners of a cancel event + */ + private void onCancel() { + if (getSubmitListener() != null) { + getSubmitListener().onCancel(); + } + } + + /** + * Handles the keyboard navigation when the resolution is set to years. + * + * @param keycode + * The keycode to process + * @param ctrl + * Is ctrl pressed? + * @param shift + * is shift pressed + * @return Returns true if the keycode was processed, else false + */ + protected boolean handleNavigationYearMode(int keycode, boolean ctrl, + boolean shift) { + + // Ctrl and Shift selection not supported + if (ctrl || shift) { + return false; + } + + else if (keycode == getPreviousKey()) { + focusNextYear(10); // Add 10 years + return true; + } + + else if (keycode == getForwardKey()) { + focusNextYear(1); // Add 1 year + return true; + } + + else if (keycode == getNextKey()) { + focusPreviousYear(10); // Subtract 10 years + return true; + } + + else if (keycode == getBackwardKey()) { + focusPreviousYear(1); // Subtract 1 year + return true; + + } else if (keycode == getSelectKey()) { + value = (Date) focusedDate.clone(); + onSubmit(); + return true; + + } else if (keycode == getResetKey()) { + // Restore showing value the selected value + focusedDate.setTime(value.getTime()); + renderCalendar(); + return true; + + } else if (keycode == getCloseKey()) { + // TODO fire listener, on users responsibility?? + + onCancel(); + return true; + } + return false; + } + + /** + * Handle the keyboard navigation when the resolution is set to MONTH + * + * @param keycode + * The keycode to handle + * @param ctrl + * Was the ctrl key pressed? + * @param shift + * Was the shift key pressed? + * @return + */ + protected boolean handleNavigationMonthMode(int keycode, boolean ctrl, + boolean shift) { + + // Ctrl selection not supported + if (ctrl) { + return false; + + } else if (keycode == getPreviousKey()) { + focusNextYear(1); // Add 1 year + return true; + + } else if (keycode == getForwardKey()) { + focusNextMonth(); // Add 1 month + return true; + + } else if (keycode == getNextKey()) { + focusPreviousYear(1); // Subtract 1 year + return true; + + } else if (keycode == getBackwardKey()) { + focusPreviousMonth(); // Subtract 1 month + return true; + + } else if (keycode == getSelectKey()) { + value = (Date) focusedDate.clone(); + onSubmit(); + return true; + + } else if (keycode == getResetKey()) { + // Restore showing value the selected value + focusedDate.setTime(value.getTime()); + renderCalendar(); + return true; + + } else if (keycode == getCloseKey() || keycode == KeyCodes.KEY_TAB) { + onCancel(); + + // TODO fire close event + + return true; + } + + return false; + } + + /** + * Handle keyboard navigation what the resolution is set to DAY + * + * @param keycode + * The keycode to handle + * @param ctrl + * Was the ctrl key pressed? + * @param shift + * Was the shift key pressed? + * @return Return true if the key press was handled by the method, else + * return false. + */ + protected boolean handleNavigationDayMode(int keycode, boolean ctrl, + boolean shift) { + + // Ctrl key is not in use + if (ctrl) { + return false; + } + + /* + * Jumps to the next day. + */ + if (keycode == getForwardKey() && !shift) { + focusNextDay(1); + return true; + + /* + * Jumps to the previous day + */ + } else if (keycode == getBackwardKey() && !shift) { + focusPreviousDay(1); + return true; + + /* + * Jumps one week forward in the calendar + */ + } else if (keycode == getNextKey() && !shift) { + focusNextDay(7); + return true; + + /* + * Jumps one week back in the calendar + */ + } else if (keycode == getPreviousKey() && !shift) { + focusPreviousDay(7); + return true; + + /* + * Selects the value that is chosen + */ + } else if (keycode == getSelectKey() && !shift) { + selectFocused(); + onSubmit(); // submit + return true; + + } else if (keycode == getCloseKey()) { + onCancel(); + // TODO close event + + return true; + + /* + * Jumps to the next month + */ + } else if (shift && keycode == getForwardKey()) { + focusNextMonth(); + return true; + + /* + * Jumps to the previous month + */ + } else if (shift && keycode == getBackwardKey()) { + focusPreviousMonth(); + return true; + + /* + * Jumps to the next year + */ + } else if (shift && keycode == getPreviousKey()) { + focusNextYear(1); + return true; + + /* + * Jumps to the previous year + */ + } else if (shift && keycode == getNextKey()) { + focusPreviousYear(1); + return true; + + /* + * Resets the selection + */ + } else if (keycode == getResetKey() && !shift) { + // Restore showing value the selected value + focusedDate = new FocusedDate(value.getYear(), value.getMonth(), + value.getDate()); + displayedMonth = new FocusedDate(value.getYear(), value.getMonth(), + 1); + renderCalendar(); + return true; + } + + return false; + } + + /** + * Handles the keyboard navigation + * + * @param keycode + * The key code that was pressed + * @param ctrl + * Was the ctrl key pressed + * @param shift + * Was the shift key pressed + * @return Return true if key press was handled by the component, else + * return false + */ + protected boolean handleNavigation(int keycode, boolean ctrl, + boolean shift) { + if (!isEnabled() || isReadonly()) { + return false; + } + + else if (resolution == Resolution.YEAR) { + return handleNavigationYearMode(keycode, ctrl, shift); + } + + else if (resolution == Resolution.MONTH) { + return handleNavigationMonthMode(keycode, ctrl, shift); + } + + else if (resolution == Resolution.DAY) { + return handleNavigationDayMode(keycode, ctrl, shift); + } + + else { + return handleNavigationDayMode(keycode, ctrl, shift); + } + + } + + /** + * Returns the reset key which will reset the calendar to the previous + * selection. By default this is backspace but it can be overriden to change + * the key to whatever you want. + * + * @return + */ + protected int getResetKey() { + return KeyCodes.KEY_BACKSPACE; + } + + /** + * Returns the select key which selects the value. By default this is the + * enter key but it can be changed to whatever you like by overriding this + * method. + * + * @return + */ + protected int getSelectKey() { + return KeyCodes.KEY_ENTER; + } + + /** + * Returns the key that closes the popup window if this is a VPopopCalendar. + * Else this does nothing. By default this is the Escape key but you can + * change the key to whatever you want by overriding this method. + * + * @return + */ + protected int getCloseKey() { + return KeyCodes.KEY_ESCAPE; + } + + /** + * The key that selects the next day in the calendar. By default this is the + * right arrow key but by overriding this method it can be changed to + * whatever you like. + * + * @return + */ + protected int getForwardKey() { + return KeyCodes.KEY_RIGHT; + } + + /** + * The key that selects the previous day in the calendar. By default this is + * the left arrow key but by overriding this method it can be changed to + * whatever you like. + * + * @return + */ + protected int getBackwardKey() { + return KeyCodes.KEY_LEFT; + } + + /** + * The key that selects the next week in the calendar. By default this is + * the down arrow key but by overriding this method it can be changed to + * whatever you like. + * + * @return + */ + protected int getNextKey() { + return KeyCodes.KEY_DOWN; + } + + /** + * The key that selects the previous week in the calendar. By default this + * is the up arrow key but by overriding this method it can be changed to + * whatever you like. + * + * @return + */ + protected int getPreviousKey() { + return KeyCodes.KEY_UP; + } + + /* + * (non-Javadoc) + * + * @see + * com.google.gwt.event.dom.client.MouseOutHandler#onMouseOut(com.google + * .gwt.event.dom.client.MouseOutEvent) + */ + @Override + public void onMouseOut(MouseOutEvent event) { + if (mouseTimer != null) { + mouseTimer.cancel(); + } + } + + /* + * (non-Javadoc) + * + * @see + * com.google.gwt.event.dom.client.MouseDownHandler#onMouseDown(com.google + * .gwt.event.dom.client.MouseDownEvent) + */ + @Override + public void onMouseDown(MouseDownEvent event) { + // Click-n-hold the left mouse button for fast-forward or fast-rewind. + // Timer is first used for a 500ms delay after mousedown. After that has + // elapsed, another timer is triggered to go off every 150ms. Both + // timers are cancelled on mouseup or mouseout. + if (event.getNativeButton() == NativeEvent.BUTTON_LEFT + && event.getSource() instanceof VEventButton) { + final VEventButton sender = (VEventButton) event.getSource(); + processClickEvent(sender); + mouseTimer = new Timer() { + @Override + public void run() { + mouseTimer = new Timer() { + @Override + public void run() { + processClickEvent(sender); + } + }; + mouseTimer.scheduleRepeating(150); + } + }; + mouseTimer.schedule(500); + } + + } + + /* + * (non-Javadoc) + * + * @see + * com.google.gwt.event.dom.client.MouseUpHandler#onMouseUp(com.google.gwt + * .event.dom.client.MouseUpEvent) + */ + @Override + public void onMouseUp(MouseUpEvent event) { + if (mouseTimer != null) { + mouseTimer.cancel(); + } + } + + /** + * Adjusts a date to fit inside the range, only if outside + * + * @param date + */ + private Date adjustDateToFitInsideRange(Date date) { + if (rangeStart != null && rangeStart.after(date)) { + date = (Date) rangeStart.clone(); + } else if (rangeEnd != null && rangeEnd.before(date)) { + date = (Date) rangeEnd.clone(); + } + return date; + } + + /** + * Sets the data of the Panel. + * + * @param currentDate + * The date to set + */ + public void setDate(Date currentDate) { + + // Check that we are not re-rendering an already active date + if (currentDate == value && currentDate != null) { + return; + } + boolean currentDateWasAdjusted = false; + // Check that selected date is inside the allowed range + if (currentDate != null + && !isDateInsideRange(currentDate, resolution)) { + currentDate = adjustDateToFitInsideRange(currentDate); + currentDateWasAdjusted = true; + } + + Date oldDisplayedMonth = displayedMonth; + value = currentDate; + + // If current date was adjusted, we will not select any date, + // since that will look like a date is selected. Instead we + // only focus on the adjusted value + if (value == null || currentDateWasAdjusted) { + // If ranges enabled, we may need to focus on a different view to + // potentially not get stuck + if (rangeStart != null || rangeEnd != null) { + Date dateThatFitsInsideRange = adjustDateToFitInsideRange( + new Date()); + focusedDate = new FocusedDate(dateThatFitsInsideRange.getYear(), + dateThatFitsInsideRange.getMonth(), + dateThatFitsInsideRange.getDate()); + displayedMonth = new FocusedDate( + dateThatFitsInsideRange.getYear(), + dateThatFitsInsideRange.getMonth(), 1); + // value was adjusted. Set selected to null to not cause + // confusion, but this is only needed (and allowed) when we have + // a day + // resolution + if (getResolution().getCalendarField() >= Resolution.DAY + .getCalendarField()) { + value = null; + } + } else { + focusedDate = displayedMonth = null; + } + } else { + focusedDate = new FocusedDate(value.getYear(), value.getMonth(), + value.getDate()); + displayedMonth = new FocusedDate(value.getYear(), value.getMonth(), + 1); + } + + // Re-render calendar if the displayed month is changed, + // or if a time selector is needed but does not exist. + if ((isTimeSelectorNeeded() && time == null) + || oldDisplayedMonth == null || value == null + || oldDisplayedMonth.getYear() != value.getYear() + || oldDisplayedMonth.getMonth() != value.getMonth()) { + renderCalendar(); + } else { + focusDay(focusedDate); + selectFocused(); + if (isTimeSelectorNeeded()) { + time.updateTimes(); + } + } + + if (!hasFocus) { + focusDay(null); + } + } + + /** + * TimeSelector is a widget consisting of list boxes that modifie the Date + * object that is given for. + * + */ + public class VTime extends FlowPanel implements ChangeHandler { + + private ListBox hours; + + private ListBox mins; + + private ListBox sec; + + private ListBox ampm; + + /** + * Constructor + */ + public VTime() { + super(); + setStyleName(VDateField.CLASSNAME + "-time"); + buildTime(); + } + + private ListBox createListBox() { + ListBox lb = new ListBox(); + lb.setStyleName("v-select"); + lb.addChangeHandler(this); + lb.addBlurHandler(VCalendarPanel.this); + lb.addFocusHandler(VCalendarPanel.this); + return lb; + } + + /** + * Constructs the ListBoxes and updates their value + * + * @param redraw + * Should new instances of the listboxes be created + */ + private void buildTime() { + clear(); + + hours = createListBox(); + if (getDateTimeService().isTwelveHourClock()) { + hours.addItem("12"); + for (int i = 1; i < 12; i++) { + hours.addItem((i < 10) ? "0" + i : "" + i); + } + } else { + for (int i = 0; i < 24; i++) { + hours.addItem((i < 10) ? "0" + i : "" + i); + } + } + + hours.addChangeHandler(this); + if (getDateTimeService().isTwelveHourClock()) { + ampm = createListBox(); + final String[] ampmText = getDateTimeService().getAmPmStrings(); + ampm.addItem(ampmText[0]); + ampm.addItem(ampmText[1]); + ampm.addChangeHandler(this); + } + + if (getResolution().getCalendarField() >= Resolution.MINUTE + .getCalendarField()) { + mins = createListBox(); + for (int i = 0; i < 60; i++) { + mins.addItem((i < 10) ? "0" + i : "" + i); + } + mins.addChangeHandler(this); + } + if (getResolution().getCalendarField() >= Resolution.SECOND + .getCalendarField()) { + sec = createListBox(); + for (int i = 0; i < 60; i++) { + sec.addItem((i < 10) ? "0" + i : "" + i); + } + sec.addChangeHandler(this); + } + + final String delimiter = getDateTimeService().getClockDelimeter(); + if (isReadonly()) { + int h = 0; + if (value != null) { + h = value.getHours(); + } + if (getDateTimeService().isTwelveHourClock()) { + h -= h < 12 ? 0 : 12; + } + add(new VLabel(h < 10 ? "0" + h : "" + h)); + } else { + add(hours); + } + + if (getResolution().getCalendarField() >= Resolution.MINUTE + .getCalendarField()) { + add(new VLabel(delimiter)); + if (isReadonly()) { + final int m = mins.getSelectedIndex(); + add(new VLabel(m < 10 ? "0" + m : "" + m)); + } else { + add(mins); + } + } + if (getResolution().getCalendarField() >= Resolution.SECOND + .getCalendarField()) { + add(new VLabel(delimiter)); + if (isReadonly()) { + final int s = sec.getSelectedIndex(); + add(new VLabel(s < 10 ? "0" + s : "" + s)); + } else { + add(sec); + } + } + if (getResolution() == Resolution.HOUR) { + add(new VLabel(delimiter + "00")); // o'clock + } + if (getDateTimeService().isTwelveHourClock()) { + add(new VLabel(" ")); + if (isReadonly()) { + int i = 0; + if (value != null) { + i = (value.getHours() < 12) ? 0 : 1; + } + add(new VLabel(ampm.getItemText(i))); + } else { + add(ampm); + } + } + + if (isReadonly()) { + return; + } + + // Update times + updateTimes(); + + ListBox lastDropDown = getLastDropDown(); + lastDropDown.addKeyDownHandler(new KeyDownHandler() { + @Override + public void onKeyDown(KeyDownEvent event) { + boolean shiftKey = event.getNativeEvent().getShiftKey(); + if (shiftKey) { + return; + } else { + int nativeKeyCode = event.getNativeKeyCode(); + if (nativeKeyCode == KeyCodes.KEY_TAB) { + onTabOut(event); + } + } + } + }); + + } + + private ListBox getLastDropDown() { + int i = getWidgetCount() - 1; + while (i >= 0) { + Widget widget = getWidget(i); + if (widget instanceof ListBox) { + return (ListBox) widget; + } + i--; + } + return null; + } + + /** + * Updates the valus to correspond to the values in value + */ + public void updateTimes() { + if (value == null) { + value = new Date(); + } + if (getDateTimeService().isTwelveHourClock()) { + int h = value.getHours(); + ampm.setSelectedIndex(h < 12 ? 0 : 1); + h -= ampm.getSelectedIndex() * 12; + hours.setSelectedIndex(h); + } else { + hours.setSelectedIndex(value.getHours()); + } + if (getResolution().getCalendarField() >= Resolution.MINUTE + .getCalendarField()) { + mins.setSelectedIndex(value.getMinutes()); + } + if (getResolution().getCalendarField() >= Resolution.SECOND + .getCalendarField()) { + sec.setSelectedIndex(value.getSeconds()); + } + if (getDateTimeService().isTwelveHourClock()) { + ampm.setSelectedIndex(value.getHours() < 12 ? 0 : 1); + } + + hours.setEnabled(isEnabled()); + if (mins != null) { + mins.setEnabled(isEnabled()); + } + if (sec != null) { + sec.setEnabled(isEnabled()); + } + if (ampm != null) { + ampm.setEnabled(isEnabled()); + } + + } + + private DateTimeService getDateTimeService() { + if (dateTimeService == null) { + dateTimeService = new DateTimeService(); + } + return dateTimeService; + } + + /* + * (non-Javadoc) VT + * + * @see + * com.google.gwt.event.dom.client.ChangeHandler#onChange(com.google.gwt + * .event.dom.client.ChangeEvent) + */ + @Override + public void onChange(ChangeEvent event) { + /* + * Value from dropdowns gets always set for the value. Like year and + * month when resolution is month or year. + */ + if (event.getSource() == hours) { + int h = hours.getSelectedIndex(); + if (getDateTimeService().isTwelveHourClock()) { + h = h + ampm.getSelectedIndex() * 12; + } + value.setHours(h); + if (timeChangeListener != null) { + timeChangeListener.changed(h, value.getMinutes(), + value.getSeconds(), + DateTimeService.getMilliseconds(value)); + } + event.preventDefault(); + event.stopPropagation(); + } else if (event.getSource() == mins) { + final int m = mins.getSelectedIndex(); + value.setMinutes(m); + if (timeChangeListener != null) { + timeChangeListener.changed(value.getHours(), m, + value.getSeconds(), + DateTimeService.getMilliseconds(value)); + } + event.preventDefault(); + event.stopPropagation(); + } else if (event.getSource() == sec) { + final int s = sec.getSelectedIndex(); + value.setSeconds(s); + if (timeChangeListener != null) { + timeChangeListener.changed(value.getHours(), + value.getMinutes(), s, + DateTimeService.getMilliseconds(value)); + } + event.preventDefault(); + event.stopPropagation(); + } else if (event.getSource() == ampm) { + final int h = hours.getSelectedIndex() + + (ampm.getSelectedIndex() * 12); + value.setHours(h); + if (timeChangeListener != null) { + timeChangeListener.changed(h, value.getMinutes(), + value.getSeconds(), + DateTimeService.getMilliseconds(value)); + } + event.preventDefault(); + event.stopPropagation(); + } + } + + } + + /** + * A widget representing a single day in the calendar panel. + */ + private class Day extends InlineHTML { + private final Date date; + + Day(Date date) { + super("" + date.getDate()); + this.date = date; + addClickHandler(dayClickHandler); + } + + public Date getDate() { + return date; + } + } + + public Date getDate() { + return value; + } + + /** + * If true should be returned if the panel will not be used after this + * event. + * + * @param event + * @return + */ + protected boolean onTabOut(DomEvent<?> event) { + if (focusOutListener != null) { + return focusOutListener.onFocusOut(event); + } + return false; + } + + /** + * A focus out listener is triggered when the panel loosed focus. This can + * happen either after a user clicks outside the panel or tabs out. + * + * @param listener + * The listener to trigger + */ + public void setFocusOutListener(FocusOutListener listener) { + focusOutListener = listener; + } + + /** + * The submit listener is called when the user selects a value from the + * calender either by clicking the day or selects it by keyboard. + * + * @param submitListener + * The listener to trigger + */ + public void setSubmitListener(SubmitListener submitListener) { + this.submitListener = submitListener; + } + + /** + * The given FocusChangeListener is notified when the focused date changes + * by user either clicking on a new date or by using the keyboard. + * + * @param listener + * The FocusChangeListener to be notified + */ + public void setFocusChangeListener(FocusChangeListener listener) { + focusChangeListener = listener; + } + + /** + * The time change listener is triggered when the user changes the time. + * + * @param listener + */ + public void setTimeChangeListener(TimeChangeListener listener) { + timeChangeListener = listener; + } + + /** + * Returns the submit listener that listens to selection made from the panel + * + * @return The listener or NULL if no listener has been set + */ + public SubmitListener getSubmitListener() { + return submitListener; + } + + /* + * (non-Javadoc) + * + * @see + * com.google.gwt.event.dom.client.BlurHandler#onBlur(com.google.gwt.event + * .dom.client.BlurEvent) + */ + @Override + public void onBlur(final BlurEvent event) { + if (event.getSource() instanceof VCalendarPanel) { + hasFocus = false; + focusDay(null); + } + } + + /* + * (non-Javadoc) + * + * @see + * com.google.gwt.event.dom.client.FocusHandler#onFocus(com.google.gwt.event + * .dom.client.FocusEvent) + */ + @Override + public void onFocus(FocusEvent event) { + if (event.getSource() instanceof VCalendarPanel) { + hasFocus = true; + + // Focuses the current day if the calendar shows the days + if (focusedDay != null) { + focusDay(focusedDate); + } + } + } + + private static final String SUBPART_NEXT_MONTH = "nextmon"; + private static final String SUBPART_PREV_MONTH = "prevmon"; + + private static final String SUBPART_NEXT_YEAR = "nexty"; + private static final String SUBPART_PREV_YEAR = "prevy"; + private static final String SUBPART_HOUR_SELECT = "h"; + private static final String SUBPART_MINUTE_SELECT = "m"; + private static final String SUBPART_SECS_SELECT = "s"; + private static final String SUBPART_AMPM_SELECT = "ampm"; + private static final String SUBPART_DAY = "day"; + private static final String SUBPART_MONTH_YEAR_HEADER = "header"; + + private Date rangeStart; + + private Date rangeEnd; + + @Override + public String getSubPartName( + com.google.gwt.user.client.Element subElement) { + if (contains(nextMonth, subElement)) { + return SUBPART_NEXT_MONTH; + } else if (contains(prevMonth, subElement)) { + return SUBPART_PREV_MONTH; + } else if (contains(nextYear, subElement)) { + return SUBPART_NEXT_YEAR; + } else if (contains(prevYear, subElement)) { + return SUBPART_PREV_YEAR; + } else if (contains(days, subElement)) { + // Day, find out which dayOfMonth and use that as the identifier + Day day = WidgetUtil.findWidget(subElement, Day.class); + if (day != null) { + Date date = day.getDate(); + int id = date.getDate(); + // Zero or negative ids map to days of the preceding month, + // past-the-end-of-month ids to days of the following month + if (date.getMonth() < displayedMonth.getMonth()) { + id -= DateTimeService.getNumberOfDaysInMonth(date); + } else if (date.getMonth() > displayedMonth.getMonth()) { + id += DateTimeService + .getNumberOfDaysInMonth(displayedMonth); + } + return SUBPART_DAY + id; + } + } else if (time != null) { + if (contains(time.hours, subElement)) { + return SUBPART_HOUR_SELECT; + } else if (contains(time.mins, subElement)) { + return SUBPART_MINUTE_SELECT; + } else if (contains(time.sec, subElement)) { + return SUBPART_SECS_SELECT; + } else if (contains(time.ampm, subElement)) { + return SUBPART_AMPM_SELECT; + + } + } else if (getCellFormatter().getElement(0, 2) + .isOrHasChild(subElement)) { + return SUBPART_MONTH_YEAR_HEADER; + } + + return null; + } + + /** + * Checks if subElement is inside the widget DOM hierarchy. + * + * @param w + * @param subElement + * @return true if {@code w} is a parent of subElement, false otherwise. + */ + private boolean contains(Widget w, Element subElement) { + if (w == null || w.getElement() == null) { + return false; + } + + return w.getElement().isOrHasChild(subElement); + } + + @Override + public com.google.gwt.user.client.Element getSubPartElement( + String subPart) { + if (SUBPART_NEXT_MONTH.equals(subPart)) { + return nextMonth.getElement(); + } + if (SUBPART_PREV_MONTH.equals(subPart)) { + return prevMonth.getElement(); + } + if (SUBPART_NEXT_YEAR.equals(subPart)) { + return nextYear.getElement(); + } + if (SUBPART_PREV_YEAR.equals(subPart)) { + return prevYear.getElement(); + } + if (SUBPART_HOUR_SELECT.equals(subPart)) { + return time.hours.getElement(); + } + if (SUBPART_MINUTE_SELECT.equals(subPart)) { + return time.mins.getElement(); + } + if (SUBPART_SECS_SELECT.equals(subPart)) { + return time.sec.getElement(); + } + if (SUBPART_AMPM_SELECT.equals(subPart)) { + return time.ampm.getElement(); + } + if (subPart.startsWith(SUBPART_DAY)) { + // Zero or negative ids map to days in the preceding month, + // past-the-end-of-month ids to days in the following month + int dayOfMonth = Integer + .parseInt(subPart.substring(SUBPART_DAY.length())); + Date date = new Date(displayedMonth.getYear(), + displayedMonth.getMonth(), dayOfMonth); + Iterator<Widget> iter = days.iterator(); + while (iter.hasNext()) { + Widget w = iter.next(); + if (w instanceof Day) { + Day day = (Day) w; + if (day.getDate().equals(date)) { + return day.getElement(); + } + } + } + } + + if (SUBPART_MONTH_YEAR_HEADER.equals(subPart)) { + return DOM.asOld( + (Element) getCellFormatter().getElement(0, 2).getChild(0)); + } + return null; + } + + @Override + protected void onDetach() { + super.onDetach(); + if (mouseTimer != null) { + mouseTimer.cancel(); + } + } + + /** + * Helper class to inform the screen reader that the user changed the + * selected date. It sets the value of a field that is outside the view, and + * is defined as a live area. That way the screen reader recognizes the + * change and reads it to the user. + */ + public class FocusedDate extends Date { + + public FocusedDate(int year, int month, int date) { + super(year, month, date); + } + + @Override + public void setTime(long time) { + super.setTime(time); + setLabel(); + } + + @Override + @Deprecated + public void setDate(int date) { + super.setDate(date); + setLabel(); + } + + @Override + @Deprecated + public void setMonth(int month) { + super.setMonth(month); + setLabel(); + } + + @Override + @Deprecated + public void setYear(int year) { + super.setYear(year); + setLabel(); + } + + private void setLabel() { + if (parent instanceof VPopupCalendar) { + ((VPopupCalendar) parent).setFocusedDate(this); + } + } + } + + /** + * Sets the start range for this component. The start range is inclusive, + * and it depends on the current resolution, what is considered inside the + * range. + * + * @param startDate + * - the allowed range's start date + */ + public void setRangeStart(Date newRangeStart) { + if (!SharedUtil.equals(rangeStart, newRangeStart)) { + rangeStart = newRangeStart; + if (initialRenderDone) { + // Dynamic updates to the range needs to render the calendar to + // update the element stylenames + renderCalendar(); + } + } + + } + + /** + * Sets the end range for this component. The end range is inclusive, and it + * depends on the current resolution, what is considered inside the range. + * + * @param endDate + * - the allowed range's end date + */ + public void setRangeEnd(Date newRangeEnd) { + if (!SharedUtil.equals(rangeEnd, newRangeEnd)) { + rangeEnd = newRangeEnd; + if (initialRenderDone) { + // Dynamic updates to the range needs to render the calendar to + // update the element stylenames + renderCalendar(); + } + } + } +} diff --git a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VDateField.java b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VDateField.java new file mode 100644 index 0000000000..eca4273e24 --- /dev/null +++ b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VDateField.java @@ -0,0 +1,230 @@ +/* + * Copyright 2000-2016 Vaadin Ltd. + * + * 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.vaadin.v7.client.ui; + +import java.util.Date; + +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.HasEnabled; +import com.vaadin.client.ApplicationConnection; +import com.vaadin.client.DateTimeService; +import com.vaadin.client.ui.Field; +import com.vaadin.shared.ui.datefield.Resolution; + +public class VDateField extends FlowPanel implements Field, HasEnabled { + + public static final String CLASSNAME = "v-datefield"; + + /** For internal use only. May be removed or replaced in the future. */ + public String paintableId; + + /** For internal use only. May be removed or replaced in the future. */ + public ApplicationConnection client; + + /** For internal use only. May be removed or replaced in the future. */ + public boolean immediate; + + @Deprecated + public static final Resolution RESOLUTION_YEAR = Resolution.YEAR; + @Deprecated + public static final Resolution RESOLUTION_MONTH = Resolution.MONTH; + @Deprecated + public static final Resolution RESOLUTION_DAY = Resolution.DAY; + @Deprecated + public static final Resolution RESOLUTION_HOUR = Resolution.HOUR; + @Deprecated + public static final Resolution RESOLUTION_MIN = Resolution.MINUTE; + @Deprecated + public static final Resolution RESOLUTION_SEC = Resolution.SECOND; + + /** For internal use only. May be removed or replaced in the future. */ + public static String resolutionToString(Resolution res) { + if (res.getCalendarField() > Resolution.DAY.getCalendarField()) { + return "full"; + } + if (res == Resolution.DAY) { + return "day"; + } + if (res == Resolution.MONTH) { + return "month"; + } + return "year"; + } + + protected Resolution currentResolution = Resolution.YEAR; + + protected String currentLocale; + + protected boolean readonly; + + protected boolean enabled; + + /** + * The date that is selected in the date field. Null if an invalid date is + * specified. + */ + private Date date = null; + + /** For internal use only. May be removed or replaced in the future. */ + public DateTimeService dts; + + protected boolean showISOWeekNumbers = false; + + public VDateField() { + setStyleName(CLASSNAME); + dts = new DateTimeService(); + } + + /** + * We need this redundant native function because Java's Date object doesn't + * have a setMilliseconds method. + * <p> + * For internal use only. May be removed or replaced in the future. + */ + public static native double getTime(int y, int m, int d, int h, int mi, + int s, int ms) + /*-{ + try { + var date = new Date(2000,1,1,1); // don't use current date here + if(y && y >= 0) date.setFullYear(y); + if(m && m >= 1) date.setMonth(m-1); + if(d && d >= 0) date.setDate(d); + if(h >= 0) date.setHours(h); + if(mi >= 0) date.setMinutes(mi); + if(s >= 0) date.setSeconds(s); + if(ms >= 0) date.setMilliseconds(ms); + return date.getTime(); + } catch (e) { + // TODO print some error message on the console + //console.log(e); + return (new Date()).getTime(); + } + }-*/; + + public int getMilliseconds() { + return DateTimeService.getMilliseconds(date); + } + + public void setMilliseconds(int ms) { + DateTimeService.setMilliseconds(date, ms); + } + + public Resolution getCurrentResolution() { + return currentResolution; + } + + public void setCurrentResolution(Resolution currentResolution) { + this.currentResolution = currentResolution; + } + + public String getCurrentLocale() { + return currentLocale; + } + + public void setCurrentLocale(String currentLocale) { + this.currentLocale = currentLocale; + } + + public Date getCurrentDate() { + return date; + } + + public void setCurrentDate(Date date) { + this.date = date; + } + + public boolean isImmediate() { + return immediate; + } + + public void setImmediate(boolean immediate) { + this.immediate = immediate; + } + + public boolean isReadonly() { + return readonly; + } + + public void setReadonly(boolean readonly) { + this.readonly = readonly; + } + + @Override + public boolean isEnabled() { + return enabled; + } + + @Override + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public DateTimeService getDateTimeService() { + return dts; + } + + public String getId() { + return paintableId; + } + + public ApplicationConnection getClient() { + return client; + } + + /** + * Returns whether ISO 8601 week numbers should be shown in the date + * selector or not. ISO 8601 defines that a week always starts with a Monday + * so the week numbers are only shown if this is the case. + * + * @return true if week number should be shown, false otherwise + */ + public boolean isShowISOWeekNumbers() { + return showISOWeekNumbers; + } + + public void setShowISOWeekNumbers(boolean showISOWeekNumbers) { + this.showISOWeekNumbers = showISOWeekNumbers; + } + + /** + * Returns a copy of the current date. Modifying the returned date will not + * modify the value of this VDateField. Use {@link #setDate(Date)} to change + * the current date. + * <p> + * For internal use only. May be removed or replaced in the future. + * + * @return A copy of the current date + */ + public Date getDate() { + Date current = getCurrentDate(); + if (current == null) { + return null; + } else { + return (Date) getCurrentDate().clone(); + } + } + + /** + * Sets the current date for this VDateField. + * + * @param date + * The new date to use + */ + protected void setDate(Date date) { + this.date = date; + } +} diff --git a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VDateFieldCalendar.java b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VDateFieldCalendar.java new file mode 100644 index 0000000000..16f6b90a5d --- /dev/null +++ b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VDateFieldCalendar.java @@ -0,0 +1,131 @@ +/* + * Copyright 2000-2016 Vaadin Ltd. + * + * 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.vaadin.v7.client.ui; + +import java.util.Date; + +import com.google.gwt.event.dom.client.DomEvent; +import com.vaadin.client.DateTimeService; +import com.vaadin.shared.ui.datefield.Resolution; +import com.vaadin.v7.client.ui.VCalendarPanel.FocusOutListener; +import com.vaadin.v7.client.ui.VCalendarPanel.SubmitListener; + +/** + * A client side implementation for InlineDateField + */ +public class VDateFieldCalendar extends VDateField { + + /** For internal use only. May be removed or replaced in the future. */ + public final VCalendarPanel calendarPanel; + + public VDateFieldCalendar() { + super(); + calendarPanel = new VCalendarPanel(); + calendarPanel.setParentField(this); + add(calendarPanel); + calendarPanel.setSubmitListener(new SubmitListener() { + @Override + public void onSubmit() { + updateValueFromPanel(); + } + + @Override + public void onCancel() { + // TODO Auto-generated method stub + + } + }); + calendarPanel.setFocusOutListener(new FocusOutListener() { + @Override + public boolean onFocusOut(DomEvent<?> event) { + updateValueFromPanel(); + return false; + } + }); + } + + /** + * TODO refactor: almost same method as in VPopupCalendar.updateValue + * <p> + * For internal use only. May be removed or replaced in the future. + */ + + @SuppressWarnings("deprecation") + public void updateValueFromPanel() { + + // If field is invisible at the beginning, client can still be null when + // this function is called. + if (getClient() == null) { + return; + } + + Date date2 = calendarPanel.getDate(); + Date currentDate = getCurrentDate(); + if (currentDate == null || date2.getTime() != currentDate.getTime()) { + setCurrentDate((Date) date2.clone()); + getClient().updateVariable(getId(), "year", date2.getYear() + 1900, + false); + if (getCurrentResolution().getCalendarField() > Resolution.YEAR + .getCalendarField()) { + getClient().updateVariable(getId(), "month", + date2.getMonth() + 1, false); + if (getCurrentResolution().getCalendarField() > Resolution.MONTH + .getCalendarField()) { + getClient().updateVariable(getId(), "day", date2.getDate(), + false); + if (getCurrentResolution() + .getCalendarField() > Resolution.DAY + .getCalendarField()) { + getClient().updateVariable(getId(), "hour", + date2.getHours(), false); + if (getCurrentResolution() + .getCalendarField() > Resolution.HOUR + .getCalendarField()) { + getClient().updateVariable(getId(), "min", + date2.getMinutes(), false); + if (getCurrentResolution() + .getCalendarField() > Resolution.MINUTE + .getCalendarField()) { + getClient().updateVariable(getId(), "sec", + date2.getSeconds(), false); + if (getCurrentResolution() + .getCalendarField() > Resolution.SECOND + .getCalendarField()) { + getClient().updateVariable(getId(), + "msec", DateTimeService + .getMilliseconds(date2), + false); + } + } + } + } + } + } + if (isImmediate()) { + getClient().sendPendingVariableChanges(); + } + } + } + + public void setTabIndex(int tabIndex) { + calendarPanel.getElement().setTabIndex(tabIndex); + } + + public int getTabIndex() { + return calendarPanel.getElement().getTabIndex(); + } +} diff --git a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VPopupCalendar.java b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VPopupCalendar.java new file mode 100644 index 0000000000..a21cfea4ab --- /dev/null +++ b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VPopupCalendar.java @@ -0,0 +1,745 @@ +/* + * Copyright 2000-2016 Vaadin Ltd. + * + * 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.vaadin.v7.client.ui; + +import java.util.Date; + +import com.google.gwt.aria.client.Id; +import com.google.gwt.aria.client.LiveValue; +import com.google.gwt.aria.client.Roles; +import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.Element; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.event.dom.client.DomEvent; +import com.google.gwt.event.dom.client.KeyCodes; +import com.google.gwt.event.dom.client.MouseOutEvent; +import com.google.gwt.event.dom.client.MouseOutHandler; +import com.google.gwt.event.dom.client.MouseOverEvent; +import com.google.gwt.event.dom.client.MouseOverHandler; +import com.google.gwt.event.logical.shared.CloseEvent; +import com.google.gwt.event.logical.shared.CloseHandler; +import com.google.gwt.i18n.client.DateTimeFormat; +import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.Event; +import com.google.gwt.user.client.Timer; +import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.PopupPanel; +import com.google.gwt.user.client.ui.PopupPanel.PositionCallback; +import com.google.gwt.user.client.ui.RootPanel; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.client.BrowserInfo; +import com.vaadin.client.ComputedStyle; +import com.vaadin.client.VConsole; +import com.vaadin.client.ui.Field; +import com.vaadin.client.ui.SubPartAware; +import com.vaadin.client.ui.VOverlay; +import com.vaadin.client.ui.aria.AriaHelper; +import com.vaadin.shared.ui.datefield.Resolution; +import com.vaadin.v7.client.ui.VCalendarPanel.FocusOutListener; +import com.vaadin.v7.client.ui.VCalendarPanel.SubmitListener; +import com.vaadin.v7.shared.ui.datefield.PopupDateFieldState; + +/** + * Represents a date selection component with a text field and a popup date + * selector. + * + * <b>Note:</b> To change the keyboard assignments used in the popup dialog you + * should extend <code>com.vaadin.client.ui.VCalendarPanel</code> and then pass + * set it by calling the <code>setCalendarPanel(VCalendarPanel panel)</code> + * method. + * + */ +public class VPopupCalendar extends VTextualDate + implements Field, ClickHandler, CloseHandler<PopupPanel>, SubPartAware { + + /** For internal use only. May be removed or replaced in the future. */ + public final Button calendarToggle = new Button(); + + /** For internal use only. May be removed or replaced in the future. */ + public VCalendarPanel calendar; + + /** For internal use only. May be removed or replaced in the future. */ + public final VOverlay popup; + + /** For internal use only. May be removed or replaced in the future. */ + public boolean parsable = true; + + private boolean open = false; + + /* + * #14857: If calendarToggle button is clicked when calendar popup is + * already open we should prevent calling openCalendarPanel() in onClick, + * since we don't want to reopen it again right after it closes. + */ + private boolean preventOpenPopupCalendar = false; + private boolean cursorOverCalendarToggleButton = false; + private boolean toggleButtonClosesWithGuarantee = false; + + private boolean textFieldEnabled = true; + + private String captionId; + + private Label selectedDate; + + private Element descriptionForAssisitveDevicesElement; + + public VPopupCalendar() { + super(); + + calendarToggle.setText(""); + calendarToggle.addClickHandler(this); + + calendarToggle.addDomHandler(new MouseOverHandler() { + @Override + public void onMouseOver(MouseOverEvent event) { + cursorOverCalendarToggleButton = true; + } + }, MouseOverEvent.getType()); + + calendarToggle.addDomHandler(new MouseOutHandler() { + @Override + public void onMouseOut(MouseOutEvent event) { + cursorOverCalendarToggleButton = false; + } + }, MouseOutEvent.getType()); + + // -2 instead of -1 to avoid FocusWidget.onAttach to reset it + calendarToggle.getElement().setTabIndex(-2); + + Roles.getButtonRole().set(calendarToggle.getElement()); + Roles.getButtonRole().setAriaHiddenState(calendarToggle.getElement(), + true); + + add(calendarToggle); + + // Description of the usage of the widget for assisitve device users + descriptionForAssisitveDevicesElement = DOM.createDiv(); + descriptionForAssisitveDevicesElement.setInnerText( + PopupDateFieldState.DESCRIPTION_FOR_ASSISTIVE_DEVICES); + AriaHelper.ensureHasId(descriptionForAssisitveDevicesElement); + Roles.getTextboxRole().setAriaDescribedbyProperty(text.getElement(), + Id.of(descriptionForAssisitveDevicesElement)); + AriaHelper.setVisibleForAssistiveDevicesOnly( + descriptionForAssisitveDevicesElement, true); + + calendar = GWT.create(VCalendarPanel.class); + calendar.setParentField(this); + calendar.setFocusOutListener(new FocusOutListener() { + @Override + public boolean onFocusOut(DomEvent<?> event) { + event.preventDefault(); + closeCalendarPanel(); + return true; + } + }); + + // FIXME: Problem is, that the element with the provided id does not + // exist yet in html. This is the same problem as with the context menu. + // Apply here the same fix (#11795) + Roles.getTextboxRole().setAriaControlsProperty(text.getElement(), + Id.of(calendar.getElement())); + Roles.getButtonRole().setAriaControlsProperty( + calendarToggle.getElement(), Id.of(calendar.getElement())); + + calendar.setSubmitListener(new SubmitListener() { + @Override + public void onSubmit() { + // Update internal value and send valuechange event if immediate + updateValue(calendar.getDate()); + + // Update text field (a must when not immediate). + buildDate(true); + + closeCalendarPanel(); + } + + @Override + public void onCancel() { + closeCalendarPanel(); + } + }); + + popup = new VOverlay(true, false); + popup.setOwner(this); + + FlowPanel wrapper = new FlowPanel(); + selectedDate = new Label(); + selectedDate.setStyleName(getStylePrimaryName() + "-selecteddate"); + AriaHelper.setVisibleForAssistiveDevicesOnly(selectedDate.getElement(), + true); + + Roles.getTextboxRole().setAriaLiveProperty(selectedDate.getElement(), + LiveValue.ASSERTIVE); + Roles.getTextboxRole().setAriaAtomicProperty(selectedDate.getElement(), + true); + wrapper.add(selectedDate); + wrapper.add(calendar); + + popup.setWidget(wrapper); + popup.addCloseHandler(this); + + DOM.setElementProperty(calendar.getElement(), "id", + "PID_VAADIN_POPUPCAL"); + + sinkEvents(Event.ONKEYDOWN); + + updateStyleNames(); + } + + @Override + protected void onAttach() { + super.onAttach(); + DOM.appendChild(RootPanel.get().getElement(), + descriptionForAssisitveDevicesElement); + } + + @Override + protected void onDetach() { + super.onDetach(); + descriptionForAssisitveDevicesElement.removeFromParent(); + closeCalendarPanel(); + } + + @SuppressWarnings("deprecation") + public void updateValue(Date newDate) { + Date currentDate = getCurrentDate(); + if (currentDate == null || newDate.getTime() != currentDate.getTime()) { + setCurrentDate((Date) newDate.clone()); + getClient().updateVariable(getId(), "year", + newDate.getYear() + 1900, false); + if (getCurrentResolution().getCalendarField() > Resolution.YEAR + .getCalendarField()) { + getClient().updateVariable(getId(), "month", + newDate.getMonth() + 1, false); + if (getCurrentResolution().getCalendarField() > Resolution.MONTH + .getCalendarField()) { + getClient().updateVariable(getId(), "day", + newDate.getDate(), false); + if (getCurrentResolution() + .getCalendarField() > Resolution.DAY + .getCalendarField()) { + getClient().updateVariable(getId(), "hour", + newDate.getHours(), false); + if (getCurrentResolution() + .getCalendarField() > Resolution.HOUR + .getCalendarField()) { + getClient().updateVariable(getId(), "min", + newDate.getMinutes(), false); + if (getCurrentResolution() + .getCalendarField() > Resolution.MINUTE + .getCalendarField()) { + getClient().updateVariable(getId(), "sec", + newDate.getSeconds(), false); + } + } + } + } + } + } + } + + /** + * Checks whether the text field is enabled. + * + * @see VPopupCalendar#setTextFieldEnabled(boolean) + * @return The current state of the text field. + */ + public boolean isTextFieldEnabled() { + return textFieldEnabled; + } + + /** + * Sets the state of the text field of this component. By default the text + * field is enabled. Disabling it causes only the button for date selection + * to be active, thus preventing the user from entering invalid dates. See + * {@link http://dev.vaadin.com/ticket/6790}. + * + * @param state + */ + public void setTextFieldEnabled(boolean textFieldEnabled) { + this.textFieldEnabled = textFieldEnabled; + updateTextFieldEnabled(); + } + + protected void updateTextFieldEnabled() { + boolean reallyEnabled = isEnabled() && isTextFieldEnabled(); + // IE has a non input disabled themeing that can not be overridden so we + // must fake the functionality using readonly and unselectable + if (BrowserInfo.get().isIE()) { + if (!reallyEnabled) { + text.getElement().setAttribute("unselectable", "on"); + text.getElement().setAttribute("readonly", ""); + text.setTabIndex(-2); + } else if (reallyEnabled + && text.getElement().hasAttribute("unselectable")) { + text.getElement().removeAttribute("unselectable"); + text.getElement().removeAttribute("readonly"); + text.setTabIndex(0); + } + } else { + text.setEnabled(reallyEnabled); + } + + if (reallyEnabled) { + calendarToggle.setTabIndex(-1); + Roles.getButtonRole() + .setAriaHiddenState(calendarToggle.getElement(), true); + } else { + calendarToggle.setTabIndex(0); + Roles.getButtonRole() + .setAriaHiddenState(calendarToggle.getElement(), false); + } + + handleAriaAttributes(); + } + + /** + * Set correct tab index for disabled text field in IE as the value set in + * setTextFieldEnabled(...) gets overridden in + * TextualDateConnection.updateFromUIDL(...) + * + * @since 7.3.1 + */ + public void setTextFieldTabIndex() { + if (BrowserInfo.get().isIE() && !textFieldEnabled) { + // index needs to be -2 because FocusWidget updates -1 to 0 onAttach + text.setTabIndex(-2); + } + } + + @Override + public void bindAriaCaption( + com.google.gwt.user.client.Element captionElement) { + if (captionElement == null) { + captionId = null; + } else { + captionId = captionElement.getId(); + } + + if (isTextFieldEnabled()) { + super.bindAriaCaption(captionElement); + } else { + AriaHelper.bindCaption(calendarToggle, captionElement); + } + + handleAriaAttributes(); + } + + private void handleAriaAttributes() { + Widget removeFromWidget; + Widget setForWidget; + + if (isTextFieldEnabled()) { + setForWidget = text; + removeFromWidget = calendarToggle; + } else { + setForWidget = calendarToggle; + removeFromWidget = text; + } + + Roles.getFormRole() + .removeAriaLabelledbyProperty(removeFromWidget.getElement()); + if (captionId == null) { + Roles.getFormRole() + .removeAriaLabelledbyProperty(setForWidget.getElement()); + } else { + Roles.getFormRole().setAriaLabelledbyProperty( + setForWidget.getElement(), Id.of(captionId)); + } + } + + /* + * (non-Javadoc) + * + * @see + * com.google.gwt.user.client.ui.UIObject#setStyleName(java.lang.String) + */ + @Override + public void setStyleName(String style) { + super.setStyleName(style); + updateStyleNames(); + } + + @Override + public void setStylePrimaryName(String style) { + removeStyleName(getStylePrimaryName() + "-popupcalendar"); + super.setStylePrimaryName(style); + updateStyleNames(); + } + + @Override + protected void updateStyleNames() { + super.updateStyleNames(); + if (getStylePrimaryName() != null && calendarToggle != null) { + addStyleName(getStylePrimaryName() + "-popupcalendar"); + calendarToggle.setStyleName(getStylePrimaryName() + "-button"); + popup.setStyleName(getStylePrimaryName() + "-popup"); + calendar.setStyleName(getStylePrimaryName() + "-calendarpanel"); + } + } + + /** + * Opens the calendar panel popup + */ + public void openCalendarPanel() { + + if (!open && !readonly && isEnabled()) { + open = true; + + if (getCurrentDate() != null) { + calendar.setDate((Date) getCurrentDate().clone()); + } else { + calendar.setDate(new Date()); + } + + // clear previous values + popup.setWidth(""); + popup.setHeight(""); + popup.setPopupPositionAndShow(new PopupPositionCallback()); + } else { + VConsole.error("Cannot reopen popup, it is already open!"); + } + } + + /* + * (non-Javadoc) + * + * @see + * com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt.event + * .dom.client.ClickEvent) + */ + @Override + public void onClick(ClickEvent event) { + if (event.getSource() == calendarToggle && isEnabled()) { + if (!preventOpenPopupCalendar) { + openCalendarPanel(); + } + preventOpenPopupCalendar = false; + } + } + + /* + * (non-Javadoc) + * + * @see + * com.google.gwt.event.logical.shared.CloseHandler#onClose(com.google.gwt + * .event.logical.shared.CloseEvent) + */ + @Override + public void onClose(CloseEvent<PopupPanel> event) { + if (event.getSource() == popup) { + buildDate(); + if (!BrowserInfo.get().isTouchDevice() && textFieldEnabled) { + /* + * Move focus to textbox, unless on touch device (avoids opening + * virtual keyboard) or if textField is disabled. + */ + focus(); + } + + open = false; + + if (cursorOverCalendarToggleButton + && !toggleButtonClosesWithGuarantee) { + preventOpenPopupCalendar = true; + } + + toggleButtonClosesWithGuarantee = false; + } + } + + /** + * Sets focus to Calendar panel. + * + * @param focus + */ + public void setFocus(boolean focus) { + calendar.setFocus(focus); + } + + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + updateTextFieldEnabled(); + calendarToggle.setEnabled(enabled); + Roles.getButtonRole().setAriaDisabledState(calendarToggle.getElement(), + !enabled); + } + + /** + * Sets the content of a special field for assistive devices, so that they + * can recognize the change and inform the user (reading out in case of + * screen reader) + * + * @param selectedDate + * Date that is currently selected + */ + public void setFocusedDate(Date selectedDate) { + this.selectedDate.setText(DateTimeFormat.getFormat("dd, MMMM, yyyy") + .format(selectedDate)); + } + + /** + * For internal use only. May be removed or replaced in the future. + * + * @see com.vaadin.client.ui.VTextualDate#buildDate() + */ + @Override + public void buildDate() { + // Save previous value + String previousValue = getText(); + super.buildDate(); + + // Restore previous value if the input could not be parsed + if (!parsable) { + setText(previousValue); + } + updateTextFieldEnabled(); + } + + /** + * Update the text field contents from the date. See {@link #buildDate()}. + * + * @param forceValid + * true to force the text field to be updated, false to only + * update if the parsable flag is true. + */ + protected void buildDate(boolean forceValid) { + if (forceValid) { + parsable = true; + } + buildDate(); + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.client.ui.VDateField#onBrowserEvent(com.google + * .gwt.user.client.Event) + */ + @Override + public void onBrowserEvent(com.google.gwt.user.client.Event event) { + super.onBrowserEvent(event); + if (DOM.eventGetType(event) == Event.ONKEYDOWN + && event.getKeyCode() == getOpenCalenderPanelKey()) { + openCalendarPanel(); + event.preventDefault(); + } + } + + /** + * Get the key code that opens the calendar panel. By default it is the down + * key but you can override this to be whatever you like + * + * @return + */ + protected int getOpenCalenderPanelKey() { + return KeyCodes.KEY_DOWN; + } + + /** + * Closes the open popup panel + */ + public void closeCalendarPanel() { + if (open) { + toggleButtonClosesWithGuarantee = true; + popup.hide(true); + } + } + + private final String CALENDAR_TOGGLE_ID = "popupButton"; + + @Override + public com.google.gwt.user.client.Element getSubPartElement( + String subPart) { + if (subPart.equals(CALENDAR_TOGGLE_ID)) { + return calendarToggle.getElement(); + } + + return super.getSubPartElement(subPart); + } + + @Override + public String getSubPartName( + com.google.gwt.user.client.Element subElement) { + if (calendarToggle.getElement().isOrHasChild(subElement)) { + return CALENDAR_TOGGLE_ID; + } + + return super.getSubPartName(subElement); + } + + /** + * Set a description that explains the usage of the Widget for users of + * assistive devices. + * + * @param descriptionForAssistiveDevices + * String with the description + */ + public void setDescriptionForAssistiveDevices( + String descriptionForAssistiveDevices) { + descriptionForAssisitveDevicesElement + .setInnerText(descriptionForAssistiveDevices); + } + + /** + * Get the description that explains the usage of the Widget for users of + * assistive devices. + * + * @return String with the description + */ + public String getDescriptionForAssistiveDevices() { + return descriptionForAssisitveDevicesElement.getInnerText(); + } + + /** + * Sets the start range for this component. The start range is inclusive, + * and it depends on the current resolution, what is considered inside the + * range. + * + * @param startDate + * - the allowed range's start date + */ + public void setRangeStart(Date rangeStart) { + calendar.setRangeStart(rangeStart); + } + + /** + * Sets the end range for this component. The end range is inclusive, and it + * depends on the current resolution, what is considered inside the range. + * + * @param endDate + * - the allowed range's end date + */ + public void setRangeEnd(Date rangeEnd) { + calendar.setRangeEnd(rangeEnd); + } + + private class PopupPositionCallback implements PositionCallback { + + @Override + public void setPosition(int offsetWidth, int offsetHeight) { + final int width = offsetWidth; + final int height = offsetHeight; + final int browserWindowWidth = Window.getClientWidth() + + Window.getScrollLeft(); + final int windowHeight = Window.getClientHeight() + + Window.getScrollTop(); + int left = calendarToggle.getAbsoluteLeft(); + + // Add a little extra space to the right to avoid + // problems with IE7 scrollbars and to make it look + // nicer. + int extraSpace = 30; + + boolean overflow = left + width + extraSpace > browserWindowWidth; + if (overflow) { + // Part of the popup is outside the browser window + // (to the right) + left = browserWindowWidth - width - extraSpace; + } + + int top = calendarToggle.getAbsoluteTop(); + int extraHeight = 2; + boolean verticallyRepositioned = false; + ComputedStyle style = new ComputedStyle(popup.getElement()); + int[] margins = style.getMargin(); + int desiredPopupBottom = top + height + + calendarToggle.getOffsetHeight() + margins[0] + + margins[2]; + + if (desiredPopupBottom > windowHeight) { + int updatedLeft = left; + left = getLeftPosition(left, width, style, overflow); + + // if position has not been changed then it means there is no + // space to make popup fully visible + if (updatedLeft == left) { + // let's try to show popup on the top of the field + int updatedTop = top - extraHeight - height - margins[0] + - margins[2]; + verticallyRepositioned = updatedTop >= 0; + if (verticallyRepositioned) { + top = updatedTop; + } + } + // Part of the popup is outside the browser window + // (below) + if (!verticallyRepositioned) { + verticallyRepositioned = true; + top = windowHeight - height - extraSpace + extraHeight; + } + } + if (verticallyRepositioned) { + popup.setPopupPosition(left, top); + } else { + popup.setPopupPosition(left, + top + calendarToggle.getOffsetHeight() + extraHeight); + } + doSetFocus(); + } + + private int getLeftPosition(int left, int width, ComputedStyle style, + boolean overflow) { + if (positionRightSide()) { + // Show to the right of the popup button unless we + // are in the lower right corner of the screen + if (overflow) { + return left; + } else { + return left + calendarToggle.getOffsetWidth(); + } + } else { + int[] margins = style.getMargin(); + int desiredLeftPosition = calendarToggle.getAbsoluteLeft() + - width - margins[1] - margins[3]; + if (desiredLeftPosition >= 0) { + return desiredLeftPosition; + } else { + return left; + } + } + } + + private boolean positionRightSide() { + int buttonRightSide = calendarToggle.getAbsoluteLeft() + + calendarToggle.getOffsetWidth(); + int textRightSide = text.getAbsoluteLeft() + text.getOffsetWidth(); + return buttonRightSide >= textRightSide; + } + + private void doSetFocus() { + /* + * We have to wait a while before focusing since the popup needs to + * be opened before we can focus + */ + Timer focusTimer = new Timer() { + @Override + public void run() { + setFocus(true); + } + }; + + focusTimer.schedule(100); + } + } + +} diff --git a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VTextualDate.java b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VTextualDate.java new file mode 100644 index 0000000000..329382d605 --- /dev/null +++ b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VTextualDate.java @@ -0,0 +1,410 @@ +/* + * Copyright 2000-2016 Vaadin Ltd. + * + * 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.vaadin.v7.client.ui; + +import java.util.Date; + +import com.google.gwt.aria.client.Roles; +import com.google.gwt.event.dom.client.BlurEvent; +import com.google.gwt.event.dom.client.BlurHandler; +import com.google.gwt.event.dom.client.ChangeEvent; +import com.google.gwt.event.dom.client.ChangeHandler; +import com.google.gwt.event.dom.client.FocusEvent; +import com.google.gwt.event.dom.client.FocusHandler; +import com.google.gwt.event.dom.client.KeyCodes; +import com.google.gwt.event.dom.client.KeyDownEvent; +import com.google.gwt.event.dom.client.KeyDownHandler; +import com.google.gwt.user.client.ui.TextBox; +import com.vaadin.client.BrowserInfo; +import com.vaadin.client.Focusable; +import com.vaadin.client.LocaleNotLoadedException; +import com.vaadin.client.LocaleService; +import com.vaadin.client.VConsole; +import com.vaadin.client.ui.Field; +import com.vaadin.client.ui.SubPartAware; +import com.vaadin.client.ui.aria.AriaHelper; +import com.vaadin.client.ui.aria.HandlesAriaCaption; +import com.vaadin.client.ui.aria.HandlesAriaInvalid; +import com.vaadin.client.ui.aria.HandlesAriaRequired; +import com.vaadin.shared.EventId; +import com.vaadin.shared.ui.datefield.Resolution; + +public class VTextualDate extends VDateField implements Field, ChangeHandler, + Focusable, SubPartAware, HandlesAriaCaption, HandlesAriaInvalid, + HandlesAriaRequired, KeyDownHandler { + + private static final String PARSE_ERROR_CLASSNAME = "-parseerror"; + + /** For internal use only. May be removed or replaced in the future. */ + public final TextBox text; + + /** For internal use only. May be removed or replaced in the future. */ + public String formatStr; + + /** For internal use only. May be removed or replaced in the future. */ + public boolean lenient; + + private static final String CLASSNAME_PROMPT = "prompt"; + + /** For internal use only. May be removed or replaced in the future. */ + public static final String ATTR_INPUTPROMPT = "prompt"; + + /** For internal use only. May be removed or replaced in the future. */ + public String inputPrompt = ""; + + private boolean prompting = false; + + public VTextualDate() { + super(); + text = new TextBox(); + text.addChangeHandler(this); + text.addFocusHandler(new FocusHandler() { + @Override + public void onFocus(FocusEvent event) { + text.addStyleName(VTextField.CLASSNAME + "-" + + VTextField.CLASSNAME_FOCUS); + if (prompting) { + text.setText(""); + setPrompting(false); + } + if (getClient() != null && getClient() + .hasEventListeners(VTextualDate.this, EventId.FOCUS)) { + getClient().updateVariable(getId(), EventId.FOCUS, "", + true); + } + + // Needed for tooltip event handling + VTextualDate.this.fireEvent(event); + } + }); + text.addBlurHandler(new BlurHandler() { + @Override + public void onBlur(BlurEvent event) { + text.removeStyleName(VTextField.CLASSNAME + "-" + + VTextField.CLASSNAME_FOCUS); + String value = getText(); + setPrompting(inputPrompt != null + && (value == null || "".equals(value))); + if (prompting) { + text.setText(readonly ? "" : inputPrompt); + } + if (getClient() != null && getClient() + .hasEventListeners(VTextualDate.this, EventId.BLUR)) { + getClient().updateVariable(getId(), EventId.BLUR, "", true); + } + + // Needed for tooltip event handling + VTextualDate.this.fireEvent(event); + } + }); + if (BrowserInfo.get().isIE()) { + addDomHandler(this, KeyDownEvent.getType()); + } + add(text); + } + + protected void updateStyleNames() { + if (text != null) { + text.setStyleName(VTextField.CLASSNAME); + text.addStyleName(getStylePrimaryName() + "-textfield"); + } + } + + protected String getFormatString() { + if (formatStr == null) { + if (currentResolution == Resolution.YEAR) { + formatStr = "yyyy"; // force full year + } else { + + try { + String frmString = LocaleService + .getDateFormat(currentLocale); + frmString = cleanFormat(frmString); + // String delim = LocaleService + // .getClockDelimiter(currentLocale); + if (currentResolution.getCalendarField() >= Resolution.HOUR + .getCalendarField()) { + if (dts.isTwelveHourClock()) { + frmString += " hh"; + } else { + frmString += " HH"; + } + if (currentResolution + .getCalendarField() >= Resolution.MINUTE + .getCalendarField()) { + frmString += ":mm"; + if (currentResolution + .getCalendarField() >= Resolution.SECOND + .getCalendarField()) { + frmString += ":ss"; + } + } + if (dts.isTwelveHourClock()) { + frmString += " aaa"; + } + + } + + formatStr = frmString; + } catch (LocaleNotLoadedException e) { + // TODO should die instead? Can the component survive + // without format string? + VConsole.error(e); + } + } + } + return formatStr; + } + + @Override + public void bindAriaCaption( + com.google.gwt.user.client.Element captionElement) { + AriaHelper.bindCaption(text, captionElement); + } + + @Override + public void setAriaRequired(boolean required) { + AriaHelper.handleInputRequired(text, required); + } + + @Override + public void setAriaInvalid(boolean invalid) { + AriaHelper.handleInputInvalid(text, invalid); + } + + /** + * Updates the text field according to the current date (provided by + * {@link #getDate()}). Takes care of updating text, enabling and disabling + * the field, setting/removing readonly status and updating readonly styles. + * <p> + * For internal use only. May be removed or replaced in the future. + * <p> + * TODO: Split part of this into a method that only updates the text as this + * is what usually is needed except for updateFromUIDL. + */ + public void buildDate() { + removeStyleName(getStylePrimaryName() + PARSE_ERROR_CLASSNAME); + // Create the initial text for the textfield + String dateText; + Date currentDate = getDate(); + if (currentDate != null) { + dateText = getDateTimeService().formatDate(currentDate, + getFormatString()); + } else { + dateText = ""; + } + + setText(dateText); + text.setEnabled(enabled); + text.setReadOnly(readonly); + + if (readonly) { + text.addStyleName("v-readonly"); + Roles.getTextboxRole().setAriaReadonlyProperty(text.getElement(), + true); + } else { + text.removeStyleName("v-readonly"); + Roles.getTextboxRole() + .removeAriaReadonlyProperty(text.getElement()); + } + + } + + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + text.setEnabled(enabled); + } + + protected void setPrompting(boolean prompting) { + this.prompting = prompting; + if (prompting) { + addStyleDependentName(CLASSNAME_PROMPT); + } else { + removeStyleDependentName(CLASSNAME_PROMPT); + } + } + + @Override + @SuppressWarnings("deprecation") + public void onChange(ChangeEvent event) { + if (!text.getText().equals("")) { + try { + String enteredDate = text.getText(); + + setDate(getDateTimeService().parseDate(enteredDate, + getFormatString(), lenient)); + + if (lenient) { + // If date value was leniently parsed, normalize text + // presentation. + // FIXME: Add a description/example here of when this is + // needed + text.setValue(getDateTimeService().formatDate(getDate(), + getFormatString()), false); + } + + // remove possibly added invalid value indication + removeStyleName(getStylePrimaryName() + PARSE_ERROR_CLASSNAME); + } catch (final Exception e) { + VConsole.log(e); + + addStyleName(getStylePrimaryName() + PARSE_ERROR_CLASSNAME); + // this is a hack that may eventually be removed + getClient().updateVariable(getId(), "lastInvalidDateString", + text.getText(), false); + setDate(null); + } + } else { + setDate(null); + // remove possibly added invalid value indication + removeStyleName(getStylePrimaryName() + PARSE_ERROR_CLASSNAME); + } + // always send the date string + getClient().updateVariable(getId(), "dateString", text.getText(), + false); + + // Update variables + // (only the smallest defining resolution needs to be + // immediate) + Date currentDate = getDate(); + getClient().updateVariable(getId(), "year", + currentDate != null ? currentDate.getYear() + 1900 : -1, + currentResolution == Resolution.YEAR && immediate); + if (currentResolution.getCalendarField() >= Resolution.MONTH + .getCalendarField()) { + getClient().updateVariable(getId(), "month", + currentDate != null ? currentDate.getMonth() + 1 : -1, + currentResolution == Resolution.MONTH && immediate); + } + if (currentResolution.getCalendarField() >= Resolution.DAY + .getCalendarField()) { + getClient().updateVariable(getId(), "day", + currentDate != null ? currentDate.getDate() : -1, + currentResolution == Resolution.DAY && immediate); + } + if (currentResolution.getCalendarField() >= Resolution.HOUR + .getCalendarField()) { + getClient().updateVariable(getId(), "hour", + currentDate != null ? currentDate.getHours() : -1, + currentResolution == Resolution.HOUR && immediate); + } + if (currentResolution.getCalendarField() >= Resolution.MINUTE + .getCalendarField()) { + getClient().updateVariable(getId(), "min", + currentDate != null ? currentDate.getMinutes() : -1, + currentResolution == Resolution.MINUTE && immediate); + } + if (currentResolution.getCalendarField() >= Resolution.SECOND + .getCalendarField()) { + getClient().updateVariable(getId(), "sec", + currentDate != null ? currentDate.getSeconds() : -1, + currentResolution == Resolution.SECOND && immediate); + } + + } + + private String cleanFormat(String format) { + // Remove unnecessary d & M if resolution is too low + if (currentResolution.getCalendarField() < Resolution.DAY + .getCalendarField()) { + format = format.replaceAll("d", ""); + } + if (currentResolution.getCalendarField() < Resolution.MONTH + .getCalendarField()) { + format = format.replaceAll("M", ""); + } + + // Remove unsupported patterns + // TODO support for 'G', era designator (used at least in Japan) + format = format.replaceAll("[GzZwWkK]", ""); + + // Remove extra delimiters ('/' and '.') + while (format.startsWith("/") || format.startsWith(".") + || format.startsWith("-")) { + format = format.substring(1); + } + while (format.endsWith("/") || format.endsWith(".") + || format.endsWith("-")) { + format = format.substring(0, format.length() - 1); + } + + // Remove duplicate delimiters + format = format.replaceAll("//", "/"); + format = format.replaceAll("\\.\\.", "."); + format = format.replaceAll("--", "-"); + + return format.trim(); + } + + @Override + public void focus() { + text.setFocus(true); + } + + protected String getText() { + if (prompting) { + return ""; + } + return text.getText(); + } + + protected void setText(String text) { + if (inputPrompt != null && (text == null || "".equals(text)) + && !this.text.getStyleName().contains(VTextField.CLASSNAME + "-" + + VTextField.CLASSNAME_FOCUS)) { + text = readonly ? "" : inputPrompt; + setPrompting(true); + } else { + setPrompting(false); + } + + this.text.setText(text); + } + + private final String TEXTFIELD_ID = "field"; + + @Override + public com.google.gwt.user.client.Element getSubPartElement( + String subPart) { + if (subPart.equals(TEXTFIELD_ID)) { + return text.getElement(); + } + + return null; + } + + @Override + public String getSubPartName( + com.google.gwt.user.client.Element subElement) { + if (text.getElement().isOrHasChild(subElement)) { + return TEXTFIELD_ID; + } + + return null; + } + + @Override + public void onKeyDown(KeyDownEvent event) { + if (BrowserInfo.get().isIE() + && event.getNativeKeyCode() == KeyCodes.KEY_ENTER) { + // IE does not send change events when pressing enter in a text + // input so we handle it using a key listener instead + onChange(null); + } + } +} diff --git a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/datefield/AbstractDateFieldConnector.java b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/datefield/AbstractDateFieldConnector.java index 0b110d66a4..bd9ba1c90d 100644 --- a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/datefield/AbstractDateFieldConnector.java +++ b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/datefield/AbstractDateFieldConnector.java @@ -22,10 +22,10 @@ import com.vaadin.client.LocaleNotLoadedException; import com.vaadin.client.Paintable; import com.vaadin.client.UIDL; import com.vaadin.client.VConsole; -import com.vaadin.client.ui.VDateField; -import com.vaadin.shared.ui.datefield.DateFieldConstants; import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.v7.client.ui.AbstractFieldConnector; +import com.vaadin.v7.client.ui.VDateField; +import com.vaadin.v7.shared.ui.datefield.DateFieldConstants; public class AbstractDateFieldConnector extends AbstractFieldConnector implements Paintable { diff --git a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/datefield/DateFieldConnector.java b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/datefield/DateFieldConnector.java index 7d81df987b..2b961cf9ac 100644 --- a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/datefield/DateFieldConnector.java +++ b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/datefield/DateFieldConnector.java @@ -25,12 +25,12 @@ import com.vaadin.client.ApplicationConnection; import com.vaadin.client.DateTimeService; import com.vaadin.client.UIDL; import com.vaadin.client.communication.StateChangeEvent; -import com.vaadin.client.ui.VCalendarPanel.FocusChangeListener; -import com.vaadin.client.ui.VCalendarPanel.TimeChangeListener; -import com.vaadin.client.ui.VPopupCalendar; import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.datefield.PopupDateFieldState; import com.vaadin.shared.ui.datefield.Resolution; +import com.vaadin.v7.client.ui.VCalendarPanel.FocusChangeListener; +import com.vaadin.v7.client.ui.VCalendarPanel.TimeChangeListener; +import com.vaadin.v7.client.ui.VPopupCalendar; +import com.vaadin.v7.shared.ui.datefield.PopupDateFieldState; import com.vaadin.v7.ui.DateField; @Connect(DateField.class) diff --git a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/datefield/InlineDateFieldConnector.java b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/datefield/InlineDateFieldConnector.java index fed8730e48..39d8e575d7 100644 --- a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/datefield/InlineDateFieldConnector.java +++ b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/datefield/InlineDateFieldConnector.java @@ -21,12 +21,12 @@ import com.vaadin.client.ApplicationConnection; import com.vaadin.client.DateTimeService; import com.vaadin.client.UIDL; import com.vaadin.client.communication.StateChangeEvent; -import com.vaadin.client.ui.VCalendarPanel.FocusChangeListener; -import com.vaadin.client.ui.VCalendarPanel.TimeChangeListener; -import com.vaadin.client.ui.VDateFieldCalendar; import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.datefield.InlineDateFieldState; import com.vaadin.shared.ui.datefield.Resolution; +import com.vaadin.v7.client.ui.VCalendarPanel.FocusChangeListener; +import com.vaadin.v7.client.ui.VCalendarPanel.TimeChangeListener; +import com.vaadin.v7.client.ui.VDateFieldCalendar; +import com.vaadin.v7.shared.ui.datefield.InlineDateFieldState; import com.vaadin.v7.ui.InlineDateField; @Connect(InlineDateField.class) diff --git a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/datefield/TextualDateConnector.java b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/datefield/TextualDateConnector.java index 6eb5f900ea..85b3664923 100644 --- a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/datefield/TextualDateConnector.java +++ b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/datefield/TextualDateConnector.java @@ -18,9 +18,9 @@ package com.vaadin.v7.client.ui.datefield; import com.vaadin.client.ApplicationConnection; import com.vaadin.client.UIDL; -import com.vaadin.client.ui.VTextualDate; import com.vaadin.shared.ui.datefield.Resolution; -import com.vaadin.shared.ui.datefield.TextualDateFieldState; +import com.vaadin.v7.client.ui.VTextualDate; +import com.vaadin.v7.shared.ui.datefield.TextualDateFieldState; public class TextualDateConnector extends AbstractDateFieldConnector { diff --git a/compatibility-server/src/main/java/com/vaadin/v7/ui/DateField.java b/compatibility-server/src/main/java/com/vaadin/v7/ui/DateField.java index b02e7b87a4..fe4d20c571 100644 --- a/compatibility-server/src/main/java/com/vaadin/v7/ui/DateField.java +++ b/compatibility-server/src/main/java/com/vaadin/v7/ui/DateField.java @@ -34,9 +34,6 @@ import com.vaadin.event.FieldEvents.FocusEvent; import com.vaadin.event.FieldEvents.FocusListener; import com.vaadin.server.PaintException; import com.vaadin.server.PaintTarget; -import com.vaadin.shared.ui.datefield.DateFieldConstants; -import com.vaadin.shared.ui.datefield.Resolution; -import com.vaadin.shared.ui.datefield.TextualDateFieldState; import com.vaadin.ui.Component; import com.vaadin.ui.LegacyComponent; import com.vaadin.ui.declarative.DesignAttributeHandler; @@ -46,6 +43,9 @@ import com.vaadin.v7.data.Validator; import com.vaadin.v7.data.Validator.InvalidValueException; import com.vaadin.v7.data.util.converter.Converter; import com.vaadin.v7.data.validator.DateRangeValidator; +import com.vaadin.v7.shared.ui.datefield.DateFieldConstants; +import com.vaadin.shared.ui.datefield.Resolution; +import com.vaadin.v7.shared.ui.datefield.TextualDateFieldState; /** * <p> diff --git a/compatibility-server/src/main/java/com/vaadin/v7/ui/PopupDateField.java b/compatibility-server/src/main/java/com/vaadin/v7/ui/PopupDateField.java index 1ae0f79b30..a7378cd45b 100644 --- a/compatibility-server/src/main/java/com/vaadin/v7/ui/PopupDateField.java +++ b/compatibility-server/src/main/java/com/vaadin/v7/ui/PopupDateField.java @@ -20,8 +20,8 @@ import java.util.Date; import com.vaadin.server.PaintException; import com.vaadin.server.PaintTarget; -import com.vaadin.shared.ui.datefield.PopupDateFieldState; import com.vaadin.v7.data.Property; +import com.vaadin.v7.shared.ui.datefield.PopupDateFieldState; /** * <p> diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/data/validator/DateRangeValidatorTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/validator/DateRangeValidatorTest.java index 225f344045..76cf54b5e9 100644 --- a/compatibility-server/src/test/java/com/vaadin/v7/tests/data/validator/DateRangeValidatorTest.java +++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/data/validator/DateRangeValidatorTest.java @@ -11,8 +11,8 @@ import java.util.TimeZone; import org.junit.Before; import org.junit.Test; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.v7.data.validator.DateRangeValidator; +import com.vaadin.shared.ui.datefield.Resolution; public class DateRangeValidatorTest { Calendar startDate = new GregorianCalendar(TimeZone.getTimeZone("GMT"), diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/datefield/DateFieldConverterTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/datefield/DateFieldConverterTest.java index a5166f9373..73a13cef65 100644 --- a/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/datefield/DateFieldConverterTest.java +++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/datefield/DateFieldConverterTest.java @@ -22,10 +22,10 @@ import java.util.Locale; import org.junit.Before; import org.junit.Test; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.v7.data.Property; import com.vaadin.v7.data.util.ObjectProperty; import com.vaadin.v7.data.util.converter.Converter; +import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.v7.ui.DateField; public class DateFieldConverterTest { diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/datefield/LegacyDateFieldDeclarativeTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/datefield/LegacyDateFieldDeclarativeTest.java index e001a3327f..cbfd2e1be7 100644 --- a/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/datefield/LegacyDateFieldDeclarativeTest.java +++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/datefield/LegacyDateFieldDeclarativeTest.java @@ -21,8 +21,8 @@ import java.util.TimeZone; import org.junit.Test; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.design.DeclarativeTestBase; +import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.v7.ui.DateField; /** diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/datefield/PopupDateFieldDeclarativeTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/datefield/PopupDateFieldDeclarativeTest.java index e6316cec3f..99f76cc746 100644 --- a/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/datefield/PopupDateFieldDeclarativeTest.java +++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/datefield/PopupDateFieldDeclarativeTest.java @@ -19,8 +19,8 @@ import java.util.Date; import org.junit.Test; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.design.DeclarativeTestBase; +import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.v7.ui.PopupDateField; /** diff --git a/compatibility-shared/src/main/java/com/vaadin/v7/shared/ui/datefield/DateFieldConstants.java b/compatibility-shared/src/main/java/com/vaadin/v7/shared/ui/datefield/DateFieldConstants.java new file mode 100644 index 0000000000..3aa399554e --- /dev/null +++ b/compatibility-shared/src/main/java/com/vaadin/v7/shared/ui/datefield/DateFieldConstants.java @@ -0,0 +1,26 @@ +/* + * Copyright 2000-2016 Vaadin Ltd. + * + * 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.vaadin.v7.shared.ui.datefield; + +import java.io.Serializable; + +@Deprecated +public class DateFieldConstants implements Serializable { + + @Deprecated + public static final String ATTR_WEEK_NUMBERS = "wn"; + +} diff --git a/compatibility-shared/src/main/java/com/vaadin/v7/shared/ui/datefield/InlineDateFieldState.java b/compatibility-shared/src/main/java/com/vaadin/v7/shared/ui/datefield/InlineDateFieldState.java new file mode 100644 index 0000000000..ab780091df --- /dev/null +++ b/compatibility-shared/src/main/java/com/vaadin/v7/shared/ui/datefield/InlineDateFieldState.java @@ -0,0 +1,24 @@ +/* + * Copyright 2000-2016 Vaadin Ltd. + * + * 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.vaadin.v7.shared.ui.datefield; + +import com.vaadin.shared.ui.datefield.TextualDateFieldState; + +public class InlineDateFieldState extends TextualDateFieldState { + { + primaryStyleName = "v-inline-datefield"; + } +} diff --git a/compatibility-shared/src/main/java/com/vaadin/v7/shared/ui/datefield/PopupDateFieldState.java b/compatibility-shared/src/main/java/com/vaadin/v7/shared/ui/datefield/PopupDateFieldState.java new file mode 100644 index 0000000000..7a2f10255a --- /dev/null +++ b/compatibility-shared/src/main/java/com/vaadin/v7/shared/ui/datefield/PopupDateFieldState.java @@ -0,0 +1,30 @@ +/* + * Copyright 2000-2016 Vaadin Ltd. + * + * 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.vaadin.v7.shared.ui.datefield; + +import com.vaadin.shared.annotations.NoLayout; + +public class PopupDateFieldState extends TextualDateFieldState { + public static final String DESCRIPTION_FOR_ASSISTIVE_DEVICES = "Arrow down key opens calendar element for choosing the date"; + + { + primaryStyleName = "v-datefield"; + } + + public boolean textFieldEnabled = true; + @NoLayout + public String descriptionForAssistiveDevices = DESCRIPTION_FOR_ASSISTIVE_DEVICES; +} diff --git a/compatibility-shared/src/main/java/com/vaadin/v7/shared/ui/datefield/TextualDateFieldState.java b/compatibility-shared/src/main/java/com/vaadin/v7/shared/ui/datefield/TextualDateFieldState.java new file mode 100644 index 0000000000..f9362dc358 --- /dev/null +++ b/compatibility-shared/src/main/java/com/vaadin/v7/shared/ui/datefield/TextualDateFieldState.java @@ -0,0 +1,41 @@ +/* + * Copyright 2000-2016 Vaadin Ltd. + * + * 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.vaadin.v7.shared.ui.datefield; + +import java.util.Date; + +import com.vaadin.shared.AbstractFieldState; +import com.vaadin.shared.annotations.NoLayout; + +public class TextualDateFieldState extends AbstractFieldState { + { + primaryStyleName = "v-datefield"; + } + + /* + * Start range that has been cleared, depending on the resolution of the + * date field + */ + @NoLayout + public Date rangeStart = null; + + /* + * End range that has been cleared, depending on the resolution of the date + * field + */ + @NoLayout + public Date rangeEnd = null; +} diff --git a/uitest/src/main/java/com/vaadin/tests/TestForBasicApplicationLayout.java b/uitest/src/main/java/com/vaadin/tests/TestForBasicApplicationLayout.java index 5b1b5c7f06..76d146e7c3 100644 --- a/uitest/src/main/java/com/vaadin/tests/TestForBasicApplicationLayout.java +++ b/uitest/src/main/java/com/vaadin/tests/TestForBasicApplicationLayout.java @@ -19,7 +19,6 @@ package com.vaadin.tests; import java.util.Locale; import com.vaadin.server.Sizeable; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Button.ClickListener; @@ -31,6 +30,7 @@ import com.vaadin.ui.Panel; import com.vaadin.ui.TabSheet; import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.themes.Reindeer; +import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.v7.ui.Table; public class TestForBasicApplicationLayout extends CustomComponent { diff --git a/uitest/src/main/java/com/vaadin/tests/components/calendar/BeanItemContainerTestUI.java b/uitest/src/main/java/com/vaadin/tests/components/calendar/BeanItemContainerTestUI.java index 0ca638fa19..be1664bce3 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/calendar/BeanItemContainerTestUI.java +++ b/uitest/src/main/java/com/vaadin/tests/components/calendar/BeanItemContainerTestUI.java @@ -21,7 +21,6 @@ import java.util.GregorianCalendar; import com.vaadin.event.Action; import com.vaadin.server.VaadinRequest; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.ui.FormLayout; import com.vaadin.ui.UI; import com.vaadin.ui.VerticalSplitPanel; @@ -31,6 +30,7 @@ import com.vaadin.v7.data.fieldgroup.FieldGroup; import com.vaadin.v7.data.fieldgroup.FieldGroup.CommitException; import com.vaadin.v7.data.util.BeanItem; import com.vaadin.v7.data.util.BeanItemContainer; +import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.v7.ui.Calendar; import com.vaadin.v7.ui.DateField; import com.vaadin.v7.ui.Table; diff --git a/uitest/src/main/java/com/vaadin/tests/components/calendar/CalendarTest.java b/uitest/src/main/java/com/vaadin/tests/components/calendar/CalendarTest.java index 7bab92a513..507d152b53 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/calendar/CalendarTest.java +++ b/uitest/src/main/java/com/vaadin/tests/components/calendar/CalendarTest.java @@ -26,7 +26,6 @@ import com.vaadin.annotations.Theme; import com.vaadin.data.Binder; import com.vaadin.server.VaadinRequest; import com.vaadin.shared.ui.MarginInfo; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.ui.Alignment; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; @@ -47,6 +46,7 @@ import com.vaadin.v7.data.fieldgroup.FieldGroup; import com.vaadin.v7.data.fieldgroup.FieldGroup.CommitException; import com.vaadin.v7.data.util.BeanItem; import com.vaadin.v7.shared.ui.combobox.FilteringMode; +import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.v7.ui.Calendar; import com.vaadin.v7.ui.Calendar.TimeFormat; import com.vaadin.v7.ui.ComboBox; diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/CustomDateFormat.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/CustomDateFormat.java index 579df7f1a8..e79cd4a054 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/CustomDateFormat.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/CustomDateFormat.java @@ -3,9 +3,9 @@ package com.vaadin.tests.components.datefield; import java.util.Calendar; import java.util.Locale; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.TestBase; import com.vaadin.ui.DateField; +import com.vaadin.shared.ui.datefield.Resolution; public class CustomDateFormat extends TestBase { diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/CustomDateFormatEEE.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/CustomDateFormatEEE.java index 575d68f291..9be320ad79 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/CustomDateFormatEEE.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/CustomDateFormatEEE.java @@ -19,10 +19,10 @@ import java.util.Calendar; import java.util.Locale; import com.vaadin.server.VaadinRequest; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.AbstractTestUI; import com.vaadin.ui.DateField; import com.vaadin.ui.VerticalLayout; +import com.vaadin.shared.ui.datefield.Resolution; public class CustomDateFormatEEE extends AbstractTestUI { diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/CustomDateFormats.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/CustomDateFormats.java index 2a231e6534..8bb08133a5 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/CustomDateFormats.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/CustomDateFormats.java @@ -7,7 +7,6 @@ import java.util.HashSet; import java.util.Locale; import java.util.Set; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.TestBase; import com.vaadin.ui.Component; import com.vaadin.ui.DateField; @@ -16,6 +15,7 @@ import com.vaadin.ui.Label; import com.vaadin.v7.data.Item; import com.vaadin.v7.data.Property; import com.vaadin.v7.data.Property.ValueChangeEvent; +import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.v7.ui.NativeSelect; public class CustomDateFormats extends TestBase { diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldChangeResolution.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldChangeResolution.java index 17b26b8288..60dbbeed37 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldChangeResolution.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldChangeResolution.java @@ -16,11 +16,11 @@ package com.vaadin.tests.components.datefield; import com.vaadin.server.VaadinRequest; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.AbstractTestUI; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Button.ClickListener; +import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.ui.DateField; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Label; diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldDayResolutionOffset.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldDayResolutionOffset.java index 4a68e648e6..dd91d762c4 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldDayResolutionOffset.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldDayResolutionOffset.java @@ -6,10 +6,10 @@ import java.util.Date; import java.util.TimeZone; import com.vaadin.server.VaadinRequest; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.AbstractTestUI; import com.vaadin.ui.DateField; import com.vaadin.ui.Label; +import com.vaadin.shared.ui.datefield.Resolution; public class DateFieldDayResolutionOffset extends AbstractTestUI { diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldEmptyValid.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldEmptyValid.java index 2e046127ac..cdfb281623 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldEmptyValid.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldEmptyValid.java @@ -4,7 +4,6 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.TestBase; import com.vaadin.tests.util.Log; import com.vaadin.ui.Button; @@ -14,6 +13,7 @@ import com.vaadin.ui.Label; import com.vaadin.v7.data.Property.ValueChangeEvent; import com.vaadin.v7.data.Property.ValueChangeListener; import com.vaadin.v7.data.util.ObjectProperty; +import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.shared.ui.label.ContentMode; import com.vaadin.v7.ui.PopupDateField; diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldExtendedRange.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldExtendedRange.java index 620b9cf12a..9865a002d0 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldExtendedRange.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldExtendedRange.java @@ -3,11 +3,11 @@ package com.vaadin.tests.components.datefield; import java.util.Calendar; import java.util.Locale; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.TestBase; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Button.ClickListener; +import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.ui.DateField; import com.vaadin.ui.GridLayout; import com.vaadin.ui.InlineDateField; diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldLocale.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldLocale.java index 38bb02bc71..5c756a02c0 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldLocale.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldLocale.java @@ -3,11 +3,11 @@ package com.vaadin.tests.components.datefield; import java.util.Date; import java.util.Locale; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.TestBase; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Button.ClickListener; +import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.ui.DateField; public class DateFieldLocale extends TestBase { diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldMinResolution.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldMinResolution.java index d153dff443..beb4caccdc 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldMinResolution.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldMinResolution.java @@ -3,11 +3,11 @@ package com.vaadin.tests.components.datefield; import java.text.SimpleDateFormat; import java.util.Calendar; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.TestBase; import com.vaadin.ui.DateField; import com.vaadin.ui.InlineDateField; import com.vaadin.ui.Label; +import com.vaadin.shared.ui.datefield.Resolution; public class DateFieldMinResolution extends TestBase { diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldPopupOffScreen.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldPopupOffScreen.java index 1f5eb4b394..1a2633f90b 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldPopupOffScreen.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldPopupOffScreen.java @@ -3,12 +3,12 @@ package com.vaadin.tests.components.datefield; import java.util.Date; import java.util.Locale; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.AbstractTestCase; import com.vaadin.ui.Alignment; import com.vaadin.ui.DateField; import com.vaadin.ui.GridLayout; import com.vaadin.ui.LegacyWindow; +import com.vaadin.shared.ui.datefield.Resolution; public class DateFieldPopupOffScreen extends AbstractTestCase { diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldRangeValidation.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldRangeValidation.java index c6422891fb..f8d2443d99 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldRangeValidation.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldRangeValidation.java @@ -4,12 +4,12 @@ import java.util.Date; import java.util.Locale; import com.vaadin.data.HasValue; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.TestBase; import com.vaadin.tests.util.CheckBoxWithPropertyDataSource; import com.vaadin.ui.CheckBox; import com.vaadin.v7.data.util.BeanItem; import com.vaadin.v7.data.validator.RangeValidator; +import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.v7.ui.PopupDateField; public class DateFieldRangeValidation extends TestBase { diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldRanges.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldRanges.java index d4912b7ebd..7a14e61057 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldRanges.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldRanges.java @@ -6,7 +6,6 @@ import java.util.Locale; import com.vaadin.server.VaadinRequest; import com.vaadin.shared.ui.MarginInfo; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.AbstractTestUI; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; @@ -19,6 +18,7 @@ import com.vaadin.ui.Label; import com.vaadin.ui.VerticalLayout; import com.vaadin.v7.data.Property.ValueChangeEvent; import com.vaadin.v7.data.Property.ValueChangeListener; +import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.v7.ui.NativeSelect; public class DateFieldRanges extends AbstractTestUI { diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldReadOnly.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldReadOnly.java index 9addeca5cf..7f7c96bfff 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldReadOnly.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldReadOnly.java @@ -4,11 +4,11 @@ import java.util.Calendar; import java.util.Locale; import com.vaadin.server.VaadinRequest; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.AbstractTestUI; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Button.ClickListener; +import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.ui.DateField; public class DateFieldReadOnly extends AbstractTestUI { diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldTest.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldTest.java index d8a165fa23..d6c61b48f6 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldTest.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldTest.java @@ -7,9 +7,9 @@ import java.util.Date; import java.util.LinkedHashMap; import java.util.Locale; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.abstractfield.AbstractFieldTest; import com.vaadin.ui.DateField; +import com.vaadin.shared.ui.datefield.Resolution; public class DateFieldTest<T extends DateField> extends AbstractFieldTest<T, Date> { diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldTimezone.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldTimezone.java index 33d1c659f0..8c52fc1a08 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldTimezone.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldTimezone.java @@ -8,13 +8,13 @@ import java.util.Date; import java.util.Locale; import java.util.TimeZone; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.TestBase; import com.vaadin.tests.util.Log; import com.vaadin.ui.DateField; import com.vaadin.v7.data.Property; import com.vaadin.v7.data.Property.ValueChangeEvent; import com.vaadin.v7.shared.ui.combobox.FilteringMode; +import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.v7.ui.ComboBox; public class DateFieldTimezone extends TestBase { diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/DatePopupStyleName.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/DatePopupStyleName.java index 64f8695308..214bd6f38d 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/DatePopupStyleName.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/DatePopupStyleName.java @@ -3,9 +3,9 @@ package com.vaadin.tests.components.datefield; import java.util.Date; import com.vaadin.server.UserError; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.TestBase; import com.vaadin.ui.DateField; +import com.vaadin.shared.ui.datefield.Resolution; public class DatePopupStyleName extends TestBase { @Override diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/DisabledDateFieldWidth.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/DisabledDateFieldWidth.java index cd7026483a..65cd45c123 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/DisabledDateFieldWidth.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/DisabledDateFieldWidth.java @@ -1,9 +1,9 @@ package com.vaadin.tests.components.datefield; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.TestBase; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.ui.DateField; import com.vaadin.ui.GridLayout; diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/InlineDateFields.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/InlineDateFields.java index 669d691634..543234a7cb 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/InlineDateFields.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/InlineDateFields.java @@ -5,10 +5,10 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.ComponentTestCase; import com.vaadin.ui.Component; import com.vaadin.ui.InlineDateField; +import com.vaadin.shared.ui.datefield.Resolution; @SuppressWarnings("serial") public class InlineDateFields extends ComponentTestCase<InlineDateField> { diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/LegacyDateFieldRanges.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/LegacyDateFieldRanges.java index 2d0eeeee97..552a3e2648 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/LegacyDateFieldRanges.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/LegacyDateFieldRanges.java @@ -6,7 +6,6 @@ import java.util.Locale; import com.vaadin.server.VaadinRequest; import com.vaadin.shared.ui.MarginInfo; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.AbstractTestUI; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; @@ -17,6 +16,7 @@ import com.vaadin.ui.Label; import com.vaadin.ui.VerticalLayout; import com.vaadin.v7.data.Property.ValueChangeEvent; import com.vaadin.v7.data.Property.ValueChangeListener; +import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.v7.ui.DateField; import com.vaadin.v7.ui.InlineDateField; import com.vaadin.v7.ui.NativeSelect; diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/LegacyDateFieldTest.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/LegacyDateFieldTest.java index 7f3b3872dc..bf048a5163 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/LegacyDateFieldTest.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/LegacyDateFieldTest.java @@ -7,8 +7,8 @@ import java.util.Date; import java.util.LinkedHashMap; import java.util.Locale; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.abstractfield.LegacyAbstractFieldTest; +import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.v7.ui.DateField; public class LegacyDateFieldTest<T extends DateField> diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/LenientMode.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/LenientMode.java index 72fed3605e..89988681e4 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/LenientMode.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/LenientMode.java @@ -5,10 +5,10 @@ import java.util.Locale; import com.vaadin.data.HasValue.ValueChange; import com.vaadin.data.HasValue.ValueChangeListener; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.TestBase; import com.vaadin.ui.Button; import com.vaadin.ui.DateField; +import com.vaadin.shared.ui.datefield.Resolution; public class LenientMode extends TestBase implements ValueChangeListener<Date> { diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/LocaleChange.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/LocaleChange.java index a7d527b41e..e791402137 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/LocaleChange.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/LocaleChange.java @@ -21,11 +21,11 @@ import java.util.Date; import java.util.Locale; import com.vaadin.server.VaadinRequest; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.AbstractTestUI; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Button.ClickListener; +import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.ui.DateField; public class LocaleChange extends AbstractTestUI { diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/LowResolution.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/LowResolution.java index 16673fefe7..02f5a2a037 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/LowResolution.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/LowResolution.java @@ -1,11 +1,11 @@ package com.vaadin.tests.components.datefield; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.TestBase; import com.vaadin.ui.Button; import com.vaadin.ui.CheckBox; import com.vaadin.ui.InlineDateField; import com.vaadin.ui.PopupDateField; +import com.vaadin.shared.ui.datefield.Resolution; @SuppressWarnings("serial") public class LowResolution extends TestBase { diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/PopupClosingWithEsc.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/PopupClosingWithEsc.java index 94fefcb429..750c3263a8 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/PopupClosingWithEsc.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/PopupClosingWithEsc.java @@ -16,10 +16,10 @@ package com.vaadin.tests.components.datefield; import com.vaadin.server.VaadinRequest; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.AbstractTestUI; import com.vaadin.ui.DateField; import com.vaadin.ui.VerticalLayout; +import com.vaadin.shared.ui.datefield.Resolution; public class PopupClosingWithEsc extends AbstractTestUI { diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/PopupDateFieldExtendedRange.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/PopupDateFieldExtendedRange.java index 2608e6e081..b5e57e76f2 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/PopupDateFieldExtendedRange.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/PopupDateFieldExtendedRange.java @@ -4,11 +4,11 @@ import java.util.Calendar; import java.util.Locale; import com.vaadin.server.VaadinRequest; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.AbstractTestUI; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Button.ClickListener; +import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.ui.PopupDateField; @SuppressWarnings("serial") diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/PopupDateFieldLocaleTest.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/PopupDateFieldLocaleTest.java index 5933581a30..fe476523b5 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/PopupDateFieldLocaleTest.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/PopupDateFieldLocaleTest.java @@ -4,9 +4,9 @@ import java.util.Calendar; import java.util.Locale; import com.vaadin.server.VaadinRequest; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.AbstractTestUI; import com.vaadin.ui.PopupDateField; +import com.vaadin.shared.ui.datefield.Resolution; public class PopupDateFieldLocaleTest extends AbstractTestUI { diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/PopupDateFieldPopup.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/PopupDateFieldPopup.java index 8bb816181c..77d77d8087 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/PopupDateFieldPopup.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/PopupDateFieldPopup.java @@ -3,9 +3,9 @@ package com.vaadin.tests.components.datefield; import java.util.Calendar; import java.util.Locale; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.TestBase; import com.vaadin.ui.PopupDateField; +import com.vaadin.shared.ui.datefield.Resolution; public class PopupDateFieldPopup extends TestBase { diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/PopupDateFieldValueChangeEvents.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/PopupDateFieldValueChangeEvents.java index a65cf18d01..385190fa65 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/PopupDateFieldValueChangeEvents.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/PopupDateFieldValueChangeEvents.java @@ -23,12 +23,12 @@ import java.util.Arrays; import java.util.Calendar; import com.vaadin.server.VaadinRequest; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.AbstractTestUIWithLog; import com.vaadin.ui.DateField; import com.vaadin.ui.HorizontalLayout; import com.vaadin.v7.data.Property.ValueChangeEvent; import com.vaadin.v7.data.Property.ValueChangeListener; +import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.v7.ui.NativeSelect; /** diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/PopupDateFields.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/PopupDateFields.java index 9bc567c0fc..4223be2b7d 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/PopupDateFields.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/PopupDateFields.java @@ -5,10 +5,10 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.ComponentTestCase; import com.vaadin.ui.Component; import com.vaadin.ui.PopupDateField; +import com.vaadin.shared.ui.datefield.Resolution; @SuppressWarnings("serial") public class PopupDateFields extends ComponentTestCase<PopupDateField> { diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/TestDatefieldYear.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/TestDatefieldYear.java index eb7545812e..9afc4ce35f 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/TestDatefieldYear.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/TestDatefieldYear.java @@ -3,9 +3,9 @@ package com.vaadin.tests.components.datefield; import java.util.Date; import java.util.Locale; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.TestBase; import com.vaadin.ui.DateField; +import com.vaadin.shared.ui.datefield.Resolution; public class TestDatefieldYear extends TestBase { diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/WidthRecalculationOnEnableStateChange.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/WidthRecalculationOnEnableStateChange.java index cf42fcad75..af4d1e9ea7 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/datefield/WidthRecalculationOnEnableStateChange.java +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/WidthRecalculationOnEnableStateChange.java @@ -2,10 +2,10 @@ package com.vaadin.tests.components.datefield; import java.util.Date; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.TestBase; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.ui.DateField; public class WidthRecalculationOnEnableStateChange extends TestBase { diff --git a/uitest/src/main/java/com/vaadin/tests/components/gridlayout/GridLayoutCellSizesUI.java b/uitest/src/main/java/com/vaadin/tests/components/gridlayout/GridLayoutCellSizesUI.java index d2ca7700ad..355afd3bcd 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/gridlayout/GridLayoutCellSizesUI.java +++ b/uitest/src/main/java/com/vaadin/tests/components/gridlayout/GridLayoutCellSizesUI.java @@ -1,12 +1,12 @@ package com.vaadin.tests.components.gridlayout; import com.vaadin.server.VaadinRequest; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.AbstractTestUI; import com.vaadin.ui.Button; import com.vaadin.ui.GridLayout; import com.vaadin.ui.InlineDateField; import com.vaadin.ui.Label; +import com.vaadin.shared.ui.datefield.Resolution; @SuppressWarnings("serial") public class GridLayoutCellSizesUI extends AbstractTestUI { diff --git a/uitest/src/main/java/com/vaadin/tests/themes/valo/CalendarTest.java b/uitest/src/main/java/com/vaadin/tests/themes/valo/CalendarTest.java index 617ec7d584..b06d93e12c 100644 --- a/uitest/src/main/java/com/vaadin/tests/themes/valo/CalendarTest.java +++ b/uitest/src/main/java/com/vaadin/tests/themes/valo/CalendarTest.java @@ -10,7 +10,6 @@ import com.vaadin.annotations.Theme; import com.vaadin.data.Binder; import com.vaadin.navigator.View; import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.tests.components.calendar.CalendarTestEvent; import com.vaadin.ui.Alignment; import com.vaadin.ui.Button; @@ -33,6 +32,7 @@ import com.vaadin.v7.data.fieldgroup.FieldGroup; import com.vaadin.v7.data.fieldgroup.FieldGroup.CommitException; import com.vaadin.v7.data.util.BeanItem; import com.vaadin.v7.shared.ui.combobox.FilteringMode; +import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.v7.ui.Calendar; import com.vaadin.v7.ui.Calendar.TimeFormat; import com.vaadin.v7.ui.ComboBox; diff --git a/uitest/src/main/java/com/vaadin/tests/themes/valo/DateFields.java b/uitest/src/main/java/com/vaadin/tests/themes/valo/DateFields.java index cae1dbc29b..82f64f4c92 100644 --- a/uitest/src/main/java/com/vaadin/tests/themes/valo/DateFields.java +++ b/uitest/src/main/java/com/vaadin/tests/themes/valo/DateFields.java @@ -21,7 +21,6 @@ import java.util.Locale; import com.vaadin.navigator.View; import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent; import com.vaadin.server.UserError; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Button.ClickListener; @@ -36,6 +35,7 @@ import com.vaadin.ui.themes.ValoTheme; import com.vaadin.v7.data.fieldgroup.FieldGroup; import com.vaadin.v7.data.util.ObjectProperty; import com.vaadin.v7.data.util.PropertysetItem; +import com.vaadin.shared.ui.datefield.Resolution; public class DateFields extends VerticalLayout implements View { public DateFields() { diff --git a/uitest/src/test/java/com/vaadin/tests/components/datefield/DateFieldChangeResolutionTest.java b/uitest/src/test/java/com/vaadin/tests/components/datefield/DateFieldChangeResolutionTest.java index 23aca038ae..f297110b00 100644 --- a/uitest/src/test/java/com/vaadin/tests/components/datefield/DateFieldChangeResolutionTest.java +++ b/uitest/src/test/java/com/vaadin/tests/components/datefield/DateFieldChangeResolutionTest.java @@ -24,9 +24,9 @@ import org.junit.Test; import org.openqa.selenium.Keys; import org.openqa.selenium.WebElement; -import com.vaadin.shared.ui.datefield.Resolution; import com.vaadin.testbench.By; import com.vaadin.tests.tb3.MultiBrowserTest; +import com.vaadin.shared.ui.datefield.Resolution; public class DateFieldChangeResolutionTest extends MultiBrowserTest { |