summaryrefslogtreecommitdiffstats
path: root/server/src/com/vaadin
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/com/vaadin')
-rw-r--r--server/src/com/vaadin/data/util/sqlcontainer/query/FreeformQuery.java18
-rw-r--r--server/src/com/vaadin/navigator/Navigator.java8
-rw-r--r--server/src/com/vaadin/server/ComponentSizeValidator.java41
-rw-r--r--server/src/com/vaadin/server/ConnectorResourceHandler.java36
-rw-r--r--server/src/com/vaadin/server/Constants.java2
-rw-r--r--server/src/com/vaadin/server/DownloadStream.java38
-rw-r--r--server/src/com/vaadin/server/FileDownloader.java14
-rw-r--r--server/src/com/vaadin/server/GAEVaadinServlet.java2
-rw-r--r--server/src/com/vaadin/server/ServerRpcManager.java12
-rw-r--r--server/src/com/vaadin/ui/AbstractComponent.java28
-rw-r--r--server/src/com/vaadin/ui/AbstractLayout.java91
-rw-r--r--server/src/com/vaadin/ui/AbstractOrderedLayout.java51
-rw-r--r--server/src/com/vaadin/ui/AbstractTextField.java33
-rw-r--r--server/src/com/vaadin/ui/ComboBox.java7
-rw-r--r--server/src/com/vaadin/ui/Grid.java86
-rw-r--r--server/src/com/vaadin/ui/GridLayout.java22
-rw-r--r--server/src/com/vaadin/ui/Table.java20
-rw-r--r--server/src/com/vaadin/ui/UI.java3
-rw-r--r--server/src/com/vaadin/ui/Window.java15
19 files changed, 367 insertions, 160 deletions
diff --git a/server/src/com/vaadin/data/util/sqlcontainer/query/FreeformQuery.java b/server/src/com/vaadin/data/util/sqlcontainer/query/FreeformQuery.java
index 79a5b6c067..6b800cb965 100644
--- a/server/src/com/vaadin/data/util/sqlcontainer/query/FreeformQuery.java
+++ b/server/src/com/vaadin/data/util/sqlcontainer/query/FreeformQuery.java
@@ -155,8 +155,13 @@ public class FreeformQuery extends AbstractTransactionalQuery implements
pstmt = c.prepareStatement(sh.getQueryString());
sh.setParameterValuesToStatement(pstmt);
rs = pstmt.executeQuery();
- rs.next();
- count = rs.getInt(1);
+ if (rs.next()) {
+ count = rs.getInt(1);
+ } else {
+ // The result can be empty when using group by and there
+ // are no matches (#18043)
+ count = 0;
+ }
} finally {
releaseConnection(c, pstmt, rs);
}
@@ -175,8 +180,13 @@ public class FreeformQuery extends AbstractTransactionalQuery implements
try {
statement = conn.createStatement();
rs = statement.executeQuery(countQuery);
- rs.next();
- count = rs.getInt(1);
+ if (rs.next()) {
+ count = rs.getInt(1);
+ } else {
+ // The result can be empty when using group by and there
+ // are no matches (#18043)
+ count = 0;
+ }
return count;
} finally {
releaseConnection(conn, statement, rs);
diff --git a/server/src/com/vaadin/navigator/Navigator.java b/server/src/com/vaadin/navigator/Navigator.java
index 65b3fec488..bd2b5711f8 100644
--- a/server/src/com/vaadin/navigator/Navigator.java
+++ b/server/src/com/vaadin/navigator/Navigator.java
@@ -745,9 +745,15 @@ public class Navigator implements Serializable {
* the requested view name is found.
*
* @param provider
- * provider to register
+ * provider to register, not <code>null</code>
+ * @throws IllegalArgumentException
+ * if the provided view provider is <code>null</code>
*/
public void addProvider(ViewProvider provider) {
+ if (provider == null) {
+ throw new IllegalArgumentException(
+ "Cannot add a null view provider");
+ }
providers.add(provider);
}
diff --git a/server/src/com/vaadin/server/ComponentSizeValidator.java b/server/src/com/vaadin/server/ComponentSizeValidator.java
index 2d88ae3b53..1fbd840932 100644
--- a/server/src/com/vaadin/server/ComponentSizeValidator.java
+++ b/server/src/com/vaadin/server/ComponentSizeValidator.java
@@ -415,7 +415,7 @@ public class ComponentSizeValidator implements Serializable {
// main window, valid situation
return true;
}
- if (parent.getHeight() < 0) {
+ if (isEffectiveUndefinedHeight(component)) {
// Undefined height
if (parent instanceof Window) {
// Sub window with undefined size has a min-height
@@ -513,10 +513,7 @@ public class ComponentSizeValidator implements Serializable {
// Sub window with undefined size has a min-width
return true;
}
-
- if (parent.getWidth() < 0) {
- // Undefined width
-
+ if (isEffectiveUndefinedWidth(parent)) {
if (parent instanceof AbstractOrderedLayout) {
AbstractOrderedLayout ol = (AbstractOrderedLayout) parent;
boolean horizontal = true;
@@ -591,6 +588,40 @@ public class ComponentSizeValidator implements Serializable {
}
+ /**
+ * Checks if this component will be rendered with undefined width, either
+ * because it has been set to undefined wide or because the parent forces it
+ * to be (100% inside undefined)
+ *
+ */
+ private static boolean isEffectiveUndefinedWidth(Component parent) {
+ if (parent == null) {
+ return false;
+ } else if (parent.getWidth() < 0) {
+ return true;
+ } else if (parent.getWidthUnits() == Unit.PERCENTAGE) {
+ return isEffectiveUndefinedWidth(parent.getParent());
+ }
+ return false;
+ }
+
+ /**
+ * Checks if this component will be rendered with undefined Height, either
+ * because it has been set to undefined wide or because the parent forces it
+ * to be (100% inside undefined)
+ *
+ */
+ private static boolean isEffectiveUndefinedHeight(Component parent) {
+ if (parent == null) {
+ return false;
+ } else if (parent.getHeight() < 0) {
+ return true;
+ } else if (parent.getHeightUnits() == Unit.PERCENTAGE) {
+ return isEffectiveUndefinedHeight(parent.getParent());
+ }
+ return false;
+ }
+
private static boolean hasNonRelativeWidthComponent(Form form) {
Layout layout = form.getLayout();
Layout footer = form.getFooter();
diff --git a/server/src/com/vaadin/server/ConnectorResourceHandler.java b/server/src/com/vaadin/server/ConnectorResourceHandler.java
index 6c486a2d65..8715134773 100644
--- a/server/src/com/vaadin/server/ConnectorResourceHandler.java
+++ b/server/src/com/vaadin/server/ConnectorResourceHandler.java
@@ -30,10 +30,11 @@ import com.vaadin.util.CurrentInstance;
public class ConnectorResourceHandler implements RequestHandler {
// APP/connector/[uiid]/[cid]/[filename.xyz]
+ private static final String CONNECTOR_RESOURCE_PREFIX = "/"
+ + ApplicationConstants.APP_PATH + "/"
+ + ConnectorResource.CONNECTOR_PATH + "/";
private static final Pattern CONNECTOR_RESOURCE_PATTERN = Pattern
- .compile("^/?" + ApplicationConstants.APP_PATH + '/'
- + ConnectorResource.CONNECTOR_PATH + '/'
- + "(\\d+)/(\\d+)/(.*)");
+ .compile("^" + CONNECTOR_RESOURCE_PREFIX + "(\\d+)/(\\d+)/(.*)");
private static Logger getLogger() {
return Logger.getLogger(ConnectorResourceHandler.class.getName());
@@ -44,12 +45,18 @@ public class ConnectorResourceHandler implements RequestHandler {
public boolean handleRequest(VaadinSession session, VaadinRequest request,
VaadinResponse response) throws IOException {
String requestPath = request.getPathInfo();
- if (requestPath == null) {
+ if (requestPath == null
+ || !requestPath.startsWith(CONNECTOR_RESOURCE_PREFIX)) {
return false;
}
Matcher matcher = CONNECTOR_RESOURCE_PATTERN.matcher(requestPath);
if (!matcher.matches()) {
- return false;
+ // This is a connector resource request based on the prefix but the
+ // pattern did not match
+ warnAboutInvalidURLEncoding(requestPath);
+ response.sendError(HttpServletResponse.SC_NOT_FOUND,
+ "Connector resource not found");
+ return true;
}
String uiId = matcher.group(1);
String cid = matcher.group(2);
@@ -102,6 +109,25 @@ public class ConnectorResourceHandler implements RequestHandler {
return true;
}
+ private boolean loggedDecodingWarning = false;
+
+ private void warnAboutInvalidURLEncoding(String requestPath) {
+ if (requestPath.contains("\n") || requestPath.indexOf(0x85) != -1) {
+ // What, path info should not contain a new line or UTF-8 Next Line
+ // (NEL) character, but it does in
+ // Tomcat 7 with default configuration in some cases (URL is encoded
+ // by the browser as UTF-8 and decoded as ISO-8859-1 by Tomcat)
+
+ if (!loggedDecodingWarning) {
+ loggedDecodingWarning = true;
+ getLogger()
+ .warning(
+ "Request path contains a new line character. This typically means that the server is incorrectly configured to use something else than UTF-8 for URL decoding (requestPath: "
+ + requestPath + ")");
+ }
+ }
+ }
+
private static boolean error(VaadinRequest request,
VaadinResponse response, String logMessage) throws IOException {
getLogger().log(Level.WARNING, logMessage);
diff --git a/server/src/com/vaadin/server/Constants.java b/server/src/com/vaadin/server/Constants.java
index 122cce2e74..5a0d852299 100644
--- a/server/src/com/vaadin/server/Constants.java
+++ b/server/src/com/vaadin/server/Constants.java
@@ -67,7 +67,7 @@ public interface Constants {
// Keep the version number in sync with push/build.xml and other locations
// listed in that file
- static final String REQUIRED_ATMOSPHERE_RUNTIME_VERSION = "2.2.4.vaadin8";
+ static final String REQUIRED_ATMOSPHERE_RUNTIME_VERSION = "2.2.7.vaadin1";
static final String INVALID_ATMOSPHERE_VERSION_WARNING = "\n"
+ "=================================================================\n"
diff --git a/server/src/com/vaadin/server/DownloadStream.java b/server/src/com/vaadin/server/DownloadStream.java
index 681c438967..65ef560974 100644
--- a/server/src/com/vaadin/server/DownloadStream.java
+++ b/server/src/com/vaadin/server/DownloadStream.java
@@ -20,6 +20,8 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@@ -40,6 +42,8 @@ import javax.servlet.http.HttpServletResponse;
@SuppressWarnings("serial")
public class DownloadStream implements Serializable {
+ public static final String CONTENT_DISPOSITION = "Content-Disposition";
+
/**
* Maximum cache time.
*/
@@ -280,17 +284,14 @@ public class DownloadStream implements Serializable {
}
}
- // suggest local filename from DownloadStream if
- // Content-Disposition
- // not explicitly set
- String contentDispositionValue = getParameter("Content-Disposition");
- if (contentDispositionValue == null) {
- contentDispositionValue = "filename=\"" + getFileName()
- + "\"";
- response.setHeader("Content-Disposition",
- contentDispositionValue);
+ // Content-Disposition: attachment generally forces download
+ String contentDisposition = getParameter(CONTENT_DISPOSITION);
+ if (contentDisposition == null) {
+ contentDisposition = getContentDispositionFilename(getFileName());
}
+ response.setHeader(CONTENT_DISPOSITION, contentDisposition);
+
int bufferSize = getBufferSize();
if (bufferSize <= 0 || bufferSize > Constants.MAX_BUFFER_SIZE) {
bufferSize = Constants.DEFAULT_BUFFER_SIZE;
@@ -318,6 +319,25 @@ public class DownloadStream implements Serializable {
}
/**
+ * Returns the filename formatted for inclusion in a Content-Disposition
+ * header. Includes both a plain version of the name and a UTF-8 version
+ *
+ * @since 7.4.8
+ * @param filename
+ * The filename to include
+ * @return A value for inclusion in a Content-Disposition header
+ */
+ public static String getContentDispositionFilename(String filename) {
+ try {
+ String encodedFilename = URLEncoder.encode(filename, "UTF-8");
+ return String.format("filename=\"%s\"; filename*=utf-8''%s",
+ encodedFilename, encodedFilename);
+ } catch (UnsupportedEncodingException e) {
+ return null;
+ }
+ }
+
+ /**
* Helper method that tries to close an output stream and ignores any
* exceptions.
*
diff --git a/server/src/com/vaadin/server/FileDownloader.java b/server/src/com/vaadin/server/FileDownloader.java
index 42c2f76e1a..b0c3bb1120 100644
--- a/server/src/com/vaadin/server/FileDownloader.java
+++ b/server/src/com/vaadin/server/FileDownloader.java
@@ -141,12 +141,17 @@ public class FileDownloader extends AbstractExtension {
}
stream = ((ConnectorResource) resource).getStream();
- if (stream.getParameter("Content-Disposition") == null) {
- // Content-Disposition: attachment generally forces download
- stream.setParameter("Content-Disposition",
- "attachment; filename=\"" + stream.getFileName() + "\"");
+ String contentDisposition = stream
+ .getParameter(DownloadStream.CONTENT_DISPOSITION);
+ if (contentDisposition == null) {
+ contentDisposition = "attachment; "
+ + DownloadStream.getContentDispositionFilename(stream
+ .getFileName());
}
+ stream.setParameter(DownloadStream.CONTENT_DISPOSITION,
+ contentDisposition);
+
// Content-Type to block eager browser plug-ins from hijacking
// the file
if (isOverrideContentType()) {
@@ -158,4 +163,5 @@ public class FileDownloader extends AbstractExtension {
stream.writeResponse(request, response);
return true;
}
+
}
diff --git a/server/src/com/vaadin/server/GAEVaadinServlet.java b/server/src/com/vaadin/server/GAEVaadinServlet.java
index df7cd0a66e..6f5c15ebdd 100644
--- a/server/src/com/vaadin/server/GAEVaadinServlet.java
+++ b/server/src/com/vaadin/server/GAEVaadinServlet.java
@@ -57,7 +57,7 @@ import com.google.apphosting.api.DeadlineExceededException;
* &lt;servlet-name&gt;HelloWorld&lt;/servlet-name&gt;
* &lt;servlet-class&gt;com.vaadin.server.GAEApplicationServlet&lt;/servlet-class&gt;
* &lt;init-param&gt;
- * &lt;param-name&gt;application&lt;/param-name&gt;
+ * &lt;param-name&gt;UI&lt;/param-name&gt;
* &lt;param-value&gt;com.vaadin.demo.HelloWorld&lt;/param-value&gt;
* &lt;/init-param&gt;
* &lt;/servlet&gt;
diff --git a/server/src/com/vaadin/server/ServerRpcManager.java b/server/src/com/vaadin/server/ServerRpcManager.java
index 3a2cb3a32c..ae99622a4a 100644
--- a/server/src/com/vaadin/server/ServerRpcManager.java
+++ b/server/src/com/vaadin/server/ServerRpcManager.java
@@ -153,19 +153,9 @@ public class ServerRpcManager<T extends ServerRpc> implements Serializable {
public void applyInvocation(ServerRpcMethodInvocation invocation)
throws RpcInvocationException {
Method method = invocation.getMethod();
- Class<?>[] parameterTypes = method.getParameterTypes();
- Object[] args = new Object[parameterTypes.length];
Object[] arguments = invocation.getParameters();
- for (int i = 0; i < args.length; i++) {
- // no conversion needed for basic cases
- // Class<?> type = parameterTypes[i];
- // if (type.isPrimitive()) {
- // type = boxedTypes.get(type);
- // }
- args[i] = arguments[i];
- }
try {
- method.invoke(implementation, args);
+ method.invoke(implementation, arguments);
} catch (Exception e) {
throw new RpcInvocationException("Unable to invoke method "
+ invocation.getMethodName() + " in "
diff --git a/server/src/com/vaadin/ui/AbstractComponent.java b/server/src/com/vaadin/ui/AbstractComponent.java
index 27d97d5e03..18c3509af7 100644
--- a/server/src/com/vaadin/ui/AbstractComponent.java
+++ b/server/src/com/vaadin/ui/AbstractComponent.java
@@ -243,6 +243,34 @@ public abstract class AbstractComponent extends AbstractClientConnector
}
}
+ /**
+ * Adds or removes a style name. Multiple styles can be specified as a
+ * space-separated list of style names.
+ *
+ * If the {@code add} parameter is true, the style name is added to the
+ * component. If the {@code add} parameter is false, the style name is
+ * removed from the component.
+ * <p>
+ * Functionally this is equivalent to using {@link #addStyleName(String)} or
+ * {@link #removeStyleName(String)}
+ *
+ * @since 7.5
+ * @param style
+ * the style name to be added or removed
+ * @param add
+ * <code>true</code> to add the given style, <code>false</code>
+ * to remove it
+ * @see #addStyleName(String)
+ * @see #removeStyleName(String)
+ */
+ public void setStyleName(String style, boolean add) {
+ if (add) {
+ addStyleName(style);
+ } else {
+ removeStyleName(style);
+ }
+ }
+
/*
* Get's the component's caption. Don't add a JavaDoc comment here, we use
* the default documentation from implemented interface.
diff --git a/server/src/com/vaadin/ui/AbstractLayout.java b/server/src/com/vaadin/ui/AbstractLayout.java
index 9cdb0a326a..0770670680 100644
--- a/server/src/com/vaadin/ui/AbstractLayout.java
+++ b/server/src/com/vaadin/ui/AbstractLayout.java
@@ -16,7 +16,12 @@
package com.vaadin.ui;
+import org.jsoup.nodes.Element;
+
import com.vaadin.shared.ui.AbstractLayoutState;
+import com.vaadin.shared.ui.MarginInfo;
+import com.vaadin.ui.declarative.DesignAttributeHandler;
+import com.vaadin.ui.declarative.DesignContext;
/**
* An abstract class that defines default implementation for the {@link Layout}
@@ -33,4 +38,90 @@ public abstract class AbstractLayout extends AbstractComponentContainer
return (AbstractLayoutState) super.getState();
}
+ /**
+ * Reads margin attributes from a design into a MarginInfo object. This
+ * helper method should be called from the
+ * {@link #readDesign(Element, DesignContext) readDesign} method of layouts
+ * that implement {@link MarginHandler}.
+ *
+ * @since 7.5
+ *
+ * @param design
+ * the design from which to read
+ * @param defMargin
+ * the default margin state for edges that are not set in the
+ * design
+ * @param context
+ * the DesignContext instance used for parsing the design
+ * @return the margin info
+ */
+ protected MarginInfo readMargin(Element design, MarginInfo defMargin,
+ DesignContext context) {
+
+ if (design.hasAttr("margin")) {
+ boolean margin = DesignAttributeHandler.readAttribute("margin",
+ design.attributes(), boolean.class);
+ return new MarginInfo(margin);
+ } else {
+ boolean left = DesignAttributeHandler.readAttribute("margin-left",
+ design.attributes(), defMargin.hasLeft(), boolean.class);
+
+ boolean right = DesignAttributeHandler.readAttribute(
+ "margin-right", design.attributes(), defMargin.hasRight(),
+ boolean.class);
+
+ boolean top = DesignAttributeHandler.readAttribute("margin-top",
+ design.attributes(), defMargin.hasTop(), boolean.class);
+
+ boolean bottom = DesignAttributeHandler.readAttribute(
+ "margin-bottom", design.attributes(),
+ defMargin.hasBottom(), boolean.class);
+
+ return new MarginInfo(top, right, bottom, left);
+ }
+ }
+
+ /**
+ * Writes margin attributes from a MarginInfo object to a design. This
+ * helper method should be called from the
+ * {@link #readDesign(Element, DesignContext) writeDesign} method of layouts
+ * that implement {@link MarginHandler}.
+ *
+ *
+ * @since 7.5
+ *
+ * @param design
+ * the design to write to
+ * @param margin
+ * the margin state to write
+ * @param defMargin
+ * the default margin state to compare against
+ * @param context
+ * the DesignContext instance used for parsing the design
+ */
+ protected void writeMargin(Element design, MarginInfo margin,
+ MarginInfo defMargin, DesignContext context) {
+ if (margin.hasAll()) {
+ DesignAttributeHandler.writeAttribute("margin",
+ design.attributes(), margin.hasAll(), defMargin.hasAll(),
+ boolean.class);
+ } else {
+
+ DesignAttributeHandler.writeAttribute("margin-left",
+ design.attributes(), margin.hasLeft(), defMargin.hasLeft(),
+ boolean.class);
+
+ DesignAttributeHandler.writeAttribute("margin-right",
+ design.attributes(), margin.hasRight(),
+ defMargin.hasRight(), boolean.class);
+
+ DesignAttributeHandler.writeAttribute("margin-top",
+ design.attributes(), margin.hasTop(), defMargin.hasTop(),
+ boolean.class);
+
+ DesignAttributeHandler.writeAttribute("margin-bottom",
+ design.attributes(), margin.hasBottom(),
+ defMargin.hasBottom(), boolean.class);
+ }
+ }
}
diff --git a/server/src/com/vaadin/ui/AbstractOrderedLayout.java b/server/src/com/vaadin/ui/AbstractOrderedLayout.java
index 0214ff4be1..afe4717212 100644
--- a/server/src/com/vaadin/ui/AbstractOrderedLayout.java
+++ b/server/src/com/vaadin/ui/AbstractOrderedLayout.java
@@ -478,30 +478,7 @@ public abstract class AbstractOrderedLayout extends AbstractLayout implements
// process default attributes
super.readDesign(design, designContext);
- // handle margins
- if (design.hasAttr("margin")) {
- setMargin(DesignAttributeHandler.readAttribute("margin",
- design.attributes(), Boolean.class));
- } else {
- boolean marginLeft = DesignAttributeHandler.readAttribute(
- "margin-left", design.attributes(), getMargin().hasLeft(),
- Boolean.class);
-
- boolean marginRight = DesignAttributeHandler.readAttribute(
- "margin-right", design.attributes(),
- getMargin().hasRight(), Boolean.class);
-
- boolean marginTop = DesignAttributeHandler.readAttribute(
- "margin-top", design.attributes(), getMargin().hasTop(),
- Boolean.class);
-
- boolean marginBottom = DesignAttributeHandler.readAttribute(
- "margin-bottom", design.attributes(), getMargin()
- .hasBottom(), Boolean.class);
-
- setMargin(new MarginInfo(marginTop, marginBottom, marginLeft,
- marginRight));
- }
+ setMargin(readMargin(design, getMargin(), designContext));
// handle children
for (Element childComponent : design.children()) {
@@ -557,31 +534,7 @@ public abstract class AbstractOrderedLayout extends AbstractLayout implements
AbstractOrderedLayout def = (AbstractOrderedLayout) designContext
.getDefaultInstance(this);
- // handle margin
- MarginInfo marginInfo = getMargin();
-
- if (marginInfo.hasAll()) {
- DesignAttributeHandler.writeAttribute("margin",
- design.attributes(), marginInfo.hasAll(), def.getMargin()
- .hasAll(), Boolean.class);
- } else {
-
- DesignAttributeHandler.writeAttribute("margin-left", design
- .attributes(), marginInfo.hasLeft(), def.getMargin()
- .hasLeft(), Boolean.class);
-
- DesignAttributeHandler.writeAttribute("margin-right", design
- .attributes(), marginInfo.hasRight(), def.getMargin()
- .hasRight(), Boolean.class);
-
- DesignAttributeHandler.writeAttribute("margin-top", design
- .attributes(), marginInfo.hasTop(), def.getMargin()
- .hasTop(), Boolean.class);
-
- DesignAttributeHandler.writeAttribute("margin-bottom", design
- .attributes(), marginInfo.hasBottom(), def.getMargin()
- .hasBottom(), Boolean.class);
- }
+ writeMargin(design, getMargin(), def.getMargin(), designContext);
// handle children
if (!designContext.shouldWriteChildren(this, def)) {
diff --git a/server/src/com/vaadin/ui/AbstractTextField.java b/server/src/com/vaadin/ui/AbstractTextField.java
index 93025ac0fd..14c135228c 100644
--- a/server/src/com/vaadin/ui/AbstractTextField.java
+++ b/server/src/com/vaadin/ui/AbstractTextField.java
@@ -126,25 +126,22 @@ public abstract class AbstractTextField extends AbstractField<String> implements
selectionPosition = -1;
}
- if (hasListeners(TextChangeEvent.class)) {
- target.addAttribute(TextFieldConstants.ATTR_TEXTCHANGE_EVENTMODE,
- getTextChangeEventMode().toString());
- target.addAttribute(TextFieldConstants.ATTR_TEXTCHANGE_TIMEOUT,
- getTextChangeTimeout());
- if (lastKnownTextContent != null) {
- /*
- * The field has be repainted for some reason (e.g. caption,
- * size, stylename), but the value has not been changed since
- * the last text change event. Let the client side know about
- * the value the server side knows. Client side may then ignore
- * the actual value, depending on its state.
- */
- target.addAttribute(
- TextFieldConstants.ATTR_NO_VALUE_CHANGE_BETWEEN_PAINTS,
- true);
- }
+ target.addAttribute(TextFieldConstants.ATTR_TEXTCHANGE_EVENTMODE,
+ getTextChangeEventMode().toString());
+ target.addAttribute(TextFieldConstants.ATTR_TEXTCHANGE_TIMEOUT,
+ getTextChangeTimeout());
+ if (lastKnownTextContent != null) {
+ /*
+ * The field has be repainted for some reason (e.g. caption, size,
+ * stylename), but the value has not been changed since the last
+ * text change event. Let the client side know about the value the
+ * server side knows. Client side may then ignore the actual value,
+ * depending on its state.
+ */
+ target.addAttribute(
+ TextFieldConstants.ATTR_NO_VALUE_CHANGE_BETWEEN_PAINTS,
+ true);
}
-
}
@Override
diff --git a/server/src/com/vaadin/ui/ComboBox.java b/server/src/com/vaadin/ui/ComboBox.java
index 4af93113f9..033ec3cd14 100644
--- a/server/src/com/vaadin/ui/ComboBox.java
+++ b/server/src/com/vaadin/ui/ComboBox.java
@@ -288,6 +288,13 @@ public class ComboBox extends AbstractSelect implements
// Paint variables
target.addVariable(this, "selected", selectedKeys);
+ if (getValue() != null && selectedKeys[0] == null) {
+ // not always available, e.g. scrollToSelectedIndex=false
+ // Give the caption for selected item still, not to make it look
+ // like there is no selection at all
+ target.addAttribute("selectedCaption",
+ getItemCaption(getValue()));
+ }
if (isNewItemsAllowed()) {
target.addVariable(this, "newitem", "");
}
diff --git a/server/src/com/vaadin/ui/Grid.java b/server/src/com/vaadin/ui/Grid.java
index 68676e5435..b0542352b9 100644
--- a/server/src/com/vaadin/ui/Grid.java
+++ b/server/src/com/vaadin/ui/Grid.java
@@ -57,7 +57,6 @@ import com.vaadin.data.RpcDataProviderExtension.DetailComponentManager;
import com.vaadin.data.Validator.InvalidValueException;
import com.vaadin.data.fieldgroup.DefaultFieldGroupFieldFactory;
import com.vaadin.data.fieldgroup.FieldGroup;
-import com.vaadin.data.fieldgroup.FieldGroup.BindException;
import com.vaadin.data.fieldgroup.FieldGroup.CommitException;
import com.vaadin.data.fieldgroup.FieldGroupFieldFactory;
import com.vaadin.data.sort.Sort;
@@ -2536,9 +2535,10 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
private Converter<?, Object> converter;
/**
- * A check for allowing the {@link #Column(Grid, GridColumnState, Object)
- * constructor} to call {@link #setConverter(Converter)} with a
- * <code>null</code>, even if model and renderer aren't compatible.
+ * A check for allowing the
+ * {@link #Column(Grid, GridColumnState, Object) constructor} to call
+ * {@link #setConverter(Converter)} with a <code>null</code>, even if
+ * model and renderer aren't compatible.
*/
private boolean isFirstConverterAssignment = true;
@@ -2598,7 +2598,9 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
}
/**
- * Sets the caption of the header.
+ * Sets the caption of the header. This caption is also used as the
+ * hiding toggle caption, unless it is explicitly set via
+ * {@link #setHidingToggleCaption(String)}.
*
* @param caption
* the text to show in the caption
@@ -2610,6 +2612,9 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
public Column setHeaderCaption(String caption)
throws IllegalStateException {
checkColumnIsAttached();
+
+ state.headerCaption = caption;
+
HeaderRow row = grid.getHeader().getDefaultRow();
if (row != null) {
row.getCell(grid.getPropertyIdByColumnId(state.id)).setText(
@@ -2637,11 +2642,11 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
* toggle for this column in the grid's sidebar when the column is
* {@link #isHidable() hidable}.
* <p>
- * By default, before triggering this setter, a user friendly version of
- * the column's {@link #getPropertyId() property id} is used.
+ * The default value is <code>null</code>, and in that case the column's
+ * {@link #getHeaderCaption() header caption} is used.
* <p>
- * <em>NOTE:</em> setting this to <code>null</code> or empty string
- * might cause the hiding toggle to not render correctly.
+ * <em>NOTE:</em> setting this to empty string might cause the hiding
+ * toggle to not render correctly.
*
* @since 7.5.0
* @param hidingToggleCaption
@@ -3302,9 +3307,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
DesignAttributeHandler.writeAttribute("hidden", attributes,
isHidden(), def.hidden, boolean.class);
DesignAttributeHandler.writeAttribute("hiding-toggle-caption",
- attributes, getHidingToggleCaption(),
- SharedUtil.propertyIdToHumanFriendly(getPropertyId()),
- String.class);
+ attributes, getHidingToggleCaption(), null, String.class);
DesignAttributeHandler.writeAttribute("property-id", attributes,
getPropertyId(), null, Object.class);
}
@@ -3372,7 +3375,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
* 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.
- *
+ *
* @param <T>
* the type this renderer knows how to present
*/
@@ -3445,7 +3448,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
* is desired. For instance, a {@code Renderer<Date>} could first turn a
* date value into a formatted string and return
* {@code encode(dateString, String.class)}.
- *
+ *
* @param value
* the value to be encoded
* @param type
@@ -3460,7 +3463,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
/**
* An abstract base class for server-side Grid extensions.
- *
+ *
* @since 7.5
*/
public static abstract class AbstractGridExtension extends
@@ -3475,7 +3478,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
/**
* Constructs a new Grid extension and extends given Grid.
- *
+ *
* @param grid
* a grid instance
*/
@@ -3977,7 +3980,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
@Override
public void bind(int rowIndex) {
- boolean success = false;
+ Exception exception = null;
try {
Object id = getContainerDataSource().getIdByIndex(rowIndex);
if (!isEditorBuffered() || editedItemId == null) {
@@ -3986,12 +3989,19 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
if (editedItemId.equals(id)) {
doEditItem();
- success = true;
}
} catch (Exception e) {
- handleError(e);
+ exception = e;
+ }
+
+ if (exception != null) {
+ handleError(exception);
+ doCancelEditor();
+ getEditorRpc().confirmBind(false);
+ } else {
+ doEditItem();
+ getEditorRpc().confirmBind(true);
}
- getEditorRpc().confirmBind(success);
}
@Override
@@ -4248,8 +4258,18 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
if (datasource.getContainerPropertyIds().contains(propertyId)
&& !columns.containsKey(propertyId)) {
appendColumn(propertyId);
- } else {
+ } else if (defaultContainer) {
addColumnProperty(propertyId, String.class, "");
+ } else {
+ if (columns.containsKey(propertyId)) {
+ throw new IllegalStateException("A column for property id '"
+ + propertyId.toString()
+ + "' already exists in this grid");
+ } else {
+ throw new IllegalStateException("Property id '"
+ + propertyId.toString()
+ + "' does not exist in the container");
+ }
}
// Inform the data provider of this new column.
@@ -4418,7 +4438,6 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
String humanFriendlyPropertyId = SharedUtil
.propertyIdToHumanFriendly(String.valueOf(datasourcePropertyId));
column.setHeaderCaption(humanFriendlyPropertyId);
- column.setHidingToggleCaption(humanFriendlyPropertyId);
if (datasource instanceof Sortable
&& ((Sortable) datasource).getSortableContainerPropertyIds()
@@ -4628,8 +4647,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
* @throws IllegalArgumentException
* if {@code rows} is zero or less
* @throws IllegalArgumentException
- * if {@code rows} is {@link Double#isInfinite(double)
- * infinite}
+ * if {@code rows} is {@link Double#isInfinite(double) infinite}
* @throws IllegalArgumentException
* if {@code rows} is {@link Double#isNaN(double) NaN}
*/
@@ -5803,13 +5821,20 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
}
Field<?> editor = editorFieldGroup.getField(propertyId);
- if (editor == null) {
- editor = editorFieldGroup.buildAndBind(propertyId);
- }
- if (editor.getParent() != Grid.this) {
- assert editor.getParent() == null;
- editor.setParent(this);
+ try {
+ if (editor == null) {
+ editor = editorFieldGroup.buildAndBind(propertyId);
+ }
+ } finally {
+ if (editor == null) {
+ editor = editorFieldGroup.getField(propertyId);
+ }
+
+ if (editor != null && editor.getParent() != Grid.this) {
+ assert editor.getParent() == null;
+ editor.setParent(this);
+ }
}
return editor;
}
@@ -5905,6 +5930,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
protected void doCancelEditor() {
editedItemId = null;
editorFieldGroup.discard();
+ editorFieldGroup.setItemDataSource(null);
}
void resetEditor() {
diff --git a/server/src/com/vaadin/ui/GridLayout.java b/server/src/com/vaadin/ui/GridLayout.java
index 35110b39ab..6ccb272704 100644
--- a/server/src/com/vaadin/ui/GridLayout.java
+++ b/server/src/com/vaadin/ui/GridLayout.java
@@ -782,7 +782,14 @@ public class GridLayout extends AbstractLayout implements
}
}
}
- // TODO forget expands for removed columns
+
+ // Forget expands for removed columns
+ if (columns < getColumns()) {
+ for (int i = columns - 1; i < getColumns(); i++) {
+ columnExpandRatio.remove(i);
+ getState().explicitColRatios.remove(i);
+ }
+ }
getState().columns = columns;
}
@@ -826,7 +833,13 @@ public class GridLayout extends AbstractLayout implements
}
}
}
- // TODO forget expands for removed rows
+ // Forget expands for removed rows
+ if (rows < getRows()) {
+ for (int i = rows - 1; i < getRows(); i++) {
+ rowExpandRatio.remove(i);
+ getState().explicitRowRatios.remove(i);
+ }
+ }
getState().rows = rows;
}
@@ -1304,6 +1317,8 @@ public class GridLayout extends AbstractLayout implements
public void readDesign(Element design, DesignContext designContext) {
super.readDesign(design, designContext);
+ setMargin(readMargin(design, getMargin(), designContext));
+
// Prepare a 2D map for reading column contents
Elements rowElements = design.getElementsByTag("row");
List<Map<Integer, Component>> rows = new ArrayList<Map<Integer, Component>>();
@@ -1434,6 +1449,9 @@ public class GridLayout extends AbstractLayout implements
super.writeDesign(design, designContext);
GridLayout def = designContext.getDefaultInstance(this);
+
+ writeMargin(design, getMargin(), def.getMargin(), designContext);
+
if (components.isEmpty()
|| !designContext.shouldWriteChildren(this, def)) {
return;
diff --git a/server/src/com/vaadin/ui/Table.java b/server/src/com/vaadin/ui/Table.java
index cb61fa31ec..42c4beab6c 100644
--- a/server/src/com/vaadin/ui/Table.java
+++ b/server/src/com/vaadin/ui/Table.java
@@ -676,26 +676,6 @@ public class Table extends AbstractSelect implements Action.Container,
}
}
- // Removes alignments, icons and headers from hidden columns
- if (this.visibleColumns != null) {
- boolean disabledHere = disableContentRefreshing();
- try {
- for (final Iterator<Object> i = this.visibleColumns.iterator(); i
- .hasNext();) {
- final Object col = i.next();
- if (!newVC.contains(col)) {
- setColumnHeader(col, null);
- setColumnAlignment(col, (Align) null);
- setColumnIcon(col, null);
- }
- }
- } finally {
- if (disabledHere) {
- enableContentRefreshing(false);
- }
- }
- }
-
this.visibleColumns = newVC;
// Assures visual refresh
diff --git a/server/src/com/vaadin/ui/UI.java b/server/src/com/vaadin/ui/UI.java
index b16d7e32d3..2129db614b 100644
--- a/server/src/com/vaadin/ui/UI.java
+++ b/server/src/com/vaadin/ui/UI.java
@@ -718,6 +718,9 @@ public abstract class UI extends AbstractSingleComponentContainer implements
page.init(request);
+ // Reset heartbeat timeout to avoid surprise if it's almost expired
+ setLastHeartbeatTimestamp(System.currentTimeMillis());
+
refresh(request);
URI newLocation = page.getLocation();
diff --git a/server/src/com/vaadin/ui/Window.java b/server/src/com/vaadin/ui/Window.java
index 61664fc95d..61ba5826b8 100644
--- a/server/src/com/vaadin/ui/Window.java
+++ b/server/src/com/vaadin/ui/Window.java
@@ -268,6 +268,21 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
}
/**
+ * Sets the position of the window on the screen using
+ * {@link #setPositionX(int)} and {@link #setPositionY(int)}
+ *
+ * @since 7.5
+ * @param x
+ * The new x coordinate for the window
+ * @param y
+ * The new y coordinate for the window
+ */
+ public void setPosition(int x, int y) {
+ setPositionX(x);
+ setPositionY(y);
+ }
+
+ /**
* Sets the distance of Window left border in pixels from left border of the
* containing (main window). Has effect only if in {@link WindowMode#NORMAL}
* mode.