<li>Separate row heights for header, body and footer in Grid</li> | <li>Separate row heights for header, body and footer in Grid</li> | ||||
<li>Support for item descriptions (tooltips) in CheckBoxGroup, RadioButtonGroup and Tree</li> | <li>Support for item descriptions (tooltips) in CheckBoxGroup, RadioButtonGroup and Tree</li> | ||||
<li>Binder supports removing bindings</li> | <li>Binder supports removing bindings</li> | ||||
<li>Binding builder methods do not have to be chained</li> | |||||
<li>Bean validation failures will revert changes in Binder</li> | |||||
<li>Notification supports CloseListener</li> | <li>Notification supports CloseListener</li> | ||||
<li>Tree now has methods to scroll it programmatically</li> | |||||
<li>The browser time zone can be obtained from WebBrowser if the browser supports it</li> | |||||
<li>AbstractDateField now supports formatting of time zone information</li> | |||||
<li>PushState based navigation support</li> | |||||
<li>VaadinSession is now stored to the HTTP session at the end of each access to support clustering</li> | |||||
<li>Grid WAI-ARIA support has been improved (aria-sort added)</li> | |||||
<li>Client side ErrorLevel support</li> | |||||
<li>VaadinService, VaadinServlet and VaadinServletService have protected no-args constructors to make DI integrations simpler</li> | |||||
</ul> | </ul> | ||||
</p> | </p> |
/** | /** | ||||
* Style name and style name prefix for the error indicator element. | * Style name and style name prefix for the error indicator element. | ||||
* | |||||
* @since 8.2 | |||||
*/ | */ | ||||
public static final String STYLE_NAME_ERROR_INDICATOR = "v-errorindicator"; | public static final String STYLE_NAME_ERROR_INDICATOR = "v-errorindicator"; | ||||
} | } |
* Constructs a new tooltip info instance. | * Constructs a new tooltip info instance. | ||||
* | * | ||||
* @param tooltip | * @param tooltip | ||||
* tooltip title | |||||
* tooltip title | |||||
*/ | */ | ||||
public TooltipInfo(String tooltip) { | public TooltipInfo(String tooltip) { | ||||
this(tooltip, ContentMode.PREFORMATTED); | this(tooltip, ContentMode.PREFORMATTED); | ||||
* @param errorLevel | * @param errorLevel | ||||
* error level | * error level | ||||
* | * | ||||
* @deprecated use {@link #TooltipInfo(String, ContentMode, String, Object, | |||||
* ErrorLevel)} instead | |||||
* @deprecated use | |||||
* {@link #TooltipInfo(String, ContentMode, String, Object, ErrorLevel)} | |||||
* instead | |||||
* @since 8.2 | * @since 8.2 | ||||
*/ | */ | ||||
@Deprecated | @Deprecated | ||||
* Constructs a new tooltip info instance. | * Constructs a new tooltip info instance. | ||||
* | * | ||||
* @param tooltip | * @param tooltip | ||||
* tooltip title | |||||
* tooltip title | |||||
* @param mode | * @param mode | ||||
* content mode | |||||
* content mode | |||||
*/ | */ | ||||
public TooltipInfo(String tooltip, ContentMode mode) { | public TooltipInfo(String tooltip, ContentMode mode) { | ||||
setTitle(tooltip); | setTitle(tooltip); | ||||
* Constructs a new tooltip info instance. | * Constructs a new tooltip info instance. | ||||
* | * | ||||
* @param tooltip | * @param tooltip | ||||
* tooltip title | |||||
* tooltip title | |||||
* @param mode | * @param mode | ||||
* content mode | |||||
* content mode | |||||
* @param errorMessage | * @param errorMessage | ||||
* error message | |||||
* error message | |||||
*/ | */ | ||||
public TooltipInfo(String tooltip, ContentMode mode, String errorMessage) { | public TooltipInfo(String tooltip, ContentMode mode, String errorMessage) { | ||||
this(tooltip, mode, errorMessage, null); | this(tooltip, mode, errorMessage, null); | ||||
* Constructs a new tooltip info instance. | * Constructs a new tooltip info instance. | ||||
* | * | ||||
* @param tooltip | * @param tooltip | ||||
* tooltip title | |||||
* tooltip title | |||||
* @param mode | * @param mode | ||||
* content mode | |||||
* content mode | |||||
* @param errorMessage | * @param errorMessage | ||||
* error message | |||||
* error message | |||||
* @param identifier | * @param identifier | ||||
* the tooltip's identifier | |||||
* the tooltip's identifier | |||||
*/ | */ | ||||
public TooltipInfo(String tooltip, ContentMode mode, String errorMessage, | public TooltipInfo(String tooltip, ContentMode mode, String errorMessage, | ||||
Object identifier) { | Object identifier) { | ||||
* Constructs a new tooltip info instance. | * Constructs a new tooltip info instance. | ||||
* | * | ||||
* @param tooltip | * @param tooltip | ||||
* tooltip title | |||||
* tooltip title | |||||
* @param mode | * @param mode | ||||
* content mode | |||||
* content mode | |||||
* @param errorMessage | * @param errorMessage | ||||
* error message | |||||
* error message | |||||
* @param identifier | * @param identifier | ||||
* the tooltip's identifier | |||||
* the tooltip's identifier | |||||
* @param errorLevel | * @param errorLevel | ||||
* error level | |||||
* error level | |||||
* @since 8.2 | |||||
*/ | */ | ||||
public TooltipInfo(String tooltip, ContentMode mode, String errorMessage, | public TooltipInfo(String tooltip, ContentMode mode, String errorMessage, | ||||
Object identifier, ErrorLevel errorLevel) { | Object identifier, ErrorLevel errorLevel) { | ||||
* Sets the tooltip's identifier. | * Sets the tooltip's identifier. | ||||
* | * | ||||
* @param identifier | * @param identifier | ||||
* the identifier to set | |||||
* the identifier to set | |||||
*/ | */ | ||||
public void setIdentifier(Object identifier) { | public void setIdentifier(Object identifier) { | ||||
this.identifier = identifier; | this.identifier = identifier; | ||||
* Sets the tooltip title. | * Sets the tooltip title. | ||||
* | * | ||||
* @param title | * @param title | ||||
* the title to set | |||||
* the title to set | |||||
*/ | */ | ||||
public void setTitle(String title) { | public void setTitle(String title) { | ||||
this.title = title; | this.title = title; | ||||
* Sets the error message. | * Sets the error message. | ||||
* | * | ||||
* @param errorMessage | * @param errorMessage | ||||
* the error message to set | |||||
* the error message to set | |||||
*/ | */ | ||||
public void setErrorMessage(String errorMessage) { | public void setErrorMessage(String errorMessage) { | ||||
errorMessageHtml = errorMessage; | errorMessageHtml = errorMessage; | ||||
* Sets the tooltip title's content mode. | * Sets the tooltip title's content mode. | ||||
* | * | ||||
* @param contentMode | * @param contentMode | ||||
* the content mode to set | |||||
* the content mode to set | |||||
*/ | */ | ||||
public void setContentMode(ContentMode contentMode) { | public void setContentMode(ContentMode contentMode) { | ||||
this.contentMode = contentMode; | this.contentMode = contentMode; | ||||
* Sets the error level. | * Sets the error level. | ||||
* | * | ||||
* @param errorLevel | * @param errorLevel | ||||
* the error level to set | |||||
* the error level to set | |||||
* @since 8.2 | * @since 8.2 | ||||
*/ | */ | ||||
public void setErrorLevel(ErrorLevel errorLevel) { | public void setErrorLevel(ErrorLevel errorLevel) { | ||||
* identifier are equal. | * identifier are equal. | ||||
* | * | ||||
* @param other | * @param other | ||||
* the reference tooltip info instance with which to compare | |||||
* the reference tooltip info instance with which to compare | |||||
* @return {@code true} if the instances are equal, {@code false} otherwise | * @return {@code true} if the instances are equal, {@code false} otherwise | ||||
*/ | */ | ||||
public boolean equals(TooltipInfo other) { | public boolean equals(TooltipInfo other) { |
} | } | ||||
} | } | ||||
/** | |||||
* Sets the time zone for the field. | |||||
* | |||||
* @param timeZone | |||||
* the new time zone to use | |||||
* @since 8.2 | |||||
*/ | |||||
public void setTimeZone(TimeZone timeZone) { | public void setTimeZone(TimeZone timeZone) { | ||||
this.timeZone = timeZone; | this.timeZone = timeZone; | ||||
} | } |
/** | /** | ||||
* Gets the validation status handler for this Binding. | * Gets the validation status handler for this Binding. | ||||
* | |||||
* | |||||
* @return the validation status handler for this binding | * @return the validation status handler for this binding | ||||
* | |||||
* | |||||
* @since 8.2 | * @since 8.2 | ||||
*/ | */ | ||||
public BindingValidationStatusHandler getValidationStatusHandler(); | public BindingValidationStatusHandler getValidationStatusHandler(); | ||||
TARGET nullRepresentation) { | TARGET nullRepresentation) { | ||||
return withConverter( | return withConverter( | ||||
fieldValue -> Objects.equals(fieldValue, nullRepresentation) | fieldValue -> Objects.equals(fieldValue, nullRepresentation) | ||||
? null | |||||
: fieldValue, | |||||
? null : fieldValue, | |||||
modelValue -> Objects.isNull(modelValue) | modelValue -> Objects.isNull(modelValue) | ||||
? nullRepresentation | |||||
: modelValue); | |||||
? nullRepresentation : modelValue); | |||||
} | } | ||||
/** | /** | ||||
* trigger validating and writing of the whole bean if using | * trigger validating and writing of the whole bean if using | ||||
* {@link #setBean(Object)}. If using {@link #readBean(Object)} only the | * {@link #setBean(Object)}. If using {@link #readBean(Object)} only the | ||||
* field validation is run. | * field validation is run. | ||||
* | |||||
* | |||||
* @param binding | * @param binding | ||||
* the binding whose value has been changed | * the binding whose value has been changed | ||||
* @since 8.2 | |||||
*/ | */ | ||||
protected void handleFieldValueChange(Binding<BEAN, ?> binding) { | protected void handleFieldValueChange(Binding<BEAN, ?> binding) { | ||||
changedBindings.add(binding); | changedBindings.add(binding); | ||||
* Changes have been succesfully saved. The set is only cleared | * Changes have been succesfully saved. The set is only cleared | ||||
* if using readBean/writeBean or when the changes are stored in | * if using readBean/writeBean or when the changes are stored in | ||||
* the currently set bean. | * the currently set bean. | ||||
* | |||||
* | |||||
* Writing changes to another bean when using setBean does not | * Writing changes to another bean when using setBean does not | ||||
* clear the set of changed bindings. | * clear the set of changed bindings. | ||||
*/ | */ | ||||
/** | /** | ||||
* Restores the state of the bean from the given values. | * Restores the state of the bean from the given values. | ||||
* | |||||
* | |||||
* @param bean | * @param bean | ||||
* the bean | * the bean | ||||
* @param oldValues | * @param oldValues | ||||
* the old values | * the old values | ||||
* | |||||
* | |||||
* @since 8.2 | * @since 8.2 | ||||
*/ | */ | ||||
@SuppressWarnings({ "unchecked", "rawtypes" }) | @SuppressWarnings({ "unchecked", "rawtypes" }) | ||||
/** | /** | ||||
* Stores the state of the given bean. | * Stores the state of the given bean. | ||||
* | |||||
* | |||||
* @param bean | * @param bean | ||||
* the bean to store the state of | * the bean to store the state of | ||||
* @param bindings | * @param bindings | ||||
* the bindings to store | * the bindings to store | ||||
* | |||||
* | |||||
* @return map from binding to value | * @return map from binding to value | ||||
* | |||||
* | |||||
* @since 8.2 | * @since 8.2 | ||||
*/ | */ | ||||
@SuppressWarnings({ "unchecked", "rawtypes" }) | @SuppressWarnings({ "unchecked", "rawtypes" }) | ||||
* Validates the values of all bound fields and returns the validation | * Validates the values of all bound fields and returns the validation | ||||
* status. This method can skip firing the event, based on the given | * status. This method can skip firing the event, based on the given | ||||
* {@code boolean}. | * {@code boolean}. | ||||
* | |||||
* | |||||
* @param fireEvent | * @param fireEvent | ||||
* {@code true} to fire validation status events; {@code false} | * {@code true} to fire validation status events; {@code false} | ||||
* to not | * to not | ||||
* @return validation status for the binder | * @return validation status for the binder | ||||
* | |||||
* | |||||
* @since 8.2 | * @since 8.2 | ||||
*/ | */ | ||||
protected BinderValidationStatus<BEAN> validate(boolean fireEvent) { | protected BinderValidationStatus<BEAN> validate(boolean fireEvent) { | ||||
Converter<FIELDVALUE, FIELDVALUE> nullRepresentationConverter = Converter | Converter<FIELDVALUE, FIELDVALUE> nullRepresentationConverter = Converter | ||||
.from(fieldValue -> fieldValue, | .from(fieldValue -> fieldValue, | ||||
modelValue -> Objects.isNull(modelValue) | modelValue -> Objects.isNull(modelValue) | ||||
? field.getEmptyValue() | |||||
: modelValue, | |||||
? field.getEmptyValue() : modelValue, | |||||
exception -> exception.getMessage()); | exception -> exception.getMessage()); | ||||
ConverterDelegate<FIELDVALUE> converter = new ConverterDelegate<>( | ConverterDelegate<FIELDVALUE> converter = new ConverterDelegate<>( | ||||
nullRepresentationConverter); | nullRepresentationConverter); | ||||
/** | /** | ||||
* Finds and removes all Bindings for the given field. | * Finds and removes all Bindings for the given field. | ||||
* | |||||
* | |||||
* @param field | * @param field | ||||
* the field to remove from bindings | * the field to remove from bindings | ||||
* | |||||
* | |||||
* @since 8.2 | * @since 8.2 | ||||
*/ | */ | ||||
public void removeBinding(HasValue<?> field) { | public void removeBinding(HasValue<?> field) { | ||||
/** | /** | ||||
* Removes the given Binding from this Binder. | * Removes the given Binding from this Binder. | ||||
* | |||||
* | |||||
* @param binding | * @param binding | ||||
* the binding to remove | * the binding to remove | ||||
* | |||||
* | |||||
* @since 8.2 | * @since 8.2 | ||||
*/ | */ | ||||
public void removeBinding(Binding<BEAN, ?> binding) { | public void removeBinding(Binding<BEAN, ?> binding) { | ||||
/** | /** | ||||
* Finds and removes the Binding for the given property name. | * Finds and removes the Binding for the given property name. | ||||
* | |||||
* | |||||
* @param propertyName | * @param propertyName | ||||
* the propertyName to remove from bindings | * the propertyName to remove from bindings | ||||
* | |||||
* | |||||
* @since 8.2 | * @since 8.2 | ||||
*/ | */ | ||||
public void removeBinding(String propertyName) { | public void removeBinding(String propertyName) { |
* (if the browser supports this feature). | * (if the browser supports this feature). | ||||
* | * | ||||
* @return the TimeZone Id if provided by the browser, null otherwise. | * @return the TimeZone Id if provided by the browser, null otherwise. | ||||
* @see <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat/resolvedOptions">Intl.DateTimeFormat.prototype.resolvedOptions()</a> | |||||
* @see <a href= | |||||
* "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat/resolvedOptions">Intl.DateTimeFormat.prototype.resolvedOptions()</a> | |||||
* @since 8.2 | |||||
*/ | */ | ||||
public String getTimeZoneId() { | public String getTimeZoneId() { | ||||
return timeZoneId; | return timeZoneId; | ||||
this.dstInEffect = Boolean.parseBoolean(dstInEffect); | this.dstInEffect = Boolean.parseBoolean(dstInEffect); | ||||
} | } | ||||
if (tzId == null || "undefined".equals(tzId)) { | if (tzId == null || "undefined".equals(tzId)) { | ||||
this.timeZoneId = null; | |||||
timeZoneId = null; | |||||
} else { | } else { | ||||
this.timeZoneId = tzId; | |||||
timeZoneId = tzId; | |||||
} | } | ||||
if (curDate != null) { | if (curDate != null) { | ||||
try { | try { |
import com.vaadin.server.AbstractExtension; | import com.vaadin.server.AbstractExtension; | ||||
import com.vaadin.server.Page; | import com.vaadin.server.Page; | ||||
import com.vaadin.server.Resource; | import com.vaadin.server.Resource; | ||||
import com.vaadin.server.ResourceReference; | |||||
import com.vaadin.shared.Position; | import com.vaadin.shared.Position; | ||||
import com.vaadin.shared.Registration; | import com.vaadin.shared.Registration; | ||||
import com.vaadin.shared.ui.notification.NotificationServerRpc; | import com.vaadin.shared.ui.notification.NotificationServerRpc; | ||||
/** | /** | ||||
* The server RPC. | * The server RPC. | ||||
* | |||||
* @since 8.2 | |||||
*/ | */ | ||||
protected NotificationServerRpc rpc = () -> { | protected NotificationServerRpc rpc = () -> { | ||||
fireEvent(new CloseEvent(Notification.this)); | fireEvent(new CloseEvent(Notification.this)); | ||||
* Sets the position of the notification message. | * Sets the position of the notification message. | ||||
* | * | ||||
* @param position | * @param position | ||||
* The desired notification position, | |||||
* not {@code null} | |||||
* The desired notification position, not {@code null} | |||||
*/ | */ | ||||
public void setPosition(Position position) { | public void setPosition(Position position) { | ||||
if (position == null) { | if (position == null) { | ||||
/** | /** | ||||
* Gets the delay before the notification disappears. | * Gets the delay before the notification disappears. | ||||
* | * | ||||
* @return the delay in milliseconds, {@value #DELAY_FOREVER} | |||||
* indicates the message has to be clicked. | |||||
* @return the delay in milliseconds, {@value #DELAY_FOREVER} indicates the | |||||
* message has to be clicked. | |||||
*/ | */ | ||||
public int getDelayMsec() { | public int getDelayMsec() { | ||||
return getState(false).delay; | return getState(false).delay; | ||||
* Sets the delay before the notification disappears. | * Sets the delay before the notification disappears. | ||||
* | * | ||||
* @param delayMsec | * @param delayMsec | ||||
* the desired delay in milliseconds, {@value #DELAY_FOREVER} | |||||
* to require the user to click the message | |||||
* the desired delay in milliseconds, {@value #DELAY_FOREVER} to | |||||
* require the user to click the message | |||||
*/ | */ | ||||
public void setDelayMsec(int delayMsec) { | public void setDelayMsec(int delayMsec) { | ||||
getState().delay = delayMsec; | getState().delay = delayMsec; | ||||
* Checks whether caption and description are interpreted as HTML or plain | * Checks whether caption and description are interpreted as HTML or plain | ||||
* text. | * text. | ||||
* | * | ||||
* @return {@code true} if the texts are used as HTML, | |||||
* {@code false} if used as plain text | |||||
* @return {@code true} if the texts are used as HTML, {@code false} if used | |||||
* as plain text | |||||
* @see #setHtmlContentAllowed(boolean) | * @see #setHtmlContentAllowed(boolean) | ||||
*/ | */ | ||||
public boolean isHtmlContentAllowed() { | public boolean isHtmlContentAllowed() { | ||||
* | * | ||||
* @param caption | * @param caption | ||||
* The message | * The message | ||||
* @return | |||||
* The Notification | |||||
* @return The Notification | |||||
*/ | */ | ||||
public static Notification show(String caption) { | public static Notification show(String caption) { | ||||
Notification notification = new Notification(caption); | Notification notification = new Notification(caption); | ||||
* The message | * The message | ||||
* @param type | * @param type | ||||
* The message type | * The message type | ||||
* @return | |||||
* The Notification | |||||
* @return The Notification | |||||
*/ | */ | ||||
public static Notification show(String caption, Type type) { | public static Notification show(String caption, Type type) { | ||||
Notification notification = new Notification(caption, type); | Notification notification = new Notification(caption, type); | ||||
* The message description | * The message description | ||||
* @param type | * @param type | ||||
* The message type | * The message type | ||||
* @return | |||||
* The Notification | |||||
* @return The Notification | |||||
*/ | */ | ||||
public static Notification show(String caption, String description, Type type) { | |||||
Notification notification = new Notification(caption, description, type); | |||||
public static Notification show(String caption, String description, | |||||
Type type) { | |||||
Notification notification = new Notification(caption, description, | |||||
type); | |||||
notification.extend(UI.getCurrent()); | notification.extend(UI.getCurrent()); | ||||
return notification; | return notification; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
/** | |||||
* Event fired when a notification is closed. | |||||
* | |||||
* @since 8.2 | |||||
*/ | |||||
public static class CloseEvent extends ConnectorEvent { | public static class CloseEvent extends ConnectorEvent { | ||||
/** | /** | ||||
/** | /** | ||||
* An interface used for listening to Notification close events. Add the | * An interface used for listening to Notification close events. Add the | ||||
* CloseListener to a Notification and | * CloseListener to a Notification and | ||||
* {@link CloseListener#notificationClose(CloseEvent)} will be called whenever the | |||||
* Notification is closed. | |||||
* {@link CloseListener#notificationClose(CloseEvent)} will be called | |||||
* whenever the Notification is closed. | |||||
* | |||||
* @since 8.2 | |||||
*/ | */ | ||||
@FunctionalInterface | @FunctionalInterface | ||||
public interface CloseListener extends Serializable { | public interface CloseListener extends Serializable { |
* @param row | * @param row | ||||
* zero based index of the item to scroll to in the current view. | * zero based index of the item to scroll to in the current view. | ||||
* @throws IllegalArgumentException | * @throws IllegalArgumentException | ||||
* if the provided row is outside the item range | |||||
* if the provided row is outside the item range | |||||
* @since 8.2 | |||||
*/ | */ | ||||
public void scrollTo(int row) throws IllegalArgumentException { | public void scrollTo(int row) throws IllegalArgumentException { | ||||
treeGrid.scrollTo(row, ScrollDestination.ANY); | treeGrid.scrollTo(row, ScrollDestination.ANY); | ||||
* {@code null} | * {@code null} | ||||
* @throws IllegalArgumentException | * @throws IllegalArgumentException | ||||
* if the provided row is outside the item range | * if the provided row is outside the item range | ||||
* @since 8.2 | |||||
*/ | */ | ||||
public void scrollTo(int row, ScrollDestination destination) { | public void scrollTo(int row, ScrollDestination destination) { | ||||
treeGrid.scrollTo(row, destination); | treeGrid.scrollTo(row, destination); | ||||
/** | /** | ||||
* Scrolls to the beginning of the first data row. | * Scrolls to the beginning of the first data row. | ||||
* | |||||
* @since 8.2 | |||||
*/ | */ | ||||
public void scrollToStart() { | public void scrollToStart() { | ||||
treeGrid.scrollToStart(); | treeGrid.scrollToStart(); | ||||
/** | /** | ||||
* Scrolls to the end of the last data row. | * Scrolls to the end of the last data row. | ||||
* | |||||
* @since 8.2 | |||||
*/ | */ | ||||
public void scrollToEnd() { | public void scrollToEnd() { | ||||
treeGrid.scrollToEnd(); | treeGrid.scrollToEnd(); |