diff options
35 files changed, 611 insertions, 15 deletions
diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/ConnectorBundleLoaderFactory.java b/client-compiler/src/com/vaadin/server/widgetsetutils/ConnectorBundleLoaderFactory.java index 7c3bb1eb77..13bd7051f6 100644 --- a/client-compiler/src/com/vaadin/server/widgetsetutils/ConnectorBundleLoaderFactory.java +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/ConnectorBundleLoaderFactory.java @@ -68,6 +68,7 @@ import com.vaadin.server.widgetsetutils.metadata.TypeVisitor; import com.vaadin.server.widgetsetutils.metadata.WidgetInitVisitor; import com.vaadin.shared.annotations.Delayed; import com.vaadin.shared.annotations.DelegateToWidget; +import com.vaadin.shared.annotations.NoLayout; import com.vaadin.shared.communication.ClientRpc; import com.vaadin.shared.communication.ServerRpc; import com.vaadin.shared.ui.Connect; @@ -454,6 +455,10 @@ public class ConnectorBundleLoaderFactory extends Generator { writer.println("var data = {"); writer.indent(); + if (property.getAnnotation(NoLayout.class) != null) { + writer.println("noLayout: 1, "); + } + writer.println("setter: function(bean, value) {"); writer.indent(); property.writeSetterBody(logger, writer, "bean", "value"); @@ -497,6 +502,7 @@ public class ConnectorBundleLoaderFactory extends Generator { writeParamTypes(w, bundle); writeProxys(w, bundle); writeDelayedInfo(w, bundle); + writeNoLayoutRpcMethods(w, bundle); w.println("%s(store);", loadNativeJsMethodName); @@ -509,6 +515,22 @@ public class ConnectorBundleLoaderFactory extends Generator { writeOnStateChangeHandlers(logger, w, bundle); } + private void writeNoLayoutRpcMethods(SplittingSourceWriter w, + ConnectorBundle bundle) { + Map<JClassType, Set<JMethod>> needsNoLayout = bundle + .getNeedsNoLayoutRpcMethods(); + for (Entry<JClassType, Set<JMethod>> entry : needsNoLayout.entrySet()) { + JClassType type = entry.getKey(); + + for (JMethod method : entry.getValue()) { + w.println("store.setNoLayoutRpcMethod(%s, \"%s\");", + getClassLiteralString(type), method.getName()); + } + + w.splitIfNeeded(); + } + } + private void writeOnStateChangeHandlers(TreeLogger logger, SplittingSourceWriter w, ConnectorBundle bundle) throws UnableToCompleteException { diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ClientRpcVisitor.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ClientRpcVisitor.java index 856f67657f..1df3d78588 100644 --- a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ClientRpcVisitor.java +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ClientRpcVisitor.java @@ -24,6 +24,7 @@ import com.google.gwt.core.ext.UnableToCompleteException; import com.google.gwt.core.ext.typeinfo.JClassType; import com.google.gwt.core.ext.typeinfo.JMethod; import com.google.gwt.core.ext.typeinfo.JType; +import com.vaadin.shared.annotations.NoLayout; public class ClientRpcVisitor extends TypeVisitor { @Override @@ -39,6 +40,9 @@ public class ClientRpcVisitor extends TypeVisitor { bundle.setNeedsInvoker(type, method); bundle.setNeedsParamTypes(type, method); + if (method.getAnnotation(NoLayout.class) != null) { + bundle.setNeedsNoLayoutRpcMethod(type, method); + } JType[] parameterTypes = method.getParameterTypes(); for (JType paramType : parameterTypes) { diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ConnectorBundle.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ConnectorBundle.java index 4a079c38b0..2c2d091d5e 100644 --- a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ConnectorBundle.java +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ConnectorBundle.java @@ -73,6 +73,7 @@ public class ConnectorBundle { private final Map<JClassType, Set<JMethod>> needsParamTypes = new HashMap<JClassType, Set<JMethod>>(); private final Map<JClassType, Set<JMethod>> needsDelayedInfo = new HashMap<JClassType, Set<JMethod>>(); private final Map<JClassType, Set<JMethod>> needsOnStateChange = new HashMap<JClassType, Set<JMethod>>(); + private final Map<JClassType, Set<JMethod>> needsNoLayoutRpcMethods = new HashMap<JClassType, Set<JMethod>>(); private final Set<Property> needsProperty = new HashSet<Property>(); private final Map<JClassType, Set<Property>> needsDelegateToWidget = new HashMap<JClassType, Set<Property>>(); @@ -634,6 +635,25 @@ public class ConnectorBundle { return Collections.unmodifiableMap(needsOnStateChange); } + public void setNeedsNoLayoutRpcMethod(JClassType type, JMethod method) { + if (!isNeedsNoLayoutRpcMethod(type, method)) { + addMapping(needsNoLayoutRpcMethods, type, method); + } + } + + private boolean isNeedsNoLayoutRpcMethod(JClassType type, JMethod method) { + if (hasMapping(needsNoLayoutRpcMethods, type, method)) { + return true; + } else { + return previousBundle != null + && previousBundle.isNeedsNoLayoutRpcMethod(type, method); + } + } + + public Map<JClassType, Set<JMethod>> getNeedsNoLayoutRpcMethods() { + return Collections.unmodifiableMap(needsNoLayoutRpcMethods); + } + public static JMethod findInheritedMethod(JClassType type, String methodName, JType... params) { diff --git a/client/src/com/vaadin/client/ApplicationConnection.java b/client/src/com/vaadin/client/ApplicationConnection.java index cba9639067..dd780406fa 100644 --- a/client/src/com/vaadin/client/ApplicationConnection.java +++ b/client/src/com/vaadin/client/ApplicationConnection.java @@ -100,6 +100,7 @@ import com.vaadin.shared.AbstractComponentState; import com.vaadin.shared.ApplicationConstants; import com.vaadin.shared.JsonConstants; import com.vaadin.shared.Version; +import com.vaadin.shared.annotations.NoLayout; import com.vaadin.shared.communication.LegacyChangeVariablesInvocation; import com.vaadin.shared.communication.MethodInvocation; import com.vaadin.shared.communication.SharedState; @@ -1541,6 +1542,8 @@ public class ApplicationConnection implements HasHandlers { } Command c = new Command() { + private boolean onlyNoLayoutUpdates = true; + @Override public void execute() { assert syncId == -1 || syncId == lastSeenServerSyncId; @@ -1630,15 +1633,17 @@ public class ApplicationConnection implements HasHandlers { + (Duration.currentTimeMillis() - processUidlStart) + " ms"); - Profiler.enter("Layout processing"); - try { - LayoutManager layoutManager = getLayoutManager(); - layoutManager.setEverythingNeedsMeasure(); - layoutManager.layoutNow(); - } catch (final Throwable e) { - VConsole.error(e); + if (!onlyNoLayoutUpdates) { + Profiler.enter("Layout processing"); + try { + LayoutManager layoutManager = getLayoutManager(); + layoutManager.setEverythingNeedsMeasure(); + layoutManager.layoutNow(); + } catch (final Throwable e) { + VConsole.error(e); + } + Profiler.leave("Layout processing"); } - Profiler.leave("Layout processing"); if (ApplicationConfiguration.isDebugMode()) { Profiler.enter("Dumping state changes to the console"); @@ -1942,6 +1947,11 @@ public class ApplicationConnection implements HasHandlers { if (connector != null) { continue; } + + // Always do layouts if there's at least one new + // connector + onlyNoLayoutUpdates = false; + int connectorType = Integer.parseInt(types .getString(connectorId)); @@ -1983,6 +1993,11 @@ public class ApplicationConnection implements HasHandlers { JsArray<ValueMap> changes = json.getJSValueMapArray("changes"); int length = changes.length(); + // Must always do layout if there's even a single legacy update + if (length != 0) { + onlyNoLayoutUpdates = false; + } + VConsole.log(" * Passing UIDL to Vaadin 6 style connectors"); // update paintables for (int i = 0; i < length; i++) { @@ -2111,11 +2126,26 @@ public class ApplicationConnection implements HasHandlers { } SharedState state = connector.getState(); + Type stateType = new Type(state.getClass() + .getName(), null); + + if (onlyNoLayoutUpdates) { + Profiler.enter("updateConnectorState @NoLayout handling"); + Set<String> keySet = stateJson.keySet(); + for (String propertyName : keySet) { + Property property = stateType + .getProperty(propertyName); + if (!property.isNoLayout()) { + onlyNoLayoutUpdates = false; + break; + } + } + Profiler.leave("updateConnectorState @NoLayout handling"); + } Profiler.enter("updateConnectorState decodeValue"); - JsonDecoder.decodeValue(new Type(state.getClass() - .getName(), null), stateJson, state, - ApplicationConnection.this); + JsonDecoder.decodeValue(stateType, stateJson, + state, ApplicationConnection.this); Profiler.leave("updateConnectorState decodeValue"); if (Profiler.isEnabled()) { @@ -2332,6 +2362,10 @@ public class ApplicationConnection implements HasHandlers { Profiler.leave("updateConnectorHierarchy detach removed connectors"); + if (result.events.size() != 0) { + onlyNoLayoutUpdates = false; + } + Profiler.leave("updateConnectorHierarchy"); return result; @@ -2460,8 +2494,16 @@ public class ApplicationConnection implements HasHandlers { for (int i = 0; i < rpcLength; i++) { try { JSONArray rpcCall = (JSONArray) rpcCalls.get(i); - rpcManager.parseAndApplyInvocation(rpcCall, - ApplicationConnection.this); + MethodInvocation invocation = rpcManager + .parseAndApplyInvocation(rpcCall, + ApplicationConnection.this); + + if (onlyNoLayoutUpdates + && !RpcManager.getMethod(invocation) + .isNoLayout()) { + onlyNoLayoutUpdates = false; + } + } catch (final Throwable e) { VConsole.error(e); } diff --git a/client/src/com/vaadin/client/communication/RpcManager.java b/client/src/com/vaadin/client/communication/RpcManager.java index 7b706fca2d..efedfe12a9 100644 --- a/client/src/com/vaadin/client/communication/RpcManager.java +++ b/client/src/com/vaadin/client/communication/RpcManager.java @@ -64,7 +64,18 @@ public class RpcManager { } } - private Method getMethod(MethodInvocation invocation) { + /** + * Gets the method that an invocation targets. + * + * @param invocation + * the method invocation to get the method for + * + * @since + * @return the method targeted by this invocation + */ + public static Method getMethod(MethodInvocation invocation) { + // Implemented here instead of in MethodInovcation since it's in shared + // and can't use our Method class. Type type = new Type(invocation.getInterfaceName(), null); Method method = type.getMethod(invocation.getMethodName()); return method; @@ -86,7 +97,7 @@ public class RpcManager { } } - public void parseAndApplyInvocation(JSONArray rpcCall, + public MethodInvocation parseAndApplyInvocation(JSONArray rpcCall, ApplicationConnection connection) { ConnectorMap connectorMap = ConnectorMap.get(connection); @@ -114,6 +125,8 @@ public class RpcManager { VConsole.log("Server to client RPC call: " + invocation); applyInvocation(invocation, connector); } + + return invocation; } private void parseMethodParameters(MethodInvocation methodInvocation, diff --git a/client/src/com/vaadin/client/metadata/Method.java b/client/src/com/vaadin/client/metadata/Method.java index d6b474fabc..d88dbf876e 100644 --- a/client/src/com/vaadin/client/metadata/Method.java +++ b/client/src/com/vaadin/client/metadata/Method.java @@ -15,6 +15,8 @@ */ package com.vaadin.client.metadata; +import com.vaadin.shared.annotations.NoLayout; + public class Method { private final Type type; @@ -100,4 +102,16 @@ public class Method { return TypeDataStore.isLastOnly(this); } + /** + * Checks whether this method is annotated with {@link NoLayout}. + * + * @since + * + * @return <code>true</code> if this method has a NoLayout annotation; + * otherwise <code>false</code> + */ + public boolean isNoLayout() { + return TypeDataStore.isNoLayoutRpcMethod(this); + } + } diff --git a/client/src/com/vaadin/client/metadata/Property.java b/client/src/com/vaadin/client/metadata/Property.java index f421a5525b..5825cf12d3 100644 --- a/client/src/com/vaadin/client/metadata/Property.java +++ b/client/src/com/vaadin/client/metadata/Property.java @@ -16,6 +16,7 @@ package com.vaadin.client.metadata; import com.vaadin.shared.annotations.DelegateToWidget; +import com.vaadin.shared.annotations.NoLayout; public class Property { private final Type bean; @@ -127,4 +128,16 @@ public class Property { return b.toString(); } + /** + * Checks whether this property is annotated with {@link NoLayout}. + * + * @since + * + * @return <code>true</code> if this property has a NoLayout annotation; + * otherwise <code>false</code> + */ + public boolean isNoLayout() { + return TypeDataStore.isNoLayoutProperty(this); + } + } diff --git a/client/src/com/vaadin/client/metadata/TypeDataStore.java b/client/src/com/vaadin/client/metadata/TypeDataStore.java index 9b1fd7d45c..a402973651 100644 --- a/client/src/com/vaadin/client/metadata/TypeDataStore.java +++ b/client/src/com/vaadin/client/metadata/TypeDataStore.java @@ -25,6 +25,7 @@ import com.vaadin.client.FastStringSet; import com.vaadin.client.JsArrayObject; import com.vaadin.client.annotations.OnStateChange; import com.vaadin.client.communication.JSONSerializer; +import com.vaadin.shared.annotations.NoLayout; public class TypeDataStore { private static final String CONSTRUCTOR_NAME = "!new"; @@ -48,6 +49,7 @@ public class TypeDataStore { private final FastStringSet delayedMethods = FastStringSet.create(); private final FastStringSet lastOnlyMethods = FastStringSet.create(); + private final FastStringSet noLayoutRpcMethods = FastStringSet.create(); private final FastStringMap<Type> returnTypes = FastStringMap.create(); private final FastStringMap<Invoker> invokers = FastStringMap.create(); @@ -345,6 +347,12 @@ public class TypeDataStore { return typeData[beanName][propertyName].setter !== undefined; }-*/; + private static native boolean hasNoLayout(JavaScriptObject typeData, + String beanName, String propertyName) + /*-{ + return typeData[beanName][propertyName].noLayout !== undefined; + }-*/; + private static native Object getJsPropertyValue(JavaScriptObject typeData, String beanName, String propertyName, Object beanInstance) /*-{ @@ -429,4 +437,50 @@ public class TypeDataStore { propertyHandlers.add(method); } } + + /** + * Checks whether the provided method is annotated with {@link NoLayout}. + * + * @param method + * the rpc method to check + * + * @since + * + * @return <code>true</code> if the method has a NoLayout annotation; + * otherwise <code>false</code> + */ + public static boolean isNoLayoutRpcMethod(Method method) { + return get().noLayoutRpcMethods.contains(method.getLookupKey()); + } + + /** + * Defines that a method is annotated with {@link NoLayout}. + * + * @since + * + * @param type + * the where the method is defined + * @param methodName + * the name of the method + */ + public void setNoLayoutRpcMethod(Class<?> type, String methodName) { + noLayoutRpcMethods.add(new Method(getType(type), methodName) + .getLookupKey()); + } + + /** + * Checks whether the provided property is annotated with {@link NoLayout}. + * + * @param property + * the property to check + * + * @since + * + * @return <code>true</code> if the property has a NoLayout annotation; + * otherwise <code>false</code> + */ + public static boolean isNoLayoutProperty(Property property) { + return hasNoLayout(get().jsTypeData, property.getBeanType() + .getSignature(), property.getName()); + } } diff --git a/shared/src/com/vaadin/shared/AbstractComponentState.java b/shared/src/com/vaadin/shared/AbstractComponentState.java index 816af978cf..f144f9e48b 100644 --- a/shared/src/com/vaadin/shared/AbstractComponentState.java +++ b/shared/src/com/vaadin/shared/AbstractComponentState.java @@ -18,6 +18,7 @@ package com.vaadin.shared; import java.util.List; +import com.vaadin.shared.annotations.NoLayout; import com.vaadin.shared.communication.SharedState; /** @@ -31,7 +32,9 @@ public class AbstractComponentState extends SharedState { public String height = ""; public String width = ""; public boolean readOnly = false; + @NoLayout public boolean immediate = false; + @NoLayout public String description = ""; // Note: for the caption, there is a difference between null and an empty // string! diff --git a/shared/src/com/vaadin/shared/annotations/NoLayout.java b/shared/src/com/vaadin/shared/annotations/NoLayout.java new file mode 100644 index 0000000000..78ff1e2984 --- /dev/null +++ b/shared/src/com/vaadin/shared/annotations/NoLayout.java @@ -0,0 +1,43 @@ +/* + * Copyright 2000-2014 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.shared.annotations; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +/** + * Annotation used to mark client RPC methods, state fields, or state setter + * methods that should not trigger an layout phase after changes have been + * processed. Whenever there's at least one change that is not marked with this + * annotation, the framework will assume some sizes might have changed an will + * therefore start a layout phase after applying the changes. + * <p> + * This annotation can be used for any RPC method or state property that does + * not cause the size of the component or its children to change. Please note + * that almost anything related to CSS (e.g. adding or removing a stylename) has + * the potential of causing sizes to change with appropriate style definitions + * in the application theme. + * + * @since + * + * @author Vaadin Ltd + */ +@Documented +@Target({ ElementType.METHOD, ElementType.FIELD }) +public @interface NoLayout { + // Just an empty marker annotation +} diff --git a/shared/src/com/vaadin/shared/communication/SharedState.java b/shared/src/com/vaadin/shared/communication/SharedState.java index e16fc51fae..b21a675a4a 100644 --- a/shared/src/com/vaadin/shared/communication/SharedState.java +++ b/shared/src/com/vaadin/shared/communication/SharedState.java @@ -22,6 +22,7 @@ import java.util.Map; import java.util.Set; import com.vaadin.shared.Connector; +import com.vaadin.shared.annotations.NoLayout; /** * Interface to be implemented by all shared state classes used to communicate @@ -64,6 +65,7 @@ public class SharedState implements Serializable { /** * A set of event identifiers with registered listeners. */ + @NoLayout public Set<String> registeredEventListeners = null; } diff --git a/shared/src/com/vaadin/shared/data/DataProviderRpc.java b/shared/src/com/vaadin/shared/data/DataProviderRpc.java index 043818d573..3e5dd9a332 100644 --- a/shared/src/com/vaadin/shared/data/DataProviderRpc.java +++ b/shared/src/com/vaadin/shared/data/DataProviderRpc.java @@ -16,6 +16,7 @@ package com.vaadin.shared.data; +import com.vaadin.shared.annotations.NoLayout; import com.vaadin.shared.communication.ClientRpc; /** @@ -51,6 +52,7 @@ public interface DataProviderRpc extends ClientRpc { * @see com.vaadin.shared.ui.grid.GridState#JSONKEY_DATA * @see com.vaadin.ui.components.grid.Renderer#encode(Object) */ + @NoLayout public void setRowData(int firstRowIndex, String rowDataJson); /** @@ -62,6 +64,7 @@ public interface DataProviderRpc extends ClientRpc { * the number of rows removed from <code>firstRowIndex</code> and * onwards */ + @NoLayout public void removeRowData(int firstRowIndex, int count); /** @@ -72,6 +75,7 @@ public interface DataProviderRpc extends ClientRpc { * @param count * the number of rows inserted at <code>firstRowIndex</code> */ + @NoLayout public void insertRowData(int firstRowIndex, int count); /** diff --git a/shared/src/com/vaadin/shared/ui/AbstractEmbeddedState.java b/shared/src/com/vaadin/shared/ui/AbstractEmbeddedState.java index f5779de43d..0cb9be8702 100644 --- a/shared/src/com/vaadin/shared/ui/AbstractEmbeddedState.java +++ b/shared/src/com/vaadin/shared/ui/AbstractEmbeddedState.java @@ -16,10 +16,12 @@ package com.vaadin.shared.ui; import com.vaadin.shared.AbstractComponentState; +import com.vaadin.shared.annotations.NoLayout; public class AbstractEmbeddedState extends AbstractComponentState { public static final String SOURCE_RESOURCE = "source"; + @NoLayout public String alternateText; } diff --git a/shared/src/com/vaadin/shared/ui/AbstractMediaState.java b/shared/src/com/vaadin/shared/ui/AbstractMediaState.java index d2ef09810b..3029bedca7 100644 --- a/shared/src/com/vaadin/shared/ui/AbstractMediaState.java +++ b/shared/src/com/vaadin/shared/ui/AbstractMediaState.java @@ -19,17 +19,21 @@ import java.util.ArrayList; import java.util.List; import com.vaadin.shared.AbstractComponentState; +import com.vaadin.shared.annotations.NoLayout; import com.vaadin.shared.communication.URLReference; public class AbstractMediaState extends AbstractComponentState { public boolean showControls; + @NoLayout public String altText; public boolean htmlContentAllowed; + @NoLayout public boolean autoplay; + @NoLayout public boolean muted; public List<URLReference> sources = new ArrayList<URLReference>(); diff --git a/shared/src/com/vaadin/shared/ui/MediaControl.java b/shared/src/com/vaadin/shared/ui/MediaControl.java index 2311d57b16..ab31d6f95f 100644 --- a/shared/src/com/vaadin/shared/ui/MediaControl.java +++ b/shared/src/com/vaadin/shared/ui/MediaControl.java @@ -16,6 +16,7 @@ package com.vaadin.shared.ui; +import com.vaadin.shared.annotations.NoLayout; import com.vaadin.shared.communication.ClientRpc; /** @@ -27,10 +28,12 @@ public interface MediaControl extends ClientRpc { /** * Start playing the media. */ + @NoLayout public void play(); /** * Pause playback of the media. */ + @NoLayout public void pause(); } diff --git a/shared/src/com/vaadin/shared/ui/TabIndexState.java b/shared/src/com/vaadin/shared/ui/TabIndexState.java index eec61a0595..1afe982546 100644 --- a/shared/src/com/vaadin/shared/ui/TabIndexState.java +++ b/shared/src/com/vaadin/shared/ui/TabIndexState.java @@ -16,6 +16,7 @@ package com.vaadin.shared.ui; import com.vaadin.shared.AbstractComponentState; +import com.vaadin.shared.annotations.NoLayout; /** * Interface implemented by state classes that support tab indexes. @@ -29,6 +30,7 @@ public class TabIndexState extends AbstractComponentState { /** * The <i>tabulator index</i> of the field. */ + @NoLayout public int tabIndex = 0; } diff --git a/shared/src/com/vaadin/shared/ui/button/ButtonState.java b/shared/src/com/vaadin/shared/ui/button/ButtonState.java index a12136870c..e5b94d95c4 100644 --- a/shared/src/com/vaadin/shared/ui/button/ButtonState.java +++ b/shared/src/com/vaadin/shared/ui/button/ButtonState.java @@ -17,6 +17,7 @@ package com.vaadin.shared.ui.button; import com.vaadin.shared.AbstractComponentState; +import com.vaadin.shared.annotations.NoLayout; import com.vaadin.shared.ui.TabIndexState; /** @@ -31,11 +32,14 @@ public class ButtonState extends TabIndexState { { primaryStyleName = "v-button"; } + @NoLayout public boolean disableOnClick = false; + @NoLayout public int clickShortcutKeyCode = 0; /** * If caption should be rendered in HTML */ public boolean htmlContentAllowed = false; + @NoLayout public String iconAltText = ""; } diff --git a/shared/src/com/vaadin/shared/ui/datefield/PopupDateFieldState.java b/shared/src/com/vaadin/shared/ui/datefield/PopupDateFieldState.java index 07726f8af0..6f10af4314 100644 --- a/shared/src/com/vaadin/shared/ui/datefield/PopupDateFieldState.java +++ b/shared/src/com/vaadin/shared/ui/datefield/PopupDateFieldState.java @@ -15,6 +15,8 @@ */ package com.vaadin.shared.ui.datefield; +import com.vaadin.shared.annotations.NoLayout; + public class PopupDateFieldState extends TextualDateFieldState { public static final String DESCRIPTION_FOR_ASSISTIVE_DEVICES = "Arrow down key opens calendar element for choosing the date"; @@ -23,5 +25,6 @@ public class PopupDateFieldState extends TextualDateFieldState { } public boolean textFieldEnabled = true; + @NoLayout public String descriptionForAssistiveDevices = DESCRIPTION_FOR_ASSISTIVE_DEVICES; } diff --git a/shared/src/com/vaadin/shared/ui/datefield/TextualDateFieldState.java b/shared/src/com/vaadin/shared/ui/datefield/TextualDateFieldState.java index 09bfb9c1a1..bf38ee04a9 100644 --- a/shared/src/com/vaadin/shared/ui/datefield/TextualDateFieldState.java +++ b/shared/src/com/vaadin/shared/ui/datefield/TextualDateFieldState.java @@ -18,6 +18,7 @@ package com.vaadin.shared.ui.datefield; import java.util.Date; import com.vaadin.shared.AbstractFieldState; +import com.vaadin.shared.annotations.NoLayout; public class TextualDateFieldState extends AbstractFieldState { { @@ -28,11 +29,13 @@ public class TextualDateFieldState extends AbstractFieldState { * Start range that has been cleared, depending on the resolution of the * date field */ + @NoLayout public Date rangeStart = null; /* * End range that has been cleared, depending on the resolution of the date * field */ + @NoLayout public Date rangeEnd = null; } diff --git a/shared/src/com/vaadin/shared/ui/panel/PanelState.java b/shared/src/com/vaadin/shared/ui/panel/PanelState.java index 6c0fcb683c..8f48fad921 100644 --- a/shared/src/com/vaadin/shared/ui/panel/PanelState.java +++ b/shared/src/com/vaadin/shared/ui/panel/PanelState.java @@ -16,11 +16,14 @@ package com.vaadin.shared.ui.panel; import com.vaadin.shared.AbstractComponentState; +import com.vaadin.shared.annotations.NoLayout; public class PanelState extends AbstractComponentState { { primaryStyleName = "v-panel"; } + @NoLayout public int tabIndex; + @NoLayout public int scrollLeft, scrollTop; } diff --git a/shared/src/com/vaadin/shared/ui/popupview/PopupViewState.java b/shared/src/com/vaadin/shared/ui/popupview/PopupViewState.java index da49e47ae8..86fda428a1 100644 --- a/shared/src/com/vaadin/shared/ui/popupview/PopupViewState.java +++ b/shared/src/com/vaadin/shared/ui/popupview/PopupViewState.java @@ -16,10 +16,12 @@ package com.vaadin.shared.ui.popupview; import com.vaadin.shared.AbstractComponentState; +import com.vaadin.shared.annotations.NoLayout; public class PopupViewState extends AbstractComponentState { public String html; + @NoLayout public boolean hideOnMouseOut; } diff --git a/shared/src/com/vaadin/shared/ui/progressindicator/ProgressBarState.java b/shared/src/com/vaadin/shared/ui/progressindicator/ProgressBarState.java index 79ef766951..6f557489dd 100644 --- a/shared/src/com/vaadin/shared/ui/progressindicator/ProgressBarState.java +++ b/shared/src/com/vaadin/shared/ui/progressindicator/ProgressBarState.java @@ -17,6 +17,7 @@ package com.vaadin.shared.ui.progressindicator; import com.vaadin.shared.AbstractFieldState; +import com.vaadin.shared.annotations.NoLayout; import com.vaadin.shared.communication.SharedState; /** @@ -32,6 +33,7 @@ public class ProgressBarState extends AbstractFieldState { primaryStyleName = PRIMARY_STYLE_NAME; } public boolean indeterminate = false; + @NoLayout public Float state = 0.0f; } diff --git a/shared/src/com/vaadin/shared/ui/progressindicator/ProgressIndicatorState.java b/shared/src/com/vaadin/shared/ui/progressindicator/ProgressIndicatorState.java index 15d0a947d7..9b3cf94d4a 100644 --- a/shared/src/com/vaadin/shared/ui/progressindicator/ProgressIndicatorState.java +++ b/shared/src/com/vaadin/shared/ui/progressindicator/ProgressIndicatorState.java @@ -15,6 +15,8 @@ */ package com.vaadin.shared.ui.progressindicator; +import com.vaadin.shared.annotations.NoLayout; + @Deprecated public class ProgressIndicatorState extends ProgressBarState { public static final String PRIMARY_STYLE_NAME = "v-progressindicator"; @@ -23,5 +25,6 @@ public class ProgressIndicatorState extends ProgressBarState { primaryStyleName = PRIMARY_STYLE_NAME; } + @NoLayout public int pollingInterval = 1000; } diff --git a/shared/src/com/vaadin/shared/ui/slider/SliderState.java b/shared/src/com/vaadin/shared/ui/slider/SliderState.java index 0e48a0c4e2..a96d35bc13 100644 --- a/shared/src/com/vaadin/shared/ui/slider/SliderState.java +++ b/shared/src/com/vaadin/shared/ui/slider/SliderState.java @@ -16,21 +16,26 @@ package com.vaadin.shared.ui.slider; import com.vaadin.shared.AbstractFieldState; +import com.vaadin.shared.annotations.NoLayout; public class SliderState extends AbstractFieldState { { primaryStyleName = "v-slider"; } + @NoLayout public double value; + @NoLayout public double maxValue = 100; + @NoLayout public double minValue = 0; /** * The number of fractional digits that are considered significant. Must be * non-negative. */ + @NoLayout public int resolution = 0; public SliderOrientation orientation = SliderOrientation.HORIZONTAL; diff --git a/shared/src/com/vaadin/shared/ui/tabsheet/TabsheetState.java b/shared/src/com/vaadin/shared/ui/tabsheet/TabsheetState.java index 98a1d2b87f..69a3330f64 100644 --- a/shared/src/com/vaadin/shared/ui/tabsheet/TabsheetState.java +++ b/shared/src/com/vaadin/shared/ui/tabsheet/TabsheetState.java @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.List; import com.vaadin.shared.AbstractComponentState; +import com.vaadin.shared.annotations.NoLayout; public class TabsheetState extends AbstractComponentState { public static final String PRIMARY_STYLE_NAME = "v-tabsheet"; @@ -31,6 +32,7 @@ public class TabsheetState extends AbstractComponentState { * Index of the component when switching focus - not related to Tabsheet * tabs. */ + @NoLayout public int tabIndex; public List<TabState> tabs = new ArrayList<TabState>(); diff --git a/shared/src/com/vaadin/shared/ui/textarea/TextAreaState.java b/shared/src/com/vaadin/shared/ui/textarea/TextAreaState.java index 380ee4c7fb..c1f9536278 100644 --- a/shared/src/com/vaadin/shared/ui/textarea/TextAreaState.java +++ b/shared/src/com/vaadin/shared/ui/textarea/TextAreaState.java @@ -16,6 +16,7 @@ package com.vaadin.shared.ui.textarea; import com.vaadin.shared.annotations.DelegateToWidget; +import com.vaadin.shared.annotations.NoLayout; import com.vaadin.shared.ui.textfield.AbstractTextFieldState; public class TextAreaState extends AbstractTextFieldState { @@ -33,6 +34,7 @@ public class TextAreaState extends AbstractTextFieldState { * Tells if word-wrapping should be used in the text area. */ @DelegateToWidget + @NoLayout public boolean wordwrap = true; } diff --git a/shared/src/com/vaadin/shared/ui/textfield/AbstractTextFieldState.java b/shared/src/com/vaadin/shared/ui/textfield/AbstractTextFieldState.java index 084d02cd7b..9d4272c22f 100644 --- a/shared/src/com/vaadin/shared/ui/textfield/AbstractTextFieldState.java +++ b/shared/src/com/vaadin/shared/ui/textfield/AbstractTextFieldState.java @@ -16,6 +16,7 @@ package com.vaadin.shared.ui.textfield; import com.vaadin.shared.AbstractFieldState; +import com.vaadin.shared.annotations.NoLayout; public class AbstractTextFieldState extends AbstractFieldState { { @@ -25,6 +26,7 @@ public class AbstractTextFieldState extends AbstractFieldState { /** * Maximum character count in text field. */ + @NoLayout public int maxLength = -1; /** @@ -35,10 +37,12 @@ public class AbstractTextFieldState extends AbstractFieldState { /** * The prompt to display in an empty field. Null when disabled. */ + @NoLayout public String inputPrompt = null; /** * The text in the field */ + @NoLayout public String text = null; } diff --git a/shared/src/com/vaadin/shared/ui/ui/ScrollClientRpc.java b/shared/src/com/vaadin/shared/ui/ui/ScrollClientRpc.java index e32a27830d..fb052a25e9 100644 --- a/shared/src/com/vaadin/shared/ui/ui/ScrollClientRpc.java +++ b/shared/src/com/vaadin/shared/ui/ui/ScrollClientRpc.java @@ -16,11 +16,14 @@ package com.vaadin.shared.ui.ui; +import com.vaadin.shared.annotations.NoLayout; import com.vaadin.shared.communication.ClientRpc; public interface ScrollClientRpc extends ClientRpc { + @NoLayout public void setScrollTop(int scrollTop); + @NoLayout public void setScrollLeft(int scrollLeft); } diff --git a/shared/src/com/vaadin/shared/ui/window/WindowState.java b/shared/src/com/vaadin/shared/ui/window/WindowState.java index fa73bea391..7dafba57ff 100644 --- a/shared/src/com/vaadin/shared/ui/window/WindowState.java +++ b/shared/src/com/vaadin/shared/ui/window/WindowState.java @@ -16,6 +16,7 @@ package com.vaadin.shared.ui.window; import com.vaadin.shared.Connector; +import com.vaadin.shared.annotations.NoLayout; import com.vaadin.shared.ui.panel.PanelState; public class WindowState extends PanelState { @@ -23,20 +24,34 @@ public class WindowState extends PanelState { primaryStyleName = "v-window"; } + @NoLayout public boolean modal = false; + @NoLayout public boolean resizable = true; + @NoLayout public boolean resizeLazy = false; + @NoLayout public boolean draggable = true; + @NoLayout public boolean centered = false; + @NoLayout public int positionX = -1; + @NoLayout public int positionY = -1; public WindowMode windowMode = WindowMode.NORMAL; + @NoLayout public String assistivePrefix = ""; + @NoLayout public String assistivePostfix = ""; + @NoLayout public Connector[] contentDescription = new Connector[0]; + @NoLayout public WindowRole role = WindowRole.DIALOG; + @NoLayout public boolean assistiveTabStop = false; + @NoLayout public String assistiveTabStopTopText = "Top of dialog"; + @NoLayout public String assistiveTabStopBottomText = "Bottom of Dialog"; } diff --git a/uitest/src/com/vaadin/tests/serialization/NoLayout.java b/uitest/src/com/vaadin/tests/serialization/NoLayout.java new file mode 100644 index 0000000000..8ce8c437a4 --- /dev/null +++ b/uitest/src/com/vaadin/tests/serialization/NoLayout.java @@ -0,0 +1,101 @@ +/* + * Copyright 2000-2014 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.tests.serialization; + +import com.vaadin.annotations.Widgetset; +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.Property.ValueChangeListener; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.tests.widgetset.TestingWidgetSet; +import com.vaadin.tests.widgetset.server.LayoutDetector; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.CheckBox; +import com.vaadin.ui.JavaScript; + +@Widgetset(TestingWidgetSet.NAME) +public class NoLayout extends AbstractTestUI { + private final LayoutDetector layoutDetector = new LayoutDetector(); + + @Override + protected void setup(VaadinRequest request) { + addComponent(layoutDetector); + + CheckBox uiPolling = new CheckBox("UI polling enabled"); + uiPolling.addValueChangeListener(new ValueChangeListener() { + @Override + public void valueChange(ValueChangeEvent event) { + if (event.getProperty().getValue() == Boolean.TRUE) { + setPollInterval(100); + } else { + setPollInterval(-1); + } + } + }); + addComponent(uiPolling); + + addComponent(new Button("Change regular state", + new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + event.getButton().setCaption( + String.valueOf(System.currentTimeMillis())); + } + })); + addComponent(new Button("Change @NoLayout state", + new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + event.getButton().setDescription( + String.valueOf(System.currentTimeMillis())); + } + })); + addComponent(new Button("Do regular RPC", new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + JavaScript.eval(""); + } + })); + + addComponent(new Button("Do @NoLayout RPC", new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + layoutDetector.doNoLayoutRpc(); + } + })); + + addComponent(new Button("Update LegacyComponent", + new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + // Assumes UI is a LegacyComponent + markAsDirty(); + } + })); + } + + @Override + protected String getTestDescription() { + return "Checks which actions trigger a layout phase"; + } + + @Override + protected Integer getTicketNumber() { + return Integer.valueOf(12936); + } + +} diff --git a/uitest/src/com/vaadin/tests/serialization/NoLayoutTest.java b/uitest/src/com/vaadin/tests/serialization/NoLayoutTest.java new file mode 100644 index 0000000000..bb312e3f3f --- /dev/null +++ b/uitest/src/com/vaadin/tests/serialization/NoLayoutTest.java @@ -0,0 +1,84 @@ +/* + * Copyright 2000-2014 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.tests.serialization; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.By; + +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.testbench.elements.CheckBoxElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class NoLayoutTest extends MultiBrowserTest { + @Test + public void testNoLayout() { + openTestURL(); + assertCounts(1, 0); + + $(CheckBoxElement.class).caption("UI polling enabled").first() + .findElement(By.tagName("input")).click(); + + // Toggling check box requires layout + assertCounts(2, 0); + + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + // Count should not change even with polling enabled + assertCounts(2, 0); + + // Disable polling + $(CheckBoxElement.class).caption("UI polling enabled").first() + .findElement(By.tagName("input")).click(); + // Toggling checkbox layotus again + assertCounts(3, 0); + + $(ButtonElement.class).caption("Change regular state").first().click(); + // Updating normal state layouts + assertCounts(4, 0); + + $(ButtonElement.class).caption("Change @NoLayout state").first(); + // Updating @NoLayout state does not layout + assertCounts(4, 0); + + $(ButtonElement.class).caption("Do regular RPC").first().click(); + // Doing normal RPC layouts + assertCounts(5, 0); + + $(ButtonElement.class).caption("Do @NoLayout RPC").first().click(); + // Doing @NoLayout RPC does not layout, but updates the RPC count + assertCounts(5, 1); + + $(ButtonElement.class).caption("Update LegacyComponent").first() + .click(); + // Painting LegacyComponent layouts + assertCounts(6, 1); + } + + private void assertCounts(int layoutCount, int rpcCount) { + Assert.assertEquals("Unexpected layout count", layoutCount, + getCount("layoutCount")); + Assert.assertEquals("Unexpected RPC count", rpcCount, + getCount("rpcCount")); + } + + private int getCount(String id) { + return Integer.parseInt(getDriver().findElement(By.id(id)).getText()); + } +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/LayoutDetectorConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/LayoutDetectorConnector.java new file mode 100644 index 0000000000..e999c83b75 --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/LayoutDetectorConnector.java @@ -0,0 +1,61 @@ +/* + * Copyright 2000-2014 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.tests.widgetset.client; + +import com.google.gwt.user.client.ui.HTML; +import com.vaadin.client.ui.AbstractComponentConnector; +import com.vaadin.client.ui.PostLayoutListener; +import com.vaadin.shared.ui.Connect; +import com.vaadin.tests.widgetset.server.LayoutDetector; + +@Connect(LayoutDetector.class) +public class LayoutDetectorConnector extends AbstractComponentConnector + implements PostLayoutListener { + private int layoutCount = 0; + private int rpcCount = 0; + + @Override + protected void init() { + super.init(); + updateText(); + + registerRpc(NoLayoutRpc.class, new NoLayoutRpc() { + @Override + public void doRpc() { + rpcCount++; + updateText(); + } + }); + } + + @Override + public HTML getWidget() { + return (HTML) super.getWidget(); + } + + @Override + public void postLayout() { + layoutCount++; + updateText(); + } + + private void updateText() { + getWidget().setHTML( + "Layout count: <span id='layoutCount'>" + layoutCount + + "</span><br />RPC count: <span id='rpcCount'>" + + rpcCount + "</span>"); + } +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/NoLayoutRpc.java b/uitest/src/com/vaadin/tests/widgetset/client/NoLayoutRpc.java new file mode 100644 index 0000000000..7c2693db1d --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/NoLayoutRpc.java @@ -0,0 +1,26 @@ +/* + * Copyright 2000-2014 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.tests.widgetset.client; + +import com.vaadin.shared.annotations.NoLayout; +import com.vaadin.shared.communication.ClientRpc; + +public interface NoLayoutRpc extends ClientRpc { + + @NoLayout + public void doRpc(); + +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/RoundTripTesterRpc.java b/uitest/src/com/vaadin/tests/widgetset/client/RoundTripTesterRpc.java index 60a3fb1448..e71f9f1230 100644 --- a/uitest/src/com/vaadin/tests/widgetset/client/RoundTripTesterRpc.java +++ b/uitest/src/com/vaadin/tests/widgetset/client/RoundTripTesterRpc.java @@ -15,10 +15,12 @@ */ package com.vaadin.tests.widgetset.client; +import com.vaadin.shared.annotations.NoLayout; import com.vaadin.shared.communication.ClientRpc; import com.vaadin.shared.communication.ServerRpc; public interface RoundTripTesterRpc extends ServerRpc, ClientRpc { + @NoLayout public void ping(int nr, String payload); public void done(); diff --git a/uitest/src/com/vaadin/tests/widgetset/server/LayoutDetector.java b/uitest/src/com/vaadin/tests/widgetset/server/LayoutDetector.java new file mode 100644 index 0000000000..4b1aea67ea --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/server/LayoutDetector.java @@ -0,0 +1,26 @@ +/* + * Copyright 2000-2014 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.tests.widgetset.server; + +import com.vaadin.tests.widgetset.client.NoLayoutRpc; +import com.vaadin.ui.AbstractComponent; + +public class LayoutDetector extends AbstractComponent { + + public void doNoLayoutRpc() { + getRpcProxy(NoLayoutRpc.class).doRpc(); + } +} |