* Introduce DateTimeFile and InlineDateTimeField.
Fixes #8132
* Correct and provide declarative tests.
* Provide a date converter and UI tests.
this.resolution = resolution;
}
- private boolean isReadonly() {
+ /**
+ * Checks whether the widget is not editable (read-only).
+ *
+ * @return {@code true} if the widget is read-only
+ */
+ protected boolean isReadonly() {
return parent.isReadonly();
}
- private boolean isEnabled() {
+ /**
+ * Checks whether the widget is enabled.
+ *
+ * @return {@code true} is the widget is enabled
+ */
+ protected boolean isEnabled() {
return parent.isEnabled();
}
}
- private DateTimeService getDateTimeService() {
+ /**
+ * Returns date time service for the widget.
+ *
+ * @see #setDateTimeService(DateTimeService)
+ *
+ * @return date time service
+ */
+ protected DateTimeService getDateTimeService() {
return dateTimeService;
}
+ /**
+ * Returns the date field which this panel is attached to.
+ *
+ * @return the "parent" date field
+ */
+ protected VDateField<R> getDateField() {
+ return parent;
+ }
+
public void setDateTimeService(DateTimeService dateTimeService) {
this.dateTimeService = dateTimeService;
}
setCellSpacing(0);
getFlexCellFormatter().setColSpan(1, 0, 5);
getFlexCellFormatter().setStyleName(1, 0,
- parent.getStylePrimaryName() + "-calendarpanel-body");
+ getDateField().getStylePrimaryName() + "-calendarpanel-body");
days.getFlexCellFormatter().setStyleName(headerRow, weekColumn,
"v-week");
isShowISOWeekNumbers());
days.getRowFormatter().setStyleName(headerRow,
- parent.getStylePrimaryName() + "-calendarpanel-weekdays");
+ getDateField().getStylePrimaryName()
+ + "-calendarpanel-weekdays");
if (isShowISOWeekNumbers()) {
days.getFlexCellFormatter().setStyleName(headerRow, weekColumn,
days.getFlexCellFormatter().setStyleName(headerRow,
firstWeekdayColumn, "");
days.getRowFormatter().addStyleName(headerRow,
- parent.getStylePrimaryName()
+ getDateField().getStylePrimaryName()
+ "-calendarpanel-weeknumbers");
} else {
days.getFlexCellFormatter().setStyleName(headerRow, weekColumn, "");
Date dayDate = (Date) curr.clone();
Day day = new Day(dayDate);
- day.setStyleName(
- parent.getStylePrimaryName() + "-calendarpanel-day");
+ day.setStyleName(getDateField().getStylePrimaryName()
+ + "-calendarpanel-day");
if (!isDateInsideRange(dayDate, getResolution(this::isDay))) {
day.addStyleDependentName(CN_OUTSIDE_RANGE);
isShowISOWeekNumbers());
if (isShowISOWeekNumbers()) {
- final String baseCssClass = parent.getStylePrimaryName()
+ final String baseCssClass = getDateField()
+ .getStylePrimaryName()
+ "-calendarpanel-weeknumber";
String weekCssClass = baseCssClass;
*/
protected void doRenderCalendar(boolean updateDate) {
super.setStylePrimaryName(
- parent.getStylePrimaryName() + "-calendarpanel");
+ getDateField().getStylePrimaryName() + "-calendarpanel");
if (focusedDate == null) {
Date now = new Date();
}
final boolean needsMonth = !isYear(getResolution());
- boolean needsBody = isDay(getResolution());
+ boolean needsBody = isBelowMonth(resolution);
buildCalendarHeader(needsMonth);
clearCalendarBody(!needsBody);
if (needsBody) {
}
private void setLabel() {
- if (parent instanceof VAbstractPopupCalendar) {
- ((VAbstractPopupCalendar) parent).setFocusedDate(this);
+ if (getDateField() instanceof VAbstractPopupCalendar) {
+ ((VAbstractPopupCalendar) getDateField()).setFocusedDate(this);
}
}
}
/**
* A client side implementation for inline date field.
*/
-public abstract class VAbstractDateFieldCalendar<R extends Enum<R>>
+public abstract class VAbstractDateFieldCalendar<PANEL extends VAbstractCalendarPanel<R>, R extends Enum<R>>
extends VDateField<R> {
/** For internal use only. May be removed or replaced in the future. */
- public final VAbstractCalendarPanel<R> calendarPanel;
+ public final PANEL calendarPanel;
- public VAbstractDateFieldCalendar(VAbstractCalendarPanel<R> panel,
- R resolution) {
+ public VAbstractDateFieldCalendar(PANEL panel, R resolution) {
super(resolution);
calendarPanel = panel;
calendarPanel.setParentField(this);
package com.vaadin.client.ui;
import java.util.Date;
-import java.util.Locale;
import com.google.gwt.aria.client.Id;
import com.google.gwt.aria.client.LiveValue;
* <code>setCalendarPanel(VAbstractCalendarPanel panel)</code> method.
*
*/
-public abstract class VAbstractPopupCalendar<R extends Enum<R>>
+public abstract class VAbstractPopupCalendar<PANEL extends VAbstractCalendarPanel<R>, R extends Enum<R>>
extends VAbstractTextualDate<R>
implements Field, ClickHandler, CloseHandler<PopupPanel>, SubPartAware {
public final Button calendarToggle = new Button();
/** For internal use only. May be removed or replaced in the future. */
- public VAbstractCalendarPanel<R> calendar;
+ public PANEL calendar;
/** For internal use only. May be removed or replaced in the future. */
public final VOverlay popup;
private final String CALENDAR_TOGGLE_ID = "popupButton";
- public VAbstractPopupCalendar(VAbstractCalendarPanel<R> calendarPanel,
- R resolution) {
+ public VAbstractPopupCalendar(PANEL calendarPanel, R resolution) {
super(resolution);
calendarToggle.setText("");
if (!calendar.isYear(getCurrentResolution())) {
getClient().updateVariable(getId(),
getResolutionVariable(
- calendar.getResolution(calendar::isMonth))
- .toLowerCase(Locale.ENGLISH),
+ calendar.getResolution(calendar::isMonth)),
newDate.getMonth() + 1, false);
if (!calendar.isMonth(getCurrentResolution())) {
getClient().updateVariable(getId(),
*
* @see #setCurrentDate(Map)
*
- * @param dateVaules
+ * @param dateValues
* a map with date values to convert into a date
* @return the date based on the dateValues map
*/
- protected abstract Date getDate(Map<R, Integer> dateVaules);
+ protected abstract Date getDate(Map<R, Integer> dateValues);
/**
* Returns all available resolutions as an array.
*
*/
public class VDateFieldCalendar
- extends VAbstractDateFieldCalendar<DateResolution> {
+ extends VAbstractDateFieldCalendar<VDateCalendarPanel, DateResolution> {
public VDateFieldCalendar() {
super(GWT.create(VDateCalendarPanel.class), DateResolution.YEAR);
--- /dev/null
+/*
+ * 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.client.ui;
+
+import java.util.Date;
+
+import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.event.dom.client.ChangeHandler;
+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.Element;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.ListBox;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.client.DateTimeService;
+import com.vaadin.shared.ui.datefield.DateTimeResolution;
+
+/**
+ * @author Vaadin Ltd
+ * @since 8.0
+ */
+public class VDateTimeCalendarPanel
+ extends VAbstractCalendarPanel<DateTimeResolution> {
+
+ 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 TimeChangeListener timeChangeListener;
+
+ private VTime time;
+
+ /**
+ * 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(VDateTimeCalendarPanel.this);
+ lb.addFocusHandler(VDateTimeCalendarPanel.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().compareTo(DateTimeResolution.MINUTE) <= 0) {
+ mins = createListBox();
+ for (int i = 0; i < 60; i++) {
+ mins.addItem((i < 10) ? "0" + i : "" + i);
+ }
+ mins.addChangeHandler(this);
+ }
+ if (getResolution().compareTo(DateTimeResolution.SECOND) <= 0) {
+ 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 (getDate() != null) {
+ h = getDate().getHours();
+ }
+ if (getDateTimeService().isTwelveHourClock()) {
+ h -= h < 12 ? 0 : 12;
+ }
+ add(new VLabel(h < 10 ? "0" + h : "" + h));
+ } else {
+ add(hours);
+ }
+
+ if (getResolution().compareTo(DateTimeResolution.MINUTE) <= 0) {
+ add(new VLabel(delimiter));
+ if (isReadonly()) {
+ final int m = mins.getSelectedIndex();
+ add(new VLabel(m < 10 ? "0" + m : "" + m));
+ } else {
+ add(mins);
+ }
+ }
+ if (getResolution().compareTo(DateTimeResolution.SECOND) <= 0) {
+ add(new VLabel(delimiter));
+ if (isReadonly()) {
+ final int s = sec.getSelectedIndex();
+ add(new VLabel(s < 10 ? "0" + s : "" + s));
+ } else {
+ add(sec);
+ }
+ }
+ if (getResolution() == DateTimeResolution.HOUR) {
+ add(new VLabel(delimiter + "00")); // o'clock
+ }
+ if (getDateTimeService().isTwelveHourClock()) {
+ add(new VLabel(" "));
+ if (isReadonly()) {
+ int i = 0;
+ if (getDate() != null) {
+ i = (getDate().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 (getDate() == null) {
+ setDate(new Date());
+ }
+ if (getDateTimeService().isTwelveHourClock()) {
+ int h = getDate().getHours();
+ ampm.setSelectedIndex(h < 12 ? 0 : 1);
+ h -= ampm.getSelectedIndex() * 12;
+ hours.setSelectedIndex(h);
+ } else {
+ hours.setSelectedIndex(getDate().getHours());
+ }
+ if (getResolution().compareTo(DateTimeResolution.MINUTE) <= 0) {
+ mins.setSelectedIndex(getDate().getMinutes());
+ }
+ if (getResolution().compareTo(DateTimeResolution.SECOND) <= 0) {
+ sec.setSelectedIndex(getDate().getSeconds());
+ }
+ if (getDateTimeService().isTwelveHourClock()) {
+ ampm.setSelectedIndex(getDate().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 (VDateTimeCalendarPanel.this.getDateTimeService() == null) {
+ setDateTimeService(new DateTimeService());
+ }
+ return VDateTimeCalendarPanel.this.getDateTimeService();
+ }
+
+ /*
+ * (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;
+ }
+ getDate().setHours(h);
+ if (timeChangeListener != null) {
+ timeChangeListener.changed(h, getDate().getMinutes(),
+ getDate().getSeconds(),
+ DateTimeService.getMilliseconds(getDate()));
+ }
+ event.preventDefault();
+ event.stopPropagation();
+ } else if (event.getSource() == mins) {
+ final int m = mins.getSelectedIndex();
+ getDate().setMinutes(m);
+ if (timeChangeListener != null) {
+ timeChangeListener.changed(getDate().getHours(), m,
+ getDate().getSeconds(),
+ DateTimeService.getMilliseconds(getDate()));
+ }
+ event.preventDefault();
+ event.stopPropagation();
+ } else if (event.getSource() == sec) {
+ final int s = sec.getSelectedIndex();
+ getDate().setSeconds(s);
+ if (timeChangeListener != null) {
+ timeChangeListener.changed(getDate().getHours(),
+ getDate().getMinutes(), s,
+ DateTimeService.getMilliseconds(getDate()));
+ }
+ event.preventDefault();
+ event.stopPropagation();
+ } else if (event.getSource() == ampm) {
+ final int h = hours.getSelectedIndex()
+ + (ampm.getSelectedIndex() * 12);
+ getDate().setHours(h);
+ if (timeChangeListener != null) {
+ timeChangeListener.changed(h, getDate().getMinutes(),
+ getDate().getSeconds(),
+ DateTimeService.getMilliseconds(getDate()));
+ }
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+
+ }
+
+ /**
+ * Dispatches an event when the panel when time is changed
+ */
+ public interface TimeChangeListener {
+
+ void changed(int hour, int min, int sec, int msec);
+ }
+
+ /**
+ * The time change listener is triggered when the user changes the time.
+ *
+ * @param listener
+ */
+ public void setTimeChangeListener(TimeChangeListener listener) {
+ timeChangeListener = listener;
+ }
+
+ @Override
+ public void setDate(Date currentDate) {
+ doSetDate(currentDate, isTimeSelectorNeeded() && time == null, () -> {
+ if (isTimeSelectorNeeded()) {
+ time.updateTimes();
+ }
+ });
+ }
+
+ @Override
+ public void setResolution(DateTimeResolution resolution) {
+ super.setResolution(resolution);
+ if (isTimeSelectorNeeded() && time != null) {
+ // resolution has changed => rebuild time UI
+ time.buildTime();
+ }
+ }
+
+ @Override
+ protected boolean acceptDayFocus() {
+ return getResolution().compareTo(DateTimeResolution.MONTH) < 0;
+ }
+
+ @Override
+ protected boolean isDay(DateTimeResolution resolution) {
+ return DateTimeResolution.DAY.equals(resolution);
+ }
+
+ @Override
+ protected boolean isMonth(DateTimeResolution resolution) {
+ return DateTimeResolution.MONTH.equals(resolution);
+ }
+
+ @Override
+ protected boolean isBelowMonth(DateTimeResolution resolution) {
+ return resolution.compareTo(DateTimeResolution.MONTH) < 0;
+ }
+
+ @Override
+ protected void doRenderCalendar(boolean updateDate) {
+ super.doRenderCalendar(updateDate);
+
+ if (isTimeSelectorNeeded()) {
+ time = new VTime();
+ setWidget(2, 0, time);
+ getFlexCellFormatter().setColSpan(2, 0, 5);
+ getFlexCellFormatter().setStyleName(2, 0,
+ getDateField().getStylePrimaryName()
+ + "-calendarpanel-time");
+ } else if (time != null) {
+ remove(time);
+ }
+ }
+
+ @Override
+ public String getSubPartName(Element subElement) {
+ 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;
+
+ }
+ }
+ return super.getSubPartName(subElement);
+ }
+
+ @Override
+ public Element getSubPartElement(String subPart) {
+ 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();
+ }
+ return super.getSubPartElement(subPart);
+ }
+
+ /**
+ * Do we need the time selector
+ *
+ * @return True if it is required
+ */
+ private boolean isTimeSelectorNeeded() {
+ return getResolution().compareTo(DateTimeResolution.DAY) < 0;
+ }
+}
--- /dev/null
+/*
+ * 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.client.ui;
+
+import java.util.Date;
+import java.util.Map;
+
+import com.google.gwt.core.client.GWT;
+import com.vaadin.shared.ui.datefield.DateTimeResolution;
+
+/**
+ * A client side implementation for inline date/time field.
+ *
+ * @author Vaadin Ltd
+ * @since 8.0
+ *
+ */
+public class VDateTimeFieldCalendar extends
+ VAbstractDateFieldCalendar<VDateTimeCalendarPanel, DateTimeResolution> {
+
+ public VDateTimeFieldCalendar() {
+ super(GWT.create(VDateTimeCalendarPanel.class),
+ DateTimeResolution.MINUTE);
+ }
+
+ @Override
+ 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(),
+ getResolutionVariable(DateTimeResolution.YEAR),
+ date2.getYear() + 1900, false);
+ if (getCurrentResolution().compareTo(DateTimeResolution.YEAR) < 0) {
+ getClient().updateVariable(getId(),
+ getResolutionVariable(DateTimeResolution.MONTH),
+ date2.getMonth() + 1, false);
+ if (getCurrentResolution()
+ .compareTo(DateTimeResolution.MONTH) < 0) {
+ getClient().updateVariable(getId(),
+ getResolutionVariable(DateTimeResolution.DAY),
+ date2.getDate(), false);
+ if (getCurrentResolution()
+ .compareTo(DateTimeResolution.DAY) < 0) {
+ getClient().updateVariable(getId(),
+ getResolutionVariable(DateTimeResolution.HOUR),
+ date2.getHours(), false);
+ if (getCurrentResolution()
+ .compareTo(DateTimeResolution.HOUR) < 0) {
+ getClient().updateVariable(getId(),
+ getResolutionVariable(
+ DateTimeResolution.MINUTE),
+ date2.getMinutes(), false);
+ if (getCurrentResolution()
+ .compareTo(DateTimeResolution.MINUTE) < 0) {
+ getClient().updateVariable(getId(),
+ getResolutionVariable(
+ DateTimeResolution.SECOND),
+ date2.getSeconds(), false);
+ }
+ }
+ }
+ }
+ }
+ getClient().sendPendingVariableChanges();
+ }
+ }
+
+ @Override
+ public String resolutionAsString() {
+ if (getCurrentResolution().compareTo(DateTimeResolution.DAY) >= 0) {
+ return getResolutionVariable(getCurrentResolution());
+ } else {
+ return "full";
+ }
+ }
+
+ @Override
+ public boolean isYear(DateTimeResolution resolution) {
+ return DateTimeResolution.YEAR.equals(resolution);
+ }
+
+ @Override
+ protected Date getDate(Map<DateTimeResolution, Integer> dateValues) {
+ return VPopupTimeCalendar.makeDate(dateValues);
+ }
+
+ @Override
+ protected DateTimeResolution[] doGetResolutions() {
+ return DateTimeResolution.values();
+ }
+
+}
* @author Vaadin Ltd
*
*/
-public class VPopupCalendar extends VAbstractPopupCalendar<DateResolution> {
+public class VPopupCalendar
+ extends VAbstractPopupCalendar<VDateCalendarPanel, DateResolution> {
public VPopupCalendar() {
super(GWT.create(VDateCalendarPanel.class), DateResolution.YEAR);
resolution == null ? DateResolution.YEAR : resolution);
}
- public static Date makeDate(Map<DateResolution, Integer> dateVaules) {
- if (dateVaules.get(DateResolution.YEAR) == -1) {
+ public static Date makeDate(Map<DateResolution, Integer> dateValues) {
+ if (dateValues.get(DateResolution.YEAR) == -1) {
return null;
}
Date date = new Date(2000 - 1900, 0, 1);
- int year = dateVaules.get(DateResolution.YEAR);
+ int year = dateValues.get(DateResolution.YEAR);
if (year >= 0) {
date.setYear(year - 1900);
}
- int month = dateVaules.get(DateResolution.MONTH);
+ int month = dateValues.get(DateResolution.MONTH);
if (month >= 0) {
date.setMonth(month - 1);
}
- int day = dateVaules.get(DateResolution.DAY);
+ int day = dateValues.get(DateResolution.DAY);
if (day >= 0) {
date.setDate(day);
}
}
}
+ @Override
+ protected String cleanFormat(String format) {
+ // Remove unnecessary d & M if resolution is too low
+ if (getCurrentResolution().compareTo(DateResolution.DAY) > 0) {
+ format = format.replaceAll("d", "");
+ }
+ if (getCurrentResolution().compareTo(DateResolution.MONTH) > 0) {
+ format = format.replaceAll("M", "");
+ }
+ return super.cleanFormat(format);
+ }
+
}
--- /dev/null
+/*
+ * 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.client.ui;
+
+import java.util.Date;
+import java.util.Map;
+
+import com.google.gwt.core.client.GWT;
+import com.vaadin.client.LocaleNotLoadedException;
+import com.vaadin.client.LocaleService;
+import com.vaadin.client.VConsole;
+import com.vaadin.shared.ui.datefield.DateTimeResolution;
+
+/**
+ * Represents a date-time selection component with a text field and a popup date
+ * selector.
+ *
+ * @author Vaadin Ltd
+ *
+ * @since 8.0
+ */
+public class VPopupTimeCalendar extends
+ VAbstractPopupCalendar<VDateTimeCalendarPanel, DateTimeResolution> {
+
+ public VPopupTimeCalendar() {
+ super(GWT.create(VDateTimeCalendarPanel.class),
+ DateTimeResolution.MINUTE);
+ }
+
+ @Override
+ protected DateTimeResolution[] doGetResolutions() {
+ return DateTimeResolution.values();
+ }
+
+ @Override
+ public String resolutionAsString() {
+ if (getCurrentResolution().compareTo(DateTimeResolution.DAY) >= 0) {
+ return getResolutionVariable(getCurrentResolution());
+ } else {
+ return "full";
+ }
+ }
+
+ @Override
+ public void setCurrentResolution(DateTimeResolution resolution) {
+ super.setCurrentResolution(
+ resolution == null ? DateTimeResolution.MINUTE : resolution);
+ }
+
+ public static Date makeDate(Map<DateTimeResolution, Integer> dateValues) {
+ if (dateValues.get(DateTimeResolution.YEAR) == -1) {
+ return null;
+ }
+ Date date = new Date(2000 - 1900, 0, 1);
+ int year = dateValues.get(DateTimeResolution.YEAR);
+ if (year >= 0) {
+ date.setYear(year - 1900);
+ }
+ int month = dateValues.get(DateTimeResolution.MONTH);
+ if (month >= 0) {
+ date.setMonth(month - 1);
+ }
+ int day = dateValues.get(DateTimeResolution.DAY);
+ if (day >= 0) {
+ date.setDate(day);
+ }
+ int hour = dateValues.get(DateTimeResolution.HOUR);
+ if (hour >= 0) {
+ date.setHours(hour);
+ }
+ int minute = dateValues.get(DateTimeResolution.MINUTE);
+ if (minute >= 0) {
+ date.setMinutes(minute);
+ }
+ int second = dateValues.get(DateTimeResolution.SECOND);
+ if (second >= 0) {
+ date.setSeconds(second);
+ }
+ return date;
+ }
+
+ @Override
+ public boolean isYear(DateTimeResolution resolution) {
+ return DateTimeResolution.YEAR.equals(resolution);
+ }
+
+ @Override
+ protected Date getDate(Map<DateTimeResolution, Integer> dateValues) {
+ return makeDate(dateValues);
+ }
+
+ @Override
+ protected void updateDateVariables() {
+ super.updateDateVariables();
+ // Update variables
+ // (only the smallest defining resolution needs to be
+ // immediate)
+ Date currentDate = getDate();
+ if (getCurrentResolution().compareTo(DateTimeResolution.MONTH) <= 0) {
+ getClient().updateVariable(getId(),
+ getResolutionVariable(DateTimeResolution.MONTH),
+ currentDate != null ? currentDate.getMonth() + 1 : -1,
+ getCurrentResolution() == DateTimeResolution.MONTH);
+ }
+ if (getCurrentResolution().compareTo(DateTimeResolution.DAY) <= 0) {
+ getClient().updateVariable(getId(),
+ getResolutionVariable(DateTimeResolution.DAY),
+ currentDate != null ? currentDate.getDate() : -1,
+ getCurrentResolution() == DateTimeResolution.DAY);
+ }
+ if (getCurrentResolution().compareTo(DateTimeResolution.HOUR) <= 0) {
+ getClient().updateVariable(getId(),
+ getResolutionVariable(DateTimeResolution.HOUR),
+ currentDate != null ? currentDate.getHours() : -1,
+ getCurrentResolution() == DateTimeResolution.HOUR);
+ }
+ if (getCurrentResolution().compareTo(DateTimeResolution.MINUTE) <= 0) {
+ getClient().updateVariable(getId(),
+ getResolutionVariable(DateTimeResolution.MINUTE),
+ currentDate != null ? currentDate.getMinutes() : -1,
+ getCurrentResolution() == DateTimeResolution.MINUTE);
+ }
+ if (getCurrentResolution().compareTo(DateTimeResolution.SECOND) <= 0) {
+ getClient().updateVariable(getId(),
+ getResolutionVariable(DateTimeResolution.SECOND),
+ currentDate != null ? currentDate.getSeconds() : -1,
+ getCurrentResolution() == DateTimeResolution.SECOND);
+ }
+ }
+
+ @Override
+ @SuppressWarnings("deprecation")
+ public void updateValue(Date newDate) {
+ Date currentDate = getCurrentDate();
+ super.updateValue(newDate);
+ if (currentDate == null || newDate.getTime() != currentDate.getTime()) {
+ if (getCurrentResolution().compareTo(DateTimeResolution.DAY) < 0) {
+ getClient().updateVariable(getId(),
+ getResolutionVariable(DateTimeResolution.HOUR),
+ newDate.getHours(), false);
+ if (getCurrentResolution()
+ .compareTo(DateTimeResolution.HOUR) < 0) {
+ getClient().updateVariable(getId(),
+ getResolutionVariable(DateTimeResolution.MINUTE),
+ newDate.getMinutes(), false);
+ if (getCurrentResolution()
+ .compareTo(DateTimeResolution.MINUTE) < 0) {
+ getClient().updateVariable(getId(),
+ getResolutionVariable(
+ DateTimeResolution.SECOND),
+ newDate.getSeconds(), false);
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ protected String getFormatString() {
+ if (formatStr == null) {
+ if (isYear(getCurrentResolution())) {
+ formatStr = "yyyy"; // force full year
+ } else {
+
+ try {
+ String frmString = LocaleService
+ .getDateFormat(currentLocale);
+ frmString = cleanFormat(frmString);
+ // String delim = LocaleService
+ // .getClockDelimiter(currentLocale);
+ if (getCurrentResolution()
+ .compareTo(DateTimeResolution.HOUR) <= 0) {
+ if (dts.isTwelveHourClock()) {
+ frmString += " hh";
+ } else {
+ frmString += " HH";
+ }
+ if (getCurrentResolution()
+ .compareTo(DateTimeResolution.MINUTE) <= 0) {
+ frmString += ":mm";
+ if (getCurrentResolution().compareTo(
+ DateTimeResolution.SECOND) <= 0) {
+ 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
+ protected String cleanFormat(String format) {
+ // Remove unnecessary d & M if resolution is too low
+ if (getCurrentResolution().compareTo(DateTimeResolution.DAY) > 0) {
+ format = format.replaceAll("d", "");
+ }
+ if (getCurrentResolution().compareTo(DateTimeResolution.MONTH) > 0) {
+ format = format.replaceAll("M", "");
+ }
+ return super.cleanFormat(format);
+ }
+
+}
import com.vaadin.client.ApplicationConnection;
import com.vaadin.client.UIDL;
import com.vaadin.client.communication.StateChangeEvent;
+import com.vaadin.client.ui.VAbstractCalendarPanel;
import com.vaadin.client.ui.VAbstractCalendarPanel.FocusChangeListener;
import com.vaadin.client.ui.VAbstractDateFieldCalendar;
import com.vaadin.shared.ui.datefield.InlineDateFieldState;
*
* @param <R>
* the resolution type which the field is based on (day, month, ...)
+ * @param <PANEL>
+ * Subclass of VAbstractCalendarPanel specific for the implementation
*/
-public abstract class AbstractInlineDateFieldConnector<R extends Enum<R>>
+public abstract class AbstractInlineDateFieldConnector<PANEL extends VAbstractCalendarPanel<R>, R extends Enum<R>>
extends AbstractDateFieldConnector<R> {
@Override
}
@Override
- public VAbstractDateFieldCalendar<R> getWidget() {
- return (VAbstractDateFieldCalendar<R>) super.getWidget();
+ public VAbstractDateFieldCalendar<PANEL, R> getWidget() {
+ return (VAbstractDateFieldCalendar<PANEL, R>) super.getWidget();
}
@Override
*/
package com.vaadin.client.ui.datefield;
+import com.vaadin.client.ui.VDateCalendarPanel;
import com.vaadin.client.ui.VPopupCalendar;
import com.vaadin.shared.ui.Connect;
import com.vaadin.shared.ui.datefield.DateResolution;
*
*/
@Connect(AbstractLocalDateField.class)
-public class DateFieldConnector extends TextualDateConnector<DateResolution> {
+public class DateFieldConnector
+ extends TextualDateConnector<VDateCalendarPanel, DateResolution> {
@Override
- protected boolean isResolutionAboveMonth() {
+ protected boolean isResolutionMonthOrHigher() {
return getWidget().getCurrentResolution()
.compareTo(DateResolution.MONTH) >= 0;
}
--- /dev/null
+/*
+ * 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.client.ui.datefield;
+
+import java.util.Date;
+
+import com.vaadin.client.DateTimeService;
+import com.vaadin.client.ui.VDateTimeCalendarPanel;
+import com.vaadin.client.ui.VDateTimeCalendarPanel.TimeChangeListener;
+import com.vaadin.client.ui.VPopupTimeCalendar;
+import com.vaadin.shared.ui.Connect;
+import com.vaadin.shared.ui.datefield.DateTimeResolution;
+import com.vaadin.shared.ui.datefield.LocalDateTimeFieldState;
+import com.vaadin.ui.AbstractLocalDateTimeField;
+
+/**
+ * The client-side connector for AbstractLocalDateTimeField.
+ *
+ * @author Vaadin Ltd
+ * @since 8.0
+ */
+@Connect(AbstractLocalDateTimeField.class)
+public class DateTimeFieldConnector extends
+ TextualDateConnector<VDateTimeCalendarPanel, DateTimeResolution> {
+
+ @Override
+ protected boolean isResolutionMonthOrHigher() {
+ return getWidget().getCurrentResolution()
+ .compareTo(DateTimeResolution.MONTH) >= 0;
+ }
+
+ @Override
+ public VPopupTimeCalendar getWidget() {
+ return (VPopupTimeCalendar) super.getWidget();
+ }
+
+ @Override
+ public LocalDateTimeFieldState getState() {
+ return (LocalDateTimeFieldState) super.getState();
+ }
+
+ @Override
+ protected void updateListeners() {
+ super.updateListeners();
+ if (getWidget().getCurrentResolution()
+ .compareTo(DateTimeResolution.DAY) < 0) {
+ getWidget().calendar
+ .setTimeChangeListener(new TimeChangeListener() {
+ @Override
+ public void changed(int hour, int min, int sec,
+ int msec) {
+ Date d = getWidget().getDate();
+ if (d == null) {
+ // date currently null, use the value from
+ // calendarPanel
+ // (~ client time at the init of the widget)
+ d = (Date) getWidget().calendar.getDate()
+ .clone();
+ }
+ d.setHours(hour);
+ d.setMinutes(min);
+ d.setSeconds(sec);
+ DateTimeService.setMilliseconds(d, msec);
+
+ // Always update time changes to the server
+ getWidget().updateValue(d);
+
+ // Update text field
+ getWidget().buildDate();
+ }
+ });
+ }
+ }
+}
*/
package com.vaadin.client.ui.datefield;
+import com.vaadin.client.ui.VDateCalendarPanel;
import com.vaadin.client.ui.VDateFieldCalendar;
import com.vaadin.shared.ui.Connect;
import com.vaadin.shared.ui.datefield.DateResolution;
import com.vaadin.ui.InlineDateField;
/**
+ * The client-side connector for InlineDateField.
+ *
* @author Vaadin Ltd
- *
+ * @since 8.0
*/
@Connect(InlineDateField.class)
-public class InlineDateFieldConnector
- extends AbstractInlineDateFieldConnector<DateResolution> {
+public class InlineDateFieldConnector extends
+ AbstractInlineDateFieldConnector<VDateCalendarPanel, DateResolution> {
@Override
protected boolean isResolutionMonthOrHigher() {
--- /dev/null
+/*
+ * 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.client.ui.datefield;
+
+import java.util.Date;
+
+import com.vaadin.client.DateTimeService;
+import com.vaadin.client.ui.VDateTimeCalendarPanel;
+import com.vaadin.client.ui.VDateTimeCalendarPanel.TimeChangeListener;
+import com.vaadin.client.ui.VDateTimeFieldCalendar;
+import com.vaadin.shared.ui.Connect;
+import com.vaadin.shared.ui.datefield.DateTimeResolution;
+import com.vaadin.ui.InlineDateTimeField;
+
+/**
+ * The client-side connector for InlineDateTimeField.
+ *
+ * @author Vaadin Ltd
+ * @since 8.0
+ */
+@Connect(InlineDateTimeField.class)
+public class InlineDateTimeFieldConnector extends
+ AbstractInlineDateFieldConnector<VDateTimeCalendarPanel, DateTimeResolution> {
+
+ @Override
+ protected boolean isResolutionMonthOrHigher() {
+ return getWidget().getCurrentResolution()
+ .compareTo(DateTimeResolution.MONTH) >= 0;
+ }
+
+ @Override
+ public VDateTimeFieldCalendar getWidget() {
+ return (VDateTimeFieldCalendar) super.getWidget();
+ }
+
+ @Override
+ protected void updateListeners() {
+ super.updateListeners();
+ if (getWidget().getCurrentResolution()
+ .compareTo(DateTimeResolution.DAY) < 0) {
+ getWidget().calendarPanel
+ .setTimeChangeListener(new TimeChangeListener() {
+ @Override
+ public void changed(int hour, int min, int sec,
+ int msec) {
+ Date d = getWidget().getDate();
+ if (d == null) {
+ // date currently null, use the value from
+ // calendarPanel
+ // (~ client time at the init of the widget)
+ d = (Date) getWidget().calendarPanel.getDate()
+ .clone();
+ }
+ d.setHours(hour);
+ d.setMinutes(min);
+ d.setSeconds(sec);
+ DateTimeService.setMilliseconds(d, msec);
+
+ // Always update time changes to the server
+ getWidget().calendarPanel.setDate(d);
+ getWidget().updateValueFromPanel();
+ }
+ });
+ }
+ }
+}
import com.vaadin.shared.ui.Connect;
import com.vaadin.ui.DateField;
+/**
+ * The client-side connector for DateField.
+ *
+ * @author Vaadin Ltd
+ * @since 8.0
+ */
@Connect(DateField.class)
public class PopupDateFieldConnector extends DateFieldConnector {
--- /dev/null
+/*
+ * 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.client.ui.datefield;
+
+import com.vaadin.shared.ui.Connect;
+import com.vaadin.ui.DateTimeField;
+
+/**
+ * The client-side connector for DateTimeField.
+ *
+ * @author Vaadin Ltd
+ * @since 8.0
+ *
+ */
+@Connect(DateTimeField.class)
+public class PopupDateTimeFieldConnector extends DateTimeFieldConnector {
+
+}
import com.vaadin.client.ApplicationConnection;
import com.vaadin.client.UIDL;
import com.vaadin.client.communication.StateChangeEvent;
+import com.vaadin.client.ui.VAbstractCalendarPanel;
import com.vaadin.client.ui.VAbstractCalendarPanel.FocusChangeListener;
import com.vaadin.client.ui.VAbstractPopupCalendar;
import com.vaadin.shared.ui.datefield.TextualDateFieldState;
-public abstract class TextualDateConnector<R extends Enum<R>>
+/**
+ * Abstract date/time field connector which extend
+ * {@link AbstractTextualDateConnector} functionality with widget that shows
+ * date/time chooser as a popup panel.
+ *
+ * @author Vaadin Ltd
+ *
+ * @since 8.0
+ *
+ * @param <PANEL>
+ * Subclass of VAbstractCalendarPanel specific for the implementation
+ * @param <R>
+ * the resolution type which the field is based on (day, month, ...)
+ */
+public abstract class TextualDateConnector<PANEL extends VAbstractCalendarPanel<R>, R extends Enum<R>>
extends AbstractTextualDateConnector<R> {
@Override
* customizing only listeners logic.
*/
protected void updateListeners() {
- if (isResolutionAboveMonth()) {
+ if (isResolutionMonthOrHigher()) {
getWidget().calendar
.setFocusChangeListener(new FocusChangeListener() {
@Override
public void focusChanged(Date date) {
-
- getWidget().updateValue(date);
- getWidget().buildDate();
- Date date2 = getWidget().calendar.getDate();
- date2.setYear(date.getYear());
- date2.setMonth(date.getMonth());
+ if (isResolutionMonthOrHigher()) {
+ getWidget().updateValue(date);
+ getWidget().buildDate();
+ Date date2 = getWidget().calendar.getDate();
+ date2.setYear(date.getYear());
+ date2.setMonth(date.getMonth());
+ }
}
});
} else {
}
}
- protected abstract boolean isResolutionAboveMonth();
+ /**
+ * Returns {@code true} is the current resolution of the widget is month or
+ * less specific (e.g. month, year, quarter, etc).
+ *
+ * @return {@code true} if the current resolution is above month
+ */
+ protected abstract boolean isResolutionMonthOrHigher();
@Override
- public VAbstractPopupCalendar<R> getWidget() {
- return (VAbstractPopupCalendar<R>) super.getWidget();
+ public VAbstractPopupCalendar<PANEL, R> getWidget() {
+ return (VAbstractPopupCalendar<PANEL, R>) super.getWidget();
}
@Override
--- /dev/null
+/*
+ * 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.data.converter;
+
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.util.Date;
+import java.util.Objects;
+
+import com.vaadin.data.Converter;
+import com.vaadin.data.Result;
+import com.vaadin.data.ValueContext;
+import com.vaadin.ui.DateTimeField;
+import com.vaadin.ui.InlineDateTimeField;
+
+/**
+ * A converter that converts between <code>LocalDateTime</code> and
+ * <code>Date</code>. This is used when a {@link DateTimeField} or
+ * {@link InlineDateTimeField} is bound to a {@link Date} property.
+ *
+ * @author Vaadin Ltd
+ */
+public class LocalDateTimeToDateConverter
+ implements Converter<LocalDateTime, Date> {
+
+ private ZoneOffset zoneOffset;
+
+ /**
+ * Creates a new converter using the given time zone.
+ *
+ * @param zoneOffset
+ * the time zone offset to use, not <code>null</code>
+ */
+ public LocalDateTimeToDateConverter(ZoneOffset zoneOffset) {
+ this.zoneOffset = Objects.requireNonNull(zoneOffset,
+ "Zone offset cannot be null");
+ }
+
+ @Override
+ public Result<Date> convertToModel(LocalDateTime localDate,
+ ValueContext context) {
+ if (localDate == null) {
+ return Result.ok(null);
+ }
+
+ return Result.ok(Date.from(localDate.toInstant(zoneOffset)));
+ }
+
+ @Override
+ public LocalDateTime convertToPresentation(Date date,
+ ValueContext context) {
+ if (date == null) {
+ return null;
+ }
+
+ return Instant.ofEpochMilli(date.getTime()).atZone(zoneOffset)
+ .toLocalDateTime();
+ }
+
+}
--- /dev/null
+/*
+ * 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.data.validator;
+
+import java.time.LocalDateTime;
+import java.util.Comparator;
+
+/**
+ * Validator for validating that a {@link LocalDateTime} is inside a given
+ * range.
+ *
+ * @author Vaadin Ltd.
+ * @since 8.0
+ */
+public class DateTimeRangeValidator extends RangeValidator<LocalDateTime> {
+
+ /**
+ * Creates a validator for checking that a {@link LocalDateTime} is within a
+ * given range.
+ * <p>
+ * By default the range is inclusive i.e. both minValue and maxValue are
+ * valid values. Use {@link #setMinValueIncluded(boolean)} or
+ * {@link #setMaxValueIncluded(boolean)} to change it.
+ * </p>
+ *
+ * @param errorMessage
+ * the message to display in case the value does not validate.
+ * @param minValue
+ * The minimum value to accept or null for no limit
+ * @param maxValue
+ * The maximum value to accept or null for no limit
+ */
+ public DateTimeRangeValidator(String errorMessage, LocalDateTime minValue,
+ LocalDateTime maxValue) {
+ super(errorMessage, Comparator.naturalOrder(), minValue, maxValue);
+ }
+
+}
import com.vaadin.shared.ui.datefield.DateResolution;
/**
+ * Abstract DateField class for {@link LocalDate} type.
+ *
* @author Vaadin Ltd
+ *
+ * @since 8.0
*
*/
public abstract class AbstractLocalDateField
*/
package com.vaadin.ui;
+import java.time.Instant;
import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.time.temporal.ChronoUnit;
+import java.util.Date;
+import java.util.Map;
+import com.vaadin.data.validator.DateTimeRangeValidator;
+import com.vaadin.data.validator.RangeValidator;
+import com.vaadin.shared.ui.datefield.AbstractTextualDateFieldState;
import com.vaadin.shared.ui.datefield.DateTimeResolution;
-import com.vaadin.shared.ui.datefield.LocalDateTimeFieldState;
/**
+ * Abstract DateField class for {@link LocalDateTime} type.
+ *
* @author Vaadin Ltd
*
+ * @since 8.0
*/
public abstract class AbstractLocalDateTimeField
extends AbstractDateField<LocalDateTime, DateTimeResolution> {
super(caption, DateTimeResolution.MINUTE);
}
+ /**
+ * Constructs a new <code>AbstractLocalDateTimeField</code> with the given
+ * caption and initial text contents.
+ *
+ * @param caption
+ * the caption <code>String</code> for the editor.
+ * @param value
+ * the LocalDateTime value.
+ */
+ public AbstractLocalDateTimeField(String caption, LocalDateTime value) {
+ super(caption, value, DateTimeResolution.MINUTE);
+ }
+
+ @Override
+ protected AbstractTextualDateFieldState getState() {
+ return (AbstractTextualDateFieldState) super.getState();
+ }
+
+ @Override
+ protected AbstractTextualDateFieldState getState(boolean markAsDirty) {
+ return (AbstractTextualDateFieldState) super.getState(markAsDirty);
+ }
+
@Override
- protected LocalDateTimeFieldState getState() {
- return (LocalDateTimeFieldState) super.getState();
+ protected int getDatePart(LocalDateTime date,
+ DateTimeResolution resolution) {
+ LocalDateTime value = date;
+ if (value == null) {
+ value = LocalDateTime.of(1, 1, 1, 0, 0);
+ }
+ switch (resolution) {
+ case DAY:
+ return value.getDayOfMonth();
+ case MONTH:
+ return value.getMonthValue();
+ case YEAR:
+ return value.getYear();
+ case HOUR:
+ return value.getHour();
+ case MINUTE:
+ return value.getMinute();
+ case SECOND:
+ return value.getSecond();
+ default:
+ assert false : "Unexpected resolution argument " + resolution;
+ return -1;
+ }
}
@Override
- protected LocalDateTimeFieldState getState(boolean markAsDirty) {
- return (LocalDateTimeFieldState) super.getState(markAsDirty);
+ protected RangeValidator<LocalDateTime> getRangeValidator() {
+ return new DateTimeRangeValidator(getDateOutOfRangeMessage(),
+ getDate(getRangeStart(), getResolution()),
+ getDate(getRangeEnd(), getResolution()));
+ }
+
+ @Override
+ protected LocalDateTime buildDate(
+ Map<DateTimeResolution, Integer> resolutionValues) {
+ return LocalDateTime.of(resolutionValues.get(DateTimeResolution.YEAR),
+ resolutionValues.getOrDefault(DateTimeResolution.MONTH, 1),
+ resolutionValues.getOrDefault(DateTimeResolution.DAY, 1),
+ resolutionValues.getOrDefault(DateTimeResolution.HOUR, 0),
+ resolutionValues.getOrDefault(DateTimeResolution.MINUTE, 0),
+ resolutionValues.getOrDefault(DateTimeResolution.SECOND, 0));
+ }
+
+ @Override
+ protected LocalDateTime convertFromDate(Date date) {
+ if (date == null) {
+ return null;
+ }
+ return Instant.ofEpochMilli(date.getTime()).atZone(ZoneOffset.UTC)
+ .toLocalDateTime();
+ }
+
+ @Override
+ protected Date convertToDate(LocalDateTime date) {
+ if (date == null) {
+ return null;
+ }
+ return Date.from(date.toInstant(ZoneOffset.UTC));
+ }
+
+ private LocalDateTime getDate(LocalDateTime date,
+ DateTimeResolution forResolution) {
+ if (date == null) {
+ return null;
+ }
+ switch (forResolution) {
+ case YEAR:
+ return date.withDayOfYear(1).toLocalDate().atStartOfDay();
+ case MONTH:
+ return date.withDayOfMonth(1).toLocalDate().atStartOfDay();
+ case DAY:
+ return date.toLocalDate().atStartOfDay();
+ case HOUR:
+ return date.truncatedTo(ChronoUnit.HOURS);
+ case MINUTE:
+ return date.truncatedTo(ChronoUnit.MINUTES);
+ case SECOND:
+ return date.truncatedTo(ChronoUnit.SECONDS);
+ default:
+ assert false : "Unexpected resolution argument " + forResolution;
+ return null;
+ }
}
}
--- /dev/null
+/*
+ * 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.ui;
+
+import java.time.LocalDateTime;
+
+import com.vaadin.shared.ui.datefield.LocalDateTimeFieldState;
+
+/**
+ * A date time entry component, which displays the actual date selector as a
+ * popup.
+ *
+ * @see AbstractLocalDateTimeField
+ * @see InlineDateTimeField
+ * @author Vaadin Ltd.
+ * @since 8.0
+ */
+public class DateTimeField extends AbstractLocalDateTimeField {
+
+ /**
+ * Constructs an empty <code>DateTimeField</code> with no caption.
+ */
+ public DateTimeField() {
+ super();
+ }
+
+ /**
+ * Constructs a new <code>DateTimeField</code> with the given caption and
+ * initial text contents.
+ *
+ * @param caption
+ * the caption <code>String</code> for the editor.
+ * @param value
+ * the LocalDateTime value.
+ */
+ public DateTimeField(String caption, LocalDateTime value) {
+ super(caption, value);
+ }
+
+ /**
+ * Constructs an empty <code>DateTimeField</code> with caption.
+ *
+ * @param caption
+ * the caption of the datefield.
+ */
+ public DateTimeField(String caption) {
+ super(caption);
+ }
+
+ /**
+ * Returns the current placeholder text.
+ *
+ * @see #setPlaceholder(String)
+ * @return the placeholder text
+ */
+ public String getPlaceholder() {
+ return getState(false).placeholder;
+ }
+
+ /**
+ * Sets the placeholder text. The placeholder is text that is displayed when
+ * the field would otherwise be empty, to prompt the user for input.
+ *
+ * @param placeholder
+ * the placeholder text to set
+ */
+ public void setPlaceholder(String placeholder) {
+ getState().placeholder = placeholder;
+ }
+
+ @Override
+ protected LocalDateTimeFieldState getState() {
+ return (LocalDateTimeFieldState) super.getState();
+ }
+
+ @Override
+ protected LocalDateTimeFieldState getState(boolean markAsDirty) {
+ return (LocalDateTimeFieldState) super.getState(markAsDirty);
+ }
+
+ /**
+ * Checks whether the text field is enabled (default) or not.
+ *
+ * @see #setTextFieldEnabled(boolean)
+ *
+ * @return <b>true</b> if the text field is enabled, <b>false</b> otherwise.
+ */
+ public boolean isTextFieldEnabled() {
+ return getState(false).textFieldEnabled;
+ }
+
+ /**
+ * Enables or disables the text field. 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
+ * <b>true</b> to enable text field, <b>false</b> to disable it.
+ */
+ public void setTextFieldEnabled(boolean state) {
+ getState().textFieldEnabled = state;
+ }
+
+ /**
+ * Set a description that explains the usage of the Widget for users of
+ * assistive devices.
+ *
+ * @param description
+ * String with the description
+ */
+ public void setAssistiveText(String description) {
+ getState().descriptionForAssistiveDevices = description;
+ }
+
+ /**
+ * Get the description that explains the usage of the Widget for users of
+ * assistive devices.
+ *
+ * @return String with the description
+ */
+ public String getAssistiveText() {
+ return getState(false).descriptionForAssistiveDevices;
+ }
+}
--- /dev/null
+/*
+ * 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.ui;
+
+import java.time.LocalDateTime;
+
+import com.vaadin.shared.ui.datefield.InlineDateTimeFieldState;
+
+/**
+ * A date time entry component, which displays the actual date selector inline.
+ *
+ * @see AbstractLocalDateTimeField
+ * @see DateTimeField
+ * @author Vaadin Ltd.
+ * @since 8.0
+ */
+public class InlineDateTimeField extends AbstractLocalDateTimeField {
+
+ /**
+ * Constructs an empty <code>InlineDateTimeField</code> with no caption.
+ */
+ public InlineDateTimeField() {
+ super();
+ }
+
+ /**
+ * Constructs a new <code>InlineDateTimeField</code> with the given caption
+ * and initial text contents.
+ *
+ * @param caption
+ * the caption <code>String</code> for the editor.
+ * @param value
+ * the LocalDate value.
+ */
+ public InlineDateTimeField(String caption, LocalDateTime value) {
+ super(caption, value);
+ }
+
+ /**
+ * Constructs an empty <code>InlineDateTimeField</code> with caption.
+ *
+ * @param caption
+ * the caption of the datefield.
+ */
+ public InlineDateTimeField(String caption) {
+ super(caption);
+ }
+
+ @Override
+ protected InlineDateTimeFieldState getState() {
+ return (InlineDateTimeFieldState) super.getState();
+ }
+
+ @Override
+ protected InlineDateTimeFieldState getState(boolean markAsDirty) {
+ return (InlineDateTimeFieldState) super.getState(markAsDirty);
+ }
+}
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.time.LocalDate;
+import java.time.LocalDateTime;
import java.util.Collections;
import java.util.Date;
import java.util.Locale;
import com.vaadin.ui.declarative.converters.DesignDateConverter;
import com.vaadin.ui.declarative.converters.DesignEnumConverter;
import com.vaadin.ui.declarative.converters.DesignLocalDateConverter;
+import com.vaadin.ui.declarative.converters.DesignLocalDateTimeConverter;
import com.vaadin.ui.declarative.converters.DesignObjectConverter;
import com.vaadin.ui.declarative.converters.DesignResourceConverter;
import com.vaadin.ui.declarative.converters.DesignShortcutActionConverter;
converterMap.put(Date.class, new DesignDateConverter());
converterMap.put(LocalDate.class, new DesignLocalDateConverter());
+ converterMap.put(LocalDateTime.class,
+ new DesignLocalDateTimeConverter());
converterMap.put(ShortcutAction.class,
new DesignShortcutActionConverter());
converterMap.put(Resource.class, new DesignResourceConverter());
--- /dev/null
+/*
+ * 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.ui.declarative.converters;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+import java.util.Locale;
+
+import com.vaadin.data.Converter;
+import com.vaadin.data.Result;
+import com.vaadin.data.ValueContext;
+import com.vaadin.ui.declarative.DesignAttributeHandler;
+
+/**
+ * A {@link LocalDate} converter to be used by {@link DesignAttributeHandler}.
+ * Provides ISO-compliant way of storing date and time.
+ *
+ * @since 8.0
+ * @author Vaadin Ltd
+ */
+public class DesignLocalDateTimeConverter
+ implements Converter<String, LocalDateTime> {
+
+ @Override
+ public Result<LocalDateTime> convertToModel(String value,
+ ValueContext context) {
+ for (String pattern : new String[] { "yyyy-MM-dd HH:mm:ssZ",
+ "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM-dd HH",
+ "yyyy-MM-dd", "yyyy-MM", "yyyy" }) {
+ try {
+ Locale effectiveLocale = context.getLocale()
+ .orElse(Locale.ENGLISH);
+ LocalDateTime date = DateTimeFormatter
+ .ofPattern(pattern, effectiveLocale)
+ .parse(value, LocalDateTime::from);
+ return Result.ok(date);
+ } catch (DateTimeParseException ignored) {
+ // not parseable, ignore and try another format
+ }
+ }
+ return Result.error("Could not parse date value: " + value);
+ }
+
+ @Override
+ public String convertToPresentation(LocalDateTime value,
+ ValueContext context) {
+ return DateTimeFormatter
+ .ofPattern("yyyy-MM-dd HH:mm:ss",
+ context.getLocale().orElse(Locale.ENGLISH))
+ .format(value);
+ }
+
+}
--- /dev/null
+/*
+ * 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.tests.data.converter;
+
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.data.Binder;
+import com.vaadin.data.ValidationException;
+import com.vaadin.data.ValueContext;
+import com.vaadin.data.converter.LocalDateTimeToDateConverter;
+import com.vaadin.ui.DateTimeField;
+
+public class LocalDateTimeToDateConverterTest extends AbstractConverterTest {
+
+ private static final LocalDateTime LOCAL_DATE = LocalDateTime.of(2017, 1, 1,
+ 1, 1, 1);
+ private static final Date DATE = createDate();
+
+ @Override
+ protected LocalDateTimeToDateConverter getConverter() {
+ return new LocalDateTimeToDateConverter(ZoneOffset.UTC);
+ }
+
+ @Test
+ public void testToModel() {
+ assertValue(DATE,
+ getConverter().convertToModel(LOCAL_DATE, new ValueContext()));
+ }
+
+ @Test
+ public void testToModelFromSqlDate() {
+ // Check that SQL dates also work (e.g. java.sql.Date.toInstant throws)
+ assertValue(new java.sql.Date(DATE.getTime()),
+ getConverter().convertToModel(LOCAL_DATE, new ValueContext()));
+ }
+
+ @Test
+ public void testToPresentation() {
+ Assert.assertEquals(LOCAL_DATE,
+ getConverter().convertToPresentation(DATE, new ValueContext()));
+ }
+
+ @Test
+ public void useWithBinder() throws ValidationException {
+ Binder<BeanWithDate> binder = new Binder<>();
+ DateTimeField dateField = new DateTimeField();
+
+ binder.forField(dateField).withConverter(getConverter())
+ .bind(BeanWithDate::getDate, BeanWithDate::setDate);
+
+ dateField.setValue(LOCAL_DATE);
+
+ BeanWithDate bean = new BeanWithDate();
+ binder.writeBean(bean);
+
+ Assert.assertEquals(DATE, bean.getDate());
+ }
+
+ public static class BeanWithDate {
+ private Date date;
+
+ public void setDate(Date date) {
+ this.date = date;
+ }
+
+ public Date getDate() {
+ return date;
+ }
+ }
+
+ private static Date createDate() {
+ Calendar calendar = Calendar
+ .getInstance(TimeZone.getTimeZone(ZoneOffset.UTC));
+ calendar.clear();
+ calendar.set(2017, Calendar.JANUARY, 1, 1, 1, 1);
+ return calendar.getTime();
+ }
+
+}
--- /dev/null
+/*
+ * 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.tests.server.component.abstractdatefield;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Locale;
+
+import org.junit.Test;
+
+import com.vaadin.shared.ui.datefield.DateTimeResolution;
+import com.vaadin.tests.server.component.abstractfield.AbstractFieldDeclarativeTest;
+import com.vaadin.ui.AbstractLocalDateTimeField;
+
+/**
+ * Abstract test class which contains tests for declarative format for
+ * properties that are common for AbstractDateField.
+ * <p>
+ * It's an abstract so it's not supposed to be run as is. Instead each
+ * declarative test for a real component should extend it and implement abstract
+ * methods to be able to test the common properties. Components specific
+ * properties should be tested additionally in the subclasses implementations.
+ *
+ * @author Vaadin Ltd
+ *
+ */
+public abstract class AbstractLocalDateTimeFieldDeclarativeTest<T extends AbstractLocalDateTimeField>
+ extends AbstractFieldDeclarativeTest<T, LocalDateTime> {
+
+ protected DateTimeFormatter DATE_FORMATTER = DateTimeFormatter
+ .ofPattern("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH);
+
+ @Override
+ public void valueDeserialization()
+ throws InstantiationException, IllegalAccessException {
+ LocalDateTime value = LocalDateTime.of(2003, 02, 27, 10, 37, 43);
+ String design = String.format("<%s value='%s'/>", getComponentTag(),
+ DATE_FORMATTER.format(value));
+
+ T component = getComponentClass().newInstance();
+ component.setValue(value);
+
+ testRead(design, component);
+ testWrite(design, component);
+ }
+
+ @Test
+ public void abstractDateFieldAttributesDeserialization()
+ throws InstantiationException, IllegalAccessException {
+ boolean showIsoWeeks = true;
+ LocalDateTime end = LocalDateTime.of(2019, 02, 27, 10, 37, 43);
+ LocalDateTime start = LocalDateTime.of(2001, 02, 27, 23, 12, 34);
+ String dateOutOfRange = "test date out of range";
+ DateTimeResolution resolution = DateTimeResolution.HOUR;
+ String dateFormat = "test format";
+ boolean lenient = true;
+ String parseErrorMsg = "test parse error";
+ String design = String.format(
+ "<%s show-iso-week-numbers range-end='%s' range-start='%s' "
+ + "date-out-of-range-message='%s' resolution='%s' "
+ + "date-format='%s' lenient parse-error-message='%s'/>",
+ getComponentTag(), DATE_FORMATTER.format(end),
+ DATE_FORMATTER.format(start), dateOutOfRange,
+ resolution.name().toLowerCase(Locale.ENGLISH), dateFormat,
+ parseErrorMsg);
+
+ T component = getComponentClass().newInstance();
+
+ component.setShowISOWeekNumbers(showIsoWeeks);
+ component.setRangeEnd(end);
+ component.setRangeStart(start);
+ component.setDateOutOfRangeMessage(dateOutOfRange);
+ component.setResolution(resolution);
+ component.setDateFormat(dateFormat);
+ component.setLenient(lenient);
+ component.setParseErrorMessage(parseErrorMsg);
+
+ testRead(design, component);
+ testWrite(design, component);
+ }
+
+ @Override
+ public void readOnlyValue()
+ throws InstantiationException, IllegalAccessException {
+ LocalDateTime value = LocalDateTime.of(2003, 02, 27, 23, 12, 34);
+ String design = String.format("<%s value='%s' readonly/>",
+ getComponentTag(), DATE_FORMATTER.format(value));
+
+ T component = getComponentClass().newInstance();
+ component.setValue(value);
+ component.setReadOnly(true);
+
+ testRead(design, component);
+ testWrite(design, component);
+ }
+
+}
testWrite(design, component);
}
+ @Test
public abstract void valueDeserialization()
throws InstantiationException, IllegalAccessException;
+ @Test
public abstract void readOnlyValue()
throws InstantiationException, IllegalAccessException;
}
public void valueDeserialization()
throws InstantiationException, IllegalAccessException {
String rgb = "fafafa";
- String design = String.format("<%s color='#%s'/>", getComponentTag());
+ String design = String.format("<%s color='#%s'/>", getComponentTag(),
+ rgb);
T colorPicker = getComponentClass().newInstance();
int colorInt = Integer.parseInt(rgb, 16);
throws InstantiationException, IllegalAccessException {
String rgb = "fafafa";
String design = String.format("<%s color='#%s' readonly/>",
- getComponentTag());
+ getComponentTag(), rgb);
T colorPicker = getComponentClass().newInstance();
int colorInt = Integer.parseInt(rgb, 16);
--- /dev/null
+/*
+ * 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.tests.server.component.datefield;
+
+import org.junit.Test;
+
+import com.vaadin.tests.server.component.abstractdatefield.AbstractLocalDateTimeFieldDeclarativeTest;
+import com.vaadin.ui.DateTimeField;
+
+/**
+ * Tests the declarative support for implementations of {@link DateTimeField}.
+ *
+ * @since 8.0
+ * @author Vaadin Ltd
+ */
+public class DateTimeFieldDeclarativeTest
+ extends AbstractLocalDateTimeFieldDeclarativeTest<DateTimeField> {
+
+ @Test
+ public void remainingAttributes()
+ throws InstantiationException, IllegalAccessException {
+ String placeholder = "foo";
+ String assistiveText = "at";
+ boolean textFieldEnabled = false;
+ String design = String.format(
+ "<%s placeholder='%s' "
+ + "assistive-text='%s' text-field-enabled='%s'/>",
+ getComponentTag(), placeholder, assistiveText,
+ textFieldEnabled);
+
+ DateTimeField component = getComponentClass().newInstance();
+ component.setPlaceholder(placeholder);
+ component.setTextFieldEnabled(textFieldEnabled);
+ component.setAssistiveText(assistiveText);
+
+ testRead(design, component);
+ testWrite(design, component);
+ }
+
+ @Override
+ protected String getComponentTag() {
+ return "vaadin-date-time-field";
+ }
+
+ @Override
+ protected Class<? extends DateTimeField> getComponentClass() {
+ return DateTimeField.class;
+ }
+
+}
--- /dev/null
+/*
+ * 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.tests.server.component.datefield;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.time.LocalDateTime;
+
+import org.junit.Test;
+
+import com.vaadin.shared.ui.datefield.DateTimeResolution;
+import com.vaadin.tests.server.component.abstractdatefield.AbstractLocalDateTimeFieldDeclarativeTest;
+import com.vaadin.ui.AbstractDateField;
+import com.vaadin.ui.InlineDateTimeField;
+import com.vaadin.ui.declarative.Design;
+
+/**
+ * Tests the declarative support for implementations of
+ * {@link AbstractDateField}.
+ *
+ * @since 7.4
+ * @author Vaadin Ltd
+ */
+public class InlineDateTimeFieldDeclarativeTest
+ extends AbstractLocalDateTimeFieldDeclarativeTest<InlineDateTimeField> {
+
+ @Test
+ public void testInlineDateFieldToFromDesign() throws Exception {
+ InlineDateTimeField field = new InlineDateTimeField("Day is",
+ LocalDateTime.of(2003, 2, 27, 4, 13, 45));
+ field.setShowISOWeekNumbers(true);
+ field.setRangeStart(LocalDateTime.of(2001, 2, 27, 6, 12, 53));
+ field.setRangeEnd(LocalDateTime.of(20011, 2, 27, 3, 43, 23));
+ field.setResolution(DateTimeResolution.SECOND);
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ Design.write(field, bos);
+
+ InlineDateTimeField result = (InlineDateTimeField) Design
+ .read(new ByteArrayInputStream(bos.toByteArray()));
+ assertEquals(field.getResolution(), result.getResolution());
+ assertEquals(field.getCaption(), result.getCaption());
+ assertEquals(field.getValue(), result.getValue());
+ assertEquals(field.getRangeStart(), result.getRangeStart());
+ assertEquals(field.getRangeEnd(), result.getRangeEnd());
+ }
+
+ @Override
+ protected String getComponentTag() {
+ return "vaadin-inline-date-time-field";
+ }
+
+ @Override
+ protected Class<? extends InlineDateTimeField> getComponentClass() {
+ return InlineDateTimeField.class;
+ }
+
+}
package com.vaadin.shared.ui.datefield;
/**
- * Resolutions for DateTimeFields
+ * Resolutions for DateTimeFields.
*
* @author Vaadin Ltd.
* @since 8.0
--- /dev/null
+/*
+ * 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.shared.ui.datefield;
+
+/**
+ * @author Vaadin Ltd
+ *
+ */
+public class InlineDateTimeFieldState extends AbstractTextualDateFieldState {
+ {
+ primaryStyleName = "v-inline-datefield";
+ }
+}
* @author Vaadin Ltd
*
*/
-public class LocalDateTimeFieldState extends AbstractTextualDateFieldState {
+public class LocalDateTimeFieldState extends TextualDateFieldState {
}
-Subproject commit 203312a80a5f76d48fc36ef8d215f8b70b8e7545
+Subproject commit e9f8b30d0db8076f24c9253f078b2931f0ecd3fa
--- /dev/null
+/*
+ * 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.testbench.customelements;
+
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+/**
+ * @author Vaadin Ltd
+ *
+ */
+@ServerClass("com.vaadin.ui.DateTimeField")
+public class DateTimeFieldElement extends DateFieldElement {
+
+}
--- /dev/null
+/*
+ * 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.testbench.customelements;
+
+import com.vaadin.testbench.elements.InlineDateFieldElement;
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+/**
+ * @author Vaadin Ltd
+ *
+ */
+@ServerClass("com.vaadin.ui.InlineDateTimeField")
+public class InlineDateTimeFieldElement extends InlineDateFieldElement {
+
+}
import java.util.Locale;
import com.vaadin.shared.ui.datefield.DateResolution;
-import com.vaadin.tests.components.TestDateField;
import com.vaadin.tests.components.abstractfield.AbstractFieldTest;
import com.vaadin.ui.AbstractLocalDateField;
-public class AbstractDateFieldTest<T extends AbstractLocalDateField>
+public abstract class AbstractDateFieldTest<T extends AbstractLocalDateField>
extends AbstractFieldTest<T, LocalDate> {
- @SuppressWarnings("unchecked")
- @Override
- protected Class<T> getTestClass() {
- return (Class<T>) TestDateField.class;
- }
-
private Command<T, LocalDate> setValue = new Command<T, LocalDate>() {
@Override
--- /dev/null
+package com.vaadin.tests.components.datefield;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
+import java.util.LinkedHashMap;
+import java.util.Locale;
+
+import com.vaadin.shared.ui.datefield.DateTimeResolution;
+import com.vaadin.tests.components.abstractfield.AbstractFieldTest;
+import com.vaadin.ui.AbstractLocalDateTimeField;
+
+public abstract class AbstractDateTimeFieldTest<T extends AbstractLocalDateTimeField>
+ extends AbstractFieldTest<T, LocalDateTime> {
+
+ private Command<T, LocalDateTime> setValue = new Command<T, LocalDateTime>() {
+
+ @Override
+ public void execute(T c, LocalDateTime value, Object data) {
+ c.setValue(value);
+ }
+ };
+
+ @Override
+ protected void createActions() {
+ super.createActions();
+ createResolutionSelectAction(CATEGORY_FEATURES);
+ createBooleanAction("Lenient", CATEGORY_FEATURES, false,
+ lenientCommand);
+ createBooleanAction("Show week numbers", CATEGORY_FEATURES, false,
+ weekNumberCommand);
+ createDateFormatSelectAction(CATEGORY_FEATURES);
+ createSetValueAction(CATEGORY_FEATURES);
+
+ }
+
+ private void createSetValueAction(String category) {
+ LinkedHashMap<String, LocalDateTime> options = new LinkedHashMap<>();
+ options.put("(null)", null);
+ options.put("(current time)", LocalDateTime.now());
+ options.put("2010-12-12", LocalDateTime.of(2010, 12, 12, 6, 34, 23));
+ createMultiClickAction("Set value", category, options, setValue, null);
+ }
+
+ private void createDateFormatSelectAction(String category) {
+ LinkedHashMap<String, String> options = new LinkedHashMap<>();
+
+ options.put("-", null);
+ options.put("d M yyyy", "d M yyyy");
+ options.put("d MM yyyy", "d MM yyyy");
+ options.put("d MMM yyyy", "d MMM yyyy");
+ options.put("d MMMM yyyy", "d MMMM yyyy");
+ options.put("dd M yyyy", "dd M yyyy");
+ options.put("ddd M yyyy", "ddd M yyyy");
+ options.put("d M y", "d M y");
+ options.put("d M yy", "d M yy");
+ options.put("d M yyy", "d M yyy");
+ options.put("d M yyyy", "d M yyyy");
+ options.put("d M 'custom text' yyyy", "d M 'custom text' yyyy");
+ options.put("'day:'d', month:'M', year: 'yyyy",
+ "'day:'d', month:'M', year: 'yyyy");
+ options.put(getDatePattern(new Locale("fi", "FI"), DateFormat.LONG),
+ getDatePattern(new Locale("fi", "FI"), DateFormat.LONG));
+ options.put(getDatePattern(new Locale("fi", "FI"), DateFormat.MEDIUM),
+ getDatePattern(new Locale("fi", "FI"), DateFormat.MEDIUM));
+ options.put(getDatePattern(new Locale("fi", "FI"), DateFormat.SHORT),
+ getDatePattern(new Locale("fi", "FI"), DateFormat.SHORT));
+
+ createSelectAction("Date format", category, options, "-",
+ dateFormatCommand);
+
+ }
+
+ private String getDatePattern(Locale locale, int dateStyle) {
+ DateFormat dateFormat = DateFormat.getDateInstance(dateStyle, locale);
+
+ if (dateFormat instanceof SimpleDateFormat) {
+ String pattern = ((SimpleDateFormat) dateFormat).toPattern();
+ return pattern;
+ }
+ return null;
+
+ }
+
+ private void createResolutionSelectAction(String category) {
+ LinkedHashMap<String, DateTimeResolution> options = new LinkedHashMap<>();
+ options.put("Year", DateTimeResolution.YEAR);
+ options.put("Month", DateTimeResolution.MONTH);
+ options.put("Day", DateTimeResolution.DAY);
+ options.put("Hour", DateTimeResolution.HOUR);
+ options.put("Min", DateTimeResolution.MINUTE);
+ options.put("Sec", DateTimeResolution.SECOND);
+
+ createSelectAction("Resolution", category, options, "Year",
+ resolutionCommand);
+ }
+
+ private Command<T, DateTimeResolution> resolutionCommand = new Command<T, DateTimeResolution>() {
+
+ @Override
+ public void execute(T c, DateTimeResolution value, Object data) {
+ c.setResolution(value);
+
+ }
+ };
+ private Command<T, Boolean> lenientCommand = new Command<T, Boolean>() {
+
+ @Override
+ public void execute(T c, Boolean value, Object data) {
+ c.setLenient(false);
+
+ }
+ };
+ private Command<T, Boolean> weekNumberCommand = new Command<T, Boolean>() {
+
+ @Override
+ public void execute(T c, Boolean value, Object data) {
+ c.setShowISOWeekNumbers(value);
+
+ }
+ };
+ private Command<T, String> dateFormatCommand = new Command<T, String>() {
+
+ @Override
+ public void execute(T c, String value, Object data) {
+ c.setDateFormat(value);
+ }
+ };
+
+}
--- /dev/null
+/*
+ * 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.tests.components.datefield;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractReindeerTestUI;
+import com.vaadin.ui.DateTimeField;
+import com.vaadin.ui.VerticalLayout;
+
+public class AriaDateTimeDisabled extends AbstractReindeerTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ VerticalLayout content = new VerticalLayout();
+ content.setMargin(true);
+ content.setSpacing(true);
+
+ final DateTimeField disabledDateField = new DateTimeField(
+ "Disabled DateField");
+ disabledDateField.setEnabled(false);
+
+ setContent(content);
+ content.addComponent(disabledDateField);
+ content.addComponent(new DateTimeField("Enabled DateField"));
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Test for aria-disabled attribute on DateField.";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 13463;
+ }
+}
--- /dev/null
+/*
+ * 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.tests.components.datefield;
+
+import java.time.LocalDateTime;
+import java.util.Locale;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.shared.ui.datefield.DateTimeResolution;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.DateTimeField;
+
+/**
+ * @author Vaadin Ltd
+ *
+ */
+public class CustomDateTimeFormat extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ setLocale(new Locale("fi", "FI"));
+
+ DateTimeField field = new DateTimeField();
+ field.setResolution(DateTimeResolution.SECOND);
+ field.setWidth("300px");
+
+ String pattern = "d. MMMM'ta 'yyyy 'klo 'H.mm.ss";
+ field.setDateFormat(pattern);
+
+ field.setValue(LocalDateTime.of(2010, 1, 1, 12, 23, 45));
+
+ addComponent(field);
+
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Month name should be visible in text box if format pattern includes it";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 3490;
+ }
+
+}
package com.vaadin.tests.components.datefield;
-import java.time.LocalDate;
+import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import com.vaadin.server.VaadinRequest;
-import com.vaadin.shared.ui.datefield.DateResolution;
+import com.vaadin.shared.ui.datefield.DateTimeResolution;
import com.vaadin.tests.components.AbstractReindeerTestUI;
-import com.vaadin.tests.components.TestDateField;
-import com.vaadin.ui.AbstractDateField;
+import com.vaadin.ui.DateTimeField;
import com.vaadin.ui.Label;
public class DateFieldDayResolutionOffset extends AbstractReindeerTestUI {
- private final String initialDateString = "09/01/2014";
+ private final String initialDateString = "09/01/2014 00:00:00";
@Override
protected void setup(VaadinRequest request) {
dateValue.setId("dateValue");
final DateTimeFormatter dateformat = getDateFormat();
- final AbstractDateField<LocalDate, DateResolution> dateField = getDateField(
- dateformat);
+ final DateTimeField dateField = getDateField(dateformat);
addComponent(dateValue);
addComponent(dateField);
.setValue(dateformat.format(dateField.getValue())));
}
- private AbstractDateField<LocalDate, DateResolution> getDateField(
- DateTimeFormatter dateformat) {
- final AbstractDateField<LocalDate, DateResolution> dateField = new TestDateField();
- LocalDate initialDate = dateformat.parse(initialDateString,
- LocalDate::from);
- dateField.setResolution(DateResolution.DAY);
+ private DateTimeField getDateField(DateTimeFormatter dateformat) {
+ final DateTimeField dateField = new DateTimeField();
+ LocalDateTime initialDate = dateformat.parse(initialDateString,
+ LocalDateTime::from);
+ dateField.setResolution(DateTimeResolution.DAY);
dateField.setValue(initialDate);
return dateField;
}
private DateTimeFormatter getDateFormat() {
final DateTimeFormatter dateformat = DateTimeFormatter
- .ofPattern("MM/dd/yyyy");
+ .ofPattern("MM/dd/yyyy HH:mm:ss");
return dateformat;
}
--- /dev/null
+/*
+ * 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.tests.components.datefield;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.shared.ui.datefield.DateTimeResolution;
+import com.vaadin.tests.components.AbstractReindeerTestUI;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.DateTimeField;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.Label;
+
+public class DateTimeFieldChangeResolution extends AbstractReindeerTestUI {
+
+ public static final String DATEFIELD_ID = "datefield";
+ // The ID of a button is BUTTON_BASE_ID + resolution, e.g. button-month
+ public static final String BUTTON_BASE_ID = "button-";
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ final DateTimeField dateField = new DateTimeField("Enter date");
+ dateField.setResolution(DateTimeResolution.YEAR);
+ dateField.setId(DATEFIELD_ID);
+ addComponent(dateField);
+
+ Label label = new Label("Select resolution");
+ addComponent(label);
+ HorizontalLayout hlayout = new HorizontalLayout();
+ addComponent(hlayout);
+ for (final DateTimeResolution value : DateTimeResolution.values()) {
+ String resolutionString = value.toString().toLowerCase();
+ Button button = new Button(resolutionString);
+ button.addClickListener(event -> dateField.setResolution(value));
+ button.setId(BUTTON_BASE_ID + resolutionString);
+ hlayout.addComponent(button);
+ }
+
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "The calendar should always have the correct resolution and the text field should be empty before selecting a date.";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 14174;
+ }
+
+}
--- /dev/null
+package com.vaadin.tests.components.datefield;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractReindeerTestUI;
+import com.vaadin.ui.DateTimeField;
+import com.vaadin.ui.InlineDateTimeField;
+
+public class DateTimeFieldElementUI extends AbstractReindeerTestUI {
+ @Override
+ protected void setup(VaadinRequest request) {
+ addComponent(new DateTimeField());
+ addComponent(new InlineDateTimeField());
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 17090;
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "DateTimeField should be accessible using TB4 DateTimeFieldElement.";
+ }
+}
--- /dev/null
+/*
+ * 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.tests.components.datefield;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractReindeerTestUI;
+import com.vaadin.ui.InlineDateTimeField;
+
+public class DateTimeFieldFastForward extends AbstractReindeerTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ addComponent(new InlineDateTimeField());
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Tests that right-click doesn't interfere with fast-forwarding (holding down left mouse button).";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 8012;
+ }
+
+}
--- /dev/null
+package com.vaadin.tests.components.datefield;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUIWithLog;
+import com.vaadin.ui.DateTimeField;
+
+public class DateTimeFieldIsValid extends AbstractTestUIWithLog {
+
+ @Override
+ protected String getTestDescription() {
+ return "A dateField with invalid text should return false in isValid both when "
+ + "handling ValueChange event and after value is changed.";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 14487;
+ }
+
+ private String pattern = "dd/MM/yy H.mm";
+ private DateTimeFormatter format = DateTimeFormatter.ofPattern(pattern);
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ final DateTimeField dateField = new DateTimeField("Insert Date: ");
+ dateField.setDateFormat(pattern);
+
+ dateField.addValueChangeListener(event -> log("valueChange: value: "
+ + format(dateField.getValue()) + ", is valid: "
+ + (dateField.getErrorMessage() == null)));
+ addComponent(dateField);
+ addButton("check dateField",
+ event -> log("buttonClick: value: "
+ + format(dateField.getValue()) + ", is valid: "
+ + (dateField.getErrorMessage() == null)));
+ }
+
+ /**
+ * @since
+ * @param value
+ * @return
+ */
+ protected String format(LocalDateTime value) {
+ if (value != null) {
+ return format.format(value);
+ } else {
+ return null;
+ }
+ }
+}
--- /dev/null
+/*
+ * 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.tests.components.datefield;
+
+import java.time.LocalDateTime;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractReindeerTestUI;
+import com.vaadin.ui.DateTimeField;
+import com.vaadin.ui.Label;
+
+public class DateTimeFieldKeyboardInput extends AbstractReindeerTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ final DateTimeField dateField = new DateTimeField("Select date",
+ LocalDateTime.of(2014, 1, 15, 7, 2));
+ dateField.setDateFormat("dd.MM.yyyy HH:mm");
+ addComponent(dateField);
+ dateField.addValueChangeListener(
+ event -> addComponent(new Label("Date has been changed.")));
+ }
+
+ @Override
+ public Integer getTicketNumber() {
+ return 16677;
+ }
+
+ @Override
+ public String getTestDescription() {
+ return "When a new date is entered in the text field using the keyboard, pressing the return key after typing the date, "
+ + "a label with the text 'Date has been changed' should appear.";
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.vaadin.tests.components.datefield;
+
+import java.time.LocalDateTime;
+import java.util.Locale;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractReindeerTestUI;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.DateTimeField;
+
+public class DateTimeFieldReadOnly extends AbstractReindeerTestUI {
+
+ @Override
+ protected String getTestDescription() {
+ return "A read-only DateField should not show the popup button and not be editable.";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 3163;
+ }
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ final DateTimeField timeField = new DateTimeField(
+ "A read-only datefield");
+ timeField.setCaption(null);
+ timeField.setIcon(null);
+ timeField.setWidth("15em");
+ timeField.addStyleName("timeField");
+ timeField.setLocale(new Locale("fi"));
+
+ // Set date so that testing always has same time
+ timeField.setValue(LocalDateTime.of(2009, 6, 12, 7, 34));
+ timeField.setReadOnly(true);
+
+ addComponent(timeField);
+
+ Button b = new Button("Switch read-only");
+ b.addClickListener(
+ event -> timeField.setReadOnly(!timeField.isReadOnly()));
+
+ addComponent(b);
+ }
+}
--- /dev/null
+/*
+ * 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.tests.components.datefield;
+
+import java.util.LinkedHashMap;
+
+import com.vaadin.ui.DateTimeField;
+
+/**
+ * @author Vaadin Ltd
+ *
+ */
+public class DateTimeFieldTest
+ extends AbstractDateTimeFieldTest<DateTimeField> {
+
+ @Override
+ protected Class<DateTimeField> getTestClass() {
+ return DateTimeField.class;
+ }
+
+ @Override
+ protected void createActions() {
+ super.createActions();
+
+ createInputPromptSelectAction(CATEGORY_FEATURES);
+ createTextEnabledAction(CATEGORY_FEATURES);
+ }
+
+ private void createInputPromptSelectAction(String category) {
+ LinkedHashMap<String, String> options = new LinkedHashMap<>();
+ options.put("<none>", null);
+ options.put("Please enter date", "Please enter date");
+ options.put("åäöÅÄÖ", "åäöÅÄÖ");
+
+ createSelectAction("Input prompt", category, options, "<none>",
+ new Command<DateTimeField, String>() {
+
+ @Override
+ public void execute(DateTimeField c, String value,
+ Object data) {
+ c.setPlaceholder(value);
+
+ }
+ });
+ }
+
+ private void createTextEnabledAction(String category) {
+ this.createBooleanAction("Text field enabled", category, true,
+ (field, value, data) -> field.setTextFieldEnabled(value));
+ }
+}
--- /dev/null
+/*
+ * 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.tests.components.datefield;
+
+import java.time.LocalDateTime;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractReindeerTestUI;
+import com.vaadin.ui.InlineDateTimeField;
+
+public class DisabledInlineDateTimeField extends AbstractReindeerTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ InlineDateTimeField df = new InlineDateTimeField("Disabled");
+ LocalDateTime date = LocalDateTime.of(2014, 6, 5, 11, 34);
+ df.setValue(date);
+ df.setEnabled(false);
+ addComponent(df);
+
+ df = new InlineDateTimeField("Read-only");
+ df.setValue(date);
+ df.setReadOnly(true);
+ addComponent(df);
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Testing disabled and read-only modes of InlineDateField.";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 10262;
+ }
+
+}
--- /dev/null
+/*
+ * 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.tests.components.datefield;
+
+import com.vaadin.ui.InlineDateTimeField;
+
+/**
+ * @author Vaadin Ltd
+ *
+ */
+public class InlineDateTimeFieldTest
+ extends AbstractDateTimeFieldTest<InlineDateTimeField> {
+
+ @Override
+ protected Class<InlineDateTimeField> getTestClass() {
+ return InlineDateTimeField.class;
+ }
+
+}
--- /dev/null
+/*
+ * 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.tests.components.datefield;
+
+import java.time.LocalDateTime;
+import java.util.Locale;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.DateTimeField;
+import com.vaadin.ui.GridLayout;
+
+/**
+ * @author Vaadin Ltd
+ *
+ */
+public class PopupDateTimeFieldStates extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ setLocale(Locale.ENGLISH);
+ final GridLayout gridLayout = new GridLayout(2, 2);
+ gridLayout.setSpacing(true);
+
+ gridLayout.addComponent(createPopupDateTimeField(true, true));
+ gridLayout.addComponent(createPopupDateTimeField(true, false));
+ gridLayout.addComponent(createPopupDateTimeField(false, true));
+ gridLayout.addComponent(createPopupDateTimeField(false, false));
+
+ getLayout().addComponent(gridLayout);
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Test that PopupDateTimeField is rendered consistently across browsers";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 14565;
+ }
+
+ private static DateTimeField createPopupDateTimeField(final boolean enabled,
+ final boolean textFieldEnabled) {
+ final DateTimeField popupDatefield = new DateTimeField();
+
+ popupDatefield.setValue(LocalDateTime.of(2014, 9, 3, 10, 34));
+ popupDatefield.setCaption("Enabled: " + enabled
+ + ", Text field enabled: " + textFieldEnabled);
+ popupDatefield.setEnabled(enabled);
+ popupDatefield.setTextFieldEnabled(textFieldEnabled);
+ return popupDatefield;
+ }
+
+}
--- /dev/null
+/*
+ * 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.tests.components.datefield;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.shared.ui.datefield.DateTimeResolution;
+import com.vaadin.tests.components.AbstractReindeerTestUI;
+import com.vaadin.ui.DateTimeField;
+import com.vaadin.ui.VerticalLayout;
+
+public class PopupTimeClosingWithEsc extends AbstractReindeerTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ DateTimeField secondResolution = new DateTimeField("Second");
+ secondResolution.setId("second");
+ secondResolution.setResolution(DateTimeResolution.SECOND);
+
+ DateTimeField minuteResolution = new DateTimeField("Minute");
+ minuteResolution.setId("minute");
+ minuteResolution.setResolution(DateTimeResolution.MINUTE);
+
+ DateTimeField hourResolution = new DateTimeField("Hour");
+ hourResolution.setId("hour");
+ hourResolution.setResolution(DateTimeResolution.HOUR);
+
+ DateTimeField month = new DateTimeField("Month");
+ month.setId("month");
+ month.setResolution(DateTimeResolution.MONTH);
+
+ VerticalLayout layout = new VerticalLayout();
+ layout.setMargin(true);
+ layout.setSpacing(true);
+ layout.addComponents(secondResolution, minuteResolution, hourResolution,
+ month);
+ setContent(layout);
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Testing that the DateField popup can be closed with ESC key.";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 12317;
+ }
+
+}
--- /dev/null
+/*
+ * 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.tests.components.datefield;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Locale;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.shared.ui.datefield.DateTimeResolution;
+import com.vaadin.tests.components.AbstractTestUIWithLog;
+import com.vaadin.ui.DateTimeField;
+
+/**
+ * @author Vaadin Ltd
+ *
+ */
+public class TimePopupSelection extends AbstractTestUIWithLog {
+
+ private static final DateTimeFormatter FORMATTER = DateTimeFormatter
+ .ofPattern("dd/MM/yyyy HH:mm:ss");
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ setLocale(Locale.ENGLISH);
+ DateTimeField field = new DateTimeField();
+ field.setResolution(DateTimeResolution.SECOND);
+
+ field.setValue(LocalDateTime.of(2017, 1, 13, 1, 0));
+
+ field.addValueChangeListener(
+ event -> log(FORMATTER.format(event.getValue())));
+
+ addComponent(field);
+ }
+
+}
+++ /dev/null
-/*
- * 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.tests.components.datefield;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.openqa.selenium.By;
-import org.openqa.selenium.Dimension;
-import org.openqa.selenium.WebElement;
-import org.openqa.selenium.interactions.Actions;
-
-import com.vaadin.testbench.elements.NotificationElement;
-import com.vaadin.tests.tb3.MultiBrowserTest;
-
-public class AbstractDateFieldTestTest extends MultiBrowserTest {
-
- @Test
- public void testMakingRequired() throws InterruptedException {
- setDebug(true);
- openTestURL();
- Thread.sleep(1000);
- menu("Component");
- menuSub("State");
- menu("Required");
- assertRequiredIndicatorVisible();
- assertNoErrorNotification();
- }
-
- private void assertRequiredIndicatorVisible() {
- getDriver().findElement(By.className("v-required-field-indicator"));
- }
-
- private void assertNoErrorNotification() {
- if (isElementPresent(NotificationElement.class)) {
- Assert.fail("Notification was present");
- }
- }
-
- @Test
- public void testValueAfterOpeningPopupInRequiredField()
- throws InterruptedException {
- setDebug(true);
- openTestURL();
- Thread.sleep(1000);
- menu("Component");
- menuSub("State");
- menu("Required");
-
- assertRequiredIndicatorVisible();
-
- menu("Component");
- menuSub("Features");
- menuSub("Resolution");
- menu("Month");
-
- menu("Component");
- menuSub("Listeners");
- menu("Value change listener");
-
- String inputtedValue = "2/12";
- getInput().sendKeys(inputtedValue);
-
- openPopup();
- closePopup();
- String actual = getInput().getAttribute("value");
- Assert.assertEquals(inputtedValue, actual);
- assertNoErrorNotification();
-
- }
-
- private void openPopup() throws InterruptedException {
- Dimension size = getInput().getSize();
- new Actions(getDriver()).moveToElement(getInput(), 0, 0)
- .moveByOffset(size.getWidth() + 5, size.getHeight() / 2)
- .click();
- // This fails in Opera for some weird reason
- // getDriver().findElement(By.className("v-datefield-button")).click();
- }
-
- private WebElement getInput() {
- return getDriver().findElement(By.xpath("//input"));
- }
-
- private void closePopup() {
- getDriver().findElement(By.tagName("body")).click();
- }
-
- /**
- * @since
- * @param string
- */
- private void menuSub(String string) {
- getDriver().findElement(By.xpath("//span[text() = '" + string + "']"))
- .click();
- new Actions(getDriver()).moveByOffset(100, 0).build().perform();
- }
-
- /**
- * @since
- * @param string
- */
- private void menu(String string) {
- getDriver().findElement(By.xpath("//span[text() = '" + string + "']"))
- .click();
-
- }
-
-}
--- /dev/null
+/*
+ * 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.tests.components.datefield;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+import com.vaadin.testbench.By;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class AriaDateTimeDisabledTest extends MultiBrowserTest {
+
+ @Test
+ public void verifyAriaDisabledAttributes() {
+ openTestURL();
+
+ // Expect aria-disabled="false" on the enabled DateField.
+ String ariaDisabled = driver
+ .findElement(By
+ .vaadin("/VVerticalLayout[0]/VPopupTimeCalendar[1]#popupButton"))
+ .getAttribute("aria-disabled");
+ assertEquals("false", ariaDisabled);
+
+ // Expect aria-disabled="true" on the disabled DateField.
+ ariaDisabled = driver.findElement(By.cssSelector(".v-disabled button"))
+ .getAttribute("aria-disabled");
+ assertEquals("true", ariaDisabled);
+ }
+
+}
--- /dev/null
+/*
+ * 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.tests.components.datefield;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+import com.vaadin.testbench.By;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+/**
+ * @author Vaadin Ltd
+ *
+ */
+public class CustomDateTimeFormatTest extends MultiBrowserTest {
+
+ @Test
+ public void checkCustomDateFormat() {
+ openTestURL();
+
+ String text = findElement(By.tagName("input")).getAttribute("value");
+ assertEquals("1. tammikuuta 2010 klo 12.23.45", text);
+ }
+
+}
select2ndOfSeptember();
LabelElement dateValue = $(LabelElement.class).id("dateValue");
- assertThat(dateValue.getText(), is("09/02/2014"));
+ assertThat(dateValue.getText(), is("09/02/2014 00:00:00"));
}
private void select2ndOfSeptember() {
--- /dev/null
+/*
+ * 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.tests.components.datefield;
+
+import static com.vaadin.tests.components.datefield.DateFieldChangeResolution.BUTTON_BASE_ID;
+import static com.vaadin.tests.components.datefield.DateFieldChangeResolution.DATEFIELD_ID;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.shared.ui.datefield.DateTimeResolution;
+import com.vaadin.testbench.By;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class DateTimeFieldChangeResolutionTest extends MultiBrowserTest {
+
+ private WebElement dateFieldButton, textField;
+ private WebElement resolutionSecond, resolutionMinute, resolutionHour,
+ resolutionDay, resolutionMonth, resolutionYear;
+
+ @Test
+ public void changeResolutionBetweenYearAndMonth() throws Exception {
+ initialize();
+ click(resolutionMonth);
+ checkHeaderAndBody(DateTimeResolution.MONTH, true);
+ click(resolutionYear);
+ checkHeaderAndBody(DateTimeResolution.YEAR, true);
+ }
+
+ @Test
+ public void changeResolutionBetweenYearAndSecond() throws Exception {
+ initialize();
+ click(resolutionSecond);
+ checkHeaderAndBody(DateTimeResolution.SECOND, true);
+ click(resolutionYear);
+ checkHeaderAndBody(DateTimeResolution.YEAR, true);
+ }
+
+ @Test
+ public void changeResolutionToDayThenMonth() throws Exception {
+ initialize();
+ checkHeaderAndBody(DateTimeResolution.YEAR, true); // check the initial
+ // state
+ click(resolutionDay);
+ checkHeaderAndBody(DateTimeResolution.DAY, true);
+ click(resolutionMonth);
+ checkHeaderAndBody(DateTimeResolution.MONTH, true);
+ }
+
+ @Test
+ public void setDateAndChangeResolution() throws Exception {
+ initialize();
+ // Set the date to previous month.
+ click(resolutionMonth);
+ openPopupDateField();
+ click(driver.findElement(By.className("v-button-prevmonth")));
+ closePopupDateField();
+ assertFalse(
+ "The text field of the calendar should not be empty after selecting a date",
+ textField.getAttribute("value").isEmpty());
+ // Change resolutions and check that the selected date is not lost and
+ // that the calendar has the correct resolution.
+ click(resolutionHour);
+ checkHeaderAndBody(DateTimeResolution.HOUR, false);
+ click(resolutionYear);
+ checkHeaderAndBody(DateTimeResolution.YEAR, false);
+ click(resolutionMinute);
+ checkHeaderAndBody(DateTimeResolution.MINUTE, false);
+ }
+
+ private void initialize() {
+ openTestURL();
+ WebElement dateField = driver.findElement(By.id(DATEFIELD_ID));
+ dateFieldButton = dateField
+ .findElement(By.className("v-datefield-button"));
+ textField = dateField
+ .findElement(By.className("v-datefield-textfield"));
+ resolutionSecond = driver.findElement(By.id(BUTTON_BASE_ID + "second"));
+ resolutionMinute = driver.findElement(By.id(BUTTON_BASE_ID + "minute"));
+ resolutionHour = driver.findElement(By.id(BUTTON_BASE_ID + "hour"));
+ resolutionDay = driver.findElement(By.id(BUTTON_BASE_ID + "day"));
+ resolutionMonth = driver.findElement(By.id(BUTTON_BASE_ID + "month"));
+ resolutionYear = driver.findElement(By.id(BUTTON_BASE_ID + "year"));
+ }
+
+ private void checkHeaderAndBody(DateTimeResolution resolution,
+ boolean textFieldIsEmpty) throws Exception {
+ // Popup date field has all kinds of strange timers on the
+ // client side
+ sleep(100);
+ // Open the popup calendar, perform checks and close the popup.
+ openPopupDateField();
+ if (resolution.compareTo(DateTimeResolution.MONTH) <= 0) {
+ checkMonthHeader();
+ } else {
+ checkYearHeader();
+ }
+ if (resolution.compareTo(DateTimeResolution.DAY) <= 0) {
+ assertTrue(
+ "A calendar with the chosen resolution should have a body",
+ calendarHasBody());
+ } else {
+ assertFalse(
+ "A calendar with the chosen resolution should not have a body",
+ calendarHasBody());
+ }
+ if (textFieldIsEmpty) {
+ assertTrue("The text field of the calendar should be empty",
+ textField.getAttribute("value").isEmpty());
+ } else {
+ assertFalse("The text field of the calendar should not be empty",
+ textField.getAttribute("value").isEmpty());
+ }
+ closePopupDateField();
+ }
+
+ private void checkMonthHeader() {
+ checkHeaderForYear();
+ checkHeaderForMonth(true);
+ }
+
+ private void checkYearHeader() {
+ checkHeaderForYear();
+ checkHeaderForMonth(false);
+ }
+
+ private boolean calendarHasBody() {
+ return isElementPresent(By.className("v-datefield-calendarpanel-body"));
+ }
+
+ private void checkHeaderForMonth(boolean buttonsExpected) {
+ // If buttonsExpected is true, check that there are buttons for changing
+ // the month. Otherwise check that there are no such buttons.
+ if (buttonsExpected) {
+ assertTrue(
+ "The calendar should have a button for switching to the previous month",
+ isElementPresent(By.cssSelector(
+ ".v-datefield-calendarpanel-header .v-datefield-calendarpanel-prevmonth .v-button-prevmonth")));
+ assertTrue(
+ "The calendar should have a button for switching to the next month",
+ isElementPresent(By.cssSelector(
+ ".v-datefield-calendarpanel-header .v-datefield-calendarpanel-nextmonth .v-button-nextmonth")));
+ } else {
+ assertFalse(
+ "The calendar should not have a button for switching to the previous month",
+ isElementPresent(By.cssSelector(
+ ".v-datefield-calendarpanel-header .v-datefield-calendarpanel-prevmonth .v-button-prevmonth")));
+ assertFalse(
+ "The calendar should not have a button for switching to the next month",
+ isElementPresent(By.cssSelector(
+ ".v-datefield-calendarpanel-header .v-datefield-calendarpanel-nextmonth .v-button-nextmonth")));
+ }
+ }
+
+ private void checkHeaderForYear() {
+ assertTrue(
+ "The calendar should have a button for switching to the previous year",
+ isElementPresent(By.cssSelector(
+ ".v-datefield-calendarpanel-header .v-datefield-calendarpanel-prevyear .v-button-prevyear")));
+ assertTrue("The calendar header should show the selected year",
+ isElementPresent(By.cssSelector(
+ ".v-datefield-calendarpanel-header .v-datefield-calendarpanel-month")));
+ assertTrue(
+ "The calendar should have a button for switching to the next year",
+ isElementPresent(By.cssSelector(
+ ".v-datefield-calendarpanel-header .v-datefield-calendarpanel-nextyear .v-button-nextyear")));
+
+ }
+
+ private void click(WebElement element) {
+ testBenchElement(element).click(5, 5);
+ }
+
+ private void openPopupDateField() {
+ click(dateFieldButton);
+ }
+
+ private void closePopupDateField() {
+ WebElement element = driver
+ .findElement(By.cssSelector(".v-datefield-calendarpanel"));
+ element.sendKeys(Keys.ESCAPE);
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.vaadin.tests.components.datefield;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+
+import org.junit.Test;
+
+import com.vaadin.testbench.customelements.DateTimeFieldElement;
+import com.vaadin.testbench.customelements.InlineDateTimeFieldElement;
+import com.vaadin.tests.tb3.SingleBrowserTest;
+
+public class DateTimeFieldElementTest extends SingleBrowserTest {
+
+ @Test
+ public void dateFieldElementIsLocated() {
+ openTestURL();
+
+ assertThat($(DateTimeFieldElement.class).all().size(), is(1));
+ assertThat($(InlineDateTimeFieldElement.class).all().size(), is(1));
+ }
+
+ @Override
+ protected Class<?> getUIClass() {
+ return DateTimeFieldElementUI.class;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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.tests.components.datefield;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.testbench.elements.VerticalLayoutElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class DateTimeFieldFastForwardTest extends MultiBrowserTest {
+
+ @Test
+ public void testFastForwardOnRightMouseClick() throws Exception {
+ openTestURL();
+ String firstMonth = getSelectedMonth();
+ WebElement nextMonthButton = driver
+ .findElement(By.className("v-button-nextmonth"));
+
+ // Click and hold left mouse button to start fast forwarding.
+ new Actions(driver).clickAndHold(nextMonthButton).perform();
+ sleep(1000);
+
+ // Right click and release the left button.
+
+ new Actions(driver).contextClick(nextMonthButton)
+ .release(nextMonthButton).perform();
+
+ // Now the fast forwarding should be ended, get the expected month.
+ String expectedMonth = getSelectedMonth();
+
+ // Make browser context menu disappear, since it will crash IE
+ $(VerticalLayoutElement.class).first().click();
+
+ Assert.assertFalse("Month did not change during fast forward",
+ firstMonth.equals(expectedMonth));
+
+ // Wait for a while.
+ Thread.sleep(1000);
+
+ // Verify that we didn't fast forward any further after the left button
+ // was released.
+ String actualMonth = getSelectedMonth();
+ assertEquals(expectedMonth, actualMonth);
+ }
+
+ private String getSelectedMonth() {
+ return driver
+ .findElement(
+ By.className("v-inline-datefield-calendarpanel-month"))
+ .getText();
+ }
+
+}
--- /dev/null
+/*
+ * 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.tests.components.datefield;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.customelements.AbstractDateFieldElement;
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+/**
+ * @author Vaadin Ltd
+ */
+public class DateTimeFieldIsValidTest extends MultiBrowserTest {
+
+ @Test
+ public void testInvalidText() throws Exception {
+ openTestURL();
+
+ waitForElementVisible(By.id("Log"));
+ waitForElementVisible(By.className("v-datefield"));
+ WebElement dateTextbox = $(AbstractDateFieldElement.class).first()
+ .findElement(By.className("v-textfield"));
+ ButtonElement button = $(ButtonElement.class).first();
+
+ dateTextbox.sendKeys("01/01/01 1.12", Keys.TAB);
+ assertLogText("1. valueChange: value: 01/01/01 1.12, is valid: true");
+ button.click();
+ assertLogText("2. buttonClick: value: 01/01/01 1.12, is valid: true");
+
+ dateTextbox.sendKeys("lala", Keys.TAB);
+ assertLogText("3. valueChange: value: null, is valid: false");
+ button.click();
+ assertLogText("4. buttonClick: value: null, is valid: false");
+
+ dateTextbox.clear();
+ dateTextbox.sendKeys("02/02/02 2.34", Keys.TAB);
+ assertLogText("5. valueChange: value: 02/02/02 2.34, is valid: true");
+ button.click();
+ assertLogText("6. buttonClick: value: 02/02/02 2.34, is valid: true");
+ }
+
+ private void assertLogText(String expected) throws Exception {
+ String text = findElement(By.vaadin("PID_SLog_row_0")).getText();
+ Assert.assertTrue("Expected '" + expected + "' found '" + text + "'",
+ text.equals(expected));
+ }
+
+}
--- /dev/null
+/*
+ * 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.tests.components.datefield;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.customelements.DateTimeFieldElement;
+import com.vaadin.testbench.elements.LabelElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class DateTimeFieldKeyboardInputTest extends MultiBrowserTest {
+
+ @Test
+ public void testValueChangeEvent() {
+ openTestURL();
+ WebElement dateFieldText = $(DateTimeFieldElement.class).first()
+ .findElement(By.tagName("input"));
+ dateFieldText.clear();
+ int numLabelsBeforeUpdate = $(LabelElement.class).all().size();
+ dateFieldText.sendKeys("20.10.2013 7:2", Keys.RETURN);
+ int numLabelsAfterUpdate = $(LabelElement.class).all().size();
+ assertTrue("Changing the date failed.",
+ numLabelsAfterUpdate == numLabelsBeforeUpdate + 1);
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.vaadin.tests.components.datefield;
+
+import java.io.IOException;
+
+import org.junit.Test;
+import org.openqa.selenium.Keys;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.customelements.AbstractDateFieldElement;
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class DateTimeFieldReadOnlyTest extends MultiBrowserTest {
+
+ @Test
+ public void readOnlyDateFieldPopupShouldNotOpen()
+ throws IOException, InterruptedException {
+ openTestURL();
+
+ compareScreen("initial-date");
+ toggleReadOnly();
+
+ openPopup();
+ compareScreen("readwrite-popup-date");
+
+ closePopup();
+ toggleReadOnly();
+ compareScreen("readonly-date");
+ }
+
+ private void closePopup() {
+ findElement(By.className("v-datefield-calendarpanel"))
+ .sendKeys(Keys.RETURN);
+ }
+
+ private void openPopup() {
+ // waiting for openPopup() in TB4 beta1:
+ // http://dev.vaadin.com/ticket/13766
+ $(AbstractDateFieldElement.class).first()
+ .findElement(By.tagName("button")).click();
+ }
+
+ private void toggleReadOnly() {
+ $(ButtonElement.class).caption("Switch read-only").first().click();
+ }
+}
--- /dev/null
+/*
+ * 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.tests.components.datefield;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.Dimension;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.testbench.elements.NotificationElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+/**
+ * @author Vaadin Ltd
+ *
+ */
+public class DateTimeFieldTestTest extends MultiBrowserTest {
+
+ @Test
+ public void testMakingRequired() throws InterruptedException {
+ setDebug(true);
+ openTestURL();
+ Thread.sleep(1000);
+ menu("Component");
+ menuSub("State");
+ menu("Required");
+ assertRequiredIndicatorVisible();
+ assertNoErrorNotification();
+ }
+
+ private void assertRequiredIndicatorVisible() {
+ getDriver().findElement(By.className("v-required-field-indicator"));
+ }
+
+ private void assertNoErrorNotification() {
+ if (isElementPresent(NotificationElement.class)) {
+ Assert.fail("Notification was present");
+ }
+ }
+
+ @Test
+ public void testValueAfterOpeningPopupInRequiredField()
+ throws InterruptedException {
+ setDebug(true);
+ openTestURL();
+ Thread.sleep(1000);
+ menu("Component");
+ menuSub("State");
+ menu("Required");
+
+ assertRequiredIndicatorVisible();
+
+ menu("Component");
+ menuSub("Features");
+ menuSub("Resolution");
+ menu("Month");
+
+ menu("Component");
+ menuSub("Listeners");
+ menu("Value change listener");
+
+ String inputtedValue = "2/12";
+ getInput().sendKeys(inputtedValue);
+
+ openPopup();
+ closePopup();
+ String actual = getInput().getAttribute("value");
+ Assert.assertEquals(inputtedValue, actual);
+ assertNoErrorNotification();
+
+ }
+
+ private void openPopup() throws InterruptedException {
+ Dimension size = getInput().getSize();
+ new Actions(getDriver()).moveToElement(getInput(), 0, 0)
+ .moveByOffset(size.getWidth() + 5, size.getHeight() / 2)
+ .click();
+ // This fails in Opera for some weird reason
+ // getDriver().findElement(By.className("v-datefield-button")).click();
+ }
+
+ private WebElement getInput() {
+ return getDriver().findElement(By.xpath("//input"));
+ }
+
+ private void closePopup() {
+ getDriver().findElement(By.tagName("body")).click();
+ }
+
+ /**
+ * @since
+ * @param string
+ */
+ private void menuSub(String string) {
+ getDriver().findElement(By.xpath("//span[text() = '" + string + "']"))
+ .click();
+ new Actions(getDriver()).moveByOffset(100, 0).build().perform();
+ }
+
+ /**
+ * @since
+ * @param string
+ */
+ private void menu(String string) {
+ getDriver().findElement(By.xpath("//span[text() = '" + string + "']"))
+ .click();
+
+ }
+
+}
--- /dev/null
+/*
+ * 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.tests.components.datefield;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class DisabledInlineDateTimeFieldTest extends MultiBrowserTest {
+
+ @Test
+ public void testDisabled() {
+ openTestURL();
+ testNextMonthControls(".v-disabled");
+ testDaySelection(".v-disabled");
+ }
+
+ @Test
+ public void testReadOnly() {
+ openTestURL();
+ testNextMonthControls(".v-readonly");
+ testDaySelection(".v-readonly");
+ }
+
+ private void testNextMonthControls(String cssClass) {
+ // Get the currently selected month.
+ String expectedMonth = getSelectedMonth(cssClass);
+
+ // Attempt to click the next month button.
+ driver.findElement(By.cssSelector(cssClass + " .v-button-nextmonth"))
+ .click();
+
+ // Assert that we did not navigate to next month.
+ String actualMonth = getSelectedMonth(cssClass);
+ assertEquals(expectedMonth, actualMonth);
+ }
+
+ private void testDaySelection(String cssClass) {
+ // We know that the first day element is not selected, because of the
+ // fixed date in the test.
+ WebElement nonSelectedDay = driver.findElement(By.cssSelector(
+ cssClass + " .v-inline-datefield-calendarpanel-day"));
+
+ // Assert it is not selected before click.
+ assertFalse(nonSelectedDay.getAttribute("class").contains("selected"));
+
+ // Click on the non-selected day.
+ nonSelectedDay.click();
+
+ // Assert that clicking did not select the day.
+ assertFalse(nonSelectedDay.getAttribute("class").contains("selected"));
+ }
+
+ private String getSelectedMonth(String selectorPrefix) {
+ return driver
+ .findElement(By.cssSelector(selectorPrefix
+ + " .v-inline-datefield-calendarpanel-month"))
+ .getText();
+ }
+
+}
--- /dev/null
+/*
+ * 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.tests.components.datefield;
+
+import org.junit.Test;
+
+import com.google.gwt.editor.client.Editor.Ignore;
+
+/**
+ * Reuse tests from super DateTimeFieldTestTest class.
+ *
+ * @author Vaadin Ltd
+ *
+ */
+public class InlineDateTimeFieldTestTest extends DateTimeFieldTestTest {
+
+ @Override
+ @Test
+ @Ignore
+ public void testValueAfterOpeningPopupInRequiredField()
+ throws InterruptedException {
+ // no popup for inline date field
+ }
+}
package com.vaadin.tests.components.datefield;
import java.io.IOException;
+import java.util.regex.Pattern;
import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
import com.vaadin.tests.tb3.MultiBrowserTest;
throws IOException, InterruptedException {
openTestURL();
+ // wait until loading indicator becomes invisible
+ WebElement loadingIndicator = findElement(
+ By.className("v-loading-indicator"));
+ Pattern pattern = Pattern.compile("display: *none;");
+ waitUntil(driver -> {
+ return pattern.matcher(loadingIndicator.getAttribute("style"))
+ .find();
+ });
+
compareScreen("dateFieldStates");
}
--- /dev/null
+package com.vaadin.tests.components.datefield;
+
+import java.io.IOException;
+import java.util.regex.Pattern;
+
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class PopupDateTimeFieldStatesTest extends MultiBrowserTest {
+
+ @Test
+ public void readOnlyDateFieldPopupShouldNotOpen()
+ throws IOException, InterruptedException {
+ openTestURL();
+
+ // wait until loading indicator becomes invisible
+ WebElement loadingIndicator = findElement(
+ By.className("v-loading-indicator"));
+ Pattern pattern = Pattern.compile("display: *none;");
+ waitUntil(driver -> {
+ return pattern.matcher(loadingIndicator.getAttribute("style"))
+ .find();
+ });
+
+ compareScreen("dateFieldStates");
+ }
+
+}
--- /dev/null
+/*
+ * 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.tests.components.datefield;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.Keys;
+
+import com.vaadin.testbench.annotations.RunLocally;
+import com.vaadin.testbench.parallel.Browser;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class PopupTimeClosingWithEscTest extends MultiBrowserTest {
+
+ @Test
+ public void testPopupClosing() {
+ openTestURL();
+
+ testPopupClosing("second");
+ testPopupClosing("minute");
+ testPopupClosing("hour");
+ testPopupClosing("month");
+ }
+
+ private void testPopupClosing(String dateFieldId) {
+ openPopup(dateFieldId);
+ assertTrue(isPopupVisible());
+ sendEscToCalendarPanel();
+ assertFalse(isPopupVisible());
+ }
+
+ private void openPopup(String dateFieldId) {
+ driver.findElement(
+ vaadinLocator("PID_S" + dateFieldId + "#popupButton")).click();
+ }
+
+ private boolean isPopupVisible() {
+ return !(driver.findElements(By.cssSelector(".v-datefield-popup"))
+ .isEmpty());
+ }
+
+ private void sendEscToCalendarPanel() {
+ driver.findElement(By.cssSelector(".v-datefield-calendarpanel"))
+ .sendKeys(Keys.ESCAPE);
+ }
+
+}
--- /dev/null
+/*
+ * 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.tests.components.datefield;
+
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.support.ui.Select;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.customelements.DateTimeFieldElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+/**
+ * @author Vaadin Ltd
+ *
+ */
+public class TimePopupSelectionTest extends MultiBrowserTest {
+
+ @Test
+ public void selectDateAndTimeFromPopup() {
+ openTestURL();
+
+ DateTimeFieldElement field = $(DateTimeFieldElement.class).first();
+ Assert.assertEquals("1/13/17 01:00:00 AM", field.getValue());
+
+ field.openPopup();
+
+ List<WebElement> timeSelects = findElement(
+ By.className("v-datefield-calendarpanel-time"))
+ .findElements(By.tagName("select"));
+
+ new Select(timeSelects.get(0)).selectByValue("09");
+ Assert.assertEquals("1/13/17 09:00:00 AM", field.getValue());
+
+ new Select(timeSelects.get(1)).selectByValue("35");
+ Assert.assertEquals("1/13/17 09:35:00 AM", field.getValue());
+
+ new Select(timeSelects.get(2)).selectByValue("41");
+ Assert.assertEquals("1/13/17 09:35:41 AM", field.getValue());
+
+ closePopup();
+
+ waitUntil(driver -> getLogRow(0).equals("1. 13/01/2017 09:35:41"));
+ }
+
+ private void closePopup() {
+ findElement(By.className("v-datefield-calendarpanel"))
+ .sendKeys(Keys.ENTER);
+ }
+}