* AbstractDateField.formatDate to be abstract Remove invalidDateString paramter, as it can be deduced * Fix test * Remove AbstractDateField.getResolutionVariable VAbstractTextualDate: rename updateDateVariables() to updateBufferedResolutions() * Revert to use fixed value of MONDAY. * release notes * updateAndSendBufferedValues() * Missed call to updateAndSendBufferedValues(); * release notetags/8.2.0.alpha3
@@ -124,6 +124,8 @@ | |||
<li><tt>SharedState</tt> field <tt>registeredEventListeners</tt> is a <tt>Map</tt> instead of <tt>Set</tt>.</li> | |||
<li>The client side <tt>SelectionModel</tt> interface has a new method <tt>isMultiSelectionAllowed</tt>.</li> | |||
<li><tt>AbstractDateField</tt> is not a <tt>LegacyComponent</tt> anymore.</li> | |||
<li><tt>AbstractDateField</tt>.<tt>formatDate</tt> is now abstract.</li> | |||
<li><tt>VAbstractTextualDate</tt>.<tt>updateDateVariables()</tt> is now <tt>updateBufferedResolutions()</tt> and <tt>updateAndSendBufferedValues()</tt>.</li> | |||
<h2>For incompatible or behavior-altering changes in 8.1, please see <a href="https://vaadin.com/download/release/8.1/8.1.0/release-notes.html#incompatible">8.1 release notes</a></h2> | |||
@@ -602,7 +602,6 @@ public class DateTimeService { | |||
} | |||
return date; | |||
} | |||
private static Logger getLogger() { |
@@ -65,81 +65,72 @@ public class LocaleService { | |||
throws LocaleNotLoadedException { | |||
if (cache.containsKey(locale)) { | |||
return cache.get(locale).monthNames; | |||
} else { | |||
throw new LocaleNotLoadedException(locale); | |||
} | |||
throw new LocaleNotLoadedException(locale); | |||
} | |||
public static String[] getShortMonthNames(String locale) | |||
throws LocaleNotLoadedException { | |||
if (cache.containsKey(locale)) { | |||
return cache.get(locale).shortMonthNames; | |||
} else { | |||
throw new LocaleNotLoadedException(locale); | |||
} | |||
throw new LocaleNotLoadedException(locale); | |||
} | |||
public static String[] getDayNames(String locale) | |||
throws LocaleNotLoadedException { | |||
if (cache.containsKey(locale)) { | |||
return cache.get(locale).dayNames; | |||
} else { | |||
throw new LocaleNotLoadedException(locale); | |||
} | |||
throw new LocaleNotLoadedException(locale); | |||
} | |||
public static String[] getShortDayNames(String locale) | |||
throws LocaleNotLoadedException { | |||
if (cache.containsKey(locale)) { | |||
return cache.get(locale).shortDayNames; | |||
} else { | |||
throw new LocaleNotLoadedException(locale); | |||
} | |||
throw new LocaleNotLoadedException(locale); | |||
} | |||
public static int getFirstDayOfWeek(String locale) | |||
throws LocaleNotLoadedException { | |||
if (cache.containsKey(locale)) { | |||
return cache.get(locale).firstDayOfWeek; | |||
} else { | |||
throw new LocaleNotLoadedException(locale); | |||
} | |||
throw new LocaleNotLoadedException(locale); | |||
} | |||
public static String getDateFormat(String locale) | |||
throws LocaleNotLoadedException { | |||
if (cache.containsKey(locale)) { | |||
return cache.get(locale).dateFormat; | |||
} else { | |||
throw new LocaleNotLoadedException(locale); | |||
} | |||
throw new LocaleNotLoadedException(locale); | |||
} | |||
public static boolean isTwelveHourClock(String locale) | |||
throws LocaleNotLoadedException { | |||
if (cache.containsKey(locale)) { | |||
return cache.get(locale).twelveHourClock; | |||
} else { | |||
throw new LocaleNotLoadedException(locale); | |||
} | |||
throw new LocaleNotLoadedException(locale); | |||
} | |||
public static String getClockDelimiter(String locale) | |||
throws LocaleNotLoadedException { | |||
if (cache.containsKey(locale)) { | |||
return cache.get(locale).hourMinuteDelimiter; | |||
} else { | |||
throw new LocaleNotLoadedException(locale); | |||
} | |||
throw new LocaleNotLoadedException(locale); | |||
} | |||
public static String[] getAmPmStrings(String locale) | |||
throws LocaleNotLoadedException { | |||
if (cache.containsKey(locale)) { | |||
return new String[] { cache.get(locale).am, cache.get(locale).pm }; | |||
} else { | |||
throw new LocaleNotLoadedException(locale); | |||
} | |||
throw new LocaleNotLoadedException(locale); | |||
} | |||
public static void addLocales(List<LocaleData> localeDatas) { |
@@ -336,9 +336,7 @@ public abstract class AbstractConnector | |||
OnStateChangeMethod method = propertyMethods.get(j); | |||
if (invokedMethods.add(method)) { | |||
method.invoke(stateChangeEvent); | |||
} | |||
} | |||
} | |||
@@ -361,7 +359,6 @@ public abstract class AbstractConnector | |||
VConsole.log( | |||
"Unregistered connector " + Util.getConnectorString(this)); | |||
} | |||
} | |||
/** | |||
@@ -447,11 +444,7 @@ public abstract class AbstractConnector | |||
return false; | |||
} | |||
if (getParent() == null) { | |||
return true; | |||
} else { | |||
return getParent().isEnabled(); | |||
} | |||
return getParent() == null || getParent().isEnabled(); | |||
} | |||
@Override | |||
@@ -474,21 +467,20 @@ public abstract class AbstractConnector | |||
* Gets the URL for a resource that has been added by the server-side | |||
* connector using | |||
* {@link com.vaadin.terminal.AbstractClientConnector#setResource(String, com.vaadin.terminal.Resource)} | |||
* with the same key. <code>null</code> is returned if no corresponding | |||
* resource is found. | |||
* with the same key. {@code null} is returned if no corresponding resource | |||
* is found. | |||
* | |||
* @param key | |||
* a string identifying the resource. | |||
* @return the resource URL as a string, or <code>null</code> if no | |||
* corresponding resource is found. | |||
* @return the resource URL as a string, or {@code null} if no corresponding | |||
* resource is found. | |||
*/ | |||
public String getResourceUrl(String key) { | |||
URLReference urlReference = getState().resources.get(key); | |||
if (urlReference == null) { | |||
return null; | |||
} else { | |||
return urlReference.getURL(); | |||
} | |||
return urlReference.getURL(); | |||
} | |||
/* |
@@ -231,16 +231,15 @@ public abstract class VAbstractPopupCalendar<PANEL extends VAbstractCalendarPane | |||
R resolution = getCurrentResolution(); | |||
if (currentDate == null || newDate.getTime() != currentDate.getTime()) { | |||
setCurrentDate((Date) newDate.clone()); | |||
bufferedResolutions.put( | |||
calendar.getResolution(calendar::isYear).name(), | |||
bufferedResolutions.put(calendar.getResolution(calendar::isYear), | |||
newDate.getYear() + 1900); | |||
if (!calendar.isYear(resolution)) { | |||
bufferedResolutions.put( | |||
calendar.getResolution(calendar::isMonth).name(), | |||
calendar.getResolution(calendar::isMonth), | |||
newDate.getMonth() + 1); | |||
if (!calendar.isMonth(resolution)) { | |||
bufferedResolutions.put( | |||
calendar.getResolution(calendar::isDay).name(), | |||
calendar.getResolution(calendar::isDay), | |||
newDate.getDate()); | |||
} | |||
} |
@@ -121,16 +121,15 @@ public abstract class VAbstractTextualDate<R extends Enum<R>> | |||
protected String createFormatString() { | |||
if (isYear(getCurrentResolution())) { | |||
return "yyyy"; // force full year | |||
} else { | |||
try { | |||
String frmString = LocaleService.getDateFormat(currentLocale); | |||
return cleanFormat(frmString); | |||
} catch (LocaleNotLoadedException e) { | |||
// TODO should die instead? Can the component survive | |||
// without format string? | |||
VConsole.error(e); | |||
return null; | |||
} | |||
} | |||
try { | |||
String frmString = LocaleService.getDateFormat(currentLocale); | |||
return cleanFormat(frmString); | |||
} catch (LocaleNotLoadedException e) { | |||
// TODO should die instead? Can the component survive | |||
// without format string? | |||
VConsole.error(e); | |||
return null; | |||
} | |||
} | |||
@@ -203,7 +202,7 @@ public abstract class VAbstractTextualDate<R extends Enum<R>> | |||
/** | |||
* Sets the time zone for the field. | |||
* | |||
* | |||
* @param timeZone | |||
* the new time zone to use | |||
* @since 8.2 | |||
@@ -243,8 +242,6 @@ public abstract class VAbstractTextualDate<R extends Enum<R>> | |||
VConsole.log(e); | |||
addStyleName(getStylePrimaryName() + PARSE_ERROR_CLASSNAME); | |||
// this is a hack that may eventually be removed | |||
bufferedInvalidDateString = true; | |||
setDate(null); | |||
} | |||
} else { | |||
@@ -255,28 +252,40 @@ public abstract class VAbstractTextualDate<R extends Enum<R>> | |||
// always send the date string | |||
bufferedDateString = text.getText(); | |||
updateDateVariables(); | |||
updateAndSendBufferedValues(); | |||
} | |||
/** | |||
* Updates the {@link VDateField#bufferedResolutions bufferedResolutions}, | |||
* then {@link #sendBufferedValues() sends} the values to the server. | |||
* | |||
* @since | |||
*/ | |||
protected final void updateAndSendBufferedValues() { | |||
updateBufferedResolutions(); | |||
sendBufferedValues(); | |||
} | |||
/** | |||
* Updates variables to send a response to the server. | |||
* Updates {@link VDateField#bufferedResolutions bufferedResolutions} before | |||
* sending a response to the server. | |||
* <p> | |||
* The method can be overridden by subclasses to provide a custom logic for | |||
* date variables to avoid overriding the {@link #onChange(ChangeEvent)} | |||
* method. | |||
* | |||
* | |||
* <p> | |||
* Note that this method should not send the buffered values, but use | |||
* {@link #updateAndSendBufferedValues()} instead | |||
* | |||
* @since | |||
*/ | |||
protected void updateDateVariables() { | |||
// Update variables | |||
// (only the smallest defining resolution needs to be | |||
// immediate) | |||
protected void updateBufferedResolutions() { | |||
Date currentDate = getDate(); | |||
bufferedResolutions.put( | |||
getResolutions().filter(this::isYear).findFirst().get().name(), | |||
currentDate != null ? currentDate.getYear() + 1900 : null); | |||
if (isYear(getCurrentResolution())) { | |||
sendBufferedValues(); | |||
if (currentDate != null) { | |||
bufferedResolutions.put( | |||
getResolutions().filter(this::isYear).findFirst().get(), | |||
currentDate.getYear() + 1900); | |||
} | |||
} | |||
@@ -432,13 +441,12 @@ public abstract class VAbstractTextualDate<R extends Enum<R>> | |||
* @since 8.1 | |||
*/ | |||
public void setISODate(String isoDate) { | |||
if (isoDate == null) { | |||
setDate(null); | |||
} else { | |||
Date date = getIsoFormatter().parse(isoDate); | |||
setDate(date); | |||
Date date = null; | |||
if (isoDate != null) { | |||
date = getIsoFormatter().parse(isoDate); | |||
} | |||
updateDateVariables(); | |||
setDate(date); | |||
updateAndSendBufferedValues(); | |||
} | |||
/** | |||
@@ -454,16 +462,14 @@ public abstract class VAbstractTextualDate<R extends Enum<R>> | |||
Date date = getDate(); | |||
if (date == null) { | |||
return null; | |||
} else { | |||
return getIsoFormatter().format(date); | |||
} | |||
return getIsoFormatter().format(date); | |||
} | |||
private DateTimeFormat getIsoFormatter() { | |||
if (supportsTime()) { | |||
return DateTimeFormat.getFormat(ISO_DATE_TIME_PATTERN); | |||
} else { | |||
return DateTimeFormat.getFormat(ISO_DATE_PATTERN); | |||
} | |||
return DateTimeFormat.getFormat(ISO_DATE_PATTERN); | |||
} | |||
} |
@@ -20,6 +20,7 @@ import java.util.Date; | |||
import java.util.HashMap; | |||
import java.util.Locale; | |||
import java.util.Map; | |||
import java.util.stream.Collectors; | |||
import java.util.stream.Stream; | |||
import com.google.gwt.user.client.ui.FlowPanel; | |||
@@ -66,13 +67,13 @@ public abstract class VDateField<R extends Enum<R>> extends FlowPanel | |||
* A temporary holder of the time units (resolutions), which would be sent | |||
* to the server through {@link #sendBufferedValues()}. | |||
* | |||
* The key is the resolution name e.g. "HOUR", "MINUTE". | |||
* The key is the resolution. | |||
* | |||
* The value can be {@code null}. | |||
* | |||
* @since | |||
*/ | |||
protected Map<String, Integer> bufferedResolutions = new HashMap<>(); | |||
protected Map<R, Integer> bufferedResolutions = new HashMap<>(); | |||
/** | |||
* A temporary holder of the date string, which would be sent to the server | |||
@@ -82,14 +83,6 @@ public abstract class VDateField<R extends Enum<R>> extends FlowPanel | |||
*/ | |||
protected String bufferedDateString; | |||
/** | |||
* A temporary holder of whether the date string was invalid or not, which | |||
* would be sent to the server through {@link #sendBufferedValues()}. | |||
* | |||
* @since | |||
*/ | |||
protected boolean bufferedInvalidDateString; | |||
/** | |||
* The date that is displayed the date field before a value is selected. If | |||
* null, display the current date. | |||
@@ -269,16 +262,16 @@ public abstract class VDateField<R extends Enum<R>> extends FlowPanel | |||
} | |||
/** | |||
* Sends the {@link #bufferedDateString}, {@link #bufferedInvalidDateString} | |||
* and {@link #bufferedResolutions} to the server, and clears their values. | |||
* Sends the {@link #bufferedDateString} and {@link #bufferedResolutions} to | |||
* the server, and clears their values. | |||
* | |||
* @since | |||
*/ | |||
public void sendBufferedValues() { | |||
rpc.update(bufferedDateString, bufferedInvalidDateString, | |||
new HashMap<>(bufferedResolutions)); | |||
rpc.update(bufferedDateString, | |||
bufferedResolutions.entrySet().stream().collect(Collectors | |||
.toMap(e -> e.getKey().name(), e -> e.getValue()))); | |||
bufferedDateString = null; | |||
bufferedInvalidDateString = false; | |||
bufferedResolutions.clear(); | |||
} | |||
@@ -15,6 +15,10 @@ | |||
*/ | |||
package com.vaadin.client.ui; | |||
import static com.vaadin.shared.ui.datefield.DateResolution.DAY; | |||
import static com.vaadin.shared.ui.datefield.DateResolution.MONTH; | |||
import static com.vaadin.shared.ui.datefield.DateResolution.YEAR; | |||
import java.util.Date; | |||
import java.util.Map; | |||
@@ -31,7 +35,7 @@ public class VDateFieldCalendar | |||
extends VAbstractDateFieldCalendar<VDateCalendarPanel, DateResolution> { | |||
public VDateFieldCalendar() { | |||
super(GWT.create(VDateCalendarPanel.class), DateResolution.YEAR); | |||
super(GWT.create(VDateCalendarPanel.class), YEAR); | |||
} | |||
/** | |||
@@ -53,16 +57,14 @@ public class VDateFieldCalendar | |||
DateResolution resolution = getCurrentResolution(); | |||
if (currentDate == null || date2.getTime() != currentDate.getTime()) { | |||
setCurrentDate((Date) date2.clone()); | |||
bufferedResolutions.put(DateResolution.YEAR.name(), | |||
bufferedResolutions.put(YEAR, | |||
// Java Date uses the year aligned to 1900 (no to zero). | |||
// So we should add 1900 to get a correct year aligned to 0. | |||
date2.getYear() + 1900); | |||
if (resolution.compareTo(DateResolution.YEAR) < 0) { | |||
bufferedResolutions.put(DateResolution.MONTH.name(), | |||
date2.getMonth() + 1); | |||
if (resolution.compareTo(DateResolution.MONTH) < 0) { | |||
bufferedResolutions.put(DateResolution.DAY.name(), | |||
date2.getDate()); | |||
if (resolution.compareTo(YEAR) < 0) { | |||
bufferedResolutions.put(MONTH, date2.getMonth() + 1); | |||
if (resolution.compareTo(MONTH) < 0) { | |||
bufferedResolutions.put(DAY, date2.getDate()); | |||
} | |||
} | |||
sendBufferedValues(); | |||
@@ -71,8 +73,7 @@ public class VDateFieldCalendar | |||
@Override | |||
public void setCurrentResolution(DateResolution resolution) { | |||
super.setCurrentResolution( | |||
resolution == null ? DateResolution.YEAR : resolution); | |||
super.setCurrentResolution(resolution == null ? YEAR : resolution); | |||
} | |||
@Override | |||
@@ -82,7 +83,7 @@ public class VDateFieldCalendar | |||
@Override | |||
public boolean isYear(DateResolution resolution) { | |||
return DateResolution.YEAR.equals(resolution); | |||
return YEAR.equals(resolution); | |||
} | |||
@Override |
@@ -15,6 +15,13 @@ | |||
*/ | |||
package com.vaadin.client.ui; | |||
import static com.vaadin.shared.ui.datefield.DateTimeResolution.DAY; | |||
import static com.vaadin.shared.ui.datefield.DateTimeResolution.HOUR; | |||
import static com.vaadin.shared.ui.datefield.DateTimeResolution.MINUTE; | |||
import static com.vaadin.shared.ui.datefield.DateTimeResolution.MONTH; | |||
import static com.vaadin.shared.ui.datefield.DateTimeResolution.SECOND; | |||
import static com.vaadin.shared.ui.datefield.DateTimeResolution.YEAR; | |||
import java.util.Date; | |||
import java.util.Map; | |||
@@ -32,8 +39,7 @@ public class VDateTimeFieldCalendar extends | |||
VAbstractDateFieldCalendar<VDateTimeCalendarPanel, DateTimeResolution> { | |||
public VDateTimeFieldCalendar() { | |||
super(GWT.create(VDateTimeCalendarPanel.class), | |||
DateTimeResolution.MINUTE); | |||
super(GWT.create(VDateTimeCalendarPanel.class), MINUTE); | |||
} | |||
@Override | |||
@@ -49,23 +55,17 @@ public class VDateTimeFieldCalendar extends | |||
DateTimeResolution resolution = getCurrentResolution(); | |||
if (currentDate == null || date2.getTime() != currentDate.getTime()) { | |||
setCurrentDate((Date) date2.clone()); | |||
addBufferedResolution(DateTimeResolution.YEAR, | |||
date2.getYear() + 1900); | |||
if (resolution.compareTo(DateTimeResolution.YEAR) < 0) { | |||
addBufferedResolution(DateTimeResolution.MONTH, | |||
date2.getMonth() + 1); | |||
if (resolution.compareTo(DateTimeResolution.MONTH) < 0) { | |||
addBufferedResolution(DateTimeResolution.DAY, | |||
date2.getDate()); | |||
if (resolution.compareTo(DateTimeResolution.DAY) < 0) { | |||
addBufferedResolution(DateTimeResolution.HOUR, | |||
date2.getHours()); | |||
if (resolution.compareTo(DateTimeResolution.HOUR) < 0) { | |||
addBufferedResolution(DateTimeResolution.MINUTE, | |||
date2.getMinutes()); | |||
if (resolution | |||
.compareTo(DateTimeResolution.MINUTE) < 0) { | |||
addBufferedResolution(DateTimeResolution.SECOND, | |||
bufferedResolutions.put(YEAR, date2.getYear() + 1900); | |||
if (resolution.compareTo(YEAR) < 0) { | |||
bufferedResolutions.put(MONTH, date2.getMonth() + 1); | |||
if (resolution.compareTo(MONTH) < 0) { | |||
bufferedResolutions.put(DAY, date2.getDate()); | |||
if (resolution.compareTo(DAY) < 0) { | |||
bufferedResolutions.put(HOUR, date2.getHours()); | |||
if (resolution.compareTo(HOUR) < 0) { | |||
bufferedResolutions.put(MINUTE, date2.getMinutes()); | |||
if (resolution.compareTo(MINUTE) < 0) { | |||
bufferedResolutions.put(SECOND, | |||
date2.getSeconds()); | |||
} | |||
} | |||
@@ -76,23 +76,17 @@ public class VDateTimeFieldCalendar extends | |||
} | |||
} | |||
private void addBufferedResolution(DateTimeResolution resolution, | |||
Integer value) { | |||
bufferedResolutions.put(resolution.name(), value); | |||
} | |||
@Override | |||
public String resolutionAsString() { | |||
if (getCurrentResolution().compareTo(DateTimeResolution.DAY) >= 0) { | |||
if (getCurrentResolution().compareTo(DAY) >= 0) { | |||
return getResolutionVariable(getCurrentResolution()); | |||
} else { | |||
return "full"; | |||
} | |||
return "full"; | |||
} | |||
@Override | |||
public boolean isYear(DateTimeResolution resolution) { | |||
return DateTimeResolution.YEAR.equals(resolution); | |||
return YEAR.equals(resolution); | |||
} | |||
@Override |
@@ -15,6 +15,10 @@ | |||
*/ | |||
package com.vaadin.client.ui; | |||
import static com.vaadin.shared.ui.datefield.DateResolution.DAY; | |||
import static com.vaadin.shared.ui.datefield.DateResolution.MONTH; | |||
import static com.vaadin.shared.ui.datefield.DateResolution.YEAR; | |||
import java.util.Date; | |||
import java.util.Map; | |||
@@ -32,7 +36,7 @@ public class VPopupCalendar | |||
extends VAbstractPopupCalendar<VDateCalendarPanel, DateResolution> { | |||
public VPopupCalendar() { | |||
super(GWT.create(VDateCalendarPanel.class), DateResolution.YEAR); | |||
super(GWT.create(VDateCalendarPanel.class), YEAR); | |||
} | |||
@Override | |||
@@ -47,24 +51,23 @@ public class VPopupCalendar | |||
@Override | |||
public void setCurrentResolution(DateResolution resolution) { | |||
super.setCurrentResolution( | |||
resolution == null ? DateResolution.YEAR : resolution); | |||
super.setCurrentResolution(resolution == null ? YEAR : resolution); | |||
} | |||
public static Date makeDate(Map<DateResolution, Integer> dateValues) { | |||
if (dateValues.get(DateResolution.YEAR) == null) { | |||
if (dateValues.get(YEAR) == null) { | |||
return null; | |||
} | |||
Date date = new Date(2000 - 1900, 0, 1); | |||
Integer year = dateValues.get(DateResolution.YEAR); | |||
Integer year = dateValues.get(YEAR); | |||
if (year != null) { | |||
date.setYear(year - 1900); | |||
} | |||
Integer month = dateValues.get(DateResolution.MONTH); | |||
Integer month = dateValues.get(MONTH); | |||
if (month != null) { | |||
date.setMonth(month - 1); | |||
} | |||
Integer day = dateValues.get(DateResolution.DAY); | |||
Integer day = dateValues.get(DAY); | |||
if (day != null) { | |||
date.setDate(day); | |||
} | |||
@@ -73,7 +76,7 @@ public class VPopupCalendar | |||
@Override | |||
public boolean isYear(DateResolution resolution) { | |||
return DateResolution.YEAR.equals(resolution); | |||
return YEAR.equals(resolution); | |||
} | |||
@Override | |||
@@ -82,31 +85,27 @@ public class VPopupCalendar | |||
} | |||
@Override | |||
protected void updateDateVariables() { | |||
super.updateDateVariables(); | |||
DateResolution resolution = getCurrentResolution(); | |||
// Update variables | |||
// (only the smallest defining resolution needs to be | |||
// immediate) | |||
protected void updateBufferedResolutions() { | |||
super.updateBufferedResolutions(); | |||
Date currentDate = getDate(); | |||
if (resolution.compareTo(DateResolution.MONTH) <= 0) { | |||
bufferedResolutions.put(DateResolution.MONTH.name(), | |||
currentDate != null ? currentDate.getMonth() + 1 : null); | |||
} | |||
if (resolution.compareTo(DateResolution.DAY) <= 0) { | |||
bufferedResolutions.put(DateResolution.DAY.name(), | |||
currentDate != null ? currentDate.getDate() : null); | |||
if (currentDate != null) { | |||
DateResolution resolution = getCurrentResolution(); | |||
if (resolution.compareTo(MONTH) <= 0) { | |||
bufferedResolutions.put(MONTH, currentDate.getMonth() + 1); | |||
} | |||
if (resolution.compareTo(DAY) <= 0) { | |||
bufferedResolutions.put(DAY, currentDate.getDate()); | |||
} | |||
} | |||
sendBufferedValues(); | |||
} | |||
@Override | |||
protected String cleanFormat(String format) { | |||
// Remove unnecessary d & M if resolution is too low | |||
if (getCurrentResolution().compareTo(DateResolution.DAY) > 0) { | |||
if (getCurrentResolution().compareTo(DAY) > 0) { | |||
format = format.replaceAll("d", ""); | |||
} | |||
if (getCurrentResolution().compareTo(DateResolution.MONTH) > 0) { | |||
if (getCurrentResolution().compareTo(MONTH) > 0) { | |||
format = format.replaceAll("M", ""); | |||
} | |||
return super.cleanFormat(format); |
@@ -15,6 +15,13 @@ | |||
*/ | |||
package com.vaadin.client.ui; | |||
import static com.vaadin.shared.ui.datefield.DateTimeResolution.DAY; | |||
import static com.vaadin.shared.ui.datefield.DateTimeResolution.HOUR; | |||
import static com.vaadin.shared.ui.datefield.DateTimeResolution.MINUTE; | |||
import static com.vaadin.shared.ui.datefield.DateTimeResolution.MONTH; | |||
import static com.vaadin.shared.ui.datefield.DateTimeResolution.SECOND; | |||
import static com.vaadin.shared.ui.datefield.DateTimeResolution.YEAR; | |||
import java.util.Date; | |||
import java.util.Map; | |||
@@ -36,8 +43,7 @@ public class VPopupTimeCalendar extends | |||
VAbstractPopupCalendar<VDateTimeCalendarPanel, DateTimeResolution> { | |||
public VPopupTimeCalendar() { | |||
super(GWT.create(VDateTimeCalendarPanel.class), | |||
DateTimeResolution.MINUTE); | |||
super(GWT.create(VDateTimeCalendarPanel.class), MINUTE); | |||
} | |||
@Override | |||
@@ -47,45 +53,43 @@ public class VPopupTimeCalendar extends | |||
@Override | |||
public String resolutionAsString() { | |||
if (getCurrentResolution().compareTo(DateTimeResolution.DAY) >= 0) { | |||
if (getCurrentResolution().compareTo(DAY) >= 0) { | |||
return getResolutionVariable(getCurrentResolution()); | |||
} else { | |||
return "full"; | |||
} | |||
return "full"; | |||
} | |||
@Override | |||
public void setCurrentResolution(DateTimeResolution resolution) { | |||
super.setCurrentResolution( | |||
resolution == null ? DateTimeResolution.MINUTE : resolution); | |||
super.setCurrentResolution(resolution == null ? MINUTE : resolution); | |||
} | |||
public static Date makeDate(Map<DateTimeResolution, Integer> dateValues) { | |||
if (dateValues.get(DateTimeResolution.YEAR) == null) { | |||
if (dateValues.get(YEAR) == null) { | |||
return null; | |||
} | |||
Date date = new Date(2000 - 1900, 0, 1); | |||
Integer year = dateValues.get(DateTimeResolution.YEAR); | |||
Integer year = dateValues.get(YEAR); | |||
if (year != null) { | |||
date.setYear(year - 1900); | |||
} | |||
Integer month = dateValues.get(DateTimeResolution.MONTH); | |||
Integer month = dateValues.get(MONTH); | |||
if (month != null) { | |||
date.setMonth(month - 1); | |||
} | |||
Integer day = dateValues.get(DateTimeResolution.DAY); | |||
Integer day = dateValues.get(DAY); | |||
if (day != null) { | |||
date.setDate(day); | |||
} | |||
Integer hour = dateValues.get(DateTimeResolution.HOUR); | |||
Integer hour = dateValues.get(HOUR); | |||
if (hour != null) { | |||
date.setHours(hour); | |||
} | |||
Integer minute = dateValues.get(DateTimeResolution.MINUTE); | |||
Integer minute = dateValues.get(MINUTE); | |||
if (minute != null) { | |||
date.setMinutes(minute); | |||
} | |||
Integer second = dateValues.get(DateTimeResolution.SECOND); | |||
Integer second = dateValues.get(SECOND); | |||
if (second != null) { | |||
date.setSeconds(second); | |||
} | |||
@@ -94,7 +98,7 @@ public class VPopupTimeCalendar extends | |||
@Override | |||
public boolean isYear(DateTimeResolution resolution) { | |||
return DateTimeResolution.YEAR.equals(resolution); | |||
return YEAR.equals(resolution); | |||
} | |||
@Override | |||
@@ -103,38 +107,27 @@ public class VPopupTimeCalendar extends | |||
} | |||
@Override | |||
protected void updateDateVariables() { | |||
super.updateDateVariables(); | |||
DateTimeResolution resolution = getCurrentResolution(); | |||
// (only the smallest defining resolution needs to be | |||
// immediate) | |||
protected void updateBufferedResolutions() { | |||
super.updateBufferedResolutions(); | |||
Date currentDate = getDate(); | |||
if (resolution.compareTo(DateTimeResolution.MONTH) <= 0) { | |||
addBufferedResolution(DateTimeResolution.MONTH, | |||
currentDate != null ? currentDate.getMonth() + 1 : null); | |||
} | |||
if (resolution.compareTo(DateTimeResolution.DAY) <= 0) { | |||
addBufferedResolution(DateTimeResolution.DAY, | |||
currentDate != null ? currentDate.getDate() : null); | |||
} | |||
if (resolution.compareTo(DateTimeResolution.HOUR) <= 0) { | |||
addBufferedResolution(DateTimeResolution.HOUR, | |||
currentDate != null ? currentDate.getHours() : null); | |||
} | |||
if (resolution.compareTo(DateTimeResolution.MINUTE) <= 0) { | |||
addBufferedResolution(DateTimeResolution.MINUTE, | |||
currentDate != null ? currentDate.getMinutes() : null); | |||
} | |||
if (resolution.compareTo(DateTimeResolution.SECOND) <= 0) { | |||
addBufferedResolution(DateTimeResolution.SECOND, | |||
currentDate != null ? currentDate.getSeconds() : null); | |||
if (currentDate != null) { | |||
DateTimeResolution resolution = getCurrentResolution(); | |||
if (resolution.compareTo(MONTH) <= 0) { | |||
bufferedResolutions.put(MONTH, currentDate.getMonth() + 1); | |||
} | |||
if (resolution.compareTo(DAY) <= 0) { | |||
bufferedResolutions.put(DAY, currentDate.getDate()); | |||
} | |||
if (resolution.compareTo(HOUR) <= 0) { | |||
bufferedResolutions.put(HOUR, currentDate.getHours()); | |||
} | |||
if (resolution.compareTo(MINUTE) <= 0) { | |||
bufferedResolutions.put(MINUTE, currentDate.getMinutes()); | |||
} | |||
if (resolution.compareTo(SECOND) <= 0) { | |||
bufferedResolutions.put(SECOND, currentDate.getSeconds()); | |||
} | |||
} | |||
sendBufferedValues(); | |||
} | |||
private void addBufferedResolution(DateTimeResolution resolutionToAdd, | |||
Integer value) { | |||
bufferedResolutions.put(resolutionToAdd.name(), value); | |||
} | |||
@Override | |||
@@ -144,16 +137,12 @@ public class VPopupTimeCalendar extends | |||
super.updateValue(newDate); | |||
DateTimeResolution resolution = getCurrentResolution(); | |||
if (currentDate == null || newDate.getTime() != currentDate.getTime()) { | |||
if (resolution.compareTo(DateTimeResolution.DAY) < 0) { | |||
bufferedResolutions.put(DateTimeResolution.HOUR.name(), | |||
newDate.getHours()); | |||
if (resolution.compareTo(DateTimeResolution.HOUR) < 0) { | |||
bufferedResolutions.put(DateTimeResolution.MINUTE.name(), | |||
newDate.getMinutes()); | |||
if (resolution.compareTo(DateTimeResolution.MINUTE) < 0) { | |||
bufferedResolutions.put( | |||
DateTimeResolution.SECOND.name(), | |||
newDate.getSeconds()); | |||
if (resolution.compareTo(DAY) < 0) { | |||
bufferedResolutions.put(HOUR, newDate.getHours()); | |||
if (resolution.compareTo(HOUR) < 0) { | |||
bufferedResolutions.put(MINUTE, newDate.getMinutes()); | |||
if (resolution.compareTo(MINUTE) < 0) { | |||
bufferedResolutions.put(SECOND, newDate.getSeconds()); | |||
} | |||
} | |||
} | |||
@@ -164,50 +153,45 @@ public class VPopupTimeCalendar extends | |||
protected String createFormatString() { | |||
if (isYear(getCurrentResolution())) { | |||
return "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"; | |||
} | |||
try { | |||
String frmString = LocaleService.getDateFormat(currentLocale); | |||
frmString = cleanFormat(frmString); | |||
// String delim = LocaleService | |||
// .getClockDelimiter(currentLocale); | |||
if (getCurrentResolution().compareTo(HOUR) <= 0) { | |||
if (dts.isTwelveHourClock()) { | |||
frmString += " hh"; | |||
} else { | |||
frmString += " HH"; | |||
} | |||
if (getCurrentResolution().compareTo(MINUTE) <= 0) { | |||
frmString += ":mm"; | |||
if (getCurrentResolution().compareTo(SECOND) <= 0) { | |||
frmString += ":ss"; | |||
} | |||
} | |||
return frmString; | |||
} catch (LocaleNotLoadedException e) { | |||
// TODO should die instead? Can the component survive | |||
// without format string? | |||
VConsole.error(e); | |||
return null; | |||
if (dts.isTwelveHourClock()) { | |||
frmString += " aaa"; | |||
} | |||
} | |||
return frmString; | |||
} catch (LocaleNotLoadedException e) { | |||
// TODO should die instead? Can the component survive | |||
// without format string? | |||
VConsole.error(e); | |||
return null; | |||
} | |||
} | |||
@Override | |||
protected String cleanFormat(String format) { | |||
// Remove unnecessary d & M if resolution is too low | |||
if (getCurrentResolution().compareTo(DateTimeResolution.DAY) > 0) { | |||
if (getCurrentResolution().compareTo(DAY) > 0) { | |||
format = format.replaceAll("d", ""); | |||
} | |||
if (getCurrentResolution().compareTo(DateTimeResolution.MONTH) > 0) { | |||
if (getCurrentResolution().compareTo(MONTH) > 0) { | |||
format = format.replaceAll("M", ""); | |||
} | |||
return super.cleanFormat(format); |
@@ -54,10 +54,9 @@ public abstract class AbstractDateFieldConnector<R extends Enum<R>> | |||
Stream<R> resolutions = widget.getResolutions(); | |||
R resolution = widget.getCurrentResolution(); | |||
return resolutions.collect(Collectors.toMap(Function.identity(), | |||
res -> res == null ? null | |||
: (resolution.compareTo(res) <= 0) | |||
? stateResolutions.get(res.name()) | |||
: null)); | |||
res -> resolution.compareTo(res) <= 0 | |||
? stateResolutions.get(res.name()) | |||
: null)); | |||
} | |||
/** | |||
@@ -68,14 +67,14 @@ public abstract class AbstractDateFieldConnector<R extends Enum<R>> | |||
* @since | |||
*/ | |||
protected Map<R, Integer> getDefaultValues() { | |||
VDateField<R> widget = getWidget(); | |||
Map<String, Integer> stateResolutions = getState().resolutions; | |||
Stream<R> resolutions = getWidget().getResolutions(); | |||
R resolution = getWidget().getCurrentResolution(); | |||
Stream<R> resolutions = widget.getResolutions(); | |||
R resolution = widget.getCurrentResolution(); | |||
return resolutions.collect(Collectors.toMap(Function.identity(), | |||
res -> res == null ? null | |||
: (resolution.compareTo(res) <= 0) | |||
? stateResolutions.get("default-" + res.name()) | |||
: null)); | |||
res -> resolution.compareTo(res) <= 0 | |||
? stateResolutions.get("default-" + res.name()) | |||
: null)); | |||
} | |||
@SuppressWarnings("unchecked") |
@@ -91,7 +91,7 @@ public abstract class AbstractComponent extends AbstractClientConnector | |||
/** | |||
* The internal error message of the component. | |||
*/ | |||
private ErrorMessage componentError = null; | |||
private ErrorMessage componentError; | |||
/** | |||
* Locale of this component. |
@@ -77,10 +77,9 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & | |||
private AbstractDateFieldServerRpc rpc = new AbstractDateFieldServerRpc() { | |||
@Override | |||
public void update(String newDateString, boolean invalidDateString, | |||
public void update(String newDateString, | |||
Map<String, Integer> resolutions) { | |||
Set<String> resolutionNames = getResolutions() | |||
.map(AbstractDateField.this::getResolutionVariable) | |||
Set<String> resolutionNames = getResolutions().map(Enum::name) | |||
.collect(Collectors.toSet()); | |||
resolutionNames.retainAll(resolutions.keySet()); | |||
if (!isReadOnly() | |||
@@ -109,7 +108,8 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & | |||
if (newDateString == null || newDateString.isEmpty()) { | |||
setValue(newDate, true); | |||
} else { | |||
if (invalidDateString) { | |||
// invalid date string | |||
if (resolutions.isEmpty()) { | |||
Result<T> parsedDate = handleUnparsableDateString( | |||
dateString); | |||
parsedDate.ifOk(v -> setValue(v, true)); | |||
@@ -173,7 +173,7 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & | |||
/* Constructors */ | |||
/** | |||
* Constructs an empty <code>AbstractDateField</code> with no caption and | |||
* Constructs an empty {@code AbstractDateField} with no caption and | |||
* specified {@code resolution}. | |||
* | |||
* @param resolution | |||
@@ -185,10 +185,10 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & | |||
} | |||
/** | |||
* Constructs an empty <code>AbstractDateField</code> with caption. | |||
* Constructs an empty {@code AbstractDateField} with caption. | |||
* | |||
* @param caption | |||
* the caption of the datefield. | |||
* the caption of the datefield | |||
* @param resolution | |||
* initial resolution for the field, not {@code null} | |||
*/ | |||
@@ -198,11 +198,11 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & | |||
} | |||
/** | |||
* Constructs a new <code>AbstractDateField</code> with the given caption | |||
* and initial text contents. | |||
* Constructs a new {@code AbstractDateField} with the given caption and | |||
* initial text contents. | |||
* | |||
* @param caption | |||
* the caption <code>String</code> for the editor. | |||
* the caption {@code String} for the editor. | |||
* @param value | |||
* the date/time value. | |||
* @param resolution | |||
@@ -227,24 +227,31 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & | |||
* Construct a date object from the individual field values received from | |||
* the client. | |||
* | |||
* @param resolutions | |||
* map of time unit (resolution) name and value, the key is the | |||
* resolution name e.g. "HOUR", "MINUTE", the value can be | |||
* {@code null} | |||
* @param oldDate | |||
* used as a fallback to get needed values if they are not | |||
* defined in the specified {@code resolutions} | |||
* | |||
* @return the date object built from the specified resolutions | |||
* @since | |||
*/ | |||
protected T reconstructDateFromFields(Map<String, Integer> variables, | |||
protected T reconstructDateFromFields(Map<String, Integer> resolutions, | |||
T oldDate) { | |||
Map<R, Integer> calendarFields = new HashMap<>(); | |||
for (R resolution : getResolutionsHigherOrEqualTo(getResolution())) { | |||
// Only handle what the client is allowed to send. The same | |||
// resolutions that are painted | |||
String variableName = getResolutionVariable(resolution); | |||
String resolutionName = resolution.name(); | |||
Integer newValue = variables.get(variableName); | |||
if (newValue != null) { | |||
calendarFields.put(resolution, newValue); | |||
} else { | |||
calendarFields.put(resolution, | |||
getDatePart(oldDate, resolution)); | |||
Integer newValue = resolutions.get(resolutionName); | |||
if (newValue == null) { | |||
newValue = getDatePart(oldDate, resolution); | |||
} | |||
calendarFields.put(resolution, newValue); | |||
} | |||
return buildDate(calendarFields); | |||
} | |||
@@ -252,8 +259,8 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & | |||
/** | |||
* Sets the start range for this component. If the value is set before this | |||
* date (taking the resolution into account), the component will not | |||
* validate. If <code>startDate</code> is set to <code>null</code>, any | |||
* value before <code>endDate</code> will be accepted by the range | |||
* validate. If {@code startDate} is set to {@code null}, any value before | |||
* {@code endDate} will be accepted by the range | |||
* | |||
* @param startDate | |||
* - the allowed range's start date | |||
@@ -315,12 +322,12 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & | |||
/** | |||
* Sets the end range for this component. If the value is set after this | |||
* date (taking the resolution into account), the component will not | |||
* validate. If <code>endDate</code> is set to <code>null</code>, any value | |||
* after <code>startDate</code> will be accepted by the range. | |||
* validate. If {@code endDate} is set to {@code null}, any value after | |||
* {@code startDate} will be accepted by the range. | |||
* | |||
* @param endDate | |||
* - the allowed range's end date (inclusive, based on the | |||
* current resolution) | |||
* the allowed range's end date (inclusive, based on the current | |||
* resolution) | |||
*/ | |||
public void setRangeEnd(T endDate) { | |||
Date date = convertToDate(endDate); | |||
@@ -336,7 +343,7 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & | |||
/** | |||
* Returns the precise rangeStart used. | |||
* | |||
* @return the precise rangeStart used, may be null. | |||
* @return the precise rangeStart used, may be {@code null}. | |||
*/ | |||
public T getRangeStart() { | |||
return convertFromDate(getState(false).rangeStart); | |||
@@ -345,7 +352,7 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & | |||
/** | |||
* Returns the precise rangeEnd used. | |||
* | |||
* @return the precise rangeEnd used, may be null. | |||
* @return the precise rangeEnd used, may be {@code null}. | |||
*/ | |||
public T getRangeEnd() { | |||
return convertFromDate(getState(false).rangeEnd); | |||
@@ -423,14 +430,14 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & | |||
// Only paint variables for the resolution and up, e.g. Resolution DAY | |||
// paints DAY,MONTH,YEAR | |||
for (R res : getResolutionsHigherOrEqualTo(getResolution())) { | |||
String variableName = getResolutionVariable(res); | |||
for (R resolution : getResolutionsHigherOrEqualTo(getResolution())) { | |||
String resolutionName = resolution.name(); | |||
Integer value = getValuePart(currentDate, res); | |||
resolutions.put(variableName, value); | |||
Integer value = getValuePart(currentDate, resolution); | |||
resolutions.put(resolutionName, value); | |||
Integer defaultValuePart = getValuePart(defaultValue, res); | |||
resolutions.put("default-" + variableName, defaultValuePart); | |||
Integer defaultValuePart = getValuePart(defaultValue, resolution); | |||
resolutions.put("default-" + resolutionName, defaultValuePart); | |||
} | |||
} | |||
@@ -501,6 +508,7 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & | |||
* default value is set, current date/time is used. | |||
* | |||
* @param defaultValue | |||
* the default value, may be {@code null} | |||
* @since 8.1.2 | |||
*/ | |||
public void setDefaultValue(T defaultValue) { | |||
@@ -581,9 +589,11 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & | |||
* {@link #handleUnparsableDateString(String)} method is overridden, the | |||
* localized message from its exception is used. | |||
* | |||
* @param parsingErrorMessage | |||
* the default parsing error message | |||
* | |||
* @see #getParseErrorMessage() | |||
* @see #handleUnparsableDateString(String) | |||
* @param parsingErrorMessage | |||
*/ | |||
public void setParseErrorMessage(String parsingErrorMessage) { | |||
defaultParseErrorMessage = parsingErrorMessage; | |||
@@ -628,8 +638,7 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & | |||
} | |||
/** | |||
* Formats date according to the components locale. To be reimplemented in | |||
* subclasses. | |||
* Formats date according to the components locale. | |||
* | |||
* @param value | |||
* the date or {@code null} | |||
@@ -637,9 +646,7 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & | |||
* {@code null} | |||
* @since 8.1.1 | |||
*/ | |||
protected String formatDate(T value) { | |||
return Objects.toString(value, ""); | |||
} | |||
protected abstract String formatDate(T value); | |||
@Override | |||
public void writeDesign(Element design, DesignContext designContext) { | |||
@@ -684,11 +691,10 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & | |||
this.value = value; | |||
// Also set the internal dateString | |||
if (value != null) { | |||
dateString = formatDate(value); | |||
} else { | |||
dateString = formatDate(getEmptyValue()); | |||
if (value == null) { | |||
value = getEmptyValue(); | |||
} | |||
dateString = formatDate(value); | |||
RangeValidator<T> validator = getRangeValidator();// TODO move range | |||
// check to internal | |||
// validator? | |||
@@ -717,9 +723,10 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & | |||
* given {@code resolution}. | |||
* | |||
* @param date | |||
* the given date | |||
* the given date, can be {@code null} | |||
* @param resolution | |||
* the resolution to extract a value from the date by | |||
* the resolution to extract a value from the date by, not | |||
* {@code null} | |||
* @return the integer value part of the date by the given resolution | |||
*/ | |||
protected abstract int getDatePart(T date, R resolution); | |||
@@ -764,10 +771,6 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & | |||
*/ | |||
protected abstract Date convertToDate(T date); | |||
private String getResolutionVariable(R resolution) { | |||
return resolution.name(); | |||
} | |||
@SuppressWarnings("unchecked") | |||
private Stream<R> getResolutions() { | |||
Type resolutionType = GenericTypeReflector.getTypeParameter(getClass(), | |||
@@ -776,11 +779,10 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster & | |||
Class<?> clazz = (Class<?>) resolutionType; | |||
return Stream.of(clazz.getEnumConstants()) | |||
.map(object -> (R) object); | |||
} else { | |||
throw new RuntimeException("Cannot detect resoluton type " | |||
+ Optional.ofNullable(resolutionType).map(Type::getTypeName) | |||
.orElse(null)); | |||
} | |||
throw new RuntimeException("Cannot detect resoluton type " | |||
+ Optional.ofNullable(resolutionType).map(Type::getTypeName) | |||
.orElse(null)); | |||
} | |||
private Iterable<R> getResolutionsHigherOrEqualTo(R resoution) { |
@@ -50,6 +50,11 @@ public class DateFieldListenersTest extends AbstractListenerMethodsTestBase { | |||
protected Date convertToDate(LocalDateTime date) { | |||
return null; | |||
} | |||
@Override | |||
protected String formatDate(LocalDateTime value) { | |||
return null; | |||
} | |||
} | |||
@Test |
@@ -33,15 +33,13 @@ public interface AbstractDateFieldServerRpc extends ServerRpc { | |||
* the value of the text field part. It enables analyzing invalid | |||
* input on the server. {@code null} if the date was chosen with | |||
* popup calendar or contains user-typed string | |||
* @param invalidDateString | |||
* Whether the last date string is invalid or not | |||
* @param resolutions | |||
* map of time unit (resolution) name and value, name is the | |||
* lower-case resolution name e.g. "hour", "minute", and value | |||
* can be {@code null} | |||
* map of time unit (resolution) name and value, the key is the | |||
* resolution name e.g. "HOUR", "MINUTE", the value can be | |||
* {@code null}. If the map is empty, that means the | |||
* {@code newDateString} is invalid | |||
*/ | |||
void update(String newDateString, boolean invalidDateString, | |||
Map<String, Integer> resolutions); | |||
void update(String newDateString, Map<String, Integer> resolutions); | |||
/** | |||
* Indicates to the server that the client-side has lost focus. |