summaryrefslogtreecommitdiffstats
path: root/server/src/com
diff options
context:
space:
mode:
authorTeemu Suo-Anttila <teemusa@vaadin.com>2015-06-01 09:32:37 +0300
committerTeemu Suo-Anttila <teemusa@vaadin.com>2015-06-01 09:34:46 +0300
commit6677046e5e23667403b8fb0499a618495796e1c8 (patch)
tree0d4bb0bf40b16be2c9e7e6158729f5bd3ff54d22 /server/src/com
parentcf563c053fdf0d6b2991eba98e1cc118a8e74e54 (diff)
parent5b92ec790e3d3949992275d54ee8ac61ad94c157 (diff)
downloadvaadin-framework-6677046e5e23667403b8fb0499a618495796e1c8.tar.gz
vaadin-framework-6677046e5e23667403b8fb0499a618495796e1c8.zip
Merge remote-tracking branch 'origin/master' into grid-unbuffered-editor
This also refactors some event handling logic. Change-Id: I9cf96381650076da01686c5d964eb3e7e92c24c0
Diffstat (limited to 'server/src/com')
-rw-r--r--server/src/com/vaadin/data/RpcDataProviderExtension.java26
-rw-r--r--server/src/com/vaadin/data/util/MethodProperty.java11
-rw-r--r--server/src/com/vaadin/data/util/NestedMethodProperty.java8
-rw-r--r--server/src/com/vaadin/data/util/converter/StringToCollectionConverter.java2
-rw-r--r--server/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java10
-rw-r--r--server/src/com/vaadin/data/util/sqlcontainer/query/TableQuery.java8
-rw-r--r--server/src/com/vaadin/event/ShortcutAction.java38
-rw-r--r--server/src/com/vaadin/server/AbstractClientConnector.java40
-rw-r--r--server/src/com/vaadin/server/SystemMessages.java29
-rw-r--r--server/src/com/vaadin/server/VaadinServlet.java3
-rw-r--r--server/src/com/vaadin/server/communication/PushRequestHandler.java2
-rw-r--r--server/src/com/vaadin/server/communication/ServerRpcHandler.java24
-rw-r--r--server/src/com/vaadin/server/communication/UidlRequestHandler.java4
-rw-r--r--server/src/com/vaadin/ui/AbstractComponent.java20
-rw-r--r--server/src/com/vaadin/ui/AbstractField.java18
-rw-r--r--server/src/com/vaadin/ui/AbstractSingleComponentContainer.java4
-rw-r--r--server/src/com/vaadin/ui/CustomLayout.java2
-rw-r--r--server/src/com/vaadin/ui/DragAndDropWrapper.java2
-rw-r--r--server/src/com/vaadin/ui/Flash.java9
-rw-r--r--server/src/com/vaadin/ui/Grid.java83
-rw-r--r--server/src/com/vaadin/ui/PasswordField.java6
-rw-r--r--server/src/com/vaadin/ui/PopupView.java4
-rw-r--r--server/src/com/vaadin/ui/ProgressBar.java15
-rw-r--r--server/src/com/vaadin/ui/RichTextArea.java5
-rw-r--r--server/src/com/vaadin/ui/Slider.java58
-rw-r--r--server/src/com/vaadin/ui/TextArea.java6
-rw-r--r--server/src/com/vaadin/ui/Tree.java2
-rw-r--r--server/src/com/vaadin/ui/UI.java29
-rw-r--r--server/src/com/vaadin/ui/Window.java102
-rw-r--r--server/src/com/vaadin/ui/declarative/DesignContext.java6
-rw-r--r--server/src/com/vaadin/ui/declarative/FieldBinder.java9
-rw-r--r--server/src/com/vaadin/ui/declarative/converters/DesignResourceConverter.java13
-rw-r--r--server/src/com/vaadin/ui/renderers/AbstractJavaScriptRenderer.java6
-rw-r--r--server/src/com/vaadin/ui/renderers/ButtonRenderer.java38
-rw-r--r--server/src/com/vaadin/ui/renderers/ClickableRenderer.java6
-rw-r--r--server/src/com/vaadin/ui/renderers/DateRenderer.java91
-rw-r--r--server/src/com/vaadin/ui/renderers/HtmlRenderer.java21
-rw-r--r--server/src/com/vaadin/ui/renderers/ImageRenderer.java4
-rw-r--r--server/src/com/vaadin/ui/renderers/NumberRenderer.java77
-rw-r--r--server/src/com/vaadin/ui/renderers/ProgressBarRenderer.java8
-rw-r--r--server/src/com/vaadin/ui/renderers/TextRenderer.java17
41 files changed, 578 insertions, 288 deletions
diff --git a/server/src/com/vaadin/data/RpcDataProviderExtension.java b/server/src/com/vaadin/data/RpcDataProviderExtension.java
index e645ec60f7..9d18736ba8 100644
--- a/server/src/com/vaadin/data/RpcDataProviderExtension.java
+++ b/server/src/com/vaadin/data/RpcDataProviderExtension.java
@@ -50,6 +50,7 @@ import com.vaadin.server.KeyMapper;
import com.vaadin.shared.data.DataProviderRpc;
import com.vaadin.shared.data.DataRequestRpc;
import com.vaadin.shared.ui.grid.DetailsConnectorChange;
+import com.vaadin.shared.ui.grid.GridClientRpc;
import com.vaadin.shared.ui.grid.GridState;
import com.vaadin.shared.ui.grid.Range;
import com.vaadin.shared.util.SharedUtil;
@@ -135,6 +136,15 @@ public class RpcDataProviderExtension extends AbstractExtension {
return String.valueOf(rollingIndex++);
}
+ /**
+ * Gets the key for a given item id. Creates a new key mapping if no
+ * existing mapping was found for the given item id.
+ *
+ * @since 7.5.0
+ * @param itemId
+ * the item id to get the key for
+ * @return the key for the given item id
+ */
public String getKey(Object itemId) {
String key = itemIdToKey.get(itemId);
if (key == null) {
@@ -1124,7 +1134,7 @@ public class RpcDataProviderExtension extends AbstractExtension {
Object propertyId = column.getPropertyId();
cellReference.set(propertyId);
String style = generator.getStyle(cellReference);
- if (style != null) {
+ if (style != null && !style.isEmpty()) {
if (cellStyles == null) {
cellStyles = Json.createObject();
}
@@ -1142,7 +1152,7 @@ public class RpcDataProviderExtension extends AbstractExtension {
private void setGeneratedRowStyles(RowStyleGenerator generator,
JsonObject rowObject) {
String rowStyle = generator.getStyle(rowReference);
- if (rowStyle != null) {
+ if (rowStyle != null && !rowStyle.isEmpty()) {
rowObject.put(GridState.JSONKEY_ROWSTYLE, rowStyle);
}
}
@@ -1428,6 +1438,11 @@ public class RpcDataProviderExtension extends AbstractExtension {
return visibleDetails.contains(itemId);
}
+ /**
+ * Refreshes all visible detail sections.
+ *
+ * @since 7.5.0
+ */
public void refreshDetails() {
for (Object itemId : ImmutableSet.copyOf(visibleDetails)) {
detailComponentManager.refresh(itemId);
@@ -1443,7 +1458,12 @@ public class RpcDataProviderExtension extends AbstractExtension {
return container.indexOfId(itemId);
}
- /** Gets the detail component manager for this data provider */
+ /**
+ * Gets the detail component manager for this data provider
+ *
+ * @since 7.5.0
+ * @return the detail component manager
+ * */
public DetailComponentManager getDetailComponentManager() {
return detailComponentManager;
}
diff --git a/server/src/com/vaadin/data/util/MethodProperty.java b/server/src/com/vaadin/data/util/MethodProperty.java
index 853f68b711..83279afa53 100644
--- a/server/src/com/vaadin/data/util/MethodProperty.java
+++ b/server/src/com/vaadin/data/util/MethodProperty.java
@@ -26,6 +26,7 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import com.vaadin.data.Property;
+import com.vaadin.shared.util.SharedUtil;
import com.vaadin.util.SerializerHelper;
/**
@@ -189,11 +190,7 @@ public class MethodProperty<T> extends AbstractProperty<T> {
// Assure that the first letter is upper cased (it is a common
// mistake to write firstName, not FirstName).
- if (Character.isLowerCase(beanPropertyName.charAt(0))) {
- final char[] buf = beanPropertyName.toCharArray();
- buf[0] = Character.toUpperCase(buf[0]);
- beanPropertyName = new String(buf);
- }
+ beanPropertyName = SharedUtil.capitalize(beanPropertyName);
// Find the get method
getMethod = null;
@@ -534,8 +531,7 @@ public class MethodProperty<T> extends AbstractProperty<T> {
*/
static Method initGetterMethod(String propertyName, final Class<?> beanClass)
throws NoSuchMethodException {
- propertyName = propertyName.substring(0, 1).toUpperCase()
- + propertyName.substring(1);
+ propertyName = SharedUtil.capitalize(propertyName);
Method getMethod = null;
try {
@@ -772,4 +768,5 @@ public class MethodProperty<T> extends AbstractProperty<T> {
private static final Logger getLogger() {
return Logger.getLogger(MethodProperty.class.getName());
}
+
}
diff --git a/server/src/com/vaadin/data/util/NestedMethodProperty.java b/server/src/com/vaadin/data/util/NestedMethodProperty.java
index 0493812861..29fe62f845 100644
--- a/server/src/com/vaadin/data/util/NestedMethodProperty.java
+++ b/server/src/com/vaadin/data/util/NestedMethodProperty.java
@@ -26,6 +26,7 @@ import java.util.List;
import com.vaadin.data.Property;
import com.vaadin.data.util.MethodProperty.MethodException;
+import com.vaadin.shared.util.SharedUtil;
/**
* Nested accessor based property for a bean.
@@ -164,11 +165,8 @@ public class NestedMethodProperty<T> extends AbstractProperty<T> {
try {
// Assure that the first letter is upper cased (it is a common
// mistake to write firstName, not FirstName).
- if (Character.isLowerCase(lastSimplePropertyName.charAt(0))) {
- final char[] buf = lastSimplePropertyName.toCharArray();
- buf[0] = Character.toUpperCase(buf[0]);
- lastSimplePropertyName = new String(buf);
- }
+ lastSimplePropertyName = SharedUtil
+ .capitalize(lastSimplePropertyName);
setMethod = lastClass.getMethod("set" + lastSimplePropertyName,
new Class[] { type });
diff --git a/server/src/com/vaadin/data/util/converter/StringToCollectionConverter.java b/server/src/com/vaadin/data/util/converter/StringToCollectionConverter.java
index a84a3575f7..495bed74f8 100644
--- a/server/src/com/vaadin/data/util/converter/StringToCollectionConverter.java
+++ b/server/src/com/vaadin/data/util/converter/StringToCollectionConverter.java
@@ -34,6 +34,8 @@ import java.util.Locale;
* {@link String} for token types. Other constructors allow to configure
* delimiter and token types.
*
+ * @since 7.5.0
+ *
* @author Vaadin Ltd
*/
public class StringToCollectionConverter implements
diff --git a/server/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java b/server/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java
index c0c660c084..f07b7ecc58 100644
--- a/server/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java
+++ b/server/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java
@@ -1012,9 +1012,15 @@ public class SQLContainer implements Container, Container.Filterable,
queryDelegate.beginTransaction();
/* Perform buffered deletions */
for (RowItem item : removedItems.values()) {
- if (!queryDelegate.removeRow(item)) {
+ try {
+ if (!queryDelegate.removeRow(item)) {
+ throw new SQLException(
+ "Removal failed for row with ID: "
+ + item.getId());
+ }
+ } catch (IllegalArgumentException e) {
throw new SQLException("Removal failed for row with ID: "
- + item.getId());
+ + item.getId(), e);
}
}
/* Perform buffered modifications */
diff --git a/server/src/com/vaadin/data/util/sqlcontainer/query/TableQuery.java b/server/src/com/vaadin/data/util/sqlcontainer/query/TableQuery.java
index bb000bd8f5..9a41766a31 100644
--- a/server/src/com/vaadin/data/util/sqlcontainer/query/TableQuery.java
+++ b/server/src/com/vaadin/data/util/sqlcontainer/query/TableQuery.java
@@ -213,8 +213,8 @@ public class TableQuery extends AbstractTransactionalQuery implements
} finally {
try {
if (r != null) {
- releaseConnection(r.getStatement().getConnection(),
- r.getStatement(), r);
+ // Do not release connection, it is done in commit()
+ releaseConnection(null, r.getStatement(), r);
}
} finally {
if (shouldCloseTransaction) {
@@ -774,8 +774,8 @@ public class TableQuery extends AbstractTransactionalQuery implements
} finally {
try {
if (rs != null) {
- releaseConnection(rs.getStatement().getConnection(),
- rs.getStatement(), rs);
+ // Do not release connection, it is done in commit()
+ releaseConnection(null, rs.getStatement(), rs);
}
} finally {
if (shouldCloseTransaction) {
diff --git a/server/src/com/vaadin/event/ShortcutAction.java b/server/src/com/vaadin/event/ShortcutAction.java
index 32b909e9f2..09accae1c7 100644
--- a/server/src/com/vaadin/event/ShortcutAction.java
+++ b/server/src/com/vaadin/event/ShortcutAction.java
@@ -17,8 +17,6 @@
package com.vaadin.event;
import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -239,42 +237,6 @@ public class ShortcutAction extends Action {
}
/**
- * Checks whether the shortcut can be triggered with the given combination
- * of keys.
- *
- * @param keyCode
- * potential match for the {@link KeyCode} that this shortcut
- * reacts to
- * @param modifierKeys
- * (optional) potential matches for the {@link ModifierKey}s
- * required for this shortcut to react
- * @return <code>true</code> if keyCode and modifierKeys are a match,
- * <code>false</code> otherwise
- */
- public boolean isTriggeredBy(int keyCode, int... modifierKeys) {
- boolean result = false;
- if (keyCode == this.keyCode) {
- if (modifierKeys == null) {
- result = (modifiers == null);
- } else if (modifiers != null) {
- List<Integer> modifierList = new ArrayList<Integer>();
- for (int modifier : modifiers) {
- modifierList.add(modifier);
- }
- for (int modifierKey : modifierKeys) {
- if (modifierList.contains(modifierKey)) {
- modifierList.remove(modifierKey);
- } else {
- return false;
- }
- }
- result = modifierList.isEmpty();
- }
- }
- return result;
- }
-
- /**
* Key codes that can be used for shortcuts
*
*/
diff --git a/server/src/com/vaadin/server/AbstractClientConnector.java b/server/src/com/vaadin/server/AbstractClientConnector.java
index 87b61c9623..0655b482ed 100644
--- a/server/src/com/vaadin/server/AbstractClientConnector.java
+++ b/server/src/com/vaadin/server/AbstractClientConnector.java
@@ -180,22 +180,40 @@ public abstract class AbstractClientConnector implements ClientConnector,
* RPC interface implementation. Also used to deduce the type.
*/
protected <T extends ServerRpc> void registerRpc(T implementation) {
+ // Search upwards until an interface is found. It must be found as T
+ // extends ServerRpc
Class<?> cls = implementation.getClass();
- Class<?>[] interfaces = cls.getInterfaces();
- while (interfaces.length == 0) {
- // Search upwards until an interface is found. It must be found as T
- // extends ServerRpc
+ Class<ServerRpc> serverRpcClass = getServerRpcInterface(cls);
+
+ while (cls != null && serverRpcClass == null) {
cls = cls.getSuperclass();
- interfaces = cls.getInterfaces();
+ serverRpcClass = getServerRpcInterface(cls);
}
- if (interfaces.length != 1
- || !(ServerRpc.class.isAssignableFrom(interfaces[0]))) {
+
+ if (serverRpcClass == null) {
throw new RuntimeException(
- "Use registerRpc(T implementation, Class<T> rpcInterfaceType) if the Rpc implementation implements more than one interface");
+ "No interface T extends ServerRpc found in the class hierarchy.");
+ }
+
+ registerRpc(implementation, serverRpcClass);
+ }
+
+ @SuppressWarnings("unchecked")
+ private Class<ServerRpc> getServerRpcInterface(Class<?> implementationClass) {
+ Class<ServerRpc> serverRpcClass = null;
+ if (implementationClass != null) {
+ for (Class<?> candidateInterface : implementationClass
+ .getInterfaces()) {
+ if (ServerRpc.class.isAssignableFrom(candidateInterface)) {
+ if (serverRpcClass != null) {
+ throw new RuntimeException(
+ "Use registerRpc(T implementation, Class<T> rpcInterfaceType) if the Rpc implementation implements more than one interface");
+ }
+ serverRpcClass = (Class<ServerRpc>) candidateInterface;
+ }
+ }
}
- @SuppressWarnings("unchecked")
- Class<T> type = (Class<T>) interfaces[0];
- registerRpc(implementation, type);
+ return serverRpcClass;
}
/**
diff --git a/server/src/com/vaadin/server/SystemMessages.java b/server/src/com/vaadin/server/SystemMessages.java
index 51e9da5800..51cc7d497d 100644
--- a/server/src/com/vaadin/server/SystemMessages.java
+++ b/server/src/com/vaadin/server/SystemMessages.java
@@ -224,35 +224,6 @@ public class SystemMessages implements Serializable {
}
/**
- * @return null to reload the application after out of sync message.
- */
- public String getOutOfSyncURL() {
- return outOfSyncURL;
- }
-
- /**
- * @return true to enable showing out of sync message
- */
- public boolean isOutOfSyncNotificationEnabled() {
- return outOfSyncNotificationEnabled;
- }
-
- /**
- * @return "Out of sync"
- */
- public String getOutOfSyncCaption() {
- return (outOfSyncNotificationEnabled ? outOfSyncCaption : null);
- }
-
- /**
- * @return "Something has caused us to be out of sync with the server.<br/>
- * Take note of any unsaved data, and <u>click here</u> to re-sync."
- */
- public String getOutOfSyncMessage() {
- return (outOfSyncNotificationEnabled ? outOfSyncMessage : null);
- }
-
- /**
* Returns the URL the user should be redirected to after dismissing the
* "you have to enable your cookies" message. Typically null.
*
diff --git a/server/src/com/vaadin/server/VaadinServlet.java b/server/src/com/vaadin/server/VaadinServlet.java
index b30f6acf16..7aada2402d 100644
--- a/server/src/com/vaadin/server/VaadinServlet.java
+++ b/server/src/com/vaadin/server/VaadinServlet.java
@@ -871,9 +871,8 @@ public class VaadinServlet extends HttpServlet implements Constants {
if (allowServePrecompressedResource(request, urlStr)) {
// try to serve a precompressed version if available
- URL url = new URL(urlStr + ".gz");
- connection = url.openConnection();
try {
+ connection = new URL(urlStr + ".gz").openConnection();
is = connection.getInputStream();
// set gzip headers
response.setHeader("Content-Encoding", "gzip");
diff --git a/server/src/com/vaadin/server/communication/PushRequestHandler.java b/server/src/com/vaadin/server/communication/PushRequestHandler.java
index 9e25f1d8ff..c01c74e5cd 100644
--- a/server/src/com/vaadin/server/communication/PushRequestHandler.java
+++ b/server/src/com/vaadin/server/communication/PushRequestHandler.java
@@ -145,7 +145,7 @@ public class PushRequestHandler implements RequestHandler,
*/
static AtmosphereFramework initAtmosphere(
final ServletConfig vaadinServletConfig) {
- AtmosphereFramework atmosphere = new AtmosphereFramework() {
+ AtmosphereFramework atmosphere = new AtmosphereFramework(false, false) {
@Override
protected void analytics() {
// Overridden to disable version number check
diff --git a/server/src/com/vaadin/server/communication/ServerRpcHandler.java b/server/src/com/vaadin/server/communication/ServerRpcHandler.java
index 450c11f5c4..65fb144810 100644
--- a/server/src/com/vaadin/server/communication/ServerRpcHandler.java
+++ b/server/src/com/vaadin/server/communication/ServerRpcHandler.java
@@ -76,13 +76,14 @@ public class ServerRpcHandler implements Serializable {
private final JsonArray invocations;
private final int syncId;
private final JsonObject json;
+ private final boolean resynchronize;
public RpcRequest(String jsonString, VaadinRequest request) {
json = JsonUtil.parse(jsonString);
JsonValue token = json.get(ApplicationConstants.CSRF_TOKEN);
if (token == null) {
- this.csrfToken = ApplicationConstants.CSRF_TOKEN_DEFAULT_VALUE;
+ csrfToken = ApplicationConstants.CSRF_TOKEN_DEFAULT_VALUE;
} else {
String csrfToken = token.asString();
if (csrfToken.equals("")) {
@@ -98,6 +99,14 @@ public class ServerRpcHandler implements Serializable {
} else {
syncId = -1;
}
+
+ if (json.hasKey(ApplicationConstants.RESYNCHRONIZE_ID)) {
+ resynchronize = json
+ .getBoolean(ApplicationConstants.RESYNCHRONIZE_ID);
+ } else {
+ resynchronize = false;
+ }
+
invocations = json.getArray(ApplicationConstants.RPC_INVOCATIONS);
}
@@ -131,6 +140,15 @@ public class ServerRpcHandler implements Serializable {
}
/**
+ * Checks if this is a request to resynchronize the client side
+ *
+ * @return true if this is a resynchronization request, false otherwise
+ */
+ public boolean isResynchronize() {
+ return resynchronize;
+ }
+
+ /**
* Gets the entire request in JSON format, as it was received from the
* client.
* <p>
@@ -186,6 +204,10 @@ public class ServerRpcHandler implements Serializable {
ui.getConnectorTracker().cleanConcurrentlyRemovedConnectorIds(
rpcRequest.getSyncId());
+
+ if (rpcRequest.isResynchronize()) {
+ ui.getSession().getCommunicationManager().repaintAll(ui);
+ }
}
/**
diff --git a/server/src/com/vaadin/server/communication/UidlRequestHandler.java b/server/src/com/vaadin/server/communication/UidlRequestHandler.java
index 6e338c5773..33a3669b7f 100644
--- a/server/src/com/vaadin/server/communication/UidlRequestHandler.java
+++ b/server/src/com/vaadin/server/communication/UidlRequestHandler.java
@@ -80,10 +80,12 @@ public class UidlRequestHandler extends SynchronizedRequestHandler implements
// repaint requested or session has timed out and new one is created
boolean repaintAll;
- // TODO PUSH repaintAll, analyzeLayouts should be
+ // TODO PUSH analyzeLayouts should be
// part of the message payload to make the functionality transport
// agnostic
+ // Resynchronize is sent in the payload but will still support the
+ // parameter also for compatibility reasons
repaintAll = (request
.getParameter(ApplicationConstants.URL_PARAMETER_REPAINT_ALL) != null);
diff --git a/server/src/com/vaadin/ui/AbstractComponent.java b/server/src/com/vaadin/ui/AbstractComponent.java
index fd8a72ee23..27d97d5e03 100644
--- a/server/src/com/vaadin/ui/AbstractComponent.java
+++ b/server/src/com/vaadin/ui/AbstractComponent.java
@@ -405,6 +405,26 @@ public abstract class AbstractComponent extends AbstractClientConnector
}
}
+ /**
+ * Returns the explicitly set immediate value.
+ *
+ * @return the explicitly set immediate value or null if
+ * {@link #setImmediate(boolean)} has not been explicitly invoked
+ */
+ protected Boolean getExplicitImmediateValue() {
+ return explicitImmediateValue;
+ }
+
+ /**
+ * Returns the immediate mode of the component.
+ * <p>
+ * Certain operations such as adding a value change listener will set the
+ * component into immediate mode if {@link #setImmediate(boolean)} has not
+ * been explicitly called with false.
+ *
+ * @return true if the component is in immediate mode (explicitly or
+ * implicitly set), false if the component if not in immediate mode
+ */
public boolean isImmediate() {
if (explicitImmediateValue != null) {
return explicitImmediateValue;
diff --git a/server/src/com/vaadin/ui/AbstractField.java b/server/src/com/vaadin/ui/AbstractField.java
index 5c02c9e5fb..cf14d1cb96 100644
--- a/server/src/com/vaadin/ui/AbstractField.java
+++ b/server/src/com/vaadin/ui/AbstractField.java
@@ -1745,6 +1745,24 @@ public abstract class AbstractField<T> extends AbstractComponent implements
}
}
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Fields are automatically set to immediate if validators have been added.
+ */
+ @Override
+ public boolean isImmediate() {
+ if (getExplicitImmediateValue() != null) {
+ return getExplicitImmediateValue();
+ }
+ // Make field immediate when there is some kind of validation present
+ // (validator or required). This will avoid the UI being in a wrong
+ // state, e.g. user entered valid data but old validation error is still
+ // shown
+ return super.isImmediate() || !getValidators().isEmpty()
+ || isRequired();
+ }
+
/*
* (non-Javadoc)
*
diff --git a/server/src/com/vaadin/ui/AbstractSingleComponentContainer.java b/server/src/com/vaadin/ui/AbstractSingleComponentContainer.java
index 767ae66515..0854ffe9c2 100644
--- a/server/src/com/vaadin/ui/AbstractSingleComponentContainer.java
+++ b/server/src/com/vaadin/ui/AbstractSingleComponentContainer.java
@@ -298,7 +298,9 @@ public abstract class AbstractSingleComponentContainer extends
* contains multiple child elements, a DesignException is thrown. This
* method should be overridden by subclasses whose design may contain
* non-content child elements.
- *
+ *
+ * @since 7.5.0
+ *
* @param children
* the child elements of the design that is being read
* @param context
diff --git a/server/src/com/vaadin/ui/CustomLayout.java b/server/src/com/vaadin/ui/CustomLayout.java
index ceb47e1e7a..d64f70e95e 100644
--- a/server/src/com/vaadin/ui/CustomLayout.java
+++ b/server/src/com/vaadin/ui/CustomLayout.java
@@ -74,6 +74,8 @@ public class CustomLayout extends AbstractLayout implements LegacyComponent {
* for setting the appropriate fields. Either
* {@link #setTemplateName(String)}, that makes layout fetch the template
* from theme, or {@link #setTemplateContents(String)}.
+ *
+ * @since 7.5.0
*/
public CustomLayout() {
setWidth(100, Unit.PERCENTAGE);
diff --git a/server/src/com/vaadin/ui/DragAndDropWrapper.java b/server/src/com/vaadin/ui/DragAndDropWrapper.java
index b813973861..ba912f15dc 100644
--- a/server/src/com/vaadin/ui/DragAndDropWrapper.java
+++ b/server/src/com/vaadin/ui/DragAndDropWrapper.java
@@ -191,6 +191,8 @@ public class DragAndDropWrapper extends CustomComponent implements DropTarget,
/**
* This is an internal constructor. Use
* {@link DragAndDropWrapper#DragAndDropWrapper(Component)} instead.
+ *
+ * @since 7.5.0
*/
@Deprecated
public DragAndDropWrapper() {
diff --git a/server/src/com/vaadin/ui/Flash.java b/server/src/com/vaadin/ui/Flash.java
index 2d0f188b84..6e99d2fe35 100644
--- a/server/src/com/vaadin/ui/Flash.java
+++ b/server/src/com/vaadin/ui/Flash.java
@@ -15,6 +15,7 @@
*/
package com.vaadin.ui;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -236,7 +237,15 @@ public class Flash extends AbstractEmbedded {
@Override
public void writeDesign(Element design, DesignContext designContext) {
super.writeDesign(design, designContext);
+
+ // Parameters, in alphabetic order
+ ArrayList<String> paramNames = new ArrayList<String>();
for (String param : getParameterNames()) {
+ paramNames.add(param);
+ }
+
+ Collections.sort(paramNames);
+ for (String param : paramNames) {
design.appendElement("parameter").attr("name", param)
.attr("value", getParameter(param));
}
diff --git a/server/src/com/vaadin/ui/Grid.java b/server/src/com/vaadin/ui/Grid.java
index 43e82560df..77785c301b 100644
--- a/server/src/com/vaadin/ui/Grid.java
+++ b/server/src/com/vaadin/ui/Grid.java
@@ -3270,14 +3270,16 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
return getState().hidable;
}
- /*
+ /**
* Writes the design attributes for this column into given element.
*
* @since 7.5.0
*
- * @param design Element to write attributes into
+ * @param design
+ * Element to write attributes into
*
- * @param designContext the design context
+ * @param designContext
+ * the design context
*/
protected void writeDesign(Element design, DesignContext designContext) {
Attributes attributes = design.attributes();
@@ -3367,20 +3369,27 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
/**
* An abstract base class for server-side Grid renderers.
* {@link com.vaadin.client.widget.grid.Renderer Grid renderers}. This class
- * currently extends the AbstractExtension superclass, but this fact should
- * be regarded as an implementation detail and subject to change in a future
- * major or minor Vaadin revision.
+ * currently extends the AbstractGridExtension superclass, but this fact
+ * should be regarded as an implementation detail and subject to change in a
+ * future major or minor Vaadin revision.
*
* @param <T>
* the type this renderer knows how to present
*/
- public static abstract class AbstractRenderer<T> extends AbstractExtension
- implements Renderer<T> {
+ public static abstract class AbstractRenderer<T> extends
+ AbstractGridExtension implements Renderer<T> {
private final Class<T> presentationType;
- protected AbstractRenderer(Class<T> presentationType) {
+ private final String nullRepresentation;
+
+ protected AbstractRenderer(Class<T> presentationType, String nullRepresentation) {
this.presentationType = presentationType;
+ this.nullRepresentation = nullRepresentation;
+ }
+
+ protected AbstractRenderer(Class<T> presentationType) {
+ this(presentationType, null);
}
/**
@@ -3410,7 +3419,19 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
@Override
public JsonValue encode(T value) {
- return encode(value, getPresentationType());
+ if (value == null) {
+ return encode(getNullRepresentation(), String.class);
+ } else {
+ return encode(value, getPresentationType());
+ }
+ }
+
+ /**
+ * Null representation for the renderer
+ * @return a textual representation of {@code null}
+ */
+ protected String getNullRepresentation() {
+ return nullRepresentation;
}
/**
@@ -3433,6 +3454,33 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
return JsonCodec.encode(value, null, type,
getUI().getConnectorTracker()).getEncodedValue();
}
+ }
+
+ /**
+ * An abstract base class for server-side Grid extensions.
+ *
+ * @since 7.5
+ */
+ public static abstract class AbstractGridExtension extends
+ AbstractExtension {
+
+ /**
+ * Constructs a new Grid extension.
+ */
+ public AbstractGridExtension() {
+ super();
+ }
+
+ /**
+ * Constructs a new Grid extension and extends given Grid.
+ *
+ * @param grid
+ * a grid instance
+ */
+ public AbstractGridExtension(Grid grid) {
+ super();
+ extend(grid);
+ }
/**
* Gets the item id for a row key.
@@ -4416,6 +4464,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
* added for any property id in propertyIds that has no corresponding column
* in this Grid.
*
+ * @since 7.5.0
+ *
* @param propertyIds
* properties in the desired column order
*/
@@ -5480,7 +5530,9 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
@Override
public Iterator<Component> iterator() {
- List<Component> componentList = new ArrayList<Component>();
+ // This is a hash set to avoid adding header/footer components inside
+ // merged cells multiple times
+ LinkedHashSet<Component> componentList = new LinkedHashSet<Component>();
Header header = getHeader();
for (int i = 0; i < header.getRowCount(); ++i) {
@@ -5797,6 +5849,13 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
column.getState().editorConnector = getEditorField(column
.getPropertyId());
}
+
+ // Must ensure that all fields, recursively, are sent to the client
+ // This is needed because the fields are hidden using isRendered
+ for (Field<?> f : getEditorFields()) {
+ f.markAsDirtyRecursive();
+ }
+
}
private void setEditorField(Object propertyId, Field<?> field) {
@@ -6184,7 +6243,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
return datasourceExtension.isDetailsVisible(itemId);
}
- protected SelectionMode getDefaultSelectionMode() {
+ private static SelectionMode getDefaultSelectionMode() {
return SelectionMode.SINGLE;
}
diff --git a/server/src/com/vaadin/ui/PasswordField.java b/server/src/com/vaadin/ui/PasswordField.java
index 1894804775..ff3b1fea1f 100644
--- a/server/src/com/vaadin/ui/PasswordField.java
+++ b/server/src/com/vaadin/ui/PasswordField.java
@@ -113,4 +113,10 @@ public class PasswordField extends AbstractTextField {
DesignAttributeHandler.writeAttribute("value", attr, getValue(),
def.getValue(), String.class);
}
+
+ @Override
+ public void clear() {
+ setValue("");
+ }
+
}
diff --git a/server/src/com/vaadin/ui/PopupView.java b/server/src/com/vaadin/ui/PopupView.java
index 12034cb56c..73c93b29f3 100644
--- a/server/src/com/vaadin/ui/PopupView.java
+++ b/server/src/com/vaadin/ui/PopupView.java
@@ -69,6 +69,8 @@ public class PopupView extends AbstractComponent implements HasComponents {
/**
* This is an internal constructor. Use
* {@link PopupView#PopupView(String, Component)} instead.
+ *
+ * @since 7.5.0
*/
@Deprecated
public PopupView() {
@@ -106,6 +108,8 @@ public class PopupView extends AbstractComponent implements HasComponents {
/**
* Creates a Content from given text representation and popup content.
*
+ * @since 7.5.0
+ *
* @param minimizedValue
* text representation when popup is hidden
* @param popupContent
diff --git a/server/src/com/vaadin/ui/ProgressBar.java b/server/src/com/vaadin/ui/ProgressBar.java
index c288695ae1..89baac1e64 100644
--- a/server/src/com/vaadin/ui/ProgressBar.java
+++ b/server/src/com/vaadin/ui/ProgressBar.java
@@ -37,11 +37,13 @@ import com.vaadin.ui.declarative.DesignContext;
public class ProgressBar extends AbstractField<Float> implements
Property.Viewer, Property.ValueChangeListener {
+ private static final float DEFAULT_VALUE = 0f;
+
/**
* Creates a new progress bar initially set to 0% progress.
*/
public ProgressBar() {
- this(0);
+ this(DEFAULT_VALUE);
}
/**
@@ -170,4 +172,15 @@ public class ProgressBar extends AbstractField<Float> implements
DesignAttributeHandler.writeAttribute("value", design.attributes(),
getValue(), defaultValue, Float.class);
}
+
+ @Override
+ public void clear() {
+ setValue(DEFAULT_VALUE);
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return super.isEmpty() || getValue() == DEFAULT_VALUE;
+
+ }
}
diff --git a/server/src/com/vaadin/ui/RichTextArea.java b/server/src/com/vaadin/ui/RichTextArea.java
index 763e42ad8b..7c23cce5cb 100644
--- a/server/src/com/vaadin/ui/RichTextArea.java
+++ b/server/src/com/vaadin/ui/RichTextArea.java
@@ -293,6 +293,11 @@ public class RichTextArea extends AbstractField<String> implements
}
@Override
+ public void clear() {
+ setValue("");
+ }
+
+ @Override
public void readDesign(Element design, DesignContext designContext) {
super.readDesign(design, designContext);
setValue(design.html());
diff --git a/server/src/com/vaadin/ui/Slider.java b/server/src/com/vaadin/ui/Slider.java
index 40a4047d53..2e00628eb0 100644
--- a/server/src/com/vaadin/ui/Slider.java
+++ b/server/src/com/vaadin/ui/Slider.java
@@ -104,9 +104,9 @@ public class Slider extends AbstractField<Double> {
*/
public Slider(double min, double max, int resolution) {
this();
- setMin(min);
- setMax(max);
setResolution(resolution);
+ setMax(max);
+ setMin(min);
}
/**
@@ -167,14 +167,15 @@ public class Slider extends AbstractField<Double> {
* The new maximum slider value
*/
public void setMax(double max) {
- getState().maxValue = max;
+ double roundedMax = getRoundedValue(max);
+ getState().maxValue = roundedMax;
- if (getMin() > max) {
- getState().minValue = max;
+ if (getMin() > roundedMax) {
+ getState().minValue = roundedMax;
}
- if (getValue() > max) {
- setValue(max);
+ if (getValue() > roundedMax) {
+ setValue(roundedMax);
}
}
@@ -195,14 +196,15 @@ public class Slider extends AbstractField<Double> {
* The new minimum slider value
*/
public void setMin(double min) {
- getState().minValue = min;
+ double roundedMin = getRoundedValue(min);
+ getState().minValue = roundedMin;
- if (getMax() < min) {
- getState().maxValue = min;
+ if (getMax() < roundedMin) {
+ getState().maxValue = roundedMin;
}
- if (getValue() < min) {
- setValue(min);
+ if (getValue() < roundedMin) {
+ setValue(roundedMin);
}
}
@@ -268,28 +270,28 @@ public class Slider extends AbstractField<Double> {
*/
@Override
protected void setValue(Double value, boolean repaintIsNotNeeded) {
- final double v = value.doubleValue();
- final int resolution = getResolution();
- double newValue;
-
- if (resolution > 0) {
- // Round up to resolution
- newValue = Math.floor(v * Math.pow(10, resolution));
- newValue = newValue / Math.pow(10, resolution);
- if (getMin() > newValue || getMax() < newValue) {
- throw new ValueOutOfBoundsException(newValue);
- }
- } else {
- newValue = (int) v;
- if (getMin() > newValue || getMax() < newValue) {
- throw new ValueOutOfBoundsException(newValue);
- }
+ double newValue = getRoundedValue(value);
+
+ if (getMin() > newValue || getMax() < newValue) {
+ throw new ValueOutOfBoundsException(newValue);
}
getState().value = newValue;
super.setValue(newValue, repaintIsNotNeeded);
}
+ private double getRoundedValue(Double value) {
+ final double v = value.doubleValue();
+ final int resolution = getResolution();
+
+ double ratio = Math.pow(10, resolution);
+ if(v >= 0) {
+ return Math.floor(v * ratio) / ratio;
+ } else {
+ return Math.ceil(v * ratio) / ratio;
+ }
+ }
+
@Override
public void setValue(Double newFieldValue) {
super.setValue(newFieldValue);
diff --git a/server/src/com/vaadin/ui/TextArea.java b/server/src/com/vaadin/ui/TextArea.java
index c8103f9c5b..b4dfb209e8 100644
--- a/server/src/com/vaadin/ui/TextArea.java
+++ b/server/src/com/vaadin/ui/TextArea.java
@@ -159,4 +159,10 @@ public class TextArea extends AbstractTextField {
super.writeDesign(design, designContext);
design.html(getValue());
}
+
+ @Override
+ public void clear() {
+ setValue("");
+ }
+
}
diff --git a/server/src/com/vaadin/ui/Tree.java b/server/src/com/vaadin/ui/Tree.java
index 48f4e54831..aac827e5b5 100644
--- a/server/src/com/vaadin/ui/Tree.java
+++ b/server/src/com/vaadin/ui/Tree.java
@@ -273,7 +273,7 @@ public class Tree extends AbstractSelect implements Container.Hierarchical,
* @param sendChildTree
* flag to indicate if client needs subtree or not (may be
* cached)
- * @return True iff the expand operation succeeded
+ * @return True if the expand operation succeeded
*/
private boolean expandItem(Object itemId, boolean sendChildTree) {
diff --git a/server/src/com/vaadin/ui/UI.java b/server/src/com/vaadin/ui/UI.java
index 8dd600ddd0..b16d7e32d3 100644
--- a/server/src/com/vaadin/ui/UI.java
+++ b/server/src/com/vaadin/ui/UI.java
@@ -16,6 +16,8 @@
package com.vaadin.ui;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
@@ -67,6 +69,7 @@ import com.vaadin.shared.ui.ui.UIConstants;
import com.vaadin.shared.ui.ui.UIServerRpc;
import com.vaadin.shared.ui.ui.UIState;
import com.vaadin.ui.Component.Focusable;
+import com.vaadin.ui.declarative.Design;
import com.vaadin.util.ConnectorHelper;
import com.vaadin.util.CurrentInstance;
@@ -211,6 +214,32 @@ public abstract class UI extends AbstractSingleComponentContainer implements
json.toString());
}
+ @Override
+ public void showServerDesign(Connector connector) {
+ if (!(connector instanceof Component)) {
+ getLogger().severe(
+ "Tried to output declarative design for " + connector
+ + ", which is not a component");
+ return;
+ }
+ if (connector instanceof UI) {
+ // We want to see the content of the UI, so we can add it to
+ // another UI or component container
+ connector = ((UI) connector).getContent();
+ }
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try {
+ Design.write((Component) connector, baos);
+ getLogger().info(
+ "Design for " + connector
+ + " requested from debug window:\n"
+ + baos.toString("UTF-8"));
+ } catch (IOException e) {
+ getLogger().log(Level.WARNING,
+ "Error producing design for " + connector, e);
+ }
+
+ }
};
/**
diff --git a/server/src/com/vaadin/ui/Window.java b/server/src/com/vaadin/ui/Window.java
index e7764ffd8d..61664fc95d 100644
--- a/server/src/com/vaadin/ui/Window.java
+++ b/server/src/com/vaadin/ui/Window.java
@@ -21,9 +21,6 @@ import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
@@ -133,7 +130,6 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
super(caption, content);
registerRpc(rpc);
setSizeUndefined();
- setCloseShortcut(ShortcutAction.KeyCode.ESCAPE);
}
/* ********************************************************************* */
@@ -820,48 +816,14 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
/*
* Actions
*/
- private LinkedHashSet<CloseShortcut> closeShortcuts = new LinkedHashSet<CloseShortcut>();
-
- protected Collection<CloseShortcut> getCloseShortcuts() {
- return Collections.unmodifiableCollection(closeShortcuts);
- }
-
- /**
- * Adds a keyboard shortcut for closing the window when user presses the
- * given {@link KeyCode} and (optional) {@link ModifierKey}s.<br/>
- * Note that this shortcut only reacts while the window has focus, closing
- * itself - if you want to close a window from a UI, use
- * {@link UI#addAction(com.vaadin.event.Action)} of the UI instead.
- * <p>
- * If there is a prior CloseShortcut with the same keycode and modifiers,
- * that gets removed before the new one is added. Prior CloseShortcuts with
- * differing keycodes or modifiers are not affected.
- *
- * @param keyCode
- * the keycode for invoking the shortcut
- * @param modifiers
- * the (optional) modifiers for invoking the shortcut, null for
- * none
- */
- public void addCloseShortcut(int keyCode, int... modifiers) {
- // make sure there are no duplicates
- removeCloseShortcut(keyCode, modifiers);
- CloseShortcut closeShortcut = new CloseShortcut(this, keyCode,
- modifiers);
- closeShortcuts.add(closeShortcut);
- addAction(closeShortcut);
- }
+ protected CloseShortcut closeShortcut;
/**
- * Sets the keyboard shortcut for closing the window when user presses the
- * given {@link KeyCode} and (optional) {@link ModifierKey}s.<br/>
+ * Makes is possible to close the window by pressing the given
+ * {@link KeyCode} and (optional) {@link ModifierKey}s.<br/>
* Note that this shortcut only reacts while the window has focus, closing
* itself - if you want to close a window from a UI, use
* {@link UI#addAction(com.vaadin.event.Action)} of the UI instead.
- * <p>
- * If there are any prior CloseShortcuts when this method is called those
- * get removed before the new one is added. <b>NOTE: this also removes the
- * default shortcut that is added for accessibility purposes.</b>
*
* @param keyCode
* the keycode for invoking the shortcut
@@ -870,61 +832,22 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
* none
*/
public void setCloseShortcut(int keyCode, int... modifiers) {
- removeCloseShortcuts();
- addCloseShortcut(keyCode, modifiers);
- }
-
- /**
- * Removes a keyboard shortcut previously set with
- * {@link #setCloseShortcut(int, int...)} or
- * {@link #addCloseShortcut(int, int...)}.
- *
- * @param keyCode
- * the keycode for invoking the shortcut
- * @param modifiers
- * the (optional) modifiers for invoking the shortcut, null for
- * none
- */
- public void removeCloseShortcut(int keyCode, int... modifiers) {
- for (CloseShortcut closeShortcut : closeShortcuts) {
- if (closeShortcut.isTriggeredBy(keyCode, modifiers)) {
- removeAction(closeShortcut);
- closeShortcuts.remove(closeShortcut);
- break;
- }
+ if (closeShortcut != null) {
+ removeAction(closeShortcut);
}
+ closeShortcut = new CloseShortcut(this, keyCode, modifiers);
+ addAction(closeShortcut);
}
/**
- * @deprecated use {@link #resetCloseShortcuts()} instead, or
- * {@link #removeCloseShortcuts()} if you also want to get rid
- * of the default shortcut
+ * Removes the keyboard shortcut previously set with
+ * {@link #setCloseShortcut(int, int...)}.
*/
- @Deprecated
public void removeCloseShortcut() {
- resetCloseShortcuts();
- }
-
- /**
- * Removes all the keyboard shortcuts previously set with
- * {@link #setCloseShortcut(int, int...)} or
- * {@link #addCloseShortcut(int, int...)} and re-adds the default shortcut
- * {@link KeyCode.ESCAPE}.
- */
- public void resetCloseShortcuts() {
- setCloseShortcut(ShortcutAction.KeyCode.ESCAPE);
- }
-
- /**
- * Removes all the keyboard shortcuts previously set with
- * {@link #setCloseShortcut(int, int...)} or
- * {@link #addCloseShortcut(int, int...)}.
- */
- public void removeCloseShortcuts() {
- for (CloseShortcut closeShortcut : closeShortcuts) {
+ if (closeShortcut != null) {
removeAction(closeShortcut);
+ closeShortcut = null;
}
- closeShortcuts.clear();
}
/**
@@ -1391,8 +1314,7 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
}
private CloseShortcut getCloseShortcut() {
- Iterator<CloseShortcut> i = getCloseShortcuts().iterator();
- return i.hasNext() ? i.next() : null;
+ return closeShortcut;
}
@Override
diff --git a/server/src/com/vaadin/ui/declarative/DesignContext.java b/server/src/com/vaadin/ui/declarative/DesignContext.java
index d6cb970ce8..0d68c22ea0 100644
--- a/server/src/com/vaadin/ui/declarative/DesignContext.java
+++ b/server/src/com/vaadin/ui/declarative/DesignContext.java
@@ -171,6 +171,8 @@ public class DesignContext implements Serializable {
* component was mapped to some string s different from localId, the mapping
* from s to component is removed.
*
+ * @since 7.5.0
+ *
* @param component
* The component whose local id is to be set.
* @param localId
@@ -186,7 +188,9 @@ public class DesignContext implements Serializable {
}
/**
- * Returns the local id for a component
+ * Returns the local id for a component.
+ *
+ * @since 7.5.0
*
* @param component
* The component whose local id to get.
diff --git a/server/src/com/vaadin/ui/declarative/FieldBinder.java b/server/src/com/vaadin/ui/declarative/FieldBinder.java
index bd906682fa..577e9f5515 100644
--- a/server/src/com/vaadin/ui/declarative/FieldBinder.java
+++ b/server/src/com/vaadin/ui/declarative/FieldBinder.java
@@ -204,11 +204,14 @@ public class FieldBinder implements Serializable {
}
return true;
} catch (IllegalAccessException e) {
- throw new FieldBindingException("Field binding failed", e);
+ throw new FieldBindingException("Field binding failed for "
+ + identifier, e);
} catch (IllegalArgumentException e) {
- throw new FieldBindingException("Field binding failed", e);
+ throw new FieldBindingException("Field binding failed for "
+ + identifier, e);
} catch (InvocationTargetException e) {
- throw new FieldBindingException("Field binding failed", e);
+ throw new FieldBindingException("Field binding failed for "
+ + identifier, e);
}
}
diff --git a/server/src/com/vaadin/ui/declarative/converters/DesignResourceConverter.java b/server/src/com/vaadin/ui/declarative/converters/DesignResourceConverter.java
index ff73b61eb2..ffa51fedd1 100644
--- a/server/src/com/vaadin/ui/declarative/converters/DesignResourceConverter.java
+++ b/server/src/com/vaadin/ui/declarative/converters/DesignResourceConverter.java
@@ -28,8 +28,8 @@ import com.vaadin.server.FontAwesome;
import com.vaadin.server.FontIcon;
import com.vaadin.server.GenericFontIcon;
import com.vaadin.server.Resource;
+import com.vaadin.server.ResourceReference;
import com.vaadin.server.ThemeResource;
-import com.vaadin.shared.ApplicationConstants;
import com.vaadin.ui.declarative.DesignAttributeHandler;
/**
@@ -109,8 +109,7 @@ public class DesignResourceConverter implements Converter<String, Resource> {
@Override
public String format(Resource value)
throws Converter.ConversionException {
- return ApplicationConstants.THEME_PROTOCOL_PREFIX
- + ((ThemeResource) value).getResourceId();
+ return new ResourceReference(value, null, null).getURL();
}
},
FONTICON {
@@ -118,8 +117,7 @@ public class DesignResourceConverter implements Converter<String, Resource> {
public Resource parse(String value) {
final String address = (value.split("://", 2))[1];
final String[] familyAndCode = address.split("/", 2);
- final int codepoint = Integer.valueOf(
- familyAndCode[1].substring(2), 16);
+ final int codepoint = Integer.valueOf(familyAndCode[1], 16);
if (FontAwesome.FONT_FAMILY.equals(familyAndCode[0])) {
try {
@@ -141,9 +139,8 @@ public class DesignResourceConverter implements Converter<String, Resource> {
public String format(Resource value)
throws Converter.ConversionException {
FontIcon icon = (FontIcon) value;
- return ApplicationConstants.FONTICON_PROTOCOL_PREFIX
- + icon.getFontFamily() + "/0x"
- + Integer.toHexString(icon.getCodepoint());
+ return new ResourceReference(icon, null, null).getURL();
+
}
},
@Deprecated
diff --git a/server/src/com/vaadin/ui/renderers/AbstractJavaScriptRenderer.java b/server/src/com/vaadin/ui/renderers/AbstractJavaScriptRenderer.java
index bed34cf6e3..104e07f02f 100644
--- a/server/src/com/vaadin/ui/renderers/AbstractJavaScriptRenderer.java
+++ b/server/src/com/vaadin/ui/renderers/AbstractJavaScriptRenderer.java
@@ -105,8 +105,12 @@ public abstract class AbstractJavaScriptRenderer<T> extends AbstractRenderer<T>
private JavaScriptCallbackHelper callbackHelper = new JavaScriptCallbackHelper(
this);
+ protected AbstractJavaScriptRenderer(Class<T> presentationType, String nullRepresentation) {
+ super(presentationType, nullRepresentation);
+ }
+
protected AbstractJavaScriptRenderer(Class<T> presentationType) {
- super(presentationType);
+ super(presentationType, null);
}
@Override
diff --git a/server/src/com/vaadin/ui/renderers/ButtonRenderer.java b/server/src/com/vaadin/ui/renderers/ButtonRenderer.java
index 0b070d3f69..a747e45713 100644
--- a/server/src/com/vaadin/ui/renderers/ButtonRenderer.java
+++ b/server/src/com/vaadin/ui/renderers/ButtonRenderer.java
@@ -15,6 +15,8 @@
*/
package com.vaadin.ui.renderers;
+import elemental.json.JsonValue;
+
/**
* A Renderer that displays a button with a textual caption. The value of the
* corresponding property is used as the caption. Click listeners can be added
@@ -27,9 +29,12 @@ public class ButtonRenderer extends ClickableRenderer<String> {
/**
* Creates a new button renderer.
+ *
+ * @param nullRepresentation
+ * the textual representation of {@code null} value
*/
- public ButtonRenderer() {
- super(String.class);
+ public ButtonRenderer(String nullRepresentation) {
+ super(String.class, nullRepresentation);
}
/**
@@ -37,9 +42,34 @@ public class ButtonRenderer extends ClickableRenderer<String> {
*
* @param listener
* the click listener to register
+ * @param nullRepresentation
+ * the textual representation of {@code null} value
*/
- public ButtonRenderer(RendererClickListener listener) {
- this();
+ public ButtonRenderer(RendererClickListener listener, String nullRepresentation) {
+ this(nullRepresentation);
addClickListener(listener);
}
+
+ /**
+ * Creates a new button renderer.
+ */
+ public ButtonRenderer() {
+ this("");
+ }
+
+ /**
+ * Creates a new button renderer and adds the given click listener to it.
+ *
+ * @param listener
+ * the click listener to register
+ */
+ public ButtonRenderer(RendererClickListener listener) {
+ this(listener, "");
+ }
+
+ @Override
+ public String getNullRepresentation() {
+ return super.getNullRepresentation();
+ }
+
}
diff --git a/server/src/com/vaadin/ui/renderers/ClickableRenderer.java b/server/src/com/vaadin/ui/renderers/ClickableRenderer.java
index 38e9acef9c..01e939bb67 100644
--- a/server/src/com/vaadin/ui/renderers/ClickableRenderer.java
+++ b/server/src/com/vaadin/ui/renderers/ClickableRenderer.java
@@ -103,7 +103,11 @@ public class ClickableRenderer<T> extends AbstractRenderer<T> {
}
protected ClickableRenderer(Class<T> presentationType) {
- super(presentationType);
+ this(presentationType, null);
+ }
+
+ protected ClickableRenderer(Class<T> presentationType, String nullRepresentation) {
+ super(presentationType, nullRepresentation);
registerRpc(new RendererClickRpc() {
@Override
public void click(String rowKey, String columnId,
diff --git a/server/src/com/vaadin/ui/renderers/DateRenderer.java b/server/src/com/vaadin/ui/renderers/DateRenderer.java
index 9dd4d19e87..092b3f405e 100644
--- a/server/src/com/vaadin/ui/renderers/DateRenderer.java
+++ b/server/src/com/vaadin/ui/renderers/DateRenderer.java
@@ -41,7 +41,7 @@ public class DateRenderer extends AbstractRenderer<Date> {
* representation for the default locale.
*/
public DateRenderer() {
- this(Locale.getDefault());
+ this(Locale.getDefault(), "");
}
/**
@@ -56,7 +56,24 @@ public class DateRenderer extends AbstractRenderer<Date> {
* if {@code locale} is {@code null}
*/
public DateRenderer(Locale locale) throws IllegalArgumentException {
- this("%s", locale);
+ this("%s", locale, "");
+ }
+
+ /**
+ * Creates a new date renderer.
+ * <p>
+ * The renderer is configured to render with the {@link Date#toString()}
+ * representation for the given locale.
+ *
+ * @param locale
+ * the locale in which to present dates
+ * @param nullRepresentation
+ * the textual representation of {@code null} value
+ * @throws IllegalArgumentException
+ * if {@code locale} is {@code null}
+ */
+ public DateRenderer(Locale locale, String nullRepresentation) throws IllegalArgumentException {
+ this("%s", locale, nullRepresentation);
}
/**
@@ -74,7 +91,27 @@ public class DateRenderer extends AbstractRenderer<Date> {
* String Syntax</a>
*/
public DateRenderer(String formatString) throws IllegalArgumentException {
- this(formatString, Locale.getDefault());
+ this(formatString, "");
+ }
+
+ /**
+ * Creates a new date renderer.
+ * <p>
+ * The renderer is configured to render with the given string format, as
+ * displayed in the default locale.
+ *
+ * @param formatString
+ * the format string with which to format the date
+ * @param nullRepresentation
+ * the textual representation of {@code null} value
+ * @throws IllegalArgumentException
+ * if {@code formatString} is {@code null}
+ * @see <a
+ * href="http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html#syntax">Format
+ * String Syntax</a>
+ */
+ public DateRenderer(String formatString, String nullRepresentation) throws IllegalArgumentException {
+ this(formatString, Locale.getDefault(), nullRepresentation);
}
/**
@@ -95,7 +132,29 @@ public class DateRenderer extends AbstractRenderer<Date> {
*/
public DateRenderer(String formatString, Locale locale)
throws IllegalArgumentException {
- super(Date.class);
+ this(formatString,locale, "");
+ }
+ /**
+ * Creates a new date renderer.
+ * <p>
+ * The renderer is configured to render with the given string format, as
+ * displayed in the given locale.
+ *
+ * @param formatString
+ * the format string to format the date with
+ * @param locale
+ * the locale to use
+ * @param nullRepresentation
+ * the textual representation of {@code null} value
+ * @throws IllegalArgumentException
+ * if either argument is {@code null}
+ * @see <a
+ * href="http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html#syntax">Format
+ * String Syntax</a>
+ */
+ public DateRenderer(String formatString, Locale locale, String nullRepresentation)
+ throws IllegalArgumentException {
+ super(Date.class, nullRepresentation);
if (formatString == null) {
throw new IllegalArgumentException("format string may not be null");
@@ -121,7 +180,20 @@ public class DateRenderer extends AbstractRenderer<Date> {
* if {@code dateFormat} is {@code null}
*/
public DateRenderer(DateFormat dateFormat) throws IllegalArgumentException {
- super(Date.class);
+ this(dateFormat, "");
+ }
+ /**
+ * Creates a new date renderer.
+ * <p>
+ * The renderer is configured to render with he given date format.
+ *
+ * @param dateFormat
+ * the date format to use when rendering dates
+ * @throws IllegalArgumentException
+ * if {@code dateFormat} is {@code null}
+ */
+ public DateRenderer(DateFormat dateFormat, String nullRepresentation) throws IllegalArgumentException {
+ super(Date.class, nullRepresentation);
if (dateFormat == null) {
throw new IllegalArgumentException("date format may not be null");
}
@@ -132,9 +204,16 @@ public class DateRenderer extends AbstractRenderer<Date> {
}
@Override
+ public String getNullRepresentation() {
+ return super.getNullRepresentation();
+ }
+
+ @Override
public JsonValue encode(Date value) {
String dateString;
- if (dateFormat != null) {
+ if (value == null) {
+ dateString = getNullRepresentation();
+ } else if (dateFormat != null) {
dateString = dateFormat.format(value);
} else {
dateString = String.format(locale, formatString, value);
diff --git a/server/src/com/vaadin/ui/renderers/HtmlRenderer.java b/server/src/com/vaadin/ui/renderers/HtmlRenderer.java
index 34774b3825..df89c60ad2 100644
--- a/server/src/com/vaadin/ui/renderers/HtmlRenderer.java
+++ b/server/src/com/vaadin/ui/renderers/HtmlRenderer.java
@@ -16,18 +16,33 @@
package com.vaadin.ui.renderers;
import com.vaadin.ui.Grid.AbstractRenderer;
+import elemental.json.JsonValue;
/**
* A renderer for presenting HTML content.
- *
- * @since 7.4
+ *
* @author Vaadin Ltd
+ * @since 7.4
*/
public class HtmlRenderer extends AbstractRenderer<String> {
/**
* Creates a new HTML renderer.
+ *
+ * @param nullRepresentation the html representation of {@code null} value
+ */
+ public HtmlRenderer(String nullRepresentation) {
+ super(String.class, nullRepresentation);
+ }
+
+ /**
+ * Creates a new HTML renderer.
*/
public HtmlRenderer() {
- super(String.class);
+ this("");
+ }
+
+ @Override
+ public String getNullRepresentation() {
+ return super.getNullRepresentation();
}
}
diff --git a/server/src/com/vaadin/ui/renderers/ImageRenderer.java b/server/src/com/vaadin/ui/renderers/ImageRenderer.java
index 4bb3671033..2fb872583e 100644
--- a/server/src/com/vaadin/ui/renderers/ImageRenderer.java
+++ b/server/src/com/vaadin/ui/renderers/ImageRenderer.java
@@ -39,7 +39,7 @@ public class ImageRenderer extends ClickableRenderer<Resource> {
* Creates a new image renderer.
*/
public ImageRenderer() {
- super(Resource.class);
+ super(Resource.class, null);
}
/**
@@ -55,7 +55,7 @@ public class ImageRenderer extends ClickableRenderer<Resource> {
@Override
public JsonValue encode(Resource resource) {
- if (!(resource instanceof ExternalResource || resource instanceof ThemeResource)) {
+ if (!(resource == null || resource instanceof ExternalResource || resource instanceof ThemeResource)) {
throw new IllegalArgumentException(
"ImageRenderer only supports ExternalResource and ThemeResource ("
+ resource.getClass().getSimpleName() + "given )");
diff --git a/server/src/com/vaadin/ui/renderers/NumberRenderer.java b/server/src/com/vaadin/ui/renderers/NumberRenderer.java
index 5c30e55b17..1d4d7e0ec9 100644
--- a/server/src/com/vaadin/ui/renderers/NumberRenderer.java
+++ b/server/src/com/vaadin/ui/renderers/NumberRenderer.java
@@ -24,7 +24,7 @@ import elemental.json.JsonValue;
/**
* A renderer for presenting number values.
- *
+ *
* @since 7.4
* @author Vaadin Ltd
*/
@@ -35,7 +35,7 @@ public class NumberRenderer extends AbstractRenderer<Number> {
/**
* Creates a new number renderer.
- * <p>
+ * <p/>
* The renderer is configured to render with the number's natural string
* representation in the default locale.
*/
@@ -45,18 +45,35 @@ public class NumberRenderer extends AbstractRenderer<Number> {
/**
* Creates a new number renderer.
- * <p>
+ * <p/>
* The renderer is configured to render the number as defined with the given
* number format.
- *
+ *
* @param numberFormat
* the number format with which to display numbers
* @throws IllegalArgumentException
* if {@code numberFormat} is {@code null}
*/
- public NumberRenderer(NumberFormat numberFormat)
+ public NumberRenderer(NumberFormat numberFormat) {
+ this(numberFormat, "");
+ }
+
+ /**
+ * Creates a new number renderer.
+ * <p/>
+ * The renderer is configured to render the number as defined with the given
+ * number format.
+ *
+ * @param numberFormat
+ * the number format with which to display numbers
+ * @param nullRepresentation
+ * the textual representation of {@code null} value
+ * @throws IllegalArgumentException
+ * if {@code numberFormat} is {@code null}
+ */
+ public NumberRenderer(NumberFormat numberFormat, String nullRepresentation)
throws IllegalArgumentException {
- super(Number.class);
+ super(Number.class, nullRepresentation);
if (numberFormat == null) {
throw new IllegalArgumentException("Number format may not be null");
@@ -69,10 +86,10 @@ public class NumberRenderer extends AbstractRenderer<Number> {
/**
* Creates a new number renderer.
- * <p>
+ * <p/>
* The renderer is configured to render with the number's natural string
* representation in the given locale.
- *
+ *
* @param locale
* the locale in which to display numbers
* @throws IllegalArgumentException
@@ -84,12 +101,29 @@ public class NumberRenderer extends AbstractRenderer<Number> {
/**
* Creates a new number renderer.
- * <p>
- * The renderer is configured to render with the given format string in the
- * default locale.
- *
+ * <p/>
+ * The renderer is configured to render with the number's natural string
+ * representation in the given locale.
+ *
* @param formatString
* the format string with which to format the number
+ * @param locale
+ * the locale in which to display numbers
+ * @throws IllegalArgumentException
+ * if {@code locale} is {@code null}
+ */
+ public NumberRenderer(String formatString, Locale locale) throws IllegalArgumentException {
+ this(formatString, locale, ""); //This will call #toString() during formatting
+ }
+
+ /**
+ * Creates a new number renderer.
+ * <p/>
+ * The renderer is configured to render with the given format string in the
+ * default locale.
+ *
+ * @param
+ * formatString the format string with which to format the number
* @throws IllegalArgumentException
* if {@code formatString} is {@code null}
* @see <a
@@ -97,15 +131,15 @@ public class NumberRenderer extends AbstractRenderer<Number> {
* String Syntax</a>
*/
public NumberRenderer(String formatString) throws IllegalArgumentException {
- this(formatString, Locale.getDefault());
+ this(formatString, Locale.getDefault(), "");
}
/**
* Creates a new number renderer.
- * <p>
+ * <p/>
* The renderer is configured to render with the given format string in the
* given locale.
- *
+ *
* @param formatString
* the format string with which to format the number
* @param locale
@@ -116,8 +150,8 @@ public class NumberRenderer extends AbstractRenderer<Number> {
* href="http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html#syntax">Format
* String Syntax</a>
*/
- public NumberRenderer(String formatString, Locale locale) {
- super(Number.class);
+ public NumberRenderer(String formatString, Locale locale, String nullRepresentation) {
+ super(Number.class, nullRepresentation);
if (formatString == null) {
throw new IllegalArgumentException("Format string may not be null");
@@ -135,7 +169,9 @@ public class NumberRenderer extends AbstractRenderer<Number> {
@Override
public JsonValue encode(Number value) {
String stringValue;
- if (formatString != null && locale != null) {
+ if (value == null) {
+ stringValue = getNullRepresentation();
+ } else if (formatString != null && locale != null) {
stringValue = String.format(locale, formatString, value);
} else if (numberFormat != null) {
stringValue = numberFormat.format(value);
@@ -160,4 +196,9 @@ public class NumberRenderer extends AbstractRenderer<Number> {
return String.format("%s [%s]", getClass().getSimpleName(), fieldInfo);
}
+
+ @Override
+ public String getNullRepresentation() {
+ return super.getNullRepresentation();
+ }
}
diff --git a/server/src/com/vaadin/ui/renderers/ProgressBarRenderer.java b/server/src/com/vaadin/ui/renderers/ProgressBarRenderer.java
index a077cd8012..1566c47222 100644
--- a/server/src/com/vaadin/ui/renderers/ProgressBarRenderer.java
+++ b/server/src/com/vaadin/ui/renderers/ProgressBarRenderer.java
@@ -21,9 +21,9 @@ import elemental.json.JsonValue;
/**
* A renderer that represents a double values as a graphical progress bar.
- *
- * @since 7.4
+ *
* @author Vaadin Ltd
+ * @since 7.4
*/
public class ProgressBarRenderer extends AbstractRenderer<Double> {
@@ -31,13 +31,15 @@ public class ProgressBarRenderer extends AbstractRenderer<Double> {
* Creates a new text renderer
*/
public ProgressBarRenderer() {
- super(Double.class);
+ super(Double.class, null);
}
@Override
public JsonValue encode(Double value) {
if (value != null) {
value = Math.max(Math.min(value, 1), 0);
+ } else {
+ value = 0d;
}
return super.encode(value);
}
diff --git a/server/src/com/vaadin/ui/renderers/TextRenderer.java b/server/src/com/vaadin/ui/renderers/TextRenderer.java
index 3723a45f70..0045024b2f 100644
--- a/server/src/com/vaadin/ui/renderers/TextRenderer.java
+++ b/server/src/com/vaadin/ui/renderers/TextRenderer.java
@@ -16,6 +16,7 @@
package com.vaadin.ui.renderers;
import com.vaadin.ui.Grid.AbstractRenderer;
+import elemental.json.JsonValue;
/**
* A renderer for presenting simple plain-text string values.
@@ -29,6 +30,20 @@ public class TextRenderer extends AbstractRenderer<String> {
* Creates a new text renderer
*/
public TextRenderer() {
- super(String.class);
+ this("");
+ }
+
+ /**
+ * Creates a new text renderer
+ * @param nullRepresentation
+ * the textual representation of {@code null} value
+ */
+ public TextRenderer(String nullRepresentation) {
+ super(String.class, nullRepresentation);
+ }
+
+ @Override
+ public String getNullRepresentation() {
+ return super.getNullRepresentation();
}
}