<build> | <build> | ||||
<plugins> | <plugins> | ||||
<plugin> | |||||
<groupId>net.revelc.code.formatter</groupId> | |||||
<artifactId>formatter-maven-plugin</artifactId> | |||||
</plugin> | |||||
<plugin> | |||||
<groupId>com.github.dantwining.whitespace-maven-plugin</groupId> | |||||
<artifactId>whitespace-maven-plugin</artifactId> | |||||
</plugin> | |||||
<plugin> | <plugin> | ||||
<artifactId>maven-resources-plugin</artifactId> | <artifactId>maven-resources-plugin</artifactId> | ||||
<executions> | <executions> |
}-*/; | }-*/; | ||||
/** | /** | ||||
* Reads a configuration parameter as an {@link Element} object. | |||||
* Please note | |||||
* that the javascript value of the parameter should also be an Element | |||||
* object, | |||||
* or else an undefined exception may be thrown when calling this method | |||||
* or methods on the returned object. | |||||
* Reads a configuration parameter as an {@link Element} object. Please | |||||
* note that the javascript value of the parameter should also be an | |||||
* Element object, or else an undefined exception may be thrown when | |||||
* calling this method or methods on the returned object. | |||||
* | * | ||||
* @param name | * @param name | ||||
* name of the configuration parameter | |||||
* @return element for the configuration parameter, or <code>null</code> if no | |||||
* value is defined | |||||
* name of the configuration parameter | |||||
* @return element for the configuration parameter, or <code>null</code> | |||||
* if no value is defined | |||||
* @since 8.4 | * @since 8.4 | ||||
*/ | */ | ||||
private native Element getConfigElement(String name) | private native Element getConfigElement(String name) |
* | * | ||||
* @param String | * @param String | ||||
* a value starting with a number | * a value starting with a number | ||||
* @return the value from the string before any non-numeric characters. | |||||
* If the value cannot be parsed to a number, returns 0. | |||||
* @return the value from the string before any non-numeric characters. If | |||||
* the value cannot be parsed to a number, returns 0. | |||||
*/ | */ | ||||
private static native int parseIntNative(final String value) | private static native int parseIntNative(final String value) | ||||
/*-{ | /*-{ |
/** | /** | ||||
* Measure child component only if child component is an | * Measure child component only if child component is an | ||||
* {@link com.vaadin.client.ui.AbstractLayoutConnector AbstractLayoutConnector} | |||||
* or implements either {@link ManagedLayout} or | |||||
* {@link ElementResizeListener}. | |||||
* {@link com.vaadin.client.ui.AbstractLayoutConnector | |||||
* AbstractLayoutConnector} or implements either {@link ManagedLayout} | |||||
* or {@link ElementResizeListener}. | |||||
*/ | */ | ||||
MEASURE_IF_NEEDED, | MEASURE_IF_NEEDED, | ||||
* all previous style names. | * all previous style names. | ||||
* | * | ||||
* @param errorLevel | * @param errorLevel | ||||
* error level | |||||
* error level | |||||
* @since 8.2 | * @since 8.2 | ||||
*/ | */ | ||||
public void updateErrorLevel(ErrorLevel errorLevel) { | public void updateErrorLevel(ErrorLevel errorLevel) { |
return connector; | return connector; | ||||
} | } | ||||
} catch (NoDataException e) { | } catch (NoDataException e) { | ||||
throw new IllegalStateException( | |||||
"There is no information about " + classType | |||||
+ ". Did you remember to compile the right widgetset?", | |||||
e); | |||||
throw new IllegalStateException("There is no information about " | |||||
+ classType | |||||
+ ". Did you remember to compile the right widgetset?", e); | |||||
} finally { | } finally { | ||||
Profiler.leave("WidgetSet.createConnector"); | Profiler.leave("WidgetSet.createConnector"); | ||||
} | } |
/** | /** | ||||
* Simple object to store another object. | * Simple object to store another object. | ||||
* | |||||
* | |||||
* @param <T> | * @param <T> | ||||
* the object type to store | * the object type to store | ||||
* @since 8.4 | * @since 8.4 | ||||
/** | /** | ||||
* Gets the current object. | * Gets the current object. | ||||
* | |||||
* | |||||
* @return the stored object | * @return the stored object | ||||
*/ | */ | ||||
public T get() { | public T get() { | ||||
/** | /** | ||||
* Sets the current object. | * Sets the current object. | ||||
* | |||||
* | |||||
* @param reference | * @param reference | ||||
* the object to store | * the object to store | ||||
*/ | */ | ||||
com.google.gwt.dom.client.Element el, String p) | com.google.gwt.dom.client.Element el, String p) | ||||
/*-{ | /*-{ | ||||
try { | try { | ||||
if (el.currentStyle) { | if (el.currentStyle) { | ||||
// IE | // IE | ||||
return el.currentStyle[p]; | return el.currentStyle[p]; | ||||
} catch (e) { | } catch (e) { | ||||
return ""; | return ""; | ||||
} | } | ||||
}-*/; | }-*/; | ||||
/** | /** | ||||
try { | try { | ||||
el.focus(); | el.focus(); | ||||
} catch (e) { | } catch (e) { | ||||
} | } | ||||
}-*/; | }-*/; | ||||
if ($wnd.document.activeElement) { | if ($wnd.document.activeElement) { | ||||
return $wnd.document.activeElement; | return $wnd.document.activeElement; | ||||
} | } | ||||
return null; | return null; | ||||
}-*/; | }-*/; | ||||
/*-{ | /*-{ | ||||
var top = elem.offsetTop; | var top = elem.offsetTop; | ||||
var height = elem.offsetHeight; | var height = elem.offsetHeight; | ||||
if (elem.parentNode != elem.offsetParent) { | if (elem.parentNode != elem.offsetParent) { | ||||
top -= elem.parentNode.offsetTop; | top -= elem.parentNode.offsetTop; | ||||
} | } | ||||
var cur = elem.parentNode; | var cur = elem.parentNode; | ||||
while (cur && (cur.nodeType == 1)) { | while (cur && (cur.nodeType == 1)) { | ||||
if (top < cur.scrollTop) { | if (top < cur.scrollTop) { | ||||
if (top + height > cur.scrollTop + cur.clientHeight) { | if (top + height > cur.scrollTop + cur.clientHeight) { | ||||
cur.scrollTop = (top + height) - cur.clientHeight; | cur.scrollTop = (top + height) - cur.clientHeight; | ||||
} | } | ||||
var offsetTop = cur.offsetTop; | var offsetTop = cur.offsetTop; | ||||
if (cur.parentNode != cur.offsetParent) { | if (cur.parentNode != cur.offsetParent) { | ||||
offsetTop -= cur.parentNode.offsetTop; | offsetTop -= cur.parentNode.offsetTop; | ||||
} | } | ||||
top += offsetTop - cur.scrollTop; | top += offsetTop - cur.scrollTop; | ||||
cur = cur.parentNode; | cur = cur.parentNode; | ||||
} | } | ||||
} | } | ||||
var heightWithoutBorder = cloneElement.offsetHeight; | var heightWithoutBorder = cloneElement.offsetHeight; | ||||
parentElement.removeChild(cloneElement); | parentElement.removeChild(cloneElement); | ||||
return heightWithBorder - heightWithoutBorder; | return heightWithBorder - heightWithoutBorder; | ||||
} | } | ||||
}-*/; | }-*/; |
final PushConfigurationState pushConfiguration) { | final PushConfigurationState pushConfiguration) { | ||||
this.connection = connection; | this.connection = connection; | ||||
connection.addHandler(ApplicationStoppedEvent.TYPE, | |||||
event -> { | |||||
if (state == State.DISCONNECT_PENDING | |||||
|| state == State.DISCONNECTED) { | |||||
return; | |||||
} | |||||
disconnect(() -> { | |||||
}); | |||||
}); | |||||
connection.addHandler(ApplicationStoppedEvent.TYPE, event -> { | |||||
if (state == State.DISCONNECT_PENDING | |||||
|| state == State.DISCONNECTED) { | |||||
return; | |||||
} | |||||
disconnect(() -> { | |||||
}); | |||||
}); | |||||
config = createConfig(); | config = createConfig(); | ||||
String debugParameter = Location.getParameter("debug"); | String debugParameter = Location.getParameter("debug"); | ||||
if ("push".equals(debugParameter)) { | if ("push".equals(debugParameter)) { |
public void setConnection(ApplicationConnection connection) { | public void setConnection(ApplicationConnection connection) { | ||||
this.connection = connection; | this.connection = connection; | ||||
connection.addHandler(ApplicationStoppedEvent.TYPE, | |||||
event -> { | |||||
if (isReconnecting()) { | |||||
giveUp(); | |||||
} | |||||
if (scheduledReconnect != null | |||||
&& scheduledReconnect.isRunning()) { | |||||
scheduledReconnect.cancel(); | |||||
} | |||||
}); | |||||
connection.addHandler(ApplicationStoppedEvent.TYPE, event -> { | |||||
if (isReconnecting()) { | |||||
giveUp(); | |||||
} | |||||
if (scheduledReconnect != null && scheduledReconnect.isRunning()) { | |||||
scheduledReconnect.cancel(); | |||||
} | |||||
}); | |||||
// Allow dialog to cache needed resources to make them available when we | // Allow dialog to cache needed resources to make them available when we | ||||
// are offline | // are offline |
method.invoke(clientRpc, invocation.getParameters()); | method.invoke(clientRpc, invocation.getParameters()); | ||||
} | } | ||||
} catch (NoDataException e) { | } catch (NoDataException e) { | ||||
throw new IllegalStateException( | |||||
"There is no information about " + method.getSignature() | |||||
+ ". Did you remember to compile the right widgetset?", | |||||
e); | |||||
throw new IllegalStateException("There is no information about " | |||||
+ method.getSignature() | |||||
+ ". Did you remember to compile the right widgetset?", e); | |||||
} | } | ||||
} | } | ||||
Type[] parameterTypes = method.getParameterTypes(); | Type[] parameterTypes = method.getParameterTypes(); | ||||
return parameterTypes; | return parameterTypes; | ||||
} catch (NoDataException e) { | } catch (NoDataException e) { | ||||
throw new IllegalStateException( | |||||
"There is no information about " + method.getSignature() | |||||
+ ". Did you remember to compile the right widgetset?", | |||||
e); | |||||
throw new IllegalStateException("There is no information about " | |||||
+ method.getSignature() | |||||
+ ". Did you remember to compile the right widgetset?", e); | |||||
} | } | ||||
} | } | ||||
import elemental.json.JsonObject; | import elemental.json.JsonObject; | ||||
/** | /** | ||||
* XhrConnectionError provides detail about an error which occurred during | |||||
* an XHR request to the server. | |||||
* XhrConnectionError provides detail about an error which occurred during an | |||||
* XHR request to the server. | |||||
* | * | ||||
* @since 7.6 | * @since 7.6 | ||||
* @author Vaadin Ltd | * @author Vaadin Ltd |
*/ | */ | ||||
JsonObject hierarchyData = newRowData.getObject( | JsonObject hierarchyData = newRowData.getObject( | ||||
HierarchicalDataCommunicatorConstants.ROW_HIERARCHY_DESCRIPTION); | HierarchicalDataCommunicatorConstants.ROW_HIERARCHY_DESCRIPTION); | ||||
if (!hierarchyData.hasKey(HierarchicalDataCommunicatorConstants.ROW_DEPTH)) { | |||||
if (!hierarchyData | |||||
.hasKey(HierarchicalDataCommunicatorConstants.ROW_DEPTH)) { | |||||
hierarchyData.put(HierarchicalDataCommunicatorConstants.ROW_DEPTH, | hierarchyData.put(HierarchicalDataCommunicatorConstants.ROW_DEPTH, | ||||
oldRowData | |||||
.getObject( | |||||
HierarchicalDataCommunicatorConstants.ROW_HIERARCHY_DESCRIPTION) | |||||
oldRowData.getObject( | |||||
HierarchicalDataCommunicatorConstants.ROW_HIERARCHY_DESCRIPTION) | |||||
.getNumber( | .getNumber( | ||||
HierarchicalDataCommunicatorConstants.ROW_DEPTH)); | HierarchicalDataCommunicatorConstants.ROW_DEPTH)); | ||||
} | } |
/** | /** | ||||
* An abstract base class for renderer connectors. A renderer connector is used | * An abstract base class for renderer connectors. A renderer connector is used | ||||
* to link a client-side {@link com.vaadin.client.renderers.Renderer Renderer} to a server-side | |||||
* {@link com.vaadin.ui.renderers.Renderer Renderer}. As a connector, it can | |||||
* use the regular Vaadin RPC and shared state mechanism to pass additional | |||||
* state and information between the client and the server. This base class | |||||
* itself only uses the basic {@link com.vaadin.shared.communication.SharedState | |||||
* SharedState} and no RPC interfaces. | |||||
* to link a client-side {@link com.vaadin.client.renderers.Renderer Renderer} | |||||
* to a server-side {@link com.vaadin.ui.renderers.Renderer Renderer}. As a | |||||
* connector, it can use the regular Vaadin RPC and shared state mechanism to | |||||
* pass additional state and information between the client and the server. This | |||||
* base class itself only uses the basic | |||||
* {@link com.vaadin.shared.communication.SharedState SharedState} and no RPC | |||||
* interfaces. | |||||
* | * | ||||
* @param <T> | * @param <T> | ||||
* the presentation type of the renderer | * the presentation type of the renderer |
public class ColumnConnector extends AbstractExtensionConnector { | public class ColumnConnector extends AbstractExtensionConnector { | ||||
public abstract static class CustomColumn | public abstract static class CustomColumn | ||||
extends Column<Object, JsonObject> { | |||||
extends Column<Object, JsonObject> { | |||||
private final String connectorId; | private final String connectorId; | ||||
private ContentMode tooltipContentMode; | private ContentMode tooltipContentMode; |
String columnId = columnToIdMap.get(cell.getColumn()); | String columnId = columnToIdMap.get(cell.getColumn()); | ||||
int rowIndex = cell.getRowIndex(); | int rowIndex = cell.getRowIndex(); | ||||
getRpcProxy(GridServerRpc.class).itemClick(rowKey, columnId, | getRpcProxy(GridServerRpc.class).itemClick(rowKey, columnId, | ||||
MouseEventDetailsBuilder | |||||
.buildMouseEventDetails(mouseEvent), rowIndex); | |||||
MouseEventDetailsBuilder.buildMouseEventDetails(mouseEvent), | |||||
rowIndex); | |||||
} | } | ||||
} | } | ||||
public void run() { | public void run() { | ||||
refresh(); | refresh(); | ||||
} | } | ||||
}; public InfoSection() { | |||||
}; | |||||
public InfoSection() { | |||||
createContent(); | createContent(); | ||||
} | } | ||||
/** | /** | ||||
* Sets the log row limit. | * Sets the log row limit. | ||||
* | * | ||||
* @param limit The limit | |||||
* @param limit | |||||
* The limit | |||||
*/ | */ | ||||
public void setLimit(int limit) { | public void setLimit(int limit) { | ||||
this.limit = limit; | this.limit = limit; |
* Returns the files parameter of the dataTransfer object. | * Returns the files parameter of the dataTransfer object. | ||||
* | * | ||||
* @param dataTransfer | * @param dataTransfer | ||||
* DataTransfer object to retrieve files from. | |||||
* DataTransfer object to retrieve files from. | |||||
* @return {@code DataTransfer.files} parameter of the given dataTransfer | * @return {@code DataTransfer.files} parameter of the given dataTransfer | ||||
* object. | |||||
* object. | |||||
*/ | */ | ||||
private native FileList getFiles(DataTransfer dataTransfer) | private native FileList getFiles(DataTransfer dataTransfer) | ||||
/*-{ | /*-{ | ||||
* Checks whether the file on the given index is indeed a file or a folder. | * Checks whether the file on the given index is indeed a file or a folder. | ||||
* | * | ||||
* @param file | * @param file | ||||
* File object to prove it is not a folder. | |||||
* File object to prove it is not a folder. | |||||
* @param fileIndex | * @param fileIndex | ||||
* Index of the file object. | |||||
* Index of the file object. | |||||
* @param dataTransfer | * @param dataTransfer | ||||
* DataTransfer object that contains the list of files. | |||||
* DataTransfer object that contains the list of files. | |||||
* @return {@code true} if the given file at the given index is not a | * @return {@code true} if the given file at the given index is not a | ||||
* folder, {@code false} otherwise. | |||||
* folder, {@code false} otherwise. | |||||
*/ | */ | ||||
private native boolean isFile(File file, int fileIndex, | private native boolean isFile(File file, int fileIndex, | ||||
DataTransfer dataTransfer) | DataTransfer dataTransfer) |
@OnStateChange("registeredEventListeners") | @OnStateChange("registeredEventListeners") | ||||
void handleContextClickListenerChange() { | void handleContextClickListenerChange() { | ||||
if (contextHandler == null && hasEventListener(EventId.CONTEXT_CLICK)) { | if (contextHandler == null && hasEventListener(EventId.CONTEXT_CLICK)) { | ||||
contextHandler = getWidget() | |||||
.addDomHandler(event -> { | |||||
final MouseEventDetails mouseEventDetails = MouseEventDetailsBuilder | |||||
.buildMouseEventDetails(event.getNativeEvent(), | |||||
getWidget().getElement()); | |||||
event.preventDefault(); | |||||
event.stopPropagation(); | |||||
sendContextClickEvent(mouseEventDetails, | |||||
event.getNativeEvent().getEventTarget()); | |||||
}, ContextMenuEvent.getType()); | |||||
contextHandler = getWidget().addDomHandler(event -> { | |||||
final MouseEventDetails mouseEventDetails = MouseEventDetailsBuilder | |||||
.buildMouseEventDetails(event.getNativeEvent(), | |||||
getWidget().getElement()); | |||||
event.preventDefault(); | |||||
event.stopPropagation(); | |||||
sendContextClickEvent(mouseEventDetails, | |||||
event.getNativeEvent().getEventTarget()); | |||||
}, ContextMenuEvent.getType()); | |||||
// if the widget has a contextclick listener, add touch support as | // if the widget has a contextclick listener, add touch support as | ||||
// well. | // well. | ||||
} | } | ||||
// Prevent selection for the element while pending long tap. | // Prevent selection for the element while pending long tap. | ||||
WidgetUtil.setTextSelectionEnabled(widget.getElement(), | |||||
false); | |||||
WidgetUtil.setTextSelectionEnabled(widget.getElement(), false); | |||||
if (BrowserInfo.get().isAndroid()) { | if (BrowserInfo.get().isAndroid()) { | ||||
// Android fires ContextMenu events automatically. | // Android fires ContextMenu events automatically. | ||||
} | } | ||||
/* | /* | ||||
* we need to build mouseEventDetails eagerly - the event won't | |||||
* be guaranteed to be around when the timer executes. At least | |||||
* this was the case with iOS devices. | |||||
* we need to build mouseEventDetails eagerly - the event won't be | |||||
* guaranteed to be around when the timer executes. At least this | |||||
* was the case with iOS devices. | |||||
*/ | */ | ||||
final MouseEventDetails mouseEventDetails = MouseEventDetailsBuilder | final MouseEventDetails mouseEventDetails = MouseEventDetailsBuilder | ||||
HasErrorIndicatorElement hasErrorIndicatorElement = (HasErrorIndicatorElement) widget; | HasErrorIndicatorElement hasErrorIndicatorElement = (HasErrorIndicatorElement) widget; | ||||
if (getState().errorMessage != null) { | if (getState().errorMessage != null) { | ||||
hasErrorIndicatorElement.setErrorIndicatorElementVisible(true); | hasErrorIndicatorElement.setErrorIndicatorElementVisible(true); | ||||
ErrorUtil.setErrorLevelStyle(hasErrorIndicatorElement.getErrorIndicatorElement(), | |||||
ErrorUtil.setErrorLevelStyle( | |||||
hasErrorIndicatorElement.getErrorIndicatorElement(), | |||||
StyleConstants.STYLE_NAME_ERROR_INDICATOR, | StyleConstants.STYLE_NAME_ERROR_INDICATOR, | ||||
getState().errorLevel); | getState().errorLevel); | ||||
} else { | } else { |
/** | /** | ||||
* Finds all the focusable children of given parent element. | * Finds all the focusable children of given parent element. | ||||
* | |||||
* | |||||
* @param parent | * @param parent | ||||
* the parent element | * the parent element | ||||
* @return array of focusable children | * @return array of focusable children | ||||
/** | /** | ||||
* Moves the focus to the first focusable child of given parent element. | * Moves the focus to the first focusable child of given parent element. | ||||
* | |||||
* | |||||
* @param parent | * @param parent | ||||
* the parent element | * the parent element | ||||
* @since 8.1.7 | * @since 8.1.7 | ||||
for (int i = 0; i < focusableChildren.length; i++) { | for (int i = 0; i < focusableChildren.length; i++) { | ||||
Element element = focusableChildren[i]; | Element element = focusableChildren[i]; | ||||
String classes = element.getAttribute("class"); | String classes = element.getAttribute("class"); | ||||
if (classes == null || !classes.toLowerCase().contains("disabled")) { | |||||
if (classes == null | |||||
|| !classes.toLowerCase().contains("disabled")) { | |||||
element.focus(); | element.focus(); | ||||
return; | return; | ||||
} | } | ||||
/** | /** | ||||
* Moves the focus to the last focusable child of given parent element. | * Moves the focus to the last focusable child of given parent element. | ||||
* | |||||
* | |||||
* @param parent | * @param parent | ||||
* the parent element | * the parent element | ||||
* @since 8.1.7 | * @since 8.1.7 |
* Sets the visibility of the error indicator element. | * Sets the visibility of the error indicator element. | ||||
* | * | ||||
* @param visible | * @param visible | ||||
* {@code true} to show the error indicator element, {@code false} | |||||
* to hide it | |||||
* {@code true} to show the error indicator element, | |||||
* {@code false} to hide it | |||||
*/ | */ | ||||
void setErrorIndicatorElementVisible(boolean visible); | void setErrorIndicatorElementVisible(boolean visible); | ||||
} | } |
private final JavaScriptConnectorHelper helper = new JavaScriptConnectorHelper( | private final JavaScriptConnectorHelper helper = new JavaScriptConnectorHelper( | ||||
this) { | this) { | ||||
@Override | @Override | ||||
protected void showInitProblem( | |||||
List<String> attemptedNames) { | |||||
protected void showInitProblem(List<String> attemptedNames) { | |||||
getWidget().showNoInitFound(attemptedNames); | getWidget().showNoInitFound(attemptedNames); | ||||
} | } | ||||
}; | }; |
private static TouchScrollDelegate activeScrollDelegate; | private static TouchScrollDelegate activeScrollDelegate; | ||||
private static final boolean ANDROID_WITH_BROKEN_SCROLL_TOP = BrowserInfo.get() | |||||
.isAndroidWithBrokenScrollTop(); | |||||
private static final boolean ANDROID_WITH_BROKEN_SCROLL_TOP = BrowserInfo | |||||
.get().isAndroidWithBrokenScrollTop(); | |||||
/** | /** | ||||
* A helper class for making a widget scrollable. Uses native scrolling if | * A helper class for making a widget scrollable. Uses native scrolling if | ||||
finalScrollTop = finalY; | finalScrollTop = finalY; | ||||
if (Math.abs(pixelsToMove) < 3 || duration < 20) { | if (Math.abs(pixelsToMove) < 3 || duration < 20) { | ||||
getLogger().info("Small 'momentum' " + pixelsToMove + " | " + duration | |||||
+ " Skipping animation,"); | |||||
getLogger().info("Small 'momentum' " + pixelsToMove + " | " | |||||
+ duration + " Skipping animation,"); | |||||
moveTransformationToScrolloffset(); | moveTransformationToScrolloffset(); | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
break; | break; | ||||
default: | default: | ||||
getLogger().info("Non touch event:" + event.getNativeEvent().getType()); | |||||
getLogger().info( | |||||
"Non touch event:" + event.getNativeEvent().getType()); | |||||
event.cancel(); | event.cancel(); | ||||
break; | break; | ||||
} | } |
} | } | ||||
String dateStrResolution = dateStrResolution(date, minResolution); | String dateStrResolution = dateStrResolution(date, minResolution); | ||||
return rangeStart.substring(0,dateStrResolution.length()) | |||||
.compareTo(dateStrResolution) <=0; | |||||
return rangeStart.substring(0, dateStrResolution.length()) | |||||
.compareTo(dateStrResolution) <= 0; | |||||
} | } | ||||
private String dateStrResolution(Date date, R minResolution) { | private String dateStrResolution(Date date, R minResolution) { | ||||
} | } | ||||
String dateStrResolution = dateStrResolution(date, minResolution); | String dateStrResolution = dateStrResolution(date, minResolution); | ||||
return rangeEnd.substring(0,dateStrResolution.length()) | |||||
return rangeEnd.substring(0, dateStrResolution.length()) | |||||
.compareTo(dateStrResolution) >= 0; | .compareTo(dateStrResolution) >= 0; | ||||
} | } | ||||
// Set assistive label to read focused date and month/year | // Set assistive label to read focused date and month/year | ||||
Roles.getButtonRole().set(day.getElement()); | Roles.getButtonRole().set(day.getElement()); | ||||
Roles.getButtonRole() | |||||
.setAriaLabelledbyProperty(day.getElement(), | |||||
Id.of(day.getElement()), | |||||
Id.of(getFlexCellFormatter().getElement(0, 2))); | |||||
Roles.getButtonRole().setAriaLabelledbyProperty( | |||||
day.getElement(), Id.of(day.getElement()), | |||||
Id.of(getFlexCellFormatter().getElement(0, 2))); | |||||
day.setStyleName(getDateField().getStylePrimaryName() | day.setStyleName(getDateField().getStylePrimaryName() | ||||
+ "-calendarpanel-day"); | + "-calendarpanel-day"); | ||||
day.addStyleDependentName(CN_FOCUSED); | day.addStyleDependentName(CN_FOCUSED); | ||||
// Reference focused day from calendar panel | // Reference focused day from calendar panel | ||||
Roles.getGridRole() | |||||
.setAriaActivedescendantProperty(getElement(), | |||||
Id.of(day.getElement())); | |||||
Roles.getGridRole().setAriaActivedescendantProperty( | |||||
getElement(), Id.of(day.getElement())); | |||||
} | } | ||||
} | } | ||||
if (curr.getMonth() != displayedMonth.getMonth()) { | if (curr.getMonth() != displayedMonth.getMonth()) { | ||||
* @param date | * @param date | ||||
*/ | */ | ||||
private Date adjustDateToFitInsideRange(Date date) { | private Date adjustDateToFitInsideRange(Date date) { | ||||
if(!isAcceptedByRangeStart(date,resolution)) { | |||||
if (!isAcceptedByRangeStart(date, resolution)) { | |||||
date = parseRangeString(rangeStart); | date = parseRangeString(rangeStart); | ||||
} else | |||||
if(!isAcceptedByRangeEnd(date,resolution)) { | |||||
} else if (!isAcceptedByRangeEnd(date, resolution)) { | |||||
date = parseRangeString(rangeEnd); | date = parseRangeString(rangeEnd); | ||||
} | } | ||||
return date; | return date; | ||||
} | } | ||||
private Date parseRangeString(String dateStr) { | private Date parseRangeString(String dateStr) { | ||||
if(dateStr == null || "".equals(dateStr)) return null; | |||||
int year = Integer.parseInt(dateStr.substring(0,4)) - 1900; | |||||
int month = parsePart(dateStr, 5, 2,1) - 1; | |||||
int day = parsePart(dateStr, 8, 2,1); | |||||
int hrs = parsePart(dateStr, 11, 2,0); | |||||
int min = parsePart(dateStr, 14, 2,0); | |||||
int sec = parsePart(dateStr, 17, 2,0); | |||||
if (dateStr == null || "".equals(dateStr)) | |||||
return null; | |||||
int year = Integer.parseInt(dateStr.substring(0, 4)) - 1900; | |||||
int month = parsePart(dateStr, 5, 2, 1) - 1; | |||||
int day = parsePart(dateStr, 8, 2, 1); | |||||
int hrs = parsePart(dateStr, 11, 2, 0); | |||||
int min = parsePart(dateStr, 14, 2, 0); | |||||
int sec = parsePart(dateStr, 17, 2, 0); | |||||
return new Date(year,month,day,hrs,min,sec); | |||||
return new Date(year, month, day, hrs, min, sec); | |||||
} | } | ||||
private int parsePart(String dateStr, int beginIndex, int length, int defValue) { | |||||
if(dateStr.length() < beginIndex + length) return defValue; | |||||
return Integer.parseInt(dateStr.substring(beginIndex, beginIndex + length)); | |||||
private int parsePart(String dateStr, int beginIndex, int length, | |||||
int defValue) { | |||||
if (dateStr.length() < beginIndex + length) | |||||
return defValue; | |||||
return Integer | |||||
.parseInt(dateStr.substring(beginIndex, beginIndex + length)); | |||||
} | } | ||||
/** | /** | ||||
* Set assistive label for the previous year element. | * Set assistive label for the previous year element. | ||||
* | * | ||||
* @param label | * @param label | ||||
* the label to set | |||||
* the label to set | |||||
* @since 8.4 | * @since 8.4 | ||||
*/ | */ | ||||
public void setAssistiveLabelPreviousYear(String label) { | public void setAssistiveLabelPreviousYear(String label) { | ||||
* Set assistive label for the next year element. | * Set assistive label for the next year element. | ||||
* | * | ||||
* @param label | * @param label | ||||
* the label to set | |||||
* the label to set | |||||
* @since 8.4 | * @since 8.4 | ||||
*/ | */ | ||||
public void setAssistiveLabelNextYear(String label) { | public void setAssistiveLabelNextYear(String label) { | ||||
* Set assistive label for the previous month element. | * Set assistive label for the previous month element. | ||||
* | * | ||||
* @param label | * @param label | ||||
* the label to set | |||||
* the label to set | |||||
* @since 8.4 | * @since 8.4 | ||||
*/ | */ | ||||
public void setAssistiveLabelPreviousMonth(String label) { | public void setAssistiveLabelPreviousMonth(String label) { | ||||
* Set assistive label for the next month element. | * Set assistive label for the next month element. | ||||
* | * | ||||
* @param label | * @param label | ||||
* the label to set | |||||
* the label to set | |||||
* @since 8.4 | * @since 8.4 | ||||
*/ | */ | ||||
public void setAssistiveLabelNextMonth(String label) { | public void setAssistiveLabelNextMonth(String label) { |
*/ | */ | ||||
public abstract class VAbstractTextualDate<R extends Enum<R>> | public abstract class VAbstractTextualDate<R extends Enum<R>> | ||||
extends VDateField<R> | extends VDateField<R> | ||||
implements ChangeHandler, Focusable, | |||||
SubPartAware, HandlesAriaCaption, HandlesAriaInvalid, | |||||
HandlesAriaRequired, KeyDownHandler { | |||||
implements ChangeHandler, Focusable, SubPartAware, HandlesAriaCaption, | |||||
HandlesAriaInvalid, HandlesAriaRequired, KeyDownHandler { | |||||
private static final String PARSE_ERROR_CLASSNAME = "-parseerror"; | private static final String PARSE_ERROR_CLASSNAME = "-parseerror"; | ||||
private static final String ISO_DATE_TIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss"; | private static final String ISO_DATE_TIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss"; | ||||
super(resoluton); | super(resoluton); | ||||
text = new TextBox(); | text = new TextBox(); | ||||
text.addChangeHandler(this); | text.addChangeHandler(this); | ||||
text.addFocusHandler( | |||||
event -> fireBlurFocusEvent(event, true)); | |||||
text.addBlurHandler( | |||||
event -> fireBlurFocusEvent(event, false)); | |||||
text.addFocusHandler(event -> fireBlurFocusEvent(event, true)); | |||||
text.addBlurHandler(event -> fireBlurFocusEvent(event, false)); | |||||
if (BrowserInfo.get().isIE()) { | if (BrowserInfo.get().isIE()) { | ||||
addDomHandler(this, KeyDownEvent.getType()); | addDomHandler(this, KeyDownEvent.getType()); | ||||
} | } | ||||
* | * | ||||
* @since 8.2 | * @since 8.2 | ||||
* @deprecated Use {@link #updateBufferedResolutions()} and | * @deprecated Use {@link #updateBufferedResolutions()} and | ||||
* {@link #sendBufferedValues()} instead. | |||||
* {@link #sendBufferedValues()} instead. | |||||
*/ | */ | ||||
@Deprecated | @Deprecated | ||||
protected final void updateAndSendBufferedValues() { | protected final void updateAndSendBufferedValues() { | ||||
} | } | ||||
} | } | ||||
private void fireBlurFocusEvent(DomEvent<?> event, | |||||
boolean focus) { | |||||
private void fireBlurFocusEvent(DomEvent<?> event, boolean focus) { | |||||
String styleName = VTextField.CLASSNAME + "-" | String styleName = VTextField.CLASSNAME + "-" | ||||
+ VTextField.CLASSNAME_FOCUS; | + VTextField.CLASSNAME_FOCUS; | ||||
if (focus) { | if (focus) { |
return $entry(function(e) { | return $entry(function(e) { | ||||
var deltaX = e.deltaX ? e.deltaX : -0.5*e.wheelDeltaX; | var deltaX = e.deltaX ? e.deltaX : -0.5*e.wheelDeltaX; | ||||
var deltaY = e.deltaY ? e.deltaY : -0.5*e.wheelDeltaY; | var deltaY = e.deltaY ? e.deltaY : -0.5*e.wheelDeltaY; | ||||
// IE8 has only delta y | // IE8 has only delta y | ||||
if (isNaN(deltaY)) { | if (isNaN(deltaY)) { | ||||
deltaY = -0.5*e.wheelDelta; | deltaY = -0.5*e.wheelDelta; | ||||
} | } | ||||
@com.vaadin.client.ui.VComboBox.JsniUtil::moveScrollFromEvent(*)(widget, deltaX, deltaY, e, e.deltaMode); | @com.vaadin.client.ui.VComboBox.JsniUtil::moveScrollFromEvent(*)(widget, deltaX, deltaY, e, e.deltaMode); | ||||
}); | }); | ||||
}-*/; | }-*/; |
*/ | */ | ||||
public void sendBufferedValues() { | public void sendBufferedValues() { | ||||
rpc.update(bufferedDateString, | rpc.update(bufferedDateString, | ||||
bufferedResolutions.entrySet().stream().collect(Collectors | |||||
.toMap(entry -> entry.getKey().name(), | |||||
bufferedResolutions.entrySet().stream().collect( | |||||
Collectors.toMap(entry -> entry.getKey().name(), | |||||
entry -> entry.getValue()))); | entry -> entry.getValue()))); | ||||
bufferedDateString = null; | bufferedDateString = null; | ||||
bufferedResolutions.clear(); | bufferedResolutions.clear(); |
if (event.isFile(i)) { | if (event.isFile(i)) { | ||||
final int fileId = filecounter++; | final int fileId = filecounter++; | ||||
final VHtml5File file = event.getFile(i); | final VHtml5File file = event.getFile(i); | ||||
getLogger().info("Preparing to upload file " + file.getName() | |||||
+ " with id " + fileId + ", size=" | |||||
getLogger().info("Preparing to upload file " | |||||
+ file.getName() + " with id " + fileId + ", size=" | |||||
+ file.getSize()); | + file.getSize()); | ||||
transferable.setData("fi" + fileIndex, "" + fileId); | transferable.setData("fi" + fileIndex, "" + fileId); | ||||
transferable.setData("fn" + fileIndex, file.getName()); | transferable.setData("fn" + fileIndex, file.getName()); |
import com.vaadin.client.WidgetUtil.ErrorUtil; | import com.vaadin.client.WidgetUtil.ErrorUtil; | ||||
import com.vaadin.shared.ui.BorderStyle; | import com.vaadin.shared.ui.BorderStyle; | ||||
public class VLink extends HTML implements ClickHandler, HasEnabled, | |||||
HasErrorIndicatorElement { | |||||
public class VLink extends HTML | |||||
implements ClickHandler, HasEnabled, HasErrorIndicatorElement { | |||||
public static final String CLASSNAME = "v-link"; | public static final String CLASSNAME = "v-link"; | ||||
import com.vaadin.shared.ui.ContentMode; | import com.vaadin.shared.ui.ContentMode; | ||||
import com.vaadin.shared.ui.menubar.MenuBarConstants; | import com.vaadin.shared.ui.menubar.MenuBarConstants; | ||||
public class VMenuBar extends FocusableFlowPanel | |||||
implements CloseHandler<PopupPanel>, KeyPressHandler, KeyDownHandler, | |||||
FocusHandler, SubPartAware, MouseOutHandler, MouseOverHandler, EventTrigger { | |||||
public class VMenuBar extends FocusableFlowPanel implements | |||||
CloseHandler<PopupPanel>, KeyPressHandler, KeyDownHandler, FocusHandler, | |||||
SubPartAware, MouseOutHandler, MouseOverHandler, EventTrigger { | |||||
// The hierarchy of VMenuBar is a bit weird as VMenuBar is the Paintable, | // The hierarchy of VMenuBar is a bit weird as VMenuBar is the Paintable, | ||||
// used for the root menu but also used for the sub menus. | // used for the root menu but also used for the sub menus. | ||||
* | * | ||||
*/ | */ | ||||
public static class CustomMenuItem extends Widget | public static class CustomMenuItem extends Widget | ||||
implements HasHTML, SubPartAware { | |||||
implements HasHTML, SubPartAware { | |||||
protected String html = null; | protected String html = null; | ||||
protected Command command = null; | protected Command command = null; | ||||
"The 'partInformation' parameter must contain the menu item id"); | "The 'partInformation' parameter must contain the menu item id"); | ||||
} | } | ||||
getTriggers().computeIfAbsent(partInformation, s-> new ArrayList<>()).add(command); | |||||
getTriggers().computeIfAbsent(partInformation, s -> new ArrayList<>()) | |||||
.add(command); | |||||
return () -> { | return () -> { | ||||
List<Command> commands = getTriggers().get(partInformation); | List<Command> commands = getTriggers().get(partInformation); | ||||
if (commands != null) { | if (commands != null) { |
import com.vaadin.shared.MouseEventDetails; | import com.vaadin.shared.MouseEventDetails; | ||||
import com.vaadin.shared.ui.button.ButtonServerRpc; | import com.vaadin.shared.ui.button.ButtonServerRpc; | ||||
public class VNativeButton extends Button implements ClickHandler, | |||||
HasErrorIndicatorElement { | |||||
public class VNativeButton extends Button | |||||
implements ClickHandler, HasErrorIndicatorElement { | |||||
public static final String CLASSNAME = "v-nativebutton"; | public static final String CLASSNAME = "v-nativebutton"; | ||||
if (visible) { | if (visible) { | ||||
if (errorIndicatorElement == null) { | if (errorIndicatorElement == null) { | ||||
errorIndicatorElement = ErrorUtil.createErrorIndicatorElement(); | errorIndicatorElement = ErrorUtil.createErrorIndicatorElement(); | ||||
getElement() | |||||
.insertBefore(errorIndicatorElement, captionElement); | |||||
getElement().insertBefore(errorIndicatorElement, | |||||
captionElement); | |||||
} | } | ||||
} else if (errorIndicatorElement != null) { | } else if (errorIndicatorElement != null) { | ||||
getElement().removeChild(errorIndicatorElement); | getElement().removeChild(errorIndicatorElement); |
// in some browsers) | // in some browsers) | ||||
if (getStyleName() | if (getStyleName() | ||||
.contains(VOverlay.ADDITIONAL_CLASSNAME_ANIMATE_IN)) { | .contains(VOverlay.ADDITIONAL_CLASSNAME_ANIMATE_IN)) { | ||||
AnimationUtil.addAnimationEndListener(getElement(), | |||||
event -> { | |||||
if (AnimationUtil.getAnimationName(event).contains( | |||||
VOverlay.ADDITIONAL_CLASSNAME_ANIMATE_IN)) { | |||||
VNotification.this.hide(); | |||||
} | |||||
}); | |||||
AnimationUtil.addAnimationEndListener(getElement(), event -> { | |||||
if (AnimationUtil.getAnimationName(event).contains( | |||||
VOverlay.ADDITIONAL_CLASSNAME_ANIMATE_IN)) { | |||||
VNotification.this.hide(); | |||||
} | |||||
}); | |||||
} else { | } else { | ||||
VNotification.super.hide(); | VNotification.super.hide(); | ||||
fireEvent(new HideEvent(this)); | fireEvent(new HideEvent(this)); | ||||
* @param description | * @param description | ||||
* The Notification description, can be {@code null}. | * The Notification description, can be {@code null}. | ||||
* @param htmlContentAllowed | * @param htmlContentAllowed | ||||
* Whether {@code caption} and {@code description} | |||||
* are interpreted as HTML or not. | |||||
* Whether {@code caption} and {@code description} are | |||||
* interpreted as HTML or not. | |||||
* @param iconUri | * @param iconUri | ||||
* The icon URI, can be {@code null}. | * The icon URI, can be {@code null}. | ||||
* @param styleName | * @param styleName | ||||
*/ | */ | ||||
public static VNotification showNotification(ApplicationConnection client, | public static VNotification showNotification(ApplicationConnection client, | ||||
String caption, String description, boolean htmlContentAllowed, | String caption, String description, boolean htmlContentAllowed, | ||||
String iconUri, String styleName, Position position, int delayMsec) { | |||||
String iconUri, String styleName, Position position, | |||||
int delayMsec) { | |||||
String html = ""; | String html = ""; | ||||
if (iconUri != null) { | if (iconUri != null) { | ||||
html += client.getIcon(iconUri).getElement().getString(); | html += client.getIcon(iconUri).getElement().getString(); |
// directly attached to the RootPanel. | // directly attached to the RootPanel. | ||||
addDomHandler(event -> { | addDomHandler(event -> { | ||||
if (shortcutActionHandler != null) { | if (shortcutActionHandler != null) { | ||||
shortcutActionHandler | |||||
.handleKeyboardEvent( | |||||
Event.as(event.getNativeEvent())); | |||||
shortcutActionHandler.handleKeyboardEvent( | |||||
Event.as(event.getNativeEvent())); | |||||
} | } | ||||
}, KeyDownEvent.getType()); | }, KeyDownEvent.getType()); | ||||
} | } |
* @author Vaadin Ltd. | * @author Vaadin Ltd. | ||||
* | * | ||||
*/ | */ | ||||
public class VTextArea extends VTextField | |||||
implements DragImageModifier { | |||||
public class VTextArea extends VTextField implements DragImageModifier { | |||||
public static final String CLASSNAME = "v-textarea"; | public static final String CLASSNAME = "v-textarea"; | ||||
private void moveSelectedItemsLeftToRight() { | private void moveSelectedItemsLeftToRight() { | ||||
Set<String> movedItems = moveSelectedItems(optionsListBox, | Set<String> movedItems = moveSelectedItems(optionsListBox, | ||||
selectionsListBox); | selectionsListBox); | ||||
selectionChangeListeners | |||||
.forEach(listener -> listener.accept(movedItems, | |||||
Collections.emptySet())); | |||||
selectionChangeListeners.forEach(listener -> listener.accept(movedItems, | |||||
Collections.emptySet())); | |||||
} | } | ||||
private void moveSelectedItemsRightToLeft() { | private void moveSelectedItemsRightToLeft() { | ||||
Set<String> movedItems = moveSelectedItems(selectionsListBox, | Set<String> movedItems = moveSelectedItems(selectionsListBox, | ||||
optionsListBox); | optionsListBox); | ||||
selectionChangeListeners | |||||
.forEach(listener -> listener.accept(Collections.emptySet(), | |||||
movedItems)); | |||||
selectionChangeListeners.forEach(listener -> listener | |||||
.accept(Collections.emptySet(), movedItems)); | |||||
} | } | ||||
private static Set<String> moveSelectedItems(ListBox source, | private static Set<String> moveSelectedItems(ListBox source, |
/** For internal use only. May be removed or replaced in the future. */ | /** For internal use only. May be removed or replaced in the future. */ | ||||
public void submit() { | public void submit() { | ||||
if (submitted || !enabled) { | if (submitted || !enabled) { | ||||
getLogger().info("Submit cancelled (disabled or already submitted)"); | |||||
getLogger() | |||||
.info("Submit cancelled (disabled or already submitted)"); | |||||
return; | return; | ||||
} | } | ||||
if (fu.getFilename().isEmpty()) { | if (fu.getFilename().isEmpty()) { |
* @param element | * @param element | ||||
* Element to move out of sight | * Element to move out of sight | ||||
* @param assistiveOnly | * @param assistiveOnly | ||||
* {@code true} when element should only be visible for | |||||
* assistive devices, {@code false} to make the element visible for all | |||||
* {@code true} when element should only be visible for assistive | |||||
* devices, {@code false} to make the element visible for all | |||||
*/ | */ | ||||
public static void setVisibleForAssistiveDevicesOnly(Element element, | public static void setVisibleForAssistiveDevicesOnly(Element element, | ||||
boolean assistiveOnly) { | boolean assistiveOnly) { |
* updates these labels. | * updates these labels. | ||||
* | * | ||||
* @param calendar | * @param calendar | ||||
* the calendar panel for which to set the assistive labels | |||||
* the calendar panel for which to set the assistive labels | |||||
* @since 8.4 | * @since 8.4 | ||||
*/ | */ | ||||
protected void setAndUpdateAssistiveLabels( | protected void setAndUpdateAssistiveLabels( | ||||
VAbstractCalendarPanel calendar) { | VAbstractCalendarPanel calendar) { | ||||
calendar.setAssistiveLabelPreviousMonth( | |||||
getState().assistiveLabels.get(AccessibleElement.PREVIOUS_MONTH)); | |||||
calendar.setAssistiveLabelPreviousMonth(getState().assistiveLabels | |||||
.get(AccessibleElement.PREVIOUS_MONTH)); | |||||
calendar.setAssistiveLabelNextMonth( | calendar.setAssistiveLabelNextMonth( | ||||
getState().assistiveLabels.get(AccessibleElement.NEXT_MONTH)); | getState().assistiveLabels.get(AccessibleElement.NEXT_MONTH)); | ||||
calendar.setAssistiveLabelPreviousYear( | |||||
getState().assistiveLabels.get(AccessibleElement.PREVIOUS_YEAR)); | |||||
calendar.setAssistiveLabelPreviousYear(getState().assistiveLabels | |||||
.get(AccessibleElement.PREVIOUS_YEAR)); | |||||
calendar.setAssistiveLabelNextYear( | calendar.setAssistiveLabelNextYear( | ||||
getState().assistiveLabels.get(AccessibleElement.NEXT_YEAR)); | getState().assistiveLabels.get(AccessibleElement.NEXT_YEAR)); | ||||
protected void updateListeners() { | protected void updateListeners() { | ||||
VAbstractDateFieldCalendar<PANEL, R> widget = getWidget(); | VAbstractDateFieldCalendar<PANEL, R> widget = getWidget(); | ||||
if (isResolutionMonthOrHigher()) { | if (isResolutionMonthOrHigher()) { | ||||
widget.calendarPanel | |||||
.setFocusChangeListener(date -> { | |||||
Date date2 = new Date(); | |||||
if (widget.calendarPanel.getDate() != null) { | |||||
date2.setTime(widget.calendarPanel.getDate() | |||||
.getTime()); | |||||
} | |||||
/* | |||||
* Update the value of calendarPanel | |||||
*/ | |||||
date2.setYear(date.getYear()); | |||||
date2.setMonth(date.getMonth()); | |||||
widget.calendarPanel.setDate(date2); | |||||
/* | |||||
* Then update the value from panel to server | |||||
*/ | |||||
widget.updateValueFromPanel(); | |||||
}); | |||||
widget.calendarPanel.setFocusChangeListener(date -> { | |||||
Date date2 = new Date(); | |||||
if (widget.calendarPanel.getDate() != null) { | |||||
date2.setTime(widget.calendarPanel.getDate().getTime()); | |||||
} | |||||
/* | |||||
* Update the value of calendarPanel | |||||
*/ | |||||
date2.setYear(date.getYear()); | |||||
date2.setMonth(date.getMonth()); | |||||
widget.calendarPanel.setDate(date2); | |||||
/* | |||||
* Then update the value from panel to server | |||||
*/ | |||||
widget.updateValueFromPanel(); | |||||
}); | |||||
} else { | } else { | ||||
widget.calendarPanel.setFocusChangeListener(null); | widget.calendarPanel.setFocusChangeListener(null); | ||||
} | } | ||||
*/ | */ | ||||
protected abstract boolean isResolutionMonthOrHigher(); | protected abstract boolean isResolutionMonthOrHigher(); | ||||
} | |||||
} |
VPopupTimeCalendar widget = getWidget(); | VPopupTimeCalendar widget = getWidget(); | ||||
if (widget.getCurrentResolution() | if (widget.getCurrentResolution() | ||||
.compareTo(DateTimeResolution.DAY) < 0) { | .compareTo(DateTimeResolution.DAY) < 0) { | ||||
widget.calendar | |||||
.setTimeChangeListener((hour, min, sec, msec) -> { | |||||
Date d = widget.getDate(); | |||||
if (d == null) { | |||||
// date currently null, use the value from | |||||
// calendarPanel | |||||
// (~ client time at the init of the widget) | |||||
d = (Date) widget.calendar.getDate().clone(); | |||||
} | |||||
d.setHours(hour); | |||||
d.setMinutes(min); | |||||
d.setSeconds(sec); | |||||
DateTimeService.setMilliseconds(d, msec); | |||||
widget.calendar.setTimeChangeListener((hour, min, sec, msec) -> { | |||||
Date d = widget.getDate(); | |||||
if (d == null) { | |||||
// date currently null, use the value from | |||||
// calendarPanel | |||||
// (~ client time at the init of the widget) | |||||
d = (Date) widget.calendar.getDate().clone(); | |||||
} | |||||
d.setHours(hour); | |||||
d.setMinutes(min); | |||||
d.setSeconds(sec); | |||||
DateTimeService.setMilliseconds(d, msec); | |||||
// Always update time changes to the server | |||||
widget.updateValue(d); | |||||
// Always update time changes to the server | |||||
widget.updateValue(d); | |||||
// Update text field | |||||
widget.buildDate(); | |||||
}); | |||||
// Update text field | |||||
widget.buildDate(); | |||||
}); | |||||
} | } | ||||
} | } | ||||
} | |||||
} |
protected boolean accept(VDragEvent drag, UIDL configuration) { | protected boolean accept(VDragEvent drag, UIDL configuration) { | ||||
String name = configuration.getStringAttribute("p"); | String name = configuration.getStringAttribute("p"); | ||||
String t = configuration.hasAttribute("t") | String t = configuration.hasAttribute("t") | ||||
? configuration.getStringAttribute("t").intern() : "s"; | |||||
? configuration.getStringAttribute("t").intern() | |||||
: "s"; | |||||
Object value = null; | Object value = null; | ||||
if (t == "s") { | if (t == "s") { | ||||
value = configuration.getStringAttribute("v"); | value = configuration.getStringAttribute("v"); |
} | } | ||||
} else { | } else { | ||||
if (widget.fileIdToReceiver.containsKey(fileId) | if (widget.fileIdToReceiver.containsKey(fileId) | ||||
&& receiverUrl != null | |||||
&& !receiverUrl | |||||
.equals(widget.fileIdToReceiver | |||||
.get(fileId))) { | |||||
&& receiverUrl != null && !receiverUrl.equals( | |||||
widget.fileIdToReceiver.get(fileId))) { | |||||
getLogger().severe( | getLogger().severe( | ||||
"Overwriting file receiver mapping for fileId " | "Overwriting file receiver mapping for fileId " | ||||
+ fileId + " . Old receiver URL: " | + fileId + " . Old receiver URL: " |
setResourceUrl(getResourceUrl("src")); | setResourceUrl(getResourceUrl("src")); | ||||
clearBrowserElement = false; | clearBrowserElement = false; | ||||
} else { | } else { | ||||
getLogger().severe( | |||||
"Unknown Embedded type '" + widget.type + "'"); | |||||
getLogger() | |||||
.severe("Unknown Embedded type '" + widget.type + "'"); | |||||
} | } | ||||
} else if (state.mimeType != null) { | } else if (state.mimeType != null) { | ||||
// remove old style name related to type | // remove old style name related to type | ||||
widget.mimetype = "flash"; | widget.mimetype = "flash"; | ||||
// Handle embedding of Flash | // Handle embedding of Flash | ||||
widget.addStyleName(VEmbedded.CLASSNAME + "-flash"); | widget.addStyleName(VEmbedded.CLASSNAME + "-flash"); | ||||
widget.setHTML(widget.createFlashEmbed(state, | |||||
getResourceUrl("src"))); | |||||
widget.setHTML( | |||||
widget.createFlashEmbed(state, getResourceUrl("src"))); | |||||
} else if (mime.equals("image/svg+xml")) { | } else if (mime.equals("image/svg+xml")) { | ||||
widget.mimetype = "svg"; | widget.mimetype = "svg"; | ||||
getLogger().severe("Unknown Embedded mimetype '" + mime + "'"); | getLogger().severe("Unknown Embedded mimetype '" + mime + "'"); | ||||
} | } | ||||
} else { | } else { | ||||
getLogger().severe("Unknown Embedded; no type or mimetype attribute"); | |||||
getLogger() | |||||
.severe("Unknown Embedded; no type or mimetype attribute"); | |||||
} | } | ||||
if (clearBrowserElement) { | if (clearBrowserElement) { |
protected int getCaptionHeight() { | protected int getCaptionHeight() { | ||||
VCaption caption = getCaption(); | VCaption caption = getCaption(); | ||||
return caption != null | return caption != null | ||||
? getLayoutManager().getOuterHeight(caption.getElement()) : 0; | |||||
? getLayoutManager().getOuterHeight(caption.getElement()) | |||||
: 0; | |||||
} | } | ||||
@Override | @Override | ||||
protected int getCaptionWidth() { | protected int getCaptionWidth() { | ||||
VCaption caption = getCaption(); | VCaption caption = getCaption(); | ||||
return caption != null | return caption != null | ||||
? getLayoutManager().getOuterWidth(caption.getElement()) : 0; | |||||
? getLayoutManager().getOuterWidth(caption.getElement()) | |||||
: 0; | |||||
} | } | ||||
public LayoutManager getLayoutManager() { | public LayoutManager getLayoutManager() { |
int captionHeight; | int captionHeight; | ||||
VCaption caption = getCaption(); | VCaption caption = getCaption(); | ||||
Style captionStyle = caption == null ? null : caption.getElement().getStyle(); | |||||
Style captionStyle = caption == null ? null | |||||
: caption.getElement().getStyle(); | |||||
if (caption == null || caption.shouldBePlacedAfterComponent()) { | if (caption == null || caption.shouldBePlacedAfterComponent()) { | ||||
style.clearPaddingTop(); | style.clearPaddingTop(); | ||||
captionHeight = 0; | captionHeight = 0; |
if (widgetEnabled) { | if (widgetEnabled) { | ||||
getWidget().getListBox().getElement().removeAttribute("disabled"); | getWidget().getListBox().getElement().removeAttribute("disabled"); | ||||
} else { | } else { | ||||
getWidget().getListBox().getElement() | |||||
.setAttribute("disabled", "disabled"); | |||||
getWidget().getListBox().getElement().setAttribute("disabled", | |||||
"disabled"); | |||||
} | } | ||||
} | } | ||||
} | } |
// Update slot style names | // Update slot style names | ||||
List<String> childStyles = child.getState().styles; | List<String> childStyles = child.getState().styles; | ||||
if (childStyles == null) { | if (childStyles == null) { | ||||
widget.setSlotStyleNames(child.getWidget(), | |||||
(String[]) null); | |||||
widget.setSlotStyleNames(child.getWidget(), (String[]) null); | |||||
} else { | } else { | ||||
widget.setSlotStyleNames(child.getWidget(), | widget.setSlotStyleNames(child.getWidget(), | ||||
childStyles.toArray(new String[childStyles.size()])); | childStyles.toArray(new String[childStyles.size()])); | ||||
if (needsFixedHeight()) { | if (needsFixedHeight()) { | ||||
// Add resize listener to ensure the widget itself is measured | // Add resize listener to ensure the widget itself is measured | ||||
getLayoutManager().addElementResizeListener( | |||||
widget.getElement(), childComponentResizeListener); | |||||
getLayoutManager().addElementResizeListener(widget.getElement(), | |||||
childComponentResizeListener); | |||||
} else { | } else { | ||||
getLayoutManager().removeElementResizeListener( | |||||
widget.getElement(), childComponentResizeListener); | |||||
getLayoutManager().removeElementResizeListener(widget.getElement(), | |||||
childComponentResizeListener); | |||||
} | } | ||||
// Then update listeners based on bookkeeping | // Then update listeners based on bookkeeping | ||||
// updateExpandedSizes causes fixed size components to temporarily | // updateExpandedSizes causes fixed size components to temporarily | ||||
// lose their size. updateExpandCompensation must be delayed until | // lose their size. updateExpandCompensation must be delayed until | ||||
// the browser has a chance to measure them. | // the browser has a chance to measure them. | ||||
Scheduler.get().scheduleFinally( | |||||
() -> widget.updateExpandCompensation()); | |||||
Scheduler.get() | |||||
.scheduleFinally(() -> widget.updateExpandCompensation()); | |||||
} else { | } else { | ||||
widget.clearExpand(); | widget.clearExpand(); | ||||
} | } | ||||
super.onUnregister(); | super.onUnregister(); | ||||
} | } | ||||
} | |||||
} |
// Restore default stylenames | // Restore default stylenames | ||||
panel.contentNode.setClassName(VPanel.CLASSNAME + "-content"); | panel.contentNode.setClassName(VPanel.CLASSNAME + "-content"); | ||||
panel.bottomDecoration | |||||
.setClassName(VPanel.CLASSNAME + "-deco"); | |||||
panel.bottomDecoration.setClassName(VPanel.CLASSNAME + "-deco"); | |||||
panel.captionNode.setClassName(VPanel.CLASSNAME + "-caption"); | panel.captionNode.setClassName(VPanel.CLASSNAME + "-caption"); | ||||
boolean hasCaption = hasCaption(); | boolean hasCaption = hasCaption(); | ||||
if (hasCaption) { | if (hasCaption) { | ||||
panel.setCaption(getState().caption); | panel.setCaption(getState().caption); | ||||
} else { | } else { | ||||
panel.setCaption(""); | panel.setCaption(""); | ||||
panel.captionNode | |||||
.setClassName(VPanel.CLASSNAME + "-nocaption"); | |||||
panel.captionNode.setClassName(VPanel.CLASSNAME + "-nocaption"); | |||||
} | } | ||||
// Add proper stylenames for all elements. This way we can prevent | // Add proper stylenames for all elements. This way we can prevent |
if (popup.captionWrapper != null) { | if (popup.captionWrapper != null) { | ||||
popup.captionWrapper.updateCaption(); | popup.captionWrapper.updateCaption(); | ||||
} else { | } else { | ||||
popup.captionWrapper = new VCaptionWrapper( | |||||
childConnector, getConnection()); | |||||
popup.captionWrapper = new VCaptionWrapper(childConnector, | |||||
getConnection()); | |||||
popup.setWidget(popup.captionWrapper); | popup.setWidget(popup.captionWrapper); | ||||
popup.captionWrapper.updateCaption(); | popup.captionWrapper.updateCaption(); | ||||
} | } | ||||
} else { | } else { | ||||
// The popup shouldn't be visible, try to hide it. | // The popup shouldn't be visible, try to hide it. | ||||
popup.hide(false,false,false); | |||||
popup.hide(false, false, false); | |||||
} | } | ||||
} | } | ||||
panel.maximumPosition = splitterState.maxPosition | panel.maximumPosition = splitterState.maxPosition | ||||
+ splitterState.maxPositionUnit; | + splitterState.maxPositionUnit; | ||||
panel.position = splitterState.position | |||||
+ splitterState.positionUnit; | |||||
panel.position = splitterState.position + splitterState.positionUnit; | |||||
panel.setPositionReversed(splitterState.positionReversed); | panel.setPositionReversed(splitterState.positionReversed); | ||||
// Widgets in the TabSheet before update | // Widgets in the TabSheet before update | ||||
List<Widget> oldWidgets = new ArrayList<>(); | List<Widget> oldWidgets = new ArrayList<>(); | ||||
for (Iterator<Widget> iterator = widget | |||||
.getWidgetIterator(); iterator.hasNext();) { | |||||
for (Iterator<Widget> iterator = widget.getWidgetIterator(); iterator | |||||
.hasNext();) { | |||||
oldWidgets.add(iterator.next()); | oldWidgets.add(iterator.next()); | ||||
} | } | ||||
@Override | @Override | ||||
public void selectRange(int start, int length) { | public void selectRange(int start, int length) { | ||||
int textLength = getAbstractTextField().getValue().length(); | int textLength = getAbstractTextField().getValue().length(); | ||||
//Enable setting cursor position after the last character | |||||
start = restrictTo(start, 0, length == 0 ? textLength : (textLength - 1)); | |||||
// Enable setting cursor position after the last character | |||||
start = restrictTo(start, 0, | |||||
length == 0 ? textLength : (textLength - 1)); | |||||
length = restrictTo(length, 0, textLength - start); | length = restrictTo(length, 0, textLength - start); | ||||
getAbstractTextField().setSelectionRange(start, length); | getAbstractTextField().setSelectionRange(start, length); | ||||
} | } |
} | } | ||||
private static boolean isCollapsed(JsonObject rowData) { | private static boolean isCollapsed(JsonObject rowData) { | ||||
assert rowData | |||||
.hasKey(HierarchicalDataCommunicatorConstants.ROW_HIERARCHY_DESCRIPTION) : "missing hierarchy data for row " | |||||
assert rowData.hasKey( | |||||
HierarchicalDataCommunicatorConstants.ROW_HIERARCHY_DESCRIPTION) : "missing hierarchy data for row " | |||||
+ rowData.asString(); | + rowData.asString(); | ||||
return rowData | |||||
.getObject( | |||||
HierarchicalDataCommunicatorConstants.ROW_HIERARCHY_DESCRIPTION) | |||||
return rowData.getObject( | |||||
HierarchicalDataCommunicatorConstants.ROW_HIERARCHY_DESCRIPTION) | |||||
.getBoolean( | .getBoolean( | ||||
HierarchicalDataCommunicatorConstants.ROW_COLLAPSED); | HierarchicalDataCommunicatorConstants.ROW_COLLAPSED); | ||||
} | } |
* Initialize UIConnector and attach UI to the rootPanelElement. | * Initialize UIConnector and attach UI to the rootPanelElement. | ||||
* | * | ||||
* @param rootPanelElement | * @param rootPanelElement | ||||
* element to attach ui into | |||||
* element to attach ui into | |||||
* @param applicationConnection | * @param applicationConnection | ||||
* application connection | |||||
* application connection | |||||
* @since 8.4 | * @since 8.4 | ||||
*/ | */ | ||||
public void init(Element rootPanelElement, | public void init(Element rootPanelElement, | ||||
ApplicationConnection applicationConnection) { | ApplicationConnection applicationConnection) { | ||||
Panel root = new AbsolutePanel(rootPanelElement) {{ | |||||
onAttach(); | |||||
}}; | |||||
Panel root = new AbsolutePanel(rootPanelElement) { | |||||
{ | |||||
onAttach(); | |||||
} | |||||
}; | |||||
initConnector(root, applicationConnection); | initConnector(root, applicationConnection); | ||||
} | } | ||||
* element. | * element. | ||||
* | * | ||||
* @param rootPanelId | * @param rootPanelId | ||||
* root panel element id | |||||
* root panel element id | |||||
* @param applicationConnection | * @param applicationConnection | ||||
* application connection | |||||
* application connection | |||||
*/ | */ | ||||
public void init(String rootPanelId, | public void init(String rootPanelId, | ||||
ApplicationConnection applicationConnection) { | ApplicationConnection applicationConnection) { | ||||
DOM.sinkEvents(ui.getElement(), Event.ONSCROLL); | DOM.sinkEvents(ui.getElement(), Event.ONSCROLL); | ||||
// Remove the v-app-loading or any splash screen added inside the div by | // Remove the v-app-loading or any splash screen added inside the div by | ||||
// the user | // the user | ||||
root.getElement().setInnerHTML(""); | root.getElement().setInnerHTML(""); |
upload.submitButton | upload.submitButton | ||||
.setText(uidl.getStringAttribute("buttoncaption")); | .setText(uidl.getStringAttribute("buttoncaption")); | ||||
if (uidl.hasAttribute("buttonstylename")) { | if (uidl.hasAttribute("buttonstylename")) { | ||||
upload.submitButton | |||||
.setStyleName(uidl.getStringAttribute("buttonstylename")); | |||||
upload.submitButton.setStyleName( | |||||
uidl.getStringAttribute("buttonstylename")); | |||||
} | } | ||||
upload.submitButton.setVisible(true); | upload.submitButton.setVisible(true); | ||||
} else { | } else { |
throws IllegalArgumentException; | throws IllegalArgumentException; | ||||
/** | /** | ||||
* Refreshes a range of columns in the current row containers in each Escalator | |||||
* section. | |||||
* Refreshes a range of columns in the current row containers in each | |||||
* Escalator section. | |||||
* <p> | * <p> | ||||
* The data for the refreshed columns is queried from the current cell | * The data for the refreshed columns is queried from the current cell | ||||
* renderer. | * renderer. |
* should the displayed data need to be fetched remotely. | * should the displayed data need to be fetched remotely. | ||||
* <p> | * <p> | ||||
* This has a similar function to {@link com.vaadin.client.widgets.Grid Grid's} | * This has a similar function to {@link com.vaadin.client.widgets.Grid Grid's} | ||||
* {@link com.vaadin.client.renderers.Renderer Renderers} | |||||
* , although they operate on different abstraction levels. | |||||
* {@link com.vaadin.client.renderers.Renderer Renderers} , although they | |||||
* operate on different abstraction levels. | |||||
* | * | ||||
* @since 7.4 | * @since 7.4 | ||||
* @author Vaadin Ltd | * @author Vaadin Ltd |
assert offset >= 0 && offset + numberOfCells <= cells | assert offset >= 0 && offset + numberOfCells <= cells | ||||
.size() : "Invalid range of cells"; | .size() : "Invalid range of cells"; | ||||
return () -> CellIterator | return () -> CellIterator | ||||
.attached( | |||||
cells.subList(offset, offset + numberOfCells)); | |||||
.attached(cells.subList(offset, offset + numberOfCells)); | |||||
} | } | ||||
/** | /** | ||||
assert offset >= 0 && offset + numberOfCells <= cells | assert offset >= 0 && offset + numberOfCells <= cells | ||||
.size() : "Invalid range of cells"; | .size() : "Invalid range of cells"; | ||||
return () -> CellIterator | return () -> CellIterator | ||||
.unattached( | |||||
cells.subList(offset, offset + numberOfCells)); | |||||
.unattached(cells.subList(offset, offset + numberOfCells)); | |||||
} | } | ||||
/** | /** |
* @author Vaadin Ltd | * @author Vaadin Ltd | ||||
* @since 8.3.2 | * @since 8.3.2 | ||||
*/ | */ | ||||
public class SpacerVisibilityChangedEvent extends GwtEvent<SpacerVisibilityChangedHandler> { | |||||
public class SpacerVisibilityChangedEvent | |||||
extends GwtEvent<SpacerVisibilityChangedHandler> { | |||||
/** | /** | ||||
* Handler type. | * Handler type. | ||||
* Creates a spacer visibility changed event. | * Creates a spacer visibility changed event. | ||||
* | * | ||||
* @param rowIndex | * @param rowIndex | ||||
* index of row to which the spacer belongs | |||||
* index of row to which the spacer belongs | |||||
* @param visible | * @param visible | ||||
* {@code true} if the spacer element is shown, {@code false} if the | |||||
* spacer element is hidden | |||||
* {@code true} if the spacer element is shown, {@code false} if | |||||
* the spacer element is hidden | |||||
*/ | */ | ||||
public SpacerVisibilityChangedEvent(int rowIndex, boolean visible) { | public SpacerVisibilityChangedEvent(int rowIndex, boolean visible) { | ||||
this.rowIndex = rowIndex; | this.rowIndex = rowIndex; | ||||
* Gets whether the spacer element is displayed. | * Gets whether the spacer element is displayed. | ||||
* | * | ||||
* @return {@code true} if the spacer element is shown, {@code false} if the | * @return {@code true} if the spacer element is shown, {@code false} if the | ||||
* spacer element is hidden | |||||
* spacer element is hidden | |||||
*/ | */ | ||||
public boolean isSpacerVisible() { | public boolean isSpacerVisible() { | ||||
return visible; | return visible; |
endBound = Math.max(finalEndBound, pageCordinate); | endBound = Math.max(finalEndBound, pageCordinate); | ||||
} else { | } else { | ||||
/* | /* | ||||
* Subsequent runs make sure that the scroll area grows (but doesn't | |||||
* shrink) with the finger, but no further than the final bound. | |||||
* Subsequent runs make sure that the scroll area grows (but | |||||
* doesn't shrink) with the finger, but no further than the | |||||
* final bound. | |||||
*/ | */ | ||||
int oldTopBound = startBound; | int oldTopBound = startBound; | ||||
if (startBound < finalStartBound) { | if (startBound < finalStartBound) { |
} | } | ||||
/** | /** | ||||
* Returns the range of available rows in {@link com.vaadin.client.data.DataSource DataSource} | |||||
* for this event. | |||||
* Returns the range of available rows in | |||||
* {@link com.vaadin.client.data.DataSource DataSource} for this event. | |||||
* | * | ||||
* @return range of available rows | * @return range of available rows | ||||
*/ | */ |
@Override | @Override | ||||
public void onKeyUp(KeyUpEvent event) { | public void onKeyUp(KeyUpEvent event) { | ||||
if (event.getNativeKeyCode() != KeyCodes.KEY_SPACE || !checkBox.isEnabled()) { | |||||
if (event.getNativeKeyCode() != KeyCodes.KEY_SPACE | |||||
|| !checkBox.isEnabled()) { | |||||
return; | return; | ||||
} | } | ||||
int logicalRow = getLogicalRowIndex(grid, checkBox.getElement()); | int logicalRow = getLogicalRowIndex(grid, checkBox.getElement()); | ||||
bottomBound = Math.max(finalBottomBound, pageY); | bottomBound = Math.max(finalBottomBound, pageY); | ||||
} else { | } else { | ||||
/* | /* | ||||
* Subsequent runs make sure that the scroll area grows (but doesn't | |||||
* shrink) with the finger, but no further than the final bound. | |||||
* Subsequent runs make sure that the scroll area grows (but | |||||
* doesn't shrink) with the finger, but no further than the | |||||
* final bound. | |||||
*/ | */ | ||||
int oldTopBound = topBound; | int oldTopBound = topBound; | ||||
if (topBound < finalTopBound) { | if (topBound < finalTopBound) { | ||||
checkBox.setEnabled(grid.isEnabled() && !grid.isEditorActive()); | checkBox.setEnabled(grid.isEnabled() && !grid.isEditorActive()); | ||||
} | } | ||||
private int getDOMRowIndex(RendererCellReference cell){ | |||||
private int getDOMRowIndex(RendererCellReference cell) { | |||||
// getRowIndex starts with zero, that's why we add an additional 1. | // getRowIndex starts with zero, that's why we add an additional 1. | ||||
// getDOMRowIndex should include getHeaderRows as well, this number | // getDOMRowIndex should include getHeaderRows as well, this number | ||||
// should be equals to aria-rowindex. | // should be equals to aria-rowindex. |
* Checks if the user is allowed to have more than on item selected. | * Checks if the user is allowed to have more than on item selected. | ||||
* <p> | * <p> | ||||
* | * | ||||
* @return <code>true</code> if the user is allowed to select multiple items, | |||||
* <code>false</code> otherwise | |||||
* @return <code>true</code> if the user is allowed to select multiple | |||||
* items, <code>false</code> otherwise | |||||
* @since 8.2 | * @since 8.2 | ||||
*/ | */ | ||||
boolean isMultiSelectionAllowed(); | boolean isMultiSelectionAllowed(); |
scrollHandler = null; | scrollHandler = null; | ||||
} | } | ||||
scrollHandler = grid | |||||
.addDataAvailableHandler(dataAvailableEvent -> { | |||||
if (dataAvailableEvent.getAvailableRows() | |||||
.contains(rowIndex)) { | |||||
setSelected(grid, rowIndex); | |||||
scrollHandler.removeHandler(); | |||||
scrollHandler = null; | |||||
} | |||||
}); | |||||
scrollHandler = grid.addDataAvailableHandler(dataAvailableEvent -> { | |||||
if (dataAvailableEvent.getAvailableRows().contains(rowIndex)) { | |||||
setSelected(grid, rowIndex); | |||||
scrollHandler.removeHandler(); | |||||
scrollHandler = null; | |||||
} | |||||
}); | |||||
grid.scrollToRow(rowIndex, ScrollDestination.ANY); | grid.scrollToRow(rowIndex, ScrollDestination.ANY); | ||||
} | } | ||||
* The following WAI-ARIA attributes are added through this class: | * The following WAI-ARIA attributes are added through this class: | ||||
* | * | ||||
* <ul> | * <ul> | ||||
* <li>aria-rowcount (since 8.2)</li> | |||||
* <li>roles provided by {@link AriaGridRole} (since 8.2)</li> | |||||
* <li>aria-rowcount (since 8.2)</li> | |||||
* <li>roles provided by {@link AriaGridRole} (since 8.2)</li> | |||||
* </ul> | * </ul> | ||||
* | * | ||||
* @since 8.2 | * @since 8.2 | ||||
/** | /** | ||||
* Sets the {@code role} attribute to the given element. | * Sets the {@code role} attribute to the given element. | ||||
* | * | ||||
* @param element element that should get the role attribute | |||||
* @param role role to be added | |||||
* @param element | |||||
* element that should get the role attribute | |||||
* @param role | |||||
* role to be added | |||||
* | * | ||||
* @since 8.2 | * @since 8.2 | ||||
*/ | */ | ||||
*/ | */ | ||||
public enum AriaGridRole { | public enum AriaGridRole { | ||||
ROW("row"), | |||||
ROWHEADER("rowheader"), | |||||
ROWGROUP("rowgroup"), | |||||
GRIDCELL("gridcell"), | |||||
COLUMNHEADER("columnheader"); | |||||
ROW("row"), ROWHEADER("rowheader"), ROWGROUP("rowgroup"), GRIDCELL( | |||||
"gridcell"), COLUMNHEADER("columnheader"); | |||||
private final String name; | private final String name; | ||||
AriaGridRole(String name) { | AriaGridRole(String name) { | ||||
this.name = name; | this.name = name; | ||||
} | } | ||||
/** | /** | ||||
* Gets the role attribute of an element to represent a cell in a row. | * Gets the role attribute of an element to represent a cell in a row. | ||||
* <p> | * <p> | ||||
* Usually {@link AriaGridRole#GRIDCELL} except for a cell in | |||||
* the header. | |||||
* Usually {@link AriaGridRole#GRIDCELL} except for a cell in the | |||||
* header. | |||||
* | * | ||||
* @return the role attribute for the element to represent cells | * @return the role attribute for the element to represent cells | ||||
* | * | ||||
/** | /** | ||||
* Gets the role attribute of an element to represent a row in a grid. | * Gets the role attribute of an element to represent a row in a grid. | ||||
* <p> | * <p> | ||||
* Usually {@link AriaGridRole#ROW} except for a row in | |||||
* the header. | |||||
* Usually {@link AriaGridRole#ROW} except for a row in the header. | |||||
* | * | ||||
* @return the role attribute for the element to represent rows | * @return the role attribute for the element to represent rows | ||||
* | * | ||||
.getColumnCount(); col++) { | .getColumnCount(); col++) { | ||||
final double colWidth = columnConfiguration | final double colWidth = columnConfiguration | ||||
.getColumnWidthActual(col); | .getColumnWidthActual(col); | ||||
final TableCellElement cellElem = createCellElement(colWidth); | |||||
final TableCellElement cellElem = createCellElement( | |||||
colWidth); | |||||
tr.appendChild(cellElem); | tr.appendChild(cellElem); | ||||
// Set stylename and position if new cell is frozen | // Set stylename and position if new cell is frozen | ||||
if (col < columnConfiguration.frozenColumns) { | if (col < columnConfiguration.frozenColumns) { |
/** | /** | ||||
* Returns whether Grid should handle events from Widgets in this | * Returns whether Grid should handle events from Widgets in this | ||||
* Column. | * Column. | ||||
* | |||||
* | |||||
* @return {@code true} to handle events from widgets; {@code false} to | * @return {@code true} to handle events from widgets; {@code false} to | ||||
* not | * not | ||||
* @since 8.3 | * @since 8.3 | ||||
/** | /** | ||||
* Helper method for making sure desired row is visible and it is properly | * Helper method for making sure desired row is visible and it is properly | ||||
* rendered. | * rendered. | ||||
* | |||||
* | |||||
* @param rowIndex | * @param rowIndex | ||||
* the row to look for | * the row to look for | ||||
* @param destination | * @param destination | ||||
/** | /** | ||||
* Helper method for making sure desired row is visible and it is properly | * Helper method for making sure desired row is visible and it is properly | ||||
* rendered. | * rendered. | ||||
* | |||||
* | |||||
* @param rowIndex | * @param rowIndex | ||||
* the row to look for | * the row to look for | ||||
* @param whenRendered | * @param whenRendered | ||||
/** | /** | ||||
* Helper method for scrolling and making sure row is visible. | * Helper method for scrolling and making sure row is visible. | ||||
* | |||||
* | |||||
* @param rowIndex | * @param rowIndex | ||||
* the row index to make visible | * the row index to make visible | ||||
* @param destination | * @param destination |
<?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||||
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.8.1//EN" "http://gwtproject.org/doctype/2.8.1/gwt-module.dtd"> | <!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.8.1//EN" "http://gwtproject.org/doctype/2.8.1/gwt-module.dtd"> | ||||
<module> | <module> | ||||
<!-- This GWT module defines the Vaadin DefaultWidgetSet. This is the module | |||||
you want to extend when creating an extended widget set, or when creating | |||||
<!-- This GWT module defines the Vaadin DefaultWidgetSet. This is the module | |||||
you want to extend when creating an extended widget set, or when creating | |||||
a specialized widget set with a subset of the components. --> | a specialized widget set with a subset of the components. --> | ||||
<!-- Hint for WidgetSetBuilder not to automatically update the file --> | <!-- Hint for WidgetSetBuilder not to automatically update the file --> | ||||
<when-type-is class="com.vaadin.client.widgets.Overlay" /> | <when-type-is class="com.vaadin.client.widgets.Overlay" /> | ||||
</replace-with> | </replace-with> | ||||
<!-- Since 7.2. Compile all permutations (browser support) into one Javascript | |||||
file. Speeds up compilation and does not make the Javascript significantly | |||||
<!-- Since 7.2. Compile all permutations (browser support) into one Javascript | |||||
file. Speeds up compilation and does not make the Javascript significantly | |||||
larger. --> | larger. --> | ||||
<collapse-all-properties /> | <collapse-all-properties /> | ||||
<?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||||
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.8.1//EN" "http://gwtproject.org/doctype/2.8.1/gwt-module.dtd"> | <!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.8.1//EN" "http://gwtproject.org/doctype/2.8.1/gwt-module.dtd"> | ||||
<module> | <module> | ||||
<!-- This GWT module inherits all Vaadin client side functionality modules. | |||||
This is the module you want to inherit in your client side project to be | |||||
<!-- This GWT module inherits all Vaadin client side functionality modules. | |||||
This is the module you want to inherit in your client side project to be | |||||
able to use com.vaadin.* classes. --> | able to use com.vaadin.* classes. --> | ||||
<!-- Hint for WidgetSetBuilder not to automatically update the file --> | <!-- Hint for WidgetSetBuilder not to automatically update the file --> | ||||
<source path="client" /> | <source path="client" /> | ||||
<source path="shared" /> | <source path="shared" /> | ||||
<!-- Use own Scheduler implementation to be able to track if commands | |||||
<!-- Use own Scheduler implementation to be able to track if commands | |||||
are running --> | are running --> | ||||
<replace-with class="com.vaadin.client.VSchedulerImpl"> | <replace-with class="com.vaadin.client.VSchedulerImpl"> | ||||
<when-type-is class="com.google.gwt.core.client.impl.SchedulerImpl" /> | <when-type-is class="com.google.gwt.core.client.impl.SchedulerImpl" /> | ||||
<when-type-is class="com.vaadin.client.communication.PushConnection" /> | <when-type-is class="com.vaadin.client.communication.PushConnection" /> | ||||
</replace-with> | </replace-with> | ||||
<!-- Set vaadin.profiler to true to include profiling support in the | |||||
<!-- Set vaadin.profiler to true to include profiling support in the | |||||
module --> | module --> | ||||
<define-property name="vaadin.profiler" values="true,false" /> | <define-property name="vaadin.profiler" values="true,false" /> | ||||
<set-property name="vaadin.profiler" value="false" /> | <set-property name="vaadin.profiler" value="false" /> | ||||
<when-property-is name="user.agent" value="gecko1_8" /> | <when-property-is name="user.agent" value="gecko1_8" /> | ||||
</none> | </none> | ||||
</set-property> | </set-property> | ||||
<!-- If no proper user agent is found, at least try some, e.g. with crawlers --> | <!-- If no proper user agent is found, at least try some, e.g. with crawlers --> | ||||
<set-property-fallback name="user.agent" value="safari" /> | <set-property-fallback name="user.agent" value="safari" /> | ||||
<!-- Fall through to this rule when the browser doesn't support pointer | |||||
<!-- Fall through to this rule when the browser doesn't support pointer | |||||
event --> | event --> | ||||
<replace-with class="com.vaadin.client.event.PointerEventSupportImpl"> | <replace-with class="com.vaadin.client.event.PointerEventSupportImpl"> | ||||
<when-type-is class="com.vaadin.client.event.PointerEventSupportImpl" /> | <when-type-is class="com.vaadin.client.event.PointerEventSupportImpl" /> |
public class ApplicationConnectionURLGenerationTest { | public class ApplicationConnectionURLGenerationTest { | ||||
private static final String[] URIS = { | |||||
"http://demo.vaadin.com/", // | |||||
private static final String[] URIS = { "http://demo.vaadin.com/", // | |||||
"https://demo.vaadin.com/", "http://demo.vaadin.com/foo", | "https://demo.vaadin.com/", "http://demo.vaadin.com/foo", | ||||
"http://demo.vaadin.com/foo?f", "http://demo.vaadin.com/foo?f=1", | "http://demo.vaadin.com/foo?f", "http://demo.vaadin.com/foo?f=1", | ||||
"http://demo.vaadin.com:1234/foo?a", | "http://demo.vaadin.com:1234/foo?a", |
<artifactId>vaadin-maven-plugin</artifactId> | <artifactId>vaadin-maven-plugin</artifactId> | ||||
<version>${vaadin.plugin.version}</version> | <version>${vaadin.plugin.version}</version> | ||||
</plugin> | </plugin> | ||||
<plugin> | |||||
<groupId>net.revelc.code.formatter</groupId> | |||||
<artifactId>formatter-maven-plugin</artifactId> | |||||
<version>2.7.2</version> | |||||
<configuration> | |||||
<configFile>${project.basedir}/../eclipse/VaadinJavaConventions.xml</configFile> | |||||
<skipJsFormatting>true</skipJsFormatting> | |||||
</configuration> | |||||
<executions> | |||||
<execution> | |||||
<id>format-source</id> | |||||
<goals> | |||||
<goal>format</goal> | |||||
</goals> | |||||
<phase>process-sources</phase> | |||||
</execution> | |||||
</executions> | |||||
</plugin> | |||||
<plugin> | |||||
<groupId>com.github.dantwining.whitespace-maven-plugin</groupId> | |||||
<artifactId>whitespace-maven-plugin</artifactId> | |||||
<version>1.0.4</version> | |||||
<executions> | |||||
<execution> | |||||
<id>trim-trailing-spaces-source</id> | |||||
<goals> | |||||
<goal>trim</goal> | |||||
</goals> | |||||
<phase>process-sources</phase> | |||||
</execution> | |||||
</executions> | |||||
</plugin> | |||||
<plugin> | <plugin> | ||||
<groupId>org.apache.maven.plugins</groupId> | <groupId>org.apache.maven.plugins</groupId> | ||||
<artifactId>maven-checkstyle-plugin</artifactId> | <artifactId>maven-checkstyle-plugin</artifactId> | ||||
</pluginManagement> | </pluginManagement> | ||||
<plugins> | <plugins> | ||||
<plugin> | |||||
<groupId>com.marvinformatics.formatter</groupId> | |||||
<artifactId>formatter-maven-plugin</artifactId> | |||||
<version>1.8.1</version> | |||||
<configuration> | |||||
<configFile>classpath:/eclipse/VaadinJavaConventions.xml</configFile> | |||||
<!-- Provide a dummy JS config file to avoid errors --> | |||||
<configJsFile>classpath:/eclipse/VaadinJavaConventions.xml</configJsFile> | |||||
</configuration> | |||||
</plugin> | |||||
<plugin> | <plugin> | ||||
<groupId>org.codehaus.mojo</groupId> | <groupId>org.codehaus.mojo</groupId> | ||||
<artifactId>animal-sniffer-maven-plugin</artifactId> | <artifactId>animal-sniffer-maven-plugin</artifactId> |
<build> | <build> | ||||
<plugins> | <plugins> | ||||
<plugin> | |||||
<groupId>net.revelc.code.formatter</groupId> | |||||
<artifactId>formatter-maven-plugin</artifactId> | |||||
</plugin> | |||||
<plugin> | |||||
<groupId>com.github.dantwining.whitespace-maven-plugin</groupId> | |||||
<artifactId>whitespace-maven-plugin</artifactId> | |||||
</plugin> | |||||
<plugin> | <plugin> | ||||
<groupId>org.apache.maven.plugins</groupId> | <groupId>org.apache.maven.plugins</groupId> | ||||
<artifactId>maven-dependency-plugin</artifactId> | <artifactId>maven-dependency-plugin</artifactId> |
* </ul> | * </ul> | ||||
* Note that you should (almost) always use URLs starting with | * Note that you should (almost) always use URLs starting with | ||||
* {@literal frontend://} so that the framework can resolve the files to either | * {@literal frontend://} so that the framework can resolve the files to either | ||||
* {@literal VAADIN/frontend/es5} or {@literal VAADIN/frontend/es6} depending on if the browser | |||||
* supports ES6 classes (most browers) or not (IE11 and Safari <= 9). Polymer | |||||
* elements rely on importing dependencies using relative paths | |||||
* {@literal VAADIN/frontend/es5} or {@literal VAADIN/frontend/es6} depending on | |||||
* if the browser supports ES6 classes (most browers) or not (IE11 and Safari <= | |||||
* 9). Polymer elements rely on importing dependencies using relative paths | |||||
* {@literal ../../other-element/other-element.html}, which will not work if | * {@literal ../../other-element/other-element.html}, which will not work if | ||||
* they are installed in different locations. | * they are installed in different locations. | ||||
* <p> | * <p> |
* <p> | * <p> | ||||
* In following usage example, the text field would be bound to property "foo" | * In following usage example, the text field would be bound to property "foo" | ||||
* in the Entity class. | * in the Entity class. | ||||
* | |||||
* <pre> | * <pre> | ||||
class Editor extends FormLayout { | |||||
@PropertyId("foo") | |||||
TextField myField = new TextField(); | |||||
} | |||||
class Entity { | |||||
String foo; | |||||
} | |||||
{ | |||||
Editor editor = new Editor(); | |||||
Binder<Entity> binder = new Binder(Entity.class); | |||||
binder.bindInstanceFields(editor); | |||||
} | |||||
</pre> | |||||
* class Editor extends FormLayout { | |||||
* @PropertyId("foo") | |||||
* TextField myField = new TextField(); | |||||
* } | |||||
* | |||||
* class Entity { | |||||
* String foo; | |||||
* } | |||||
* | |||||
* { | |||||
* Editor editor = new Editor(); | |||||
* Binder<Entity> binder = new Binder(Entity.class); | |||||
* binder.bindInstanceFields(editor); | |||||
* } | |||||
* </pre> | |||||
* | * | ||||
* @since 8.0 | * @since 8.0 | ||||
* @author Vaadin Ltd | * @author Vaadin Ltd |
* When this instance is deserialized, it will be replaced with a | * When this instance is deserialized, it will be replaced with a | ||||
* property set for the corresponding bean type and property name. | * property set for the corresponding bean type and property name. | ||||
*/ | */ | ||||
return get(instanceKey.type,instanceKey.checkNestedDefinitions, | |||||
new PropertyFilterDefinition(instanceKey.depth,instanceKey.ignorePackageNames)); | |||||
return get(instanceKey.type, instanceKey.checkNestedDefinitions, | |||||
new PropertyFilterDefinition(instanceKey.depth, | |||||
instanceKey.ignorePackageNames)); | |||||
} | } | ||||
} | } | ||||
* serialize a DTO that when deserialized will get the corresponding | * serialize a DTO that when deserialized will get the corresponding | ||||
* property definition from the cache. | * property definition from the cache. | ||||
*/ | */ | ||||
return new SerializedPropertyDefinition(getPropertySet().instanceKey.type, | |||||
getName()); | |||||
return new SerializedPropertyDefinition( | |||||
getPropertySet().instanceKey.type, getName()); | |||||
} | } | ||||
} | } | ||||
super(propertySet, parent.getType(), descriptor); | super(propertySet, parent.getType(), descriptor); | ||||
this.parent = parent; | this.parent = parent; | ||||
} | } | ||||
@Override | @Override | ||||
public ValueProvider<T, V> getGetter() { | public ValueProvider<T, V> getGetter() { | ||||
return bean -> { | return bean -> { | ||||
public String getName() { | public String getName() { | ||||
return parent.getName() + "." + super.getName(); | return parent.getName() + "." + super.getName(); | ||||
} | } | ||||
@Override | @Override | ||||
public String getTopLevelName() { | public String getTopLevelName() { | ||||
return super.getName(); | return super.getName(); | ||||
} | } | ||||
private Object writeReplace() { | private Object writeReplace() { | ||||
/* | /* | ||||
* Instead of serializing this actual property definition, only | * Instead of serializing this actual property definition, only | ||||
* serialize a DTO that when deserialized will get the corresponding | * serialize a DTO that when deserialized will get the corresponding | ||||
* property definition from the cache. | * property definition from the cache. | ||||
*/ | */ | ||||
return new SerializedPropertyDefinition(getPropertySet().instanceKey.type, | |||||
getName()); | |||||
return new SerializedPropertyDefinition( | |||||
getPropertySet().instanceKey.type, getName()); | |||||
} | } | ||||
/** | /** | ||||
* Gets the parent property definition. | * Gets the parent property definition. | ||||
this.instanceKey = instanceKey; | this.instanceKey = instanceKey; | ||||
try { | try { | ||||
definitions = BeanUtil.getBeanPropertyDescriptors(instanceKey.type).stream() | |||||
.filter(BeanPropertySet::hasNonObjectReadMethod) | |||||
definitions = BeanUtil.getBeanPropertyDescriptors(instanceKey.type) | |||||
.stream().filter(BeanPropertySet::hasNonObjectReadMethod) | |||||
.map(descriptor -> new BeanPropertyDefinition<>(this, | .map(descriptor -> new BeanPropertyDefinition<>(this, | ||||
instanceKey.type, descriptor)) | instanceKey.type, descriptor)) | ||||
.collect(Collectors.toMap(PropertyDefinition::getName, | .collect(Collectors.toMap(PropertyDefinition::getName, | ||||
} | } | ||||
} | } | ||||
private BeanPropertySet(InstanceKey<T> instanceKey, Map<String, PropertyDefinition<T, ?>> definitions) { | |||||
private BeanPropertySet(InstanceKey<T> instanceKey, | |||||
Map<String, PropertyDefinition<T, ?>> definitions) { | |||||
this.instanceKey = instanceKey; | this.instanceKey = instanceKey; | ||||
this.definitions = new HashMap<>(definitions); | this.definitions = new HashMap<>(definitions); | ||||
} | } | ||||
private BeanPropertySet(InstanceKey<T> instanceKey, boolean checkNestedDefinitions, | |||||
PropertyFilterDefinition propertyFilterDefinition) { | |||||
private BeanPropertySet(InstanceKey<T> instanceKey, | |||||
boolean checkNestedDefinitions, | |||||
PropertyFilterDefinition propertyFilterDefinition) { | |||||
this(instanceKey); | this(instanceKey); | ||||
if (checkNestedDefinitions) { | if (checkNestedDefinitions) { | ||||
Objects.requireNonNull(propertyFilterDefinition, | Objects.requireNonNull(propertyFilterDefinition, | ||||
Objects.requireNonNull(beanType, "Bean type cannot be null"); | Objects.requireNonNull(beanType, "Bean type cannot be null"); | ||||
InstanceKey key = new InstanceKey(beanType, false, 0, null); | InstanceKey key = new InstanceKey(beanType, false, 0, null); | ||||
// Cache the reflection results | // Cache the reflection results | ||||
return (PropertySet<T>) INSTANCES.computeIfAbsent(key, | |||||
ignored -> new BeanPropertySet<>(key)).copy(); | |||||
return (PropertySet<T>) INSTANCES | |||||
.computeIfAbsent(key, ignored -> new BeanPropertySet<>(key)) | |||||
.copy(); | |||||
} | } | ||||
private BeanPropertySet<T> copy() { | private BeanPropertySet<T> copy() { | ||||
return new BeanPropertySet<>(instanceKey,definitions); | |||||
return new BeanPropertySet<>(instanceKey, definitions); | |||||
} | } | ||||
/** | /** | ||||
InstanceKey key = new InstanceKey(beanType, false, | InstanceKey key = new InstanceKey(beanType, false, | ||||
filterDefinition.getMaxNestingDepth(), | filterDefinition.getMaxNestingDepth(), | ||||
filterDefinition.getIgnorePackageNamesStartingWith()); | filterDefinition.getIgnorePackageNamesStartingWith()); | ||||
return (PropertySet<T>) INSTANCES.computeIfAbsent(key, | |||||
k -> new BeanPropertySet<>(key, checkNestedDefinitions, | |||||
filterDefinition)).copy(); | |||||
return (PropertySet<T>) INSTANCES | |||||
.computeIfAbsent(key, k -> new BeanPropertySet<>(key, | |||||
checkNestedDefinitions, filterDefinition)) | |||||
.copy(); | |||||
} | } | ||||
@Override | @Override | ||||
/** | /** | ||||
* Gets the bean type of this bean property set. | * Gets the bean type of this bean property set. | ||||
* | |||||
* | |||||
* @since 8.2 | * @since 8.2 | ||||
* @return the bean type of this bean property set | * @return the bean type of this bean property set | ||||
*/ | */ |
public BeanValidationBinder(Class<BEAN> beanType) { | public BeanValidationBinder(Class<BEAN> beanType) { | ||||
super(beanType); | super(beanType); | ||||
if (!BeanUtil.checkBeanValidationAvailable()) { | if (!BeanUtil.checkBeanValidationAvailable()) { | ||||
throw new IllegalStateException( | |||||
BeanValidationBinder.class.getSimpleName() | |||||
+ " cannot be used because a JSR-303 Bean Validation " | |||||
+ "implementation not found on the classpath or could not be initialized. Use " | |||||
+ Binder.class.getSimpleName() + " instead"); | |||||
throw new IllegalStateException(BeanValidationBinder.class | |||||
.getSimpleName() | |||||
+ " cannot be used because a JSR-303 Bean Validation " | |||||
+ "implementation not found on the classpath or could not be initialized. Use " | |||||
+ Binder.class.getSimpleName() + " instead"); | |||||
} | } | ||||
this.beanType = beanType; | this.beanType = beanType; | ||||
} | } |
/** | /** | ||||
* Gets the current read-only status for this Binding. | * Gets the current read-only status for this Binding. | ||||
* | |||||
* | |||||
* @see #setReadOnly(boolean) | * @see #setReadOnly(boolean) | ||||
* | |||||
* | |||||
* @return {@code true} if read-only; {@code false} if not | * @return {@code true} if read-only; {@code false} if not | ||||
* @since 8.4 | * @since 8.4 | ||||
*/ | */ |
* handling. | * handling. | ||||
* <p> | * <p> | ||||
* The default handler will show | * The default handler will show | ||||
* {@link com.vaadin.ui.AbstractComponent#setComponentError(com.vaadin.server.ErrorMessage) an | |||||
* error message} for failed field validations. For bean level validation errors | |||||
* it will display the first error message in | |||||
* {@link com.vaadin.ui.AbstractComponent#setComponentError(com.vaadin.server.ErrorMessage) | |||||
* an error message} for failed field validations. For bean level validation | |||||
* errors it will display the first error message in | |||||
* {@link Binder#setStatusLabel(com.vaadin.ui.Label) status label}, if one has | * {@link Binder#setStatusLabel(com.vaadin.ui.Label) status label}, if one has | ||||
* been set. | * been set. | ||||
* | * |
* {@link BindingBuilder#withValidationStatusHandler(BindingValidationStatusHandler)} | * {@link BindingBuilder#withValidationStatusHandler(BindingValidationStatusHandler)} | ||||
* Register} an instance of this class to be able to override the default | * Register} an instance of this class to be able to override the default | ||||
* handling, which is to show | * handling, which is to show | ||||
* {@link com.vaadin.ui.AbstractComponent#setComponentError(com.vaadin.server.ErrorMessage) an | |||||
* error message} for failed field validations. | |||||
* {@link com.vaadin.ui.AbstractComponent#setComponentError(com.vaadin.server.ErrorMessage) | |||||
* an error message} for failed field validations. | |||||
* | * | ||||
* @author Vaadin Ltd | * @author Vaadin Ltd | ||||
* | * |
/** | /** | ||||
* Gets the top level name of this property. | * Gets the top level name of this property. | ||||
* | |||||
* | |||||
* @return the top level property name, not <code>null</code> | * @return the top level property name, not <code>null</code> | ||||
* @since 8.3 | * @since 8.3 | ||||
*/ | */ |
* @author Vaadin Ltd | * @author Vaadin Ltd | ||||
* @since 8.2 | * @since 8.2 | ||||
*/ | */ | ||||
public class PropertyFilterDefinition | |||||
implements Serializable { | |||||
public class PropertyFilterDefinition implements Serializable { | |||||
private int maxNestingDepth; | private int maxNestingDepth; | ||||
private List<String> ignorePackageNamesStartingWith; | private List<String> ignorePackageNamesStartingWith; | ||||
/** | /** | ||||
* Create a property filter with max nesting depth and package names | |||||
* to ignore. | |||||
* Create a property filter with max nesting depth and package names to | |||||
* ignore. | |||||
* | * | ||||
* @param maxNestingDepth | * @param maxNestingDepth | ||||
* The maximum amount of nesting levels for | |||||
* sub-properties. | |||||
* The maximum amount of nesting levels for sub-properties. | |||||
* @param ignorePackageNamesStartingWith | * @param ignorePackageNamesStartingWith | ||||
* Ignore package names that start with this string, for | |||||
* example "java.lang". | |||||
* Ignore package names that start with this string, for example | |||||
* "java.lang". | |||||
*/ | */ | ||||
public PropertyFilterDefinition(int maxNestingDepth, | public PropertyFilterDefinition(int maxNestingDepth, | ||||
List<String> ignorePackageNamesStartingWith) { | List<String> ignorePackageNamesStartingWith) { | ||||
* @return default property filter | * @return default property filter | ||||
*/ | */ | ||||
public static PropertyFilterDefinition getDefaultFilter() { | public static PropertyFilterDefinition getDefaultFilter() { | ||||
return new PropertyFilterDefinition(BeanPropertySet.NestedBeanPropertyDefinition.MAX_PROPERTY_NESTING_DEPTH, | |||||
return new PropertyFilterDefinition( | |||||
BeanPropertySet.NestedBeanPropertyDefinition.MAX_PROPERTY_NESTING_DEPTH, | |||||
Arrays.asList("java")); | Arrays.asList("java")); | ||||
} | } | ||||
} | } |
* Get the parent item for the given item. | * Get the parent item for the given item. | ||||
* | * | ||||
* @param item | * @param item | ||||
* the item for which to retrieve the parent item for | |||||
* the item for which to retrieve the parent item for | |||||
* @return parent item for the given item or {@code null} if the item is a | * @return parent item for the given item or {@code null} if the item is a | ||||
* root item. | * root item. | ||||
* @throws IllegalArgumentException | * @throws IllegalArgumentException | ||||
* if the item does not exist in this structure | |||||
* if the item does not exist in this structure | |||||
* @since 8.1.1 | * @since 8.1.1 | ||||
*/ | */ | ||||
public T getParent(T item) { | public T getParent(T item) { | ||||
/** | /** | ||||
* Moves an item to become a child of the given parent item. The new parent | * Moves an item to become a child of the given parent item. The new parent | ||||
* item must exist in the hierarchy. Setting the parent to {@code null} | * item must exist in the hierarchy. Setting the parent to {@code null} | ||||
* makes the item a root item. After making changes to the tree data, {@link | |||||
* TreeDataProvider#refreshAll()} should be called. | |||||
* makes the item a root item. After making changes to the tree data, | |||||
* {@link TreeDataProvider#refreshAll()} should be called. | |||||
* | * | ||||
* @param item | * @param item | ||||
* the item to be set as the child of {@code parent} | |||||
* the item to be set as the child of {@code parent} | |||||
* @param parent | * @param parent | ||||
* the item to be set as parent or {@code null} to set the item as | |||||
* root | |||||
* the item to be set as parent or {@code null} to set the item | |||||
* as root | |||||
* @since 8.1 | * @since 8.1 | ||||
*/ | */ | ||||
public void setParent(T item, T parent) { | public void setParent(T item, T parent) { | ||||
* {@link TreeDataProvider#refreshAll()} should be called. | * {@link TreeDataProvider#refreshAll()} should be called. | ||||
* | * | ||||
* @param item | * @param item | ||||
* the item to be moved | |||||
* the item to be moved | |||||
* @param sibling | * @param sibling | ||||
* the item after which the moved item will be located, or {@code | |||||
* the item after which the moved item will be located, or {@code | |||||
* null} to move item to first position | * null} to move item to first position | ||||
* @since 8.1 | * @since 8.1 | ||||
*/ | */ | ||||
if (!Objects.equals(parent, | if (!Objects.equals(parent, | ||||
itemToWrapperMap.get(sibling).getParent())) { | itemToWrapperMap.get(sibling).getParent())) { | ||||
throw new IllegalArgumentException( | |||||
"Items '" + item + "' and '" + sibling | |||||
+ "' don't have the same parent"); | |||||
throw new IllegalArgumentException("Items '" + item + "' and '" | |||||
+ sibling + "' don't have the same parent"); | |||||
} | } | ||||
List<T> children = itemToWrapperMap.get(parent).getChildren(); | List<T> children = itemToWrapperMap.get(parent).getChildren(); |
* @return a list of all validation errors | * @return a list of all validation errors | ||||
*/ | */ | ||||
public List<ValidationResult> getValidationErrors() { | public List<ValidationResult> getValidationErrors() { | ||||
List<ValidationResult> errors = | |||||
getFieldValidationErrors().stream() | |||||
.map(s -> s.getResult().get()) | |||||
.collect(Collectors.toList()); | |||||
List<ValidationResult> errors = getFieldValidationErrors().stream() | |||||
.map(s -> s.getResult().get()).collect(Collectors.toList()); | |||||
errors.addAll(getBeanValidationErrors()); | errors.addAll(getBeanValidationErrors()); | ||||
return errors; | return errors; | ||||
} | } |
* @author Vaadin Ltd | * @author Vaadin Ltd | ||||
* @since 8.0 | * @since 8.0 | ||||
*/ | */ | ||||
public class LocalDateTimeToDateConverter implements Converter<LocalDateTime, Date> { | |||||
public class LocalDateTimeToDateConverter | |||||
implements Converter<LocalDateTime, Date> { | |||||
private ZoneId zoneId; | private ZoneId zoneId; | ||||
/** | /** | ||||
* Creates a new converter using the given time zone. | * Creates a new converter using the given time zone. | ||||
* | * | ||||
* @param zoneId the time zone to use, not <code>null</code> | |||||
* @param zoneId | |||||
* the time zone to use, not <code>null</code> | |||||
*/ | */ | ||||
public LocalDateTimeToDateConverter(ZoneId zoneId) { | public LocalDateTimeToDateConverter(ZoneId zoneId) { | ||||
this.zoneId = Objects.requireNonNull(zoneId, "Zone identifier cannot be null"); | |||||
this.zoneId = Objects.requireNonNull(zoneId, | |||||
"Zone identifier cannot be null"); | |||||
} | } | ||||
@Override | @Override | ||||
public Result<Date> convertToModel(LocalDateTime localDate, ValueContext context) { | |||||
public Result<Date> convertToModel(LocalDateTime localDate, | |||||
ValueContext context) { | |||||
if (localDate == null) { | if (localDate == null) { | ||||
return Result.ok(null); | return Result.ok(null); | ||||
} | } | ||||
} | } | ||||
@Override | @Override | ||||
public LocalDateTime convertToPresentation(Date date, ValueContext context) { | |||||
public LocalDateTime convertToPresentation(Date date, | |||||
ValueContext context) { | |||||
if (date == null) { | if (date == null) { | ||||
return null; | return null; | ||||
} | } | ||||
return Instant.ofEpochMilli(date.getTime()).atZone(zoneId).toLocalDateTime(); | |||||
return Instant.ofEpochMilli(date.getTime()).atZone(zoneId) | |||||
.toLocalDateTime(); | |||||
} | } | ||||
} | } |
public class StringToDateConverter implements Converter<String, Date> { | public class StringToDateConverter implements Converter<String, Date> { | ||||
/** | /** | ||||
* Returns the format used by {@link #convertToPresentation(Date, ValueContext)} | |||||
* and {@link #convertToModel(String, ValueContext)}. | |||||
* Returns the format used by | |||||
* {@link #convertToPresentation(Date, ValueContext)} and | |||||
* {@link #convertToModel(String, ValueContext)}. | |||||
* | * | ||||
* @param locale | * @param locale | ||||
* The locale to use | * The locale to use |
* @param <F> | * @param <F> | ||||
* filter type | * filter type | ||||
*/ | */ | ||||
public abstract class AbstractHierarchicalDataProvider<T, F> | |||||
extends AbstractDataProvider<T, F> | |||||
implements HierarchicalDataProvider<T, F> { | |||||
public abstract class AbstractHierarchicalDataProvider<T, F> extends | |||||
AbstractDataProvider<T, F> implements HierarchicalDataProvider<T, F> { | |||||
} | } |
* // ComboBox uses String as the filter type | * // ComboBox uses String as the filter type | ||||
* DataProvider<Person, String> wrappedProvider = dataProvider | * DataProvider<Person, String> wrappedProvider = dataProvider | ||||
* .withConvertedFilter(filterText -> { | * .withConvertedFilter(filterText -> { | ||||
* SerializablePredicate<Person> predicate = person -> person.getName() | |||||
* .startsWith(filterText); | |||||
* SerializablePredicate<Person> predicate = person -> person | |||||
* .getName().startsWith(filterText); | |||||
* return predicate; | * return predicate; | ||||
* }); | * }); | ||||
* comboBox.setDataProvider(wrappedProvider); | * comboBox.setDataProvider(wrappedProvider); |
public class GridSortOrder<T> extends SortOrder<Column<T, ?>> { | public class GridSortOrder<T> extends SortOrder<Column<T, ?>> { | ||||
/** | /** | ||||
* Construct sorting information for usage in a {@link com.vaadin.ui.Grid Grid}. | |||||
* Construct sorting information for usage in a {@link com.vaadin.ui.Grid | |||||
* Grid}. | |||||
* | * | ||||
* @param column | * @param column | ||||
* the column to be sorted | * the column to be sorted |
} | } | ||||
/** | /** | ||||
* Create new {@code HierarchyMapper} for the given data provider. | |||||
* May be overridden in subclasses. | |||||
* Create new {@code HierarchyMapper} for the given data provider. May be | |||||
* overridden in subclasses. | |||||
* | * | ||||
* @param dataProvider the data provider | |||||
* @param <F> Query type | |||||
* @param dataProvider | |||||
* the data provider | |||||
* @param <F> | |||||
* Query type | |||||
* @return new {@link HierarchyMapper} | * @return new {@link HierarchyMapper} | ||||
*/ | */ | ||||
protected <F> HierarchyMapper<T, F> createHierarchyMapper(HierarchicalDataProvider<T, F> dataProvider) { | |||||
protected <F> HierarchyMapper<T, F> createHierarchyMapper( | |||||
HierarchicalDataProvider<T, F> dataProvider) { | |||||
return new HierarchyMapper<>(dataProvider); | return new HierarchyMapper<>(dataProvider); | ||||
} | } | ||||
* method will have no effect if the row is already collapsed. | * method will have no effect if the row is already collapsed. | ||||
* {@code syncAndRefresh} indicates whether the changes should be | * {@code syncAndRefresh} indicates whether the changes should be | ||||
* synchronised to the client and the data provider be notified. | * synchronised to the client and the data provider be notified. | ||||
* | |||||
* | |||||
* @param item | * @param item | ||||
* the item to collapse | * the item to collapse | ||||
* @param syncAndRefresh | * @param syncAndRefresh | ||||
* changes, {@code false} otherwise. | * changes, {@code false} otherwise. | ||||
*/ | */ | ||||
public void collapse(T item, boolean syncAndRefresh) { | public void collapse(T item, boolean syncAndRefresh) { | ||||
Integer index = syncAndRefresh ? mapper.getIndexOf(item).orElse(null) : null; | |||||
Integer index = syncAndRefresh ? mapper.getIndexOf(item).orElse(null) | |||||
: null; | |||||
doCollapse(item, index, syncAndRefresh); | doCollapse(item, index, syncAndRefresh); | ||||
} | } | ||||
* will have no effect if the row is already collapsed. The index is | * will have no effect if the row is already collapsed. The index is | ||||
* provided by the client-side or calculated from a full data request. | * provided by the client-side or calculated from a full data request. | ||||
* | * | ||||
* | |||||
* | |||||
* @param item | * @param item | ||||
* the item to collapse | * the item to collapse | ||||
* @param index | * @param index | ||||
* provided by the client-side or calculated from a full data request. | * provided by the client-side or calculated from a full data request. | ||||
* {@code syncAndRefresh} indicates whether the changes should be | * {@code syncAndRefresh} indicates whether the changes should be | ||||
* synchronised to the client and the data provider be notified. | * synchronised to the client and the data provider be notified. | ||||
* | |||||
* | |||||
* @param item | * @param item | ||||
* the item to collapse | * the item to collapse | ||||
* @param index | * @param index | ||||
* false} otherwise. | * false} otherwise. | ||||
*/ | */ | ||||
public void expand(T item, boolean syncAndRefresh) { | public void expand(T item, boolean syncAndRefresh) { | ||||
Integer index = syncAndRefresh ? mapper.getIndexOf(item).orElse(null) : null; | |||||
Integer index = syncAndRefresh ? mapper.getIndexOf(item).orElse(null) | |||||
: null; | |||||
doExpand(item, index, syncAndRefresh); | doExpand(item, index, syncAndRefresh); | ||||
} | } | ||||
Range addedRows = mapper.expand(item, index); | Range addedRows = mapper.expand(item, index); | ||||
if (syncAndRefresh) { | if (syncAndRefresh) { | ||||
if (!reset && !addedRows.isEmpty()) { | if (!reset && !addedRows.isEmpty()) { | ||||
getClientRpc() | |||||
.insertRows(addedRows.getStart(), addedRows.length()); | |||||
Stream<T> children = mapper | |||||
.fetchItems(item, | |||||
Range.withLength(0, addedRows.length())); | |||||
getClientRpc().insertRows(addedRows.getStart(), | |||||
addedRows.length()); | |||||
Stream<T> children = mapper.fetchItems(item, | |||||
Range.withLength(0, addedRows.length())); | |||||
pushData(addedRows.getStart(), | pushData(addedRows.getStart(), | ||||
children.collect(Collectors.toList())); | children.collect(Collectors.toList())); | ||||
} | } |
/** | /** | ||||
* Find parent for the given item among open folders. | * Find parent for the given item among open folders. | ||||
* @param item the item | |||||
* @return parent item or {@code null} for root items or if the parent is closed | |||||
* | |||||
* @param item | |||||
* the item | |||||
* @return parent item or {@code null} for root items or if the parent is | |||||
* closed | |||||
*/ | */ | ||||
protected T getParentOfItem(T item) { | protected T getParentOfItem(T item) { | ||||
Objects.requireNonNull(item, "Can not find the parent of null"); | Objects.requireNonNull(item, "Can not find the parent of null"); | ||||
/** | /** | ||||
* Removes all children of an item identified by a given id. Items removed | * Removes all children of an item identified by a given id. Items removed | ||||
* by this method as well as the original item are all marked to be | * by this method as well as the original item are all marked to be | ||||
* collapsed. | |||||
* May be overridden in subclasses for removing obsolete data to avoid memory leaks. | |||||
* collapsed. May be overridden in subclasses for removing obsolete data to | |||||
* avoid memory leaks. | |||||
* | * | ||||
* @param id | * @param id | ||||
* the item id | * the item id | ||||
} | } | ||||
} | } | ||||
expandedItemIds.remove(id); | expandedItemIds.remove(id); | ||||
invalidatedChildren.stream().map(getDataProvider()::getId).forEach(x -> { | |||||
removeChildren(x); | |||||
parentIdMap.remove(x); | |||||
}); | |||||
invalidatedChildren.stream().map(getDataProvider()::getId) | |||||
.forEach(x -> { | |||||
removeChildren(x); | |||||
parentIdMap.remove(x); | |||||
}); | |||||
} | } | ||||
/** | /** | ||||
} | } | ||||
/** | /** | ||||
* Register parent and children items into inner structures. | |||||
* May be overridden in subclasses. | |||||
* Register parent and children items into inner structures. May be | |||||
* overridden in subclasses. | |||||
* | * | ||||
* @param parent the parent item | |||||
* @param childList list of parents children to be registered. | |||||
* @param parent | |||||
* the parent item | |||||
* @param childList | |||||
* list of parents children to be registered. | |||||
*/ | */ | ||||
protected void registerChildren(T parent, List<T> childList) { | protected void registerChildren(T parent, List<T> childList) { | ||||
childMap.put(parent, new HashSet<>(childList)); | childMap.put(parent, new HashSet<>(childList)); | ||||
childList.forEach(x -> parentIdMap.put(getDataProvider().getId(x), parent)); | |||||
childList.forEach( | |||||
x -> parentIdMap.put(getDataProvider().getId(x), parent)); | |||||
} | } | ||||
/** | /** |
ValueProvider<T, String> valueProvider, Locale locale) { | ValueProvider<T, String> valueProvider, Locale locale) { | ||||
Objects.requireNonNull(locale, "Locale cannot be null"); | Objects.requireNonNull(locale, "Locale cannot be null"); | ||||
return InMemoryDataProviderHelpers.filteringByCaseInsensitiveString( | return InMemoryDataProviderHelpers.filteringByCaseInsensitiveString( | ||||
this, valueProvider, | |||||
String::contains, () -> locale); | |||||
this, valueProvider, String::contains, () -> locale); | |||||
} | } | ||||
/** | /** | ||||
*/ | */ | ||||
public default DataProvider<T, String> filteringByPrefix( | public default DataProvider<T, String> filteringByPrefix( | ||||
ValueProvider<T, String> valueProvider, Locale locale) { | ValueProvider<T, String> valueProvider, Locale locale) { | ||||
return InMemoryDataProviderHelpers.filteringByCaseInsensitiveString(this, valueProvider, | |||||
String::startsWith, () -> locale); | |||||
return InMemoryDataProviderHelpers.filteringByCaseInsensitiveString( | |||||
this, valueProvider, String::startsWith, () -> locale); | |||||
} | } | ||||
/** | /** | ||||
*/ | */ | ||||
public default DataProvider<T, String> filteringByPrefix( | public default DataProvider<T, String> filteringByPrefix( | ||||
ValueProvider<T, String> valueProvider) { | ValueProvider<T, String> valueProvider) { | ||||
return InMemoryDataProviderHelpers.filteringByCaseInsensitiveString(this, valueProvider, | |||||
String::startsWith, InMemoryDataProviderHelpers.CURRENT_LOCALE_SUPPLIER); | |||||
return InMemoryDataProviderHelpers.filteringByCaseInsensitiveString( | |||||
this, valueProvider, String::startsWith, | |||||
InMemoryDataProviderHelpers.CURRENT_LOCALE_SUPPLIER); | |||||
} | } | ||||
} | } |
* | * | ||||
* | * | ||||
*/ | */ | ||||
public class ActionManager | |||||
implements Action.Handler, Action.Notifier { | |||||
public class ActionManager implements Action.Handler, Action.Notifier { | |||||
private static final long serialVersionUID = 1641868163608066491L; | private static final long serialVersionUID = 1641868163608066491L; | ||||
* @param <T> | * @param <T> | ||||
* collapsed item type | * collapsed item type | ||||
*/ | */ | ||||
public class CollapseEvent<T> extends Component.Event implements HasUserOriginated { | |||||
public class CollapseEvent<T> extends Component.Event | |||||
implements HasUserOriginated { | |||||
private final T collapsedItem; | private final T collapsedItem; | ||||
import com.vaadin.ui.UI; | import com.vaadin.ui.UI; | ||||
/** | /** | ||||
* Event which is fired for all registered MarkDirtyListeners when a | |||||
* connector is marked as dirty. | |||||
* Event which is fired for all registered MarkDirtyListeners when a connector | |||||
* is marked as dirty. | |||||
* | * | ||||
* @since 8.4 | * @since 8.4 | ||||
*/ | */ |
* Method called when a client connector has been marked as dirty. | * Method called when a client connector has been marked as dirty. | ||||
* | * | ||||
* @param event | * @param event | ||||
* marked as dirty connector event object | |||||
* marked as dirty connector event object | |||||
*/ | */ | ||||
void connectorMarkedAsDirty(MarkedAsDirtyConnectorEvent event); | void connectorMarkedAsDirty(MarkedAsDirtyConnectorEvent event); | ||||
} | } |
public void paint(PaintTarget target) throws PaintException; | public void paint(PaintTarget target) throws PaintException; | ||||
/** | /** | ||||
* This needs to be implemented if and only if a criterion does some lazy server side | |||||
* initialization. The UIDL painted in this method will be passed to client | |||||
* side drop handler implementation. Implementation can assume that | |||||
* {@link #accept(DragAndDropEvent)} is called before this method. | |||||
* This needs to be implemented if and only if a criterion does some lazy | |||||
* server side initialization. The UIDL painted in this method will be | |||||
* passed to client side drop handler implementation. Implementation can | |||||
* assume that {@link #accept(DragAndDropEvent)} is called before this | |||||
* method. | |||||
* | * | ||||
* @param target | * @param target | ||||
* @throws PaintException | * @throws PaintException |
* | * | ||||
* @since 6.3 | * @since 6.3 | ||||
*/ | */ | ||||
public abstract class ClientSideCriterion | |||||
implements AcceptCriterion { | |||||
public abstract class ClientSideCriterion implements AcceptCriterion { | |||||
/* | /* | ||||
* All criteria that extend this must be completely validatable on client | * All criteria that extend this must be completely validatable on client |
* | * | ||||
* @since 6.3 | * @since 6.3 | ||||
*/ | */ | ||||
public abstract class ServerSideCriterion | |||||
implements AcceptCriterion { | |||||
public abstract class ServerSideCriterion implements AcceptCriterion { | |||||
private static final long serialVersionUID = 2128510128911628902L; | private static final long serialVersionUID = 2128510128911628902L; | ||||
/** | /** | ||||
* Crate a new bootstrap fragment response. | * Crate a new bootstrap fragment response. | ||||
* | * | ||||
* @see BootstrapResponse#BootstrapResponse(BootstrapHandler, VaadinRequest, VaadinSession, Class, UIProvider) | |||||
* @see BootstrapResponse#BootstrapResponse(BootstrapHandler, VaadinRequest, | |||||
* VaadinSession, Class, UIProvider) | |||||
* | * | ||||
* @param handler | * @param handler | ||||
* the bootstrap handler that is firing the event | * the bootstrap handler that is firing the event |
protected String encodeQueryStringParameterValue(String queryString) { | protected String encodeQueryStringParameterValue(String queryString) { | ||||
String encodedString = null; | String encodedString = null; | ||||
try { | try { | ||||
encodedString = URLEncoder.encode(queryString, | |||||
UTF_8.name()); | |||||
encodedString = URLEncoder.encode(queryString, UTF_8.name()); | |||||
} catch (UnsupportedEncodingException e) { | } catch (UnsupportedEncodingException e) { | ||||
// should never happen | // should never happen | ||||
throw new RuntimeException("Could not find UTF-8", e); | throw new RuntimeException("Could not find UTF-8", e); | ||||
mainDiv.attr("id", context.getAppId()); | mainDiv.attr("id", context.getAppId()); | ||||
mainDiv.addClass("v-app"); | mainDiv.addClass("v-app"); | ||||
mainDiv.addClass(context.getThemeName()); | mainDiv.addClass(context.getThemeName()); | ||||
mainDiv.addClass(context.getUIClass().getSimpleName() | |||||
.toLowerCase(Locale.ROOT)); | |||||
mainDiv.addClass( | |||||
context.getUIClass().getSimpleName().toLowerCase(Locale.ROOT)); | |||||
if (style != null && !style.isEmpty()) { | if (style != null && !style.isEmpty()) { | ||||
mainDiv.attr("style", style); | mainDiv.attr("style", style); | ||||
} | } |