diff options
Diffstat (limited to 'server/src')
36 files changed, 599 insertions, 437 deletions
diff --git a/server/src/com/vaadin/Application.java b/server/src/com/vaadin/Application.java index d4768abfb4..c832645405 100644 --- a/server/src/com/vaadin/Application.java +++ b/server/src/com/vaadin/Application.java @@ -33,6 +33,7 @@ import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.LinkedList; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Map.Entry; @@ -57,6 +58,7 @@ import com.vaadin.terminal.ApplicationResource; import com.vaadin.terminal.CombinedRequest; import com.vaadin.terminal.DeploymentConfiguration; import com.vaadin.terminal.RequestHandler; +import com.vaadin.terminal.RootProvider; import com.vaadin.terminal.Terminal; import com.vaadin.terminal.VariableOwner; import com.vaadin.terminal.WrappedRequest; @@ -504,6 +506,8 @@ public class Application implements Terminal.ErrorListener, Serializable { */ private Set<Integer> initedRoots = new HashSet<Integer>(); + private List<RootProvider> rootProviders = new LinkedList<RootProvider>(); + /** * Gets the user of the application. * @@ -1874,55 +1878,21 @@ public class Application implements Terminal.ErrorListener, Serializable { */ protected Root getRoot(WrappedRequest request) throws RootRequiresMoreInformationException { - String rootClassName = getRootClassName(request); - try { - ClassLoader classLoader = request.getDeploymentConfiguration() - .getClassLoader(); - if (classLoader == null) { - classLoader = getClass().getClassLoader(); - } - Class<? extends Root> rootClass = Class.forName(rootClassName, - true, classLoader).asSubclass(Root.class); - try { - Root root = rootClass.newInstance(); - return root; - } catch (Exception e) { - throw new RuntimeException("Could not instantiate root class " - + rootClassName, e); + + // Iterate in reverse order - test check newest provider first + for (int i = rootProviders.size() - 1; i >= 0; i--) { + RootProvider provider = rootProviders.get(i); + + Class<? extends Root> rootClass = provider.getRootClass(this, + request); + + if (rootClass != null) { + return provider.instantiateRoot(this, rootClass, request); } - } catch (ClassNotFoundException e) { - throw new RuntimeException("Could not load root class " - + rootClassName, e); } - } - /** - * Provides the name of the <code>Root</code> class that should be used for - * a request. The class must have an accessible no-args constructor. - * <p> - * The default implementation uses the {@value #ROOT_PARAMETER} parameter - * from web.xml. - * </p> - * <p> - * This method is mainly used by the default implementation of - * {@link #getRoot(WrappedRequest)}. If you override that method with your - * own functionality, the results of this method might not be used. - * </p> - * - * @param request - * the request for which a new root is required - * @return the name of the root class to use - * - * @since 7.0 - */ - protected String getRootClassName(WrappedRequest request) { - Object rootClassNameObj = getProperties().get(ROOT_PARAMETER); - if (rootClassNameObj instanceof String) { - return (String) rootClassNameObj; - } else { - throw new RuntimeException("No " + ROOT_PARAMETER - + " defined in web.xml"); - } + throw new RuntimeException( + "No root providers available or providers are not able to find root instance"); } /** @@ -2170,6 +2140,14 @@ public class Application implements Terminal.ErrorListener, Serializable { return configuration.isProductionMode(); } + public void addRootProvider(RootProvider rootProvider) { + rootProviders.add(rootProvider); + } + + public void removeRootProvider(RootProvider rootProvider) { + rootProviders.remove(rootProvider); + } + /** * Finds the {@link Root} to which a particular request belongs. If the * request originates from an existing Root, that root is returned. In other diff --git a/server/src/com/vaadin/data/Buffered.java b/server/src/com/vaadin/data/Buffered.java index 5461d34fbd..2472524bbc 100644 --- a/server/src/com/vaadin/data/Buffered.java +++ b/server/src/com/vaadin/data/Buffered.java @@ -83,8 +83,8 @@ public interface Buffered extends Serializable { * * @return <code>true</code> if the object is in write-through mode, * <code>false</code> if it's not. - * @deprecated Use {@link #setBuffered(boolean)} instead. Note that - * setReadThrough(true), setWriteThrough(true) equals + * @deprecated As of 7.0, use {@link #setBuffered(boolean)} instead. Note + * that setReadThrough(true), setWriteThrough(true) equals * setBuffered(false) */ @Deprecated @@ -105,8 +105,8 @@ public interface Buffered extends Serializable { * If the implicit commit operation fails because of a * validation error. * - * @deprecated Use {@link #setBuffered(boolean)} instead. Note that - * setReadThrough(true), setWriteThrough(true) equals + * @deprecated As of 7.0, use {@link #setBuffered(boolean)} instead. Note + * that setReadThrough(true), setWriteThrough(true) equals * setBuffered(false) */ @Deprecated @@ -126,8 +126,8 @@ public interface Buffered extends Serializable { * * @return <code>true</code> if the object is in read-through mode, * <code>false</code> if it's not. - * @deprecated Use {@link #isBuffered(boolean)} instead. Note that - * setReadThrough(true), setWriteThrough(true) equals + * @deprecated As of 7.0, use {@link #isBuffered(boolean)} instead. Note + * that setReadThrough(true), setWriteThrough(true) equals * setBuffered(false) */ @Deprecated @@ -145,8 +145,8 @@ public interface Buffered extends Serializable { * @throws SourceException * If the operation fails because of an exception is thrown by * the data source. The cause is included in the exception. - * @deprecated Use {@link #setBuffered(boolean)} instead. Note that - * setReadThrough(true), setWriteThrough(true) equals + * @deprecated As of 7.0, use {@link #setBuffered(boolean)} instead. Note + * that setReadThrough(true), setWriteThrough(true) equals * setBuffered(false) */ @Deprecated diff --git a/server/src/com/vaadin/data/util/sqlcontainer/ColumnProperty.java b/server/src/com/vaadin/data/util/sqlcontainer/ColumnProperty.java index 3e55633574..0146c92b5c 100644 --- a/server/src/com/vaadin/data/util/sqlcontainer/ColumnProperty.java +++ b/server/src/com/vaadin/data/util/sqlcontainer/ColumnProperty.java @@ -20,6 +20,7 @@ import java.sql.Time; import java.sql.Timestamp; import com.vaadin.data.Property; +import com.vaadin.data.util.converter.Converter.ConversionException; /** * ColumnProperty represents the value of one column in a RowItem. In addition @@ -47,6 +48,7 @@ final public class ColumnProperty implements Property { private boolean modified; private boolean versionColumn; + private boolean primaryKey = false; /** * Prevent instantiation without required parameters. @@ -55,9 +57,50 @@ final public class ColumnProperty implements Property { private ColumnProperty() { } + /** + * Deprecated constructor for ColumnProperty. If this is used the primary + * keys are not identified correctly in some cases for some databases (i.e. + * Oracle). See http://dev.vaadin.com/ticket/9145. + * + * @param propertyId + * @param readOnly + * @param allowReadOnlyChange + * @param nullable + * @param value + * @param type + * + * @deprecated + */ + @Deprecated public ColumnProperty(String propertyId, boolean readOnly, boolean allowReadOnlyChange, boolean nullable, Object value, Class<?> type) { + this(propertyId, readOnly, allowReadOnlyChange, nullable, false, value, + type); + } + + /** + * Creates a new ColumnProperty instance. + * + * @param propertyId + * The ID of this property. + * @param readOnly + * Whether this property is read-only. + * @param allowReadOnlyChange + * Whether the read-only status of this property can be changed. + * @param nullable + * Whether this property accepts null values. + * @param primaryKey + * Whether this property corresponds to a database primary key. + * @param value + * The value of this property. + * @param type + * The type of this property. + */ + public ColumnProperty(String propertyId, boolean readOnly, + boolean allowReadOnlyChange, boolean nullable, boolean primaryKey, + Object value, Class<?> type) { + if (propertyId == null) { throw new IllegalArgumentException("Properties must be named."); } @@ -71,8 +114,15 @@ final public class ColumnProperty implements Property { this.allowReadOnlyChange = allowReadOnlyChange; this.nullable = nullable; this.readOnly = readOnly; + this.primaryKey = primaryKey; } + /** + * Returns the current value for this property. To get the previous value + * (if one exists) for a modified property use {@link #getOldValue()}. + * + * @return + */ @Override public Object getValue() { if (isModified()) { @@ -81,8 +131,20 @@ final public class ColumnProperty implements Property { return value; } + /** + * Returns the original non-modified value of this property if it has been + * modified. + * + * @return The original value if <code>isModified()</code> is true, + * <code>getValue()</code> otherwise. + */ + public Object getOldValue() { + return value; + } + @Override - public void setValue(Object newValue) throws ReadOnlyException { + public void setValue(Object newValue) throws ReadOnlyException, + ConversionException { if (newValue == null && !nullable) { throw new NotNullableException( "Null values are not allowed for this property."); @@ -158,6 +220,17 @@ final public class ColumnProperty implements Property { return readOnly; } + /** + * Returns whether the read-only status of this property can be changed + * using {@link #setReadOnly(boolean)}. + * <p> + * Used to prevent setting to read/write mode a property that is not allowed + * to be written by the underlying database. Also used for values like + * VERSION and AUTO_INCREMENT fields that might be set to read-only by the + * container but the database still allows writes. + * + * @return true if the read-only status can be changed, false otherwise. + */ public boolean isReadOnlyChangeAllowed() { return allowReadOnlyChange; } @@ -169,6 +242,10 @@ final public class ColumnProperty implements Property { } } + public boolean isPrimaryKey() { + return primaryKey; + } + public String getPropertyId() { return propertyId; } @@ -214,6 +291,32 @@ final public class ColumnProperty implements Property { } /** + * Return whether the value of this property should be persisted to the + * database. + * + * @return true if the value should be written to the database, false + * otherwise. + */ + public boolean isPersistent() { + if (isVersionColumn()) { + return false; + } else if (isReadOnlyChangeAllowed() && !isReadOnly()) { + return true; + } else { + return false; + } + } + + /** + * Returns whether or not this property is used as a row identifier. + * + * @return true if the property is a row identifier, false otherwise. + */ + public boolean isRowIdentifier() { + return isPrimaryKey() || isVersionColumn(); + } + + /** * An exception that signals that a <code>null</code> value was passed to * the <code>setValue</code> method, but the value of this property can not * be set to <code>null</code>. diff --git a/server/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java b/server/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java index 78700caee9..f772e2701c 100644 --- a/server/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java +++ b/server/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java @@ -68,7 +68,9 @@ public class SQLContainer implements Container, Container.Filterable, private final List<String> propertyIds = new ArrayList<String>(); private final Map<String, Class<?>> propertyTypes = new HashMap<String, Class<?>>(); private final Map<String, Boolean> propertyReadOnly = new HashMap<String, Boolean>(); + private final Map<String, Boolean> propertyPersistable = new HashMap<String, Boolean>(); private final Map<String, Boolean> propertyNullable = new HashMap<String, Boolean>(); + private final Map<String, Boolean> propertyPrimaryKey = new HashMap<String, Boolean>(); /** Filters (WHERE) and sorters (ORDER BY) */ private final List<Filter> filters = new ArrayList<Filter>(); @@ -150,11 +152,14 @@ public class SQLContainer implements Container, Container.Filterable, List<ColumnProperty> itemProperties = new ArrayList<ColumnProperty>(); for (String propertyId : propertyIds) { /* Default settings for new item properties. */ - itemProperties - .add(new ColumnProperty(propertyId, propertyReadOnly - .get(propertyId), - !propertyReadOnly.get(propertyId), propertyNullable - .get(propertyId), null, getType(propertyId))); + ColumnProperty cp = new ColumnProperty(propertyId, + propertyReadOnly.get(propertyId), + propertyPersistable.get(propertyId), + propertyNullable.get(propertyId), + propertyPrimaryKey.get(propertyId), null, + getType(propertyId)); + + itemProperties.add(cp); } RowItem newRowItem = new RowItem(this, itemId, itemProperties); @@ -546,7 +551,9 @@ public class SQLContainer implements Container, Container.Filterable, @Override public void removeContainerFilter(Filter filter) { filters.remove(filter); - refresh(); + // TODO this cannot be added before ComboBox is fixed + // (Select.requestRepaint() must not affect filter string) + // refresh(); } /** @@ -1141,14 +1148,22 @@ public class SQLContainer implements Container, Container.Filterable, */ boolean readOnly = rsmd.isAutoIncrement(i) || rsmd.isReadOnly(i); - if (delegate instanceof TableQuery - && rsmd.getColumnLabel(i).equals( - ((TableQuery) delegate).getVersionColumn())) { - readOnly = true; + + boolean persistable = !rsmd.isReadOnly(i); + + if (delegate instanceof TableQuery) { + if (rsmd.getColumnLabel(i).equals( + ((TableQuery) delegate).getVersionColumn())) { + readOnly = true; + } } + propertyReadOnly.put(colName, readOnly); + propertyPersistable.put(colName, persistable); propertyNullable.put(colName, rsmd.isNullable(i) == ResultSetMetaData.columnNullable); + propertyPrimaryKey.put(colName, delegate.getPrimaryKeyColumns() + .contains(rsmd.getColumnLabel(i))); propertyTypes.put(colName, type); } rs.getStatement().close(); @@ -1248,10 +1263,13 @@ public class SQLContainer implements Container, Container.Filterable, * column. */ if (propertiesToAdd.contains(colName)) { + cp = new ColumnProperty(colName, propertyReadOnly.get(colName), - !propertyReadOnly.get(colName), - propertyNullable.get(colName), value, type); + propertyPersistable.get(colName), + propertyNullable.get(colName), + propertyPrimaryKey.get(colName), value, + type); itemProperties.add(cp); propertiesToAdd.remove(colName); } diff --git a/server/src/com/vaadin/data/util/sqlcontainer/query/generator/DefaultSQLGenerator.java b/server/src/com/vaadin/data/util/sqlcontainer/query/generator/DefaultSQLGenerator.java index c4b640e274..6ebefcd85c 100644 --- a/server/src/com/vaadin/data/util/sqlcontainer/query/generator/DefaultSQLGenerator.java +++ b/server/src/com/vaadin/data/util/sqlcontainer/query/generator/DefaultSQLGenerator.java @@ -327,10 +327,8 @@ public class DefaultSQLGenerator implements SQLGenerator { && cp.getPropertyId().equalsIgnoreCase("rownum")) { continue; } - Object value = cp.getValue() == null ? null : cp.getValue(); - /* Only include properties whose read-only status can be altered */ - if (cp.isReadOnlyChangeAllowed() && !cp.isVersionColumn()) { - columnToValueMap.put(cp.getPropertyId(), value); + if (cp.isPersistent()) { + columnToValueMap.put(cp.getPropertyId(), cp.getValue()); } } return columnToValueMap; @@ -345,8 +343,16 @@ public class DefaultSQLGenerator implements SQLGenerator { && cp.getPropertyId().equalsIgnoreCase("rownum")) { continue; } - Object value = cp.getValue() == null ? null : cp.getValue(); - if (!cp.isReadOnlyChangeAllowed() || cp.isVersionColumn()) { + + if (cp.isRowIdentifier()) { + Object value; + if (cp.isPrimaryKey()) { + // If the value of a primary key has changed, its old value + // should be used to identify the row (#9145) + value = cp.getOldValue(); + } else { + value = cp.getValue(); + } rowIdentifiers.put(cp.getPropertyId(), value); } } diff --git a/server/src/com/vaadin/terminal/AbstractClientConnector.java b/server/src/com/vaadin/terminal/AbstractClientConnector.java index 0eb38a3d13..bc1cd2af1a 100644 --- a/server/src/com/vaadin/terminal/AbstractClientConnector.java +++ b/server/src/com/vaadin/terminal/AbstractClientConnector.java @@ -518,4 +518,9 @@ public abstract class AbstractClientConnector implements ClientConnector { return getParent().isConnectorEnabled(); } } + + @Override + public void beforeClientResponse(boolean initial) { + // Do nothing by default + } } diff --git a/server/src/com/vaadin/terminal/AbstractRootProvider.java b/server/src/com/vaadin/terminal/AbstractRootProvider.java new file mode 100644 index 0000000000..0b63003440 --- /dev/null +++ b/server/src/com/vaadin/terminal/AbstractRootProvider.java @@ -0,0 +1,35 @@ +/*
+ * Copyright 2011 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.vaadin.terminal;
+
+import com.vaadin.Application;
+import com.vaadin.ui.Root;
+
+public abstract class AbstractRootProvider implements RootProvider {
+
+ @Override
+ public Root instantiateRoot(Application application,
+ Class<? extends Root> type, WrappedRequest request) {
+ try {
+ return type.newInstance();
+ } catch (InstantiationException e) {
+ throw new RuntimeException("Could not instantiate root class", e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException("Could not access root class", e);
+ }
+ }
+}
diff --git a/server/src/com/vaadin/terminal/DefaultRootProvider.java b/server/src/com/vaadin/terminal/DefaultRootProvider.java new file mode 100644 index 0000000000..cbf8c98828 --- /dev/null +++ b/server/src/com/vaadin/terminal/DefaultRootProvider.java @@ -0,0 +1,51 @@ +/*
+ * Copyright 2011 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.vaadin.terminal;
+
+import com.vaadin.Application;
+import com.vaadin.RootRequiresMoreInformationException;
+import com.vaadin.ui.Root;
+
+public class DefaultRootProvider extends AbstractRootProvider {
+
+ @Override
+ public Class<? extends Root> getRootClass(Application application,
+ WrappedRequest request) throws RootRequiresMoreInformationException {
+ Object rootClassNameObj = application
+ .getProperty(Application.ROOT_PARAMETER);
+
+ if (rootClassNameObj instanceof String) {
+ String rootClassName = rootClassNameObj.toString();
+
+ ClassLoader classLoader = request.getDeploymentConfiguration()
+ .getClassLoader();
+ if (classLoader == null) {
+ classLoader = getClass().getClassLoader();
+ }
+ try {
+ Class<? extends Root> rootClass = Class.forName(rootClassName,
+ true, classLoader).asSubclass(Root.class);
+
+ return rootClass;
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException("Could not find root class", e);
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/server/src/com/vaadin/terminal/Page.java b/server/src/com/vaadin/terminal/Page.java index d5d474e2e3..8eb77b7d0d 100644 --- a/server/src/com/vaadin/terminal/Page.java +++ b/server/src/com/vaadin/terminal/Page.java @@ -24,6 +24,7 @@ import java.util.LinkedList; import java.util.List; import com.vaadin.event.EventRouter; +import com.vaadin.shared.ui.BorderStyle; import com.vaadin.shared.ui.root.PageClientRpc; import com.vaadin.shared.ui.root.RootConstants; import com.vaadin.terminal.WrappedRequest.BrowserDetails; @@ -128,7 +129,7 @@ public class Page implements Serializable { /** * The border style of the target window */ - private final int border; + private final BorderStyle border; /** * Creates a new open resource. @@ -145,7 +146,7 @@ public class Page implements Serializable { * The border style of the target window */ private OpenResource(Resource resource, String name, int width, - int height, int border) { + int height, BorderStyle border) { this.resource = resource; this.name = name; this.width = width; @@ -174,10 +175,10 @@ public class Page implements Serializable { target.addAttribute("height", height); } switch (border) { - case BORDER_MINIMAL: + case MINIMAL: target.addAttribute("border", "minimal"); break; - case BORDER_NONE: + case NONE: target.addAttribute("border", "none"); break; } @@ -193,19 +194,20 @@ public class Page implements Serializable { /** * A border style used for opening resources in a window without a border. */ - public static final int BORDER_NONE = 0; + @Deprecated + public static final BorderStyle BORDER_NONE = BorderStyle.NONE; /** * A border style used for opening resources in a window with a minimal * border. */ - public static final int BORDER_MINIMAL = 1; + public static final BorderStyle BORDER_MINIMAL = BorderStyle.MINIMAL; /** * A border style that indicates that the default border style should be * used when opening resources. */ - public static final int BORDER_DEFAULT = 2; + public static final BorderStyle BORDER_DEFAULT = BorderStyle.DEFAULT; /** * Listener that listens changes in URI fragment. @@ -376,23 +378,17 @@ public class Page implements Serializable { .getBrowser(); } - public void setBrowserWindowSize(Integer width, Integer height) { + public void setBrowserWindowSize(int width, int height) { boolean fireEvent = false; - if (width != null) { - int newWidth = width.intValue(); - if (newWidth != browserWindowWidth) { - browserWindowWidth = newWidth; - fireEvent = true; - } + if (width != browserWindowWidth) { + browserWindowWidth = width; + fireEvent = true; } - if (height != null) { - int newHeight = height.intValue(); - if (newHeight != browserWindowHeight) { - browserWindowHeight = newHeight; - fireEvent = true; - } + if (height != browserWindowHeight) { + browserWindowHeight = height; + fireEvent = true; } if (fireEvent) { @@ -587,11 +583,10 @@ public class Page implements Serializable { * @param height * the height of the window in pixels * @param border - * the border style of the window. See {@link #BORDER_NONE - * Window.BORDER_* constants} + * the border style of the window. */ public void open(Resource resource, String windowName, int width, - int height, int border) { + int height, BorderStyle border) { openList.add(new OpenResource(resource, windowName, width, height, border)); root.requestRepaint(); diff --git a/server/src/com/vaadin/terminal/RootProvider.java b/server/src/com/vaadin/terminal/RootProvider.java new file mode 100644 index 0000000000..476cf1bd78 --- /dev/null +++ b/server/src/com/vaadin/terminal/RootProvider.java @@ -0,0 +1,29 @@ +/*
+ * Copyright 2011 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.vaadin.terminal;
+
+import com.vaadin.Application;
+import com.vaadin.RootRequiresMoreInformationException;
+import com.vaadin.ui.Root;
+
+public interface RootProvider {
+ public Class<? extends Root> getRootClass(Application application,
+ WrappedRequest request) throws RootRequiresMoreInformationException;
+
+ public Root instantiateRoot(Application application,
+ Class<? extends Root> type, WrappedRequest request);
+}
diff --git a/server/src/com/vaadin/terminal/Terminal.java b/server/src/com/vaadin/terminal/Terminal.java index 29cb649d54..a02bcb50bb 100644 --- a/server/src/com/vaadin/terminal/Terminal.java +++ b/server/src/com/vaadin/terminal/Terminal.java @@ -25,44 +25,12 @@ import java.io.Serializable; * * @author Vaadin Ltd. * @since 3.0 + * @deprecated Currently only a container for ErrorEvent and ErrorListener */ +@Deprecated public interface Terminal extends Serializable { /** - * Gets the name of the default theme for this terminal. - * - * @return the name of the theme that is used by default by this terminal. - */ - public String getDefaultTheme(); - - /** - * Gets the width of the terminal screen in pixels. This is the width of the - * screen and not the width available for the application. - * <p> - * Note that the screen width is typically not available in the - * {@link com.vaadin.Application#init()} method as this is called before the - * browser has a chance to report the screen size to the server. - * </p> - * - * @return the width of the terminal screen. - */ - public int getScreenWidth(); - - /** - * Gets the height of the terminal screen in pixels. This is the height of - * the screen and not the height available for the application. - * - * <p> - * Note that the screen height is typically not available in the - * {@link com.vaadin.Application#init()} method as this is called before the - * browser has a chance to report the screen size to the server. - * </p> - * - * @return the height of the terminal screen. - */ - public int getScreenHeight(); - - /** * An error event implementation for Terminal. */ public interface ErrorEvent extends Serializable { diff --git a/server/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java b/server/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java index 3099903454..8bb14af45f 100644 --- a/server/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java +++ b/server/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java @@ -68,7 +68,9 @@ import com.vaadin.external.json.JSONException; import com.vaadin.external.json.JSONObject; import com.vaadin.shared.ApplicationConstants; import com.vaadin.shared.Connector; +import com.vaadin.shared.JavaScriptConnectorState; import com.vaadin.shared.Version; +import com.vaadin.shared.communication.LegacyChangeVariablesInvocation; import com.vaadin.shared.communication.MethodInvocation; import com.vaadin.shared.communication.SharedState; import com.vaadin.shared.communication.UidlValue; @@ -822,6 +824,7 @@ public abstract class AbstractCommunicationManager implements Serializable { if (repaintAll) { getClientCache(root).clear(); rootConnectorTracker.markAllConnectorsDirty(); + rootConnectorTracker.markAllClientSidesUninitialized(); // Reset sent locales locales = null; @@ -836,9 +839,9 @@ public abstract class AbstractCommunicationManager implements Serializable { "Found " + dirtyVisibleConnectors.size() + " dirty connectors to paint"); for (ClientConnector connector : dirtyVisibleConnectors) { - if (connector instanceof Component) { - ((Component) connector).updateState(); - } + boolean initialized = rootConnectorTracker + .isClientSideInitialized(connector); + connector.beforeClientResponse(!initialized); } rootConnectorTracker.markAllConnectorsClean(); @@ -887,23 +890,36 @@ public abstract class AbstractCommunicationManager implements Serializable { try { Class<? extends SharedState> stateType = connector .getStateType(); - SharedState referenceState = null; - if (repaintAll) { + Object diffState = rootConnectorTracker + .getDiffState(connector); + if (diffState == null) { + diffState = new JSONObject(); // Use an empty state object as reference for full // repaints - try { - referenceState = stateType.newInstance(); - } catch (Exception e) { - getLogger().log( - Level.WARNING, - "Error creating reference object for state of type " - + stateType.getName()); + boolean emptyInitialState = JavaScriptConnectorState.class + .isAssignableFrom(stateType); + if (!emptyInitialState) { + try { + SharedState referenceState = stateType + .newInstance(); + diffState = JsonCodec.encode(referenceState, + null, stateType, + root.getConnectorTracker()); + } catch (Exception e) { + getLogger().log( + Level.WARNING, + "Error creating reference object for state of type " + + stateType.getName()); + } } + rootConnectorTracker.setDiffState(connector, diffState); } - Object stateJson = JsonCodec.encode(state, referenceState, - stateType, root.getConnectorTracker()); + JSONObject stateJson = (JSONObject) JsonCodec.encode(state, + diffState, stateType, root.getConnectorTracker()); - sharedStates.put(connector.getConnectorId(), stateJson); + if (stateJson.length() != 0) { + sharedStates.put(connector.getConnectorId(), stateJson); + } } catch (JSONException e) { throw new PaintException( "Failed to serialize shared state for connector " @@ -1254,6 +1270,10 @@ public abstract class AbstractCommunicationManager implements Serializable { dragAndDropService.printJSONResponse(outWriter); } + for (ClientConnector connector : dirtyVisibleConnectors) { + rootConnectorTracker.markClientSideInitialized(connector); + } + writePerformanceData(outWriter); } diff --git a/server/src/com/vaadin/terminal/gwt/server/ApplicationServlet.java b/server/src/com/vaadin/terminal/gwt/server/ApplicationServlet.java index 06bc70872d..52885f3fbb 100644 --- a/server/src/com/vaadin/terminal/gwt/server/ApplicationServlet.java +++ b/server/src/com/vaadin/terminal/gwt/server/ApplicationServlet.java @@ -20,6 +20,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import com.vaadin.Application; +import com.vaadin.terminal.DefaultRootProvider; import com.vaadin.terminal.gwt.server.ServletPortletHelper.ApplicationClassException; /** @@ -69,6 +70,7 @@ public class ApplicationServlet extends AbstractApplicationServlet { // Creates a new application instance try { final Application application = getApplicationClass().newInstance(); + application.addRootProvider(new DefaultRootProvider()); return application; } catch (final IllegalAccessException e) { diff --git a/server/src/com/vaadin/terminal/gwt/server/ClientConnector.java b/server/src/com/vaadin/terminal/gwt/server/ClientConnector.java index eef4e240ec..c9fe2563f9 100644 --- a/server/src/com/vaadin/terminal/gwt/server/ClientConnector.java +++ b/server/src/com/vaadin/terminal/gwt/server/ClientConnector.java @@ -157,4 +157,24 @@ public interface ClientConnector extends Connector, RpcTarget { * attached to any Root */ public Root getRoot(); + + /** + * Called before the shared state and RPC invocations are sent to the + * client. Gives the connector an opportunity to set computed/dynamic state + * values or to invoke last minute RPC methods depending on other component + * features. + * <p> + * This method must not alter the component hierarchy in any way. Calling + * requestRepaint() from this method will have no effect. + * </p> + * + * @param initial + * <code>true</code> if the client-side connector will be created + * and initialized after this method has been invoked. + * <code>false</code> if there is already an initialized + * client-side connector. + * + * @since 7.0 + */ + public void beforeClientResponse(boolean initial); } diff --git a/server/src/com/vaadin/terminal/gwt/server/DragAndDropService.java b/server/src/com/vaadin/terminal/gwt/server/DragAndDropService.java index bb96c6e53e..56d5ed1393 100644 --- a/server/src/com/vaadin/terminal/gwt/server/DragAndDropService.java +++ b/server/src/com/vaadin/terminal/gwt/server/DragAndDropService.java @@ -322,4 +322,9 @@ public class DragAndDropService implements VariableOwner, ClientConnector { public Root getRoot() { return null; } + + @Override + public void beforeClientResponse(boolean initial) { + // Nothing to do + } } diff --git a/server/src/com/vaadin/terminal/gwt/server/JsonCodec.java b/server/src/com/vaadin/terminal/gwt/server/JsonCodec.java index 60197b0b3a..892f7ec526 100644 --- a/server/src/com/vaadin/terminal/gwt/server/JsonCodec.java +++ b/server/src/com/vaadin/terminal/gwt/server/JsonCodec.java @@ -165,6 +165,10 @@ public class JsonCodec implements Serializable { } else if (targetType == JSONObject.class || targetType == JSONArray.class) { return value; + } else if (Enum.class.isAssignableFrom(getClassForType(targetType))) { + Class<?> classForType = getClassForType(targetType); + return decodeEnum(classForType.asSubclass(Enum.class), + (String) value); } else { return decodeObject(targetType, (JSONObject) value, connectorTracker); @@ -420,9 +424,8 @@ public class JsonCodec implements Serializable { } } - private static Object decodeEnum(Class<? extends Enum> cls, JSONObject value) { - String enumIdentifier = String.valueOf(value); - return Enum.valueOf(cls, enumIdentifier); + private static Object decodeEnum(Class<? extends Enum> cls, String value) { + return Enum.valueOf(cls, value); } private static String[] decodeStringArray(JSONArray jsonArray) @@ -491,10 +494,6 @@ public class JsonCodec implements Serializable { throws JSONException { Class<?> targetClass = getClassForType(targetType); - if (Enum.class.isAssignableFrom(targetClass)) { - return decodeEnum(targetClass.asSubclass(Enum.class), - serializedObject); - } try { Object decodedObject = targetClass.newInstance(); @@ -527,9 +526,8 @@ public class JsonCodec implements Serializable { } } - public static Object encode(Object value, Object referenceValue, - Type valueType, ConnectorTracker connectorTracker) - throws JSONException { + public static Object encode(Object value, Object diffState, Type valueType, + ConnectorTracker connectorTracker) throws JSONException { if (valueType == null) { throw new IllegalArgumentException("type must be defined"); @@ -596,7 +594,7 @@ public class JsonCodec implements Serializable { } else { // Any object that we do not know how to encode we encode by looping // through fields - return encodeObject(value, referenceValue, connectorTracker); + return encodeObject(value, (JSONObject) diffState, connectorTracker); } } @@ -604,7 +602,7 @@ public class JsonCodec implements Serializable { return JSONObject.NULL; } - private static Object encodeObject(Object value, Object referenceValue, + private static Object encodeObject(Object value, JSONObject diffState, ConnectorTracker connectorTracker) throws JSONException { JSONObject jsonMap = new JSONObject(); @@ -621,10 +619,14 @@ public class JsonCodec implements Serializable { Type fieldType = getterMethod.getGenericReturnType(); Object fieldValue = getterMethod.invoke(value, (Object[]) null); boolean equals = false; - Object referenceFieldValue = null; - if (referenceValue != null) { - referenceFieldValue = getterMethod.invoke(referenceValue, - (Object[]) null); + Object diffStateValue = null; + if (diffState != null && diffState.has(fieldName)) { + diffStateValue = diffState.get(fieldName); + Object referenceFieldValue = decodeInternalOrCustomType( + fieldType, diffStateValue, connectorTracker); + if (JSONObject.NULL.equals(diffStateValue)) { + diffStateValue = null; + } equals = equals(fieldValue, referenceFieldValue); } if (!equals) { @@ -638,8 +640,15 @@ public class JsonCodec implements Serializable { } jsonMap.put( fieldName, - encode(fieldValue, referenceFieldValue, fieldType, + encode(fieldValue, diffStateValue, fieldType, connectorTracker)); + if (diffState != null) { + diffState.put( + fieldName, + encode(fieldValue, null, fieldType, + connectorTracker)); + } + // } else { // System.out.println("Skipping field " + fieldName // + " of type " + fieldType.getName() diff --git a/server/src/com/vaadin/terminal/gwt/server/LegacyChangeVariablesInvocation.java b/server/src/com/vaadin/terminal/gwt/server/LegacyChangeVariablesInvocation.java deleted file mode 100644 index fc3fbd6c00..0000000000 --- a/server/src/com/vaadin/terminal/gwt/server/LegacyChangeVariablesInvocation.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2011 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.terminal.gwt.server; - -import java.util.HashMap; -import java.util.Map; - -import com.vaadin.shared.ApplicationConstants; -import com.vaadin.shared.communication.MethodInvocation; - -public class LegacyChangeVariablesInvocation extends MethodInvocation { - private Map<String, Object> variableChanges = new HashMap<String, Object>(); - - public LegacyChangeVariablesInvocation(String connectorId, - String variableName, Object value) { - super(connectorId, ApplicationConstants.UPDATE_VARIABLE_INTERFACE, - ApplicationConstants.UPDATE_VARIABLE_METHOD); - setVariableChange(variableName, value); - } - - public static boolean isLegacyVariableChange(String interfaceName, - String methodName) { - return ApplicationConstants.UPDATE_VARIABLE_METHOD - .equals(interfaceName) - && ApplicationConstants.UPDATE_VARIABLE_METHOD - .equals(methodName); - } - - public void setVariableChange(String name, Object value) { - variableChanges.put(name, value); - } - - public Map<String, Object> getVariableChanges() { - return variableChanges; - } - -} diff --git a/server/src/com/vaadin/terminal/gwt/server/WebBrowser.java b/server/src/com/vaadin/terminal/gwt/server/WebBrowser.java index 90aef4283d..37bc81cfcf 100644 --- a/server/src/com/vaadin/terminal/gwt/server/WebBrowser.java +++ b/server/src/com/vaadin/terminal/gwt/server/WebBrowser.java @@ -20,7 +20,6 @@ import java.util.Date; import java.util.Locale; import com.vaadin.shared.VBrowserDetails; -import com.vaadin.terminal.Terminal; import com.vaadin.terminal.WrappedRequest; /** @@ -30,7 +29,7 @@ import com.vaadin.terminal.WrappedRequest; * * @author Vaadin Ltd. */ -public class WebBrowser implements Terminal { +public class WebBrowser { private int screenHeight = 0; private int screenWidth = 0; @@ -48,34 +47,21 @@ public class WebBrowser implements Terminal { private long clientServerTimeDelta; /** - * There is no default-theme for this terminal type. + * Gets the height of the screen in pixels. This is the full screen + * resolution and not the height available for the application. * - * @return Always returns null. + * @return the height of the screen in pixels. */ - - @Override - public String getDefaultTheme() { - return null; - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.Terminal#getScreenHeight() - */ - - @Override public int getScreenHeight() { return screenHeight; } - /* - * (non-Javadoc) + /** + * Gets the width of the screen in pixels. This is the full screen + * resolution and not the width available for the application. * - * @see com.vaadin.terminal.Terminal#getScreenWidth() + * @return the width of the screen in pixels. */ - - @Override public int getScreenWidth() { return screenWidth; } diff --git a/server/src/com/vaadin/ui/AbsoluteLayout.java b/server/src/com/vaadin/ui/AbsoluteLayout.java index 9851a79bcd..a3bc577fe3 100644 --- a/server/src/com/vaadin/ui/AbsoluteLayout.java +++ b/server/src/com/vaadin/ui/AbsoluteLayout.java @@ -169,8 +169,8 @@ public class AbsoluteLayout extends AbstractLayout implements } @Override - public void updateState() { - super.updateState(); + public void beforeClientResponse(boolean initial) { + super.beforeClientResponse(initial); // This could be in internalRemoveComponent and internalSetComponent if // Map<Connector,String> was supported. We cannot get the child diff --git a/server/src/com/vaadin/ui/AbstractComponent.java b/server/src/com/vaadin/ui/AbstractComponent.java index fb3993d0cf..cde5217ca1 100644 --- a/server/src/com/vaadin/ui/AbstractComponent.java +++ b/server/src/com/vaadin/ui/AbstractComponent.java @@ -717,13 +717,9 @@ public abstract class AbstractComponent extends AbstractClientConnector return (ComponentState) super.getState(); } - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Component#updateState() - */ @Override - public void updateState() { + public void beforeClientResponse(boolean initial) { + super.beforeClientResponse(initial); // TODO This logic should be on the client side and the state should // simply be a data object with "width" and "height". if (getHeight() >= 0 diff --git a/server/src/com/vaadin/ui/AbstractField.java b/server/src/com/vaadin/ui/AbstractField.java index 2d14acf442..b914fb4c46 100644 --- a/server/src/com/vaadin/ui/AbstractField.java +++ b/server/src/com/vaadin/ui/AbstractField.java @@ -394,8 +394,8 @@ public abstract class AbstractField<T> extends AbstractComponent implements * @throws InvalidValueException * If the implicit commit operation fails because of a * validation error. - * @deprecated Use {@link #setBuffered(boolean)} instead. Note that - * setReadThrough(true), setWriteThrough(true) equals + * @deprecated As of 7.0, use {@link #setBuffered(boolean)} instead. Note + * that setReadThrough(true), setWriteThrough(true) equals * setBuffered(false) */ @Override @@ -435,8 +435,8 @@ public abstract class AbstractField<T> extends AbstractComponent implements * @throws SourceException * If the operation fails because of an exception is thrown by * the data source. The cause is included in the exception. - * @deprecated Use {@link #setBuffered(boolean)} instead. Note that - * setReadThrough(true), setWriteThrough(true) equals + * @deprecated As of 7.0, use {@link #setBuffered(boolean)} instead. Note + * that setReadThrough(true), setWriteThrough(true) equals * setBuffered(false) */ @Override @@ -1620,8 +1620,8 @@ public abstract class AbstractField<T> extends AbstractComponent implements } @Override - public void updateState() { - super.updateState(); + public void beforeClientResponse(boolean initial) { + super.beforeClientResponse(initial); // Hide the error indicator if needed getState().setHideErrors(shouldHideErrors()); diff --git a/server/src/com/vaadin/ui/AbstractLayout.java b/server/src/com/vaadin/ui/AbstractLayout.java index c26812f3fc..dd1d5eab12 100644 --- a/server/src/com/vaadin/ui/AbstractLayout.java +++ b/server/src/com/vaadin/ui/AbstractLayout.java @@ -17,7 +17,6 @@ package com.vaadin.ui; import com.vaadin.shared.ui.AbstractLayoutState; -import com.vaadin.ui.Layout.MarginHandler; /** * An abstract class that defines default implementation for the {@link Layout} @@ -26,62 +25,12 @@ import com.vaadin.ui.Layout.MarginHandler; * @author Vaadin Ltd. * @since 5.0 */ -@SuppressWarnings("serial") public abstract class AbstractLayout extends AbstractComponentContainer - implements Layout, MarginHandler { - - protected MarginInfo margins = new MarginInfo(false); + implements Layout { @Override public AbstractLayoutState getState() { return (AbstractLayoutState) super.getState(); } - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Layout#setMargin(boolean) - */ - @Override - public void setMargin(boolean enabled) { - margins.setMargins(enabled); - getState().setMarginsBitmask(margins.getBitMask()); - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Layout.MarginHandler#getMargin() - */ - @Override - public MarginInfo getMargin() { - return margins; - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Layout.MarginHandler#setMargin(MarginInfo) - */ - @Override - public void setMargin(MarginInfo marginInfo) { - margins.setMargins(marginInfo); - getState().setMarginsBitmask(margins.getBitMask()); - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Layout#setMargin(boolean, boolean, boolean, boolean) - */ - @Override - public void setMargin(boolean topEnabled, boolean rightEnabled, - boolean bottomEnabled, boolean leftEnabled) { - margins.setMargins(topEnabled, rightEnabled, bottomEnabled, leftEnabled); - getState().setMarginsBitmask(margins.getBitMask()); - requestRepaint(); - } - } diff --git a/server/src/com/vaadin/ui/AbstractOrderedLayout.java b/server/src/com/vaadin/ui/AbstractOrderedLayout.java index a7cc780414..3ac4e76bdb 100644 --- a/server/src/com/vaadin/ui/AbstractOrderedLayout.java +++ b/server/src/com/vaadin/ui/AbstractOrderedLayout.java @@ -25,6 +25,7 @@ import com.vaadin.event.LayoutEvents.LayoutClickNotifier; import com.vaadin.shared.Connector; import com.vaadin.shared.EventId; import com.vaadin.shared.MouseEventDetails; +import com.vaadin.shared.ui.MarginInfo; import com.vaadin.shared.ui.orderedlayout.AbstractOrderedLayoutServerRpc; import com.vaadin.shared.ui.orderedlayout.AbstractOrderedLayoutState; import com.vaadin.shared.ui.orderedlayout.AbstractOrderedLayoutState.ChildComponentData; @@ -32,7 +33,8 @@ import com.vaadin.terminal.Sizeable; @SuppressWarnings("serial") public abstract class AbstractOrderedLayout extends AbstractLayout implements - Layout.AlignmentHandler, Layout.SpacingHandler, LayoutClickNotifier { + Layout.AlignmentHandler, Layout.SpacingHandler, LayoutClickNotifier, + Layout.MarginHandler { private AbstractOrderedLayoutServerRpc rpc = new AbstractOrderedLayoutServerRpc() { @@ -392,4 +394,26 @@ public abstract class AbstractOrderedLayout extends AbstractLayout implements return components.get(index); } + public void setMargin(boolean enabled) { + setMargin(new MarginInfo(enabled)); + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.ui.Layout.MarginHandler#getMargin() + */ + public MarginInfo getMargin() { + return new MarginInfo(getState().getMarginsBitmask()); + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.ui.Layout.MarginHandler#setMargin(MarginInfo) + */ + public void setMargin(MarginInfo marginInfo) { + getState().setMarginsBitmask(marginInfo.getBitMask()); + requestRepaint(); + } } diff --git a/server/src/com/vaadin/ui/AbstractTextField.java b/server/src/com/vaadin/ui/AbstractTextField.java index c8bbadd0ab..86315f801f 100644 --- a/server/src/com/vaadin/ui/AbstractTextField.java +++ b/server/src/com/vaadin/ui/AbstractTextField.java @@ -97,8 +97,8 @@ public abstract class AbstractTextField extends AbstractField<String> implements } @Override - public void updateState() { - super.updateState(); + public void beforeClientResponse(boolean initial) { + super.beforeClientResponse(initial); String value = getValue(); if (value == null) { diff --git a/server/src/com/vaadin/ui/Component.java b/server/src/com/vaadin/ui/Component.java index ac668168f2..ff7ed47930 100644 --- a/server/src/com/vaadin/ui/Component.java +++ b/server/src/com/vaadin/ui/Component.java @@ -637,18 +637,6 @@ public interface Component extends ClientConnector, Sizeable, Serializable { public ComponentState getState(); /** - * Called before the shared state is sent to the client. Gives the component - * an opportunity to set computed/dynamic state values e.g. state values - * that depend on other component features. - * <p> - * This method must not alter the component hierarchy in any way. - * </p> - * - * @since 7.0 - */ - public void updateState(); - - /** * Adds an unique id for component that get's transferred to terminal for * testing purposes. Keeping identifiers unique is the responsibility of the * programmer. diff --git a/server/src/com/vaadin/ui/ConnectorTracker.java b/server/src/com/vaadin/ui/ConnectorTracker.java index 12ad377b62..2afe7f9025 100644 --- a/server/src/com/vaadin/ui/ConnectorTracker.java +++ b/server/src/com/vaadin/ui/ConnectorTracker.java @@ -20,6 +20,7 @@ import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.Map; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; @@ -39,7 +40,8 @@ import com.vaadin.terminal.gwt.server.ClientConnector; * Tracks which {@link ClientConnector}s are dirty so they can be updated to the * client when the following response is sent. A connector is dirty when an * operation has been performed on it on the server and as a result of this - * operation new information needs to be sent to its {@link ServerConnector}. + * operation new information needs to be sent to its + * {@link com.vaadin.terminal.gwt.client.ServerConnector}. * </p> * * @author Vaadin Ltd @@ -50,8 +52,10 @@ public class ConnectorTracker implements Serializable { private final HashMap<String, ClientConnector> connectorIdToConnector = new HashMap<String, ClientConnector>(); private Set<ClientConnector> dirtyConnectors = new HashSet<ClientConnector>(); + private Set<ClientConnector> uninitializedConnectors = new HashSet<ClientConnector>(); private Root root; + private Map<ClientConnector, Object> diffStates = new HashMap<ClientConnector, Object>(); /** * Gets a logger for this class @@ -91,6 +95,7 @@ public class ConnectorTracker implements Serializable { .get(connectorId); if (previouslyRegistered == null) { connectorIdToConnector.put(connectorId, connector); + uninitializedConnectors.add(connector); getLogger().fine( "Registered " + connector.getClass().getSimpleName() + " (" + connectorId + ")"); @@ -136,6 +141,49 @@ public class ConnectorTracker implements Serializable { "Unregistered " + connector.getClass().getSimpleName() + " (" + connectorId + ")"); connectorIdToConnector.remove(connectorId); + uninitializedConnectors.remove(connector); + diffStates.remove(connector); + } + + /** + * Checks whether the given connector has already been initialized in the + * browser. The given connector should be registered with this connector + * tracker. + * + * @param connector + * the client connector to check + * @return <code>true</code> if the initial state has previously been sent + * to the browser, <code>false</code> if the client-side doesn't + * already know anything about the connector. + */ + public boolean isClientSideInitialized(ClientConnector connector) { + assert connectorIdToConnector.get(connector.getConnectorId()) == connector : "Connector should be registered with this ConnectorTracker"; + return !uninitializedConnectors.contains(connector); + } + + /** + * Marks the given connector as initialized, meaning that the client-side + * state has been initialized for the connector. + * + * @see #isClientSideInitialized(ClientConnector) + * + * @param connector + * the connector that should be marked as initialized + */ + public void markClientSideInitialized(ClientConnector connector) { + uninitializedConnectors.remove(connector); + } + + /** + * Marks all currently registered connectors as uninitialized. This should + * be done when the client-side has been reset but the server-side state is + * retained. + * + * @see #isClientSideInitialized(ClientConnector) + */ + public void markAllClientSidesUninitialized() { + uninitializedConnectors.addAll(connectorIdToConnector.values()); + diffStates.clear(); } /** @@ -175,6 +223,8 @@ public class ConnectorTracker implements Serializable { "cleanConnectorMap unregistered connector " + getConnectorAndParentInfo(connector) + "). This should have been done when the connector was detached."); + uninitializedConnectors.remove(connector); + diffStates.remove(connector); iterator.remove(); } } @@ -327,4 +377,12 @@ public class ConnectorTracker implements Serializable { return dirtyConnectors; } + public Object getDiffState(ClientConnector connector) { + return diffStates.get(connector); + } + + public void setDiffState(ClientConnector connector, Object diffState) { + diffStates.put(connector, diffState); + } + } diff --git a/server/src/com/vaadin/ui/CssLayout.java b/server/src/com/vaadin/ui/CssLayout.java index c43f347e68..0192debc4a 100644 --- a/server/src/com/vaadin/ui/CssLayout.java +++ b/server/src/com/vaadin/ui/CssLayout.java @@ -197,8 +197,8 @@ public class CssLayout extends AbstractLayout implements LayoutClickNotifier { } @Override - public void updateState() { - super.updateState(); + public void beforeClientResponse(boolean initial) { + super.beforeClientResponse(initial); getState().getChildCss().clear(); for (Iterator<Component> ci = getComponentIterator(); ci.hasNext();) { Component child = ci.next(); diff --git a/server/src/com/vaadin/ui/CustomLayout.java b/server/src/com/vaadin/ui/CustomLayout.java index 2da443bfa5..d47b2f92b3 100644 --- a/server/src/com/vaadin/ui/CustomLayout.java +++ b/server/src/com/vaadin/ui/CustomLayout.java @@ -291,33 +291,6 @@ public class CustomLayout extends AbstractLayout implements Vaadin6Component { requestRepaint(); } - /** - * Although most layouts support margins, CustomLayout does not. The - * behaviour of this layout is determined almost completely by the actual - * template. - * - * @throws UnsupportedOperationException - */ - @Override - public void setMargin(boolean enabled) { - throw new UnsupportedOperationException( - "CustomLayout does not support margins."); - } - - /** - * Although most layouts support margins, CustomLayout does not. The - * behaviour of this layout is determined almost completely by the actual - * template. - * - * @throws UnsupportedOperationException - */ - @Override - public void setMargin(boolean topEnabled, boolean rightEnabled, - boolean bottomEnabled, boolean leftEnabled) { - throw new UnsupportedOperationException( - "CustomLayout does not support margins."); - } - @Override public void changeVariables(Object source, Map<String, Object> variables) { // Nothing to see here diff --git a/server/src/com/vaadin/ui/DateField.java b/server/src/com/vaadin/ui/DateField.java index 5130d665eb..790f3568d5 100644 --- a/server/src/com/vaadin/ui/DateField.java +++ b/server/src/com/vaadin/ui/DateField.java @@ -131,7 +131,7 @@ public class DateField extends AbstractField<Date> implements /** * Resolution identifier: seconds. * - * @deprecated Use {@link Resolution#SECOND} + * @deprecated As of 7.0, use {@link Resolution#SECOND} */ @Deprecated public static final Resolution RESOLUTION_SEC = Resolution.SECOND; @@ -139,7 +139,7 @@ public class DateField extends AbstractField<Date> implements /** * Resolution identifier: minutes. * - * @deprecated Use {@link Resolution#MINUTE} + * @deprecated As of 7.0, use {@link Resolution#MINUTE} */ @Deprecated public static final Resolution RESOLUTION_MIN = Resolution.MINUTE; @@ -147,7 +147,7 @@ public class DateField extends AbstractField<Date> implements /** * Resolution identifier: hours. * - * @deprecated Use {@link Resolution#HOUR} + * @deprecated As of 7.0, use {@link Resolution#HOUR} */ @Deprecated public static final Resolution RESOLUTION_HOUR = Resolution.HOUR; @@ -155,7 +155,7 @@ public class DateField extends AbstractField<Date> implements /** * Resolution identifier: days. * - * @deprecated Use {@link Resolution#DAY} + * @deprecated As of 7.0, use {@link Resolution#DAY} */ @Deprecated public static final Resolution RESOLUTION_DAY = Resolution.DAY; @@ -163,7 +163,7 @@ public class DateField extends AbstractField<Date> implements /** * Resolution identifier: months. * - * @deprecated Use {@link Resolution#MONTH} + * @deprecated As of 7.0, use {@link Resolution#MONTH} */ @Deprecated public static final Resolution RESOLUTION_MONTH = Resolution.MONTH; @@ -171,7 +171,7 @@ public class DateField extends AbstractField<Date> implements /** * Resolution identifier: years. * - * @deprecated Use {@link Resolution#YEAR} + * @deprecated As of 7.0, use {@link Resolution#YEAR} */ @Deprecated public static final Resolution RESOLUTION_YEAR = Resolution.YEAR; diff --git a/server/src/com/vaadin/ui/FormLayout.java b/server/src/com/vaadin/ui/FormLayout.java index c4ba4665ea..15ea478597 100644 --- a/server/src/com/vaadin/ui/FormLayout.java +++ b/server/src/com/vaadin/ui/FormLayout.java @@ -16,6 +16,8 @@ package com.vaadin.ui; +import com.vaadin.shared.ui.MarginInfo; + /** * FormLayout is used by {@link Form} to layout fields. It may also be used * separately without {@link Form}. @@ -36,7 +38,7 @@ public class FormLayout extends AbstractOrderedLayout { public FormLayout() { super(); setSpacing(true); - setMargin(true, false, true, false); + setMargin(new MarginInfo(true, false, true, false)); setWidth(100, UNITS_PERCENTAGE); } diff --git a/server/src/com/vaadin/ui/GridLayout.java b/server/src/com/vaadin/ui/GridLayout.java index 5a748c04f6..b31ab82741 100644 --- a/server/src/com/vaadin/ui/GridLayout.java +++ b/server/src/com/vaadin/ui/GridLayout.java @@ -30,6 +30,7 @@ import com.vaadin.event.LayoutEvents.LayoutClickNotifier; import com.vaadin.shared.Connector; import com.vaadin.shared.EventId; import com.vaadin.shared.MouseEventDetails; +import com.vaadin.shared.ui.MarginInfo; import com.vaadin.shared.ui.gridlayout.GridLayoutServerRpc; import com.vaadin.shared.ui.gridlayout.GridLayoutState; import com.vaadin.terminal.LegacyPaint; @@ -63,8 +64,8 @@ import com.vaadin.terminal.Vaadin6Component; */ @SuppressWarnings("serial") public class GridLayout extends AbstractLayout implements - Layout.AlignmentHandler, Layout.SpacingHandler, LayoutClickNotifier, - Vaadin6Component { + Layout.AlignmentHandler, Layout.SpacingHandler, Layout.MarginHandler, + LayoutClickNotifier, Vaadin6Component { private GridLayoutServerRpc rpc = new GridLayoutServerRpc() { @@ -1416,4 +1417,37 @@ public class GridLayout extends AbstractLayout implements LayoutClickEvent.class, listener); } + /* + * (non-Javadoc) + * + * @see com.vaadin.ui.Layout.MarginHandler#setMargin(boolean) + */ + @Override + public void setMargin(boolean enabled) { + setMargin(new MarginInfo(enabled)); + } + + /* + * (non-Javadoc) + * + * @see + * com.vaadin.ui.Layout.MarginHandler#setMargin(com.vaadin.shared.ui.MarginInfo + * ) + */ + @Override + public void setMargin(MarginInfo marginInfo) { + getState().setMarginsBitmask(marginInfo.getBitMask()); + requestRepaint(); + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.ui.Layout.MarginHandler#getMargin() + */ + @Override + public MarginInfo getMargin() { + return new MarginInfo(getState().getMarginsBitmask()); + } + } diff --git a/server/src/com/vaadin/ui/Layout.java b/server/src/com/vaadin/ui/Layout.java index 6a95d23f8c..9c7cd2b477 100644 --- a/server/src/com/vaadin/ui/Layout.java +++ b/server/src/com/vaadin/ui/Layout.java @@ -18,8 +18,8 @@ package com.vaadin.ui; import java.io.Serializable; -import com.vaadin.shared.ui.VMarginInfo; import com.vaadin.shared.ui.AlignmentInfo.Bits; +import com.vaadin.shared.ui.MarginInfo; /** * Extension to the {@link ComponentContainer} interface which adds the @@ -33,30 +33,6 @@ import com.vaadin.shared.ui.AlignmentInfo.Bits; public interface Layout extends ComponentContainer, Serializable { /** - * Enable layout margins. Affects all four sides of the layout. This will - * tell the client-side implementation to leave extra space around the - * layout. The client-side implementation decides the actual amount, and it - * can vary between themes. - * - * @param enabled - */ - public void setMargin(boolean enabled); - - /** - * Enable specific layout margins. This will tell the client-side - * implementation to leave extra space around the layout in specified edges, - * clockwise from top (top, right, bottom, left). The client-side - * implementation decides the actual amount, and it can vary between themes. - * - * @param top - * @param right - * @param bottom - * @param left - */ - public void setMargin(boolean top, boolean right, boolean bottom, - boolean left); - - /** * AlignmentHandler is most commonly an advanced {@link Layout} that can * align its components. */ @@ -197,6 +173,19 @@ public interface Layout extends ComponentContainer, Serializable { * its components). */ public interface MarginHandler extends Serializable { + + /** + * Enable layout margins. Affects all four sides of the layout. This + * will tell the client-side implementation to leave extra space around + * the layout. The client-side implementation decides the actual amount, + * and it can vary between themes. + * + * @param enabled + * true if margins should be enabled on all sides, false to + * disable all margins + */ + public void setMargin(boolean enabled); + /** * Enable margins for this layout. * @@ -224,16 +213,4 @@ public interface Layout extends ComponentContainer, Serializable { public MarginInfo getMargin(); } - @SuppressWarnings("serial") - public static class MarginInfo extends VMarginInfo implements Serializable { - - public MarginInfo(boolean enabled) { - super(enabled, enabled, enabled, enabled); - } - - public MarginInfo(boolean top, boolean right, boolean bottom, - boolean left) { - super(top, right, bottom, left); - } - } } diff --git a/server/src/com/vaadin/ui/Link.java b/server/src/com/vaadin/ui/Link.java index 57f2088054..ae2934f878 100644 --- a/server/src/com/vaadin/ui/Link.java +++ b/server/src/com/vaadin/ui/Link.java @@ -18,7 +18,7 @@ package com.vaadin.ui; import java.util.Map; -import com.vaadin.terminal.Page; +import com.vaadin.shared.ui.BorderStyle; import com.vaadin.terminal.PaintException; import com.vaadin.terminal.PaintTarget; import com.vaadin.terminal.Resource; @@ -34,19 +34,22 @@ import com.vaadin.terminal.Vaadin6Component; public class Link extends AbstractComponent implements Vaadin6Component { /* Target window border type constant: No window border */ - public static final int TARGET_BORDER_NONE = Page.BORDER_NONE; + @Deprecated + public static final BorderStyle TARGET_BORDER_NONE = BorderStyle.NONE; /* Target window border type constant: Minimal window border */ - public static final int TARGET_BORDER_MINIMAL = Page.BORDER_MINIMAL; + @Deprecated + public static final BorderStyle TARGET_BORDER_MINIMAL = BorderStyle.MINIMAL; /* Target window border type constant: Default window border */ - public static final int TARGET_BORDER_DEFAULT = Page.BORDER_DEFAULT; + @Deprecated + public static final BorderStyle TARGET_BORDER_DEFAULT = BorderStyle.DEFAULT; private Resource resource = null; private String targetName; - private int targetBorder = TARGET_BORDER_DEFAULT; + private BorderStyle targetBorder = BorderStyle.DEFAULT; private int targetWidth = -1; @@ -89,7 +92,7 @@ public class Link extends AbstractComponent implements Vaadin6Component { * */ public Link(String caption, Resource resource, String targetName, - int width, int height, int border) { + int width, int height, BorderStyle border) { setCaption(caption); this.resource = resource; setTargetName(targetName); @@ -131,10 +134,10 @@ public class Link extends AbstractComponent implements Vaadin6Component { // Target window border switch (getTargetBorder()) { - case TARGET_BORDER_MINIMAL: + case MINIMAL: target.addAttribute("border", "minimal"); break; - case TARGET_BORDER_NONE: + case NONE: target.addAttribute("border", "none"); break; } @@ -145,7 +148,7 @@ public class Link extends AbstractComponent implements Vaadin6Component { * * @return the target window border. */ - public int getTargetBorder() { + public BorderStyle getTargetBorder() { return targetBorder; } @@ -183,13 +186,9 @@ public class Link extends AbstractComponent implements Vaadin6Component { * @param targetBorder * the targetBorder to set. */ - public void setTargetBorder(int targetBorder) { - if (targetBorder == TARGET_BORDER_DEFAULT - || targetBorder == TARGET_BORDER_MINIMAL - || targetBorder == TARGET_BORDER_NONE) { - this.targetBorder = targetBorder; - requestRepaint(); - } + public void setTargetBorder(BorderStyle targetBorder) { + this.targetBorder = targetBorder; + requestRepaint(); } /** diff --git a/server/src/com/vaadin/ui/Root.java b/server/src/com/vaadin/ui/Root.java index dd3f016fc9..14abf0f24f 100644 --- a/server/src/com/vaadin/ui/Root.java +++ b/server/src/com/vaadin/ui/Root.java @@ -36,6 +36,7 @@ import com.vaadin.event.MouseEvents.ClickEvent; import com.vaadin.event.MouseEvents.ClickListener; import com.vaadin.shared.EventId; import com.vaadin.shared.MouseEventDetails; +import com.vaadin.shared.ui.BorderStyle; import com.vaadin.shared.ui.root.RootConstants; import com.vaadin.shared.ui.root.RootServerRpc; import com.vaadin.shared.ui.root.RootState; @@ -285,13 +286,12 @@ public abstract class Root extends AbstractComponentContainer implements * @param height * the height of the window in pixels * @param border - * the border style of the window. See {@link #BORDER_NONE - * Window.BORDER_* constants} + * the border style of the window. * @deprecated As of 7.0, use getPage().open instead */ @Deprecated public void open(Resource resource, String windowName, int width, - int height, int border) { + int height, BorderStyle border) { getPage().open(resource, windowName, width, height, border); } @@ -472,6 +472,13 @@ public abstract class Root extends AbstractComponentContainer implements public void click(MouseEventDetails mouseDetails) { fireEvent(new ClickEvent(Root.this, mouseDetails)); } + + @Override + public void resize(int viewWidth, int viewHeight, int windowWidth, + int windowHeight) { + // TODO We're not doing anything with the view dimensions + getPage().setBrowserWindowSize(windowWidth, windowHeight); + } }; /** @@ -637,12 +644,6 @@ public abstract class Root extends AbstractComponentContainer implements .get(RootConstants.FRAGMENT_VARIABLE); getPage().setFragment(fragment, true); } - - if (variables.containsKey("height") || variables.containsKey("width")) { - getPage().setBrowserWindowSize((Integer) variables.get("width"), - (Integer) variables.get("height")); - } - } /* diff --git a/server/src/com/vaadin/ui/Table.java b/server/src/com/vaadin/ui/Table.java index 6f7f88f883..2bbb69beaf 100644 --- a/server/src/com/vaadin/ui/Table.java +++ b/server/src/com/vaadin/ui/Table.java @@ -4470,7 +4470,7 @@ public class Table extends AbstractSelect implements Action.Container, * would support this. * * @return True iff sorting is disabled. - * @deprecated Use {@link #isSortEnabled()} instead + * @deprecated As of 7.0, use {@link #isSortEnabled()} instead */ @Deprecated public boolean isSortDisabled() { @@ -4491,7 +4491,7 @@ public class Table extends AbstractSelect implements Action.Container, * * @param sortDisabled * True iff sorting is disabled. - * @deprecated Use {@link #setSortEnabled(boolean)} instead + * @deprecated As of 7.0, use {@link #setSortEnabled(boolean)} instead */ @Deprecated public void setSortDisabled(boolean sortDisabled) { diff --git a/server/src/com/vaadin/ui/Window.java b/server/src/com/vaadin/ui/Window.java index 13ef7e5784..d1d2c25d8b 100644 --- a/server/src/com/vaadin/ui/Window.java +++ b/server/src/com/vaadin/ui/Window.java @@ -32,7 +32,6 @@ import com.vaadin.event.ShortcutAction.KeyCode; import com.vaadin.event.ShortcutAction.ModifierKey; import com.vaadin.event.ShortcutListener; import com.vaadin.shared.MouseEventDetails; -import com.vaadin.shared.ui.root.RootConstants; import com.vaadin.shared.ui.window.WindowServerRpc; import com.vaadin.shared.ui.window.WindowState; import com.vaadin.terminal.PaintException; @@ -76,10 +75,6 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier, } }; - private int browserWindowWidth = -1; - - private int browserWindowHeight = -1; - /** * Creates a new unnamed window with a default layout. */ @@ -170,20 +165,6 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier, .get("width") != getWidth())) { sizeHasChanged = true; } - Integer browserHeightVar = (Integer) variables - .get(RootConstants.BROWSER_HEIGHT_VAR); - if (browserHeightVar != null - && browserHeightVar.intValue() != browserWindowHeight) { - browserWindowHeight = browserHeightVar.intValue(); - sizeHasChanged = true; - } - Integer browserWidthVar = (Integer) variables - .get(RootConstants.BROWSER_WIDTH_VAR); - if (browserWidthVar != null - && browserWidthVar.intValue() != browserWindowWidth) { - browserWindowWidth = browserWidthVar.intValue(); - sizeHasChanged = true; - } super.changeVariables(source, variables); |