diff options
author | Johannes Dahlström <johannesd@vaadin.com> | 2012-08-22 17:12:54 +0300 |
---|---|---|
committer | Johannes Dahlström <johannesd@vaadin.com> | 2012-08-22 17:12:54 +0300 |
commit | 7e3d95735858ba8726a7dc472a054ba279d7af21 (patch) | |
tree | bbc3556e8b0b20d03e1ccd1678d831010bdc96ef /client | |
parent | 3f36eee94aa400b85a4b322d3247b72a9eee25d0 (diff) | |
parent | 88776600733901f3f9891aa90a11a5aeb2b97ef4 (diff) | |
download | vaadin-framework-7e3d95735858ba8726a7dc472a054ba279d7af21.tar.gz vaadin-framework-7e3d95735858ba8726a7dc472a054ba279d7af21.zip |
Merge branch 'master' into root-cleanup
Conflicts:
client/src/com/vaadin/terminal/gwt/client/ui/root/RootConnector.java
Diffstat (limited to 'client')
30 files changed, 600 insertions, 252 deletions
diff --git a/client/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/client/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java index cd90403139..b4635c6d80 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java +++ b/client/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java @@ -22,6 +22,7 @@ import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -54,9 +55,9 @@ import com.google.gwt.user.client.ui.Widget; import com.vaadin.shared.ApplicationConstants; import com.vaadin.shared.ComponentState; 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; import com.vaadin.terminal.gwt.client.ApplicationConfiguration.ErrorMessage; import com.vaadin.terminal.gwt.client.ResourceLoader.ResourceLoadEvent; import com.vaadin.terminal.gwt.client.ResourceLoader.ResourceLoadListener; @@ -132,7 +133,18 @@ public class ApplicationConnection { private final HashMap<String, String> resourcesMap = new HashMap<String, String>(); - private ArrayList<MethodInvocation> pendingInvocations = new ArrayList<MethodInvocation>(); + /** + * The pending method invocations that will be send to the server by + * {@link #sendPendingCommand}. The key is defined differently based on + * whether the method invocation is enqueued with lastonly. With lastonly + * enabled, the method signature ( {@link MethodInvocation#getLastonlyTag()} + * ) is used as the key to make enable removing a previously enqueued + * invocation. Without lastonly, an incremental id based on + * {@link #lastInvocationTag} is used to get unique values. + */ + private LinkedHashMap<String, MethodInvocation> pendingInvocations = new LinkedHashMap<String, MethodInvocation>(); + + private int lastInvocationTag = 0; private WidgetSet widgetSet; @@ -155,7 +167,7 @@ public class ApplicationConnection { private ApplicationConfiguration configuration; /** List of pending variable change bursts that must be submitted in order */ - private final ArrayList<ArrayList<MethodInvocation>> pendingBursts = new ArrayList<ArrayList<MethodInvocation>>(); + private final ArrayList<LinkedHashMap<String, MethodInvocation>> pendingBursts = new ArrayList<LinkedHashMap<String, MethodInvocation>>(); /** Timer for automatic refirect to SessionExpiredURL */ private Timer redirectTimer; @@ -888,12 +900,11 @@ public class ApplicationConnection { private void checkForPendingVariableBursts() { cleanVariableBurst(pendingInvocations); if (pendingBursts.size() > 0) { - for (Iterator<ArrayList<MethodInvocation>> iterator = pendingBursts - .iterator(); iterator.hasNext();) { - cleanVariableBurst(iterator.next()); + for (LinkedHashMap<String, MethodInvocation> pendingBurst : pendingBursts) { + cleanVariableBurst(pendingBurst); } - ArrayList<MethodInvocation> nextBurst = pendingBursts.get(0); - pendingBursts.remove(0); + LinkedHashMap<String, MethodInvocation> nextBurst = pendingBursts + .remove(0); buildAndSendVariableBurst(nextBurst, false); } } @@ -904,13 +915,15 @@ public class ApplicationConnection { * * @param variableBurst */ - private void cleanVariableBurst(ArrayList<MethodInvocation> variableBurst) { - for (int i = 1; i < variableBurst.size(); i++) { - String id = variableBurst.get(i).getConnectorId(); + private void cleanVariableBurst( + LinkedHashMap<String, MethodInvocation> variableBurst) { + Iterator<MethodInvocation> iterator = variableBurst.values().iterator(); + while (iterator.hasNext()) { + String id = iterator.next().getConnectorId(); if (!getConnectorMap().hasConnector(id) && !getConnectorMap().isDragAndDropPaintable(id)) { // variable owner does not exist anymore - variableBurst.remove(i); + iterator.remove(); VConsole.log("Removed variable from removed component: " + id); } } @@ -1462,9 +1475,12 @@ public class ApplicationConnection { .getName(), null), stateJson, state, ApplicationConnection.this); - StateChangeEvent event = GWT - .create(StateChangeEvent.class); - event.setConnector(connector); + Set<String> changedProperties = new HashSet<String>(); + addJsonFields(stateJson, changedProperties, ""); + + StateChangeEvent event = new StateChangeEvent( + connector, changedProperties); + events.add(event); } } catch (final Throwable e) { @@ -1476,6 +1492,30 @@ public class ApplicationConnection { } /** + * Recursively adds the names of all fields in all objects in the + * provided json object. + * + * @param json + * the json object to process + * @param fields + * a set of all currently added fields + * @param context + * the base name of the current object + */ + private void addJsonFields(JSONObject json, Set<String> fields, + String context) { + for (String key : json.keySet()) { + String fieldName = context + key; + fields.add(fieldName); + + JSONObject object = json.get(key).isObject(); + if (object != null) { + addJsonFields(object, fields, fieldName + "."); + } + } + } + + /** * Updates the connector hierarchy and returns a list of events that * should be fired after update of the hierarchy and the state is * done. @@ -1695,12 +1735,10 @@ public class ApplicationConnection { private void addVariableToQueue(String connectorId, String variableName, Object value, boolean immediate) { + boolean lastOnly = !immediate; // note that type is now deduced from value - // TODO could eliminate invocations of same shared variable setter - addMethodInvocationToQueue(new MethodInvocation(connectorId, - ApplicationConstants.UPDATE_VARIABLE_INTERFACE, - ApplicationConstants.UPDATE_VARIABLE_METHOD, new Object[] { - variableName, new UidlValue(value) }), immediate); + addMethodInvocationToQueue(new LegacyChangeVariablesInvocation( + connectorId, variableName, value), lastOnly, lastOnly); } /** @@ -1710,16 +1748,31 @@ public class ApplicationConnection { * * @param invocation * RPC method invocation - * @param immediate - * true to trigger sending within a short time window (possibly - * combining subsequent calls to a single request), false to let - * the framework delay sending of RPC calls and variable changes - * until the next immediate change + * @param delayed + * <code>false</code> to trigger sending within a short time + * window (possibly combining subsequent calls to a single + * request), <code>true</code> to let the framework delay sending + * of RPC calls and variable changes until the next non-delayed + * change + * @param lastonly + * <code>true</code> to remove all previously delayed invocations + * of the same method that were also enqueued with lastonly set + * to <code>true</code>. <code>false</code> to add invocation to + * the end of the queue without touching previously enqueued + * invocations. */ public void addMethodInvocationToQueue(MethodInvocation invocation, - boolean immediate) { - pendingInvocations.add(invocation); - if (immediate) { + boolean delayed, boolean lastonly) { + String tag; + if (lastonly) { + tag = invocation.getLastonlyTag(); + assert !tag.matches("\\d+") : "getLastonlyTag value must have at least one non-digit character"; + pendingInvocations.remove(tag); + } else { + tag = Integer.toString(lastInvocationTag++); + } + pendingInvocations.put(tag, invocation); + if (!delayed) { sendPendingVariableChanges(); } } @@ -1750,14 +1803,15 @@ public class ApplicationConnection { }; private boolean deferedSendPending = false; - @SuppressWarnings("unchecked") private void doSendPendingVariableChanges() { if (applicationRunning) { if (hasActiveRequest()) { // skip empty queues if there are pending bursts to be sent if (pendingInvocations.size() > 0 || pendingBursts.size() == 0) { pendingBursts.add(pendingInvocations); - pendingInvocations = new ArrayList<MethodInvocation>(); + pendingInvocations = new LinkedHashMap<String, MethodInvocation>(); + // Keep tag string short + lastInvocationTag = 0; } } else { buildAndSendVariableBurst(pendingInvocations, false); @@ -1778,17 +1832,18 @@ public class ApplicationConnection { * Should we use synchronous request? */ private void buildAndSendVariableBurst( - ArrayList<MethodInvocation> pendingInvocations, boolean forceSync) { + LinkedHashMap<String, MethodInvocation> pendingInvocations, + boolean forceSync) { final StringBuffer req = new StringBuffer(); while (!pendingInvocations.isEmpty()) { if (ApplicationConfiguration.isDebugMode()) { - Util.logVariableBurst(this, pendingInvocations); + Util.logVariableBurst(this, pendingInvocations.values()); } JSONArray reqJson = new JSONArray(); - for (MethodInvocation invocation : pendingInvocations) { + for (MethodInvocation invocation : pendingInvocations.values()) { JSONArray invocationJson = new JSONArray(); invocationJson.set(0, new JSONString(invocation.getConnectorId())); @@ -1812,6 +1867,8 @@ public class ApplicationConnection { req.append(escapeBurstContents(reqJson.toString())); pendingInvocations.clear(); + // Keep tag string short + lastInvocationTag = 0; // Append all the bursts to this synchronous request if (forceSync && !pendingBursts.isEmpty()) { pendingInvocations = pendingBursts.get(0); diff --git a/client/src/com/vaadin/terminal/gwt/client/BrowserInfo.java b/client/src/com/vaadin/terminal/gwt/client/BrowserInfo.java index de2d9a9cd8..680131c70c 100644 --- a/client/src/com/vaadin/terminal/gwt/client/BrowserInfo.java +++ b/client/src/com/vaadin/terminal/gwt/client/BrowserInfo.java @@ -139,7 +139,7 @@ public class BrowserInfo { if (browserDetails.isFirefox()) { browserIdentifier = BROWSER_FIREFOX; majorVersionClass = browserIdentifier - + browserDetails.getBrowserMajorVersion(); + + getBrowserMajorVersion(); minorVersionClass = majorVersionClass + browserDetails.getBrowserMinorVersion(); browserEngineClass = ENGINE_GECKO; @@ -151,21 +151,21 @@ public class BrowserInfo { } else if (browserDetails.isSafari()) { browserIdentifier = BROWSER_SAFARI; majorVersionClass = browserIdentifier - + browserDetails.getBrowserMajorVersion(); + + getBrowserMajorVersion(); minorVersionClass = majorVersionClass + browserDetails.getBrowserMinorVersion(); browserEngineClass = ENGINE_WEBKIT; } else if (browserDetails.isIE()) { browserIdentifier = BROWSER_IE; majorVersionClass = browserIdentifier - + browserDetails.getBrowserMajorVersion(); + + getBrowserMajorVersion(); minorVersionClass = majorVersionClass + browserDetails.getBrowserMinorVersion(); browserEngineClass = ENGINE_TRIDENT; } else if (browserDetails.isOpera()) { browserIdentifier = BROWSER_OPERA; majorVersionClass = browserIdentifier - + browserDetails.getBrowserMajorVersion(); + + getBrowserMajorVersion(); minorVersionClass = majorVersionClass + browserDetails.getBrowserMinorVersion(); browserEngineClass = ENGINE_PRESTO; @@ -222,11 +222,11 @@ public class BrowserInfo { } public boolean isIE8() { - return isIE() && browserDetails.getBrowserMajorVersion() == 8; + return isIE() && getBrowserMajorVersion() == 8; } public boolean isIE9() { - return isIE() && browserDetails.getBrowserMajorVersion() == 9; + return isIE() && getBrowserMajorVersion() == 9; } public boolean isChrome() { @@ -274,7 +274,7 @@ public class BrowserInfo { return -1; } - return browserDetails.getBrowserMajorVersion(); + return getBrowserMajorVersion(); } public float getOperaVersion() { @@ -282,7 +282,7 @@ public class BrowserInfo { return -1; } - return browserDetails.getBrowserMajorVersion(); + return getBrowserMajorVersion(); } public boolean isOpera() { @@ -290,13 +290,11 @@ public class BrowserInfo { } public boolean isOpera10() { - return browserDetails.isOpera() - && browserDetails.getBrowserMajorVersion() == 10; + return browserDetails.isOpera() && getBrowserMajorVersion() == 10; } public boolean isOpera11() { - return browserDetails.isOpera() - && browserDetails.getBrowserMajorVersion() == 11; + return browserDetails.isOpera() && getBrowserMajorVersion() == 11; } public native static String getBrowserString() @@ -387,4 +385,51 @@ public class BrowserInfo { private int getOperatingSystemMajorVersion() { return browserDetails.getOperatingSystemMajorVersion(); } + + /** + * Returns the browser major version e.g., 3 for Firefox 3.5, 4 for Chrome + * 4, 8 for Internet Explorer 8. + * <p> + * Note that Internet Explorer 8 and newer will return the document mode so + * IE8 rendering as IE7 will return 7. + * </p> + * + * @return The major version of the browser. + */ + public int getBrowserMajorVersion() { + return browserDetails.getBrowserMajorVersion(); + } + + /** + * Returns the browser minor version e.g., 5 for Firefox 3.5. + * + * @see #getBrowserMajorVersion() + * + * @return The minor version of the browser, or -1 if not known/parsed. + */ + public int getBrowserMinorVersion() { + return browserDetails.getBrowserMinorVersion(); + } + + /** + * Checks if the browser version is newer or equal to the given major+minor + * version. + * + * @param majorVersion + * The major version to check for + * @param minorVersion + * The minor version to check for + * @return true if the browser version is newer or equal to the given + * version + */ + public boolean isBrowserVersionNewerOrEqual(int majorVersion, + int minorVersion) { + if (getBrowserMajorVersion() == majorVersion) { + // Same major + return (getBrowserMinorVersion() >= minorVersion); + } + + // Older or newer major + return (getBrowserMajorVersion() > majorVersion); + } } diff --git a/client/src/com/vaadin/terminal/gwt/client/JavaScriptConnectorHelper.java b/client/src/com/vaadin/terminal/gwt/client/JavaScriptConnectorHelper.java index 98c014b5ec..6494ae3480 100644 --- a/client/src/com/vaadin/terminal/gwt/client/JavaScriptConnectorHelper.java +++ b/client/src/com/vaadin/terminal/gwt/client/JavaScriptConnectorHelper.java @@ -267,7 +267,7 @@ public class JavaScriptConnectorHelper { } connector.getConnection().addMethodInvocationToQueue( new MethodInvocation(connector.getConnectorId(), iface, method, - parameters), true); + parameters), false, false); } private String findWildcardInterface(String method) { @@ -298,7 +298,8 @@ public class JavaScriptConnectorHelper { connector.getConnectorId(), "com.vaadin.ui.JavaScript$JavaScriptCallbackRpc", "call", new Object[] { name, new JSONArray(arguments) }); - connector.getConnection().addMethodInvocationToQueue(invocation, true); + connector.getConnection().addMethodInvocationToQueue(invocation, false, + false); } public void setNativeState(JavaScriptObject state) { diff --git a/client/src/com/vaadin/terminal/gwt/client/ServerConnector.java b/client/src/com/vaadin/terminal/gwt/client/ServerConnector.java index ff37f04f04..8788de74bf 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ServerConnector.java +++ b/client/src/com/vaadin/terminal/gwt/client/ServerConnector.java @@ -75,7 +75,7 @@ public interface ServerConnector extends Connector { String rpcInterfaceId); /** - * Adds a handler that is called whenever some part of the state has been + * Adds a handler that is called whenever any part of the state has been * updated by the server. * * @param handler @@ -86,6 +86,21 @@ public interface ServerConnector extends Connector { public HandlerRegistration addStateChangeHandler(StateChangeHandler handler); /** + * Adds a handler that is called whenever the given part of the state has + * been updated by the server. + * + * @param propertyName + * the name of the property for which the handler should be + * called + * @param handler + * The handler that should be added. + * @return A handler registration reference that can be used to unregister + * the handler + */ + public HandlerRegistration addStateChangeHandler(String propertyName, + StateChangeHandler handler); + + /** * Sends the given event to all registered handlers. * * @param event diff --git a/client/src/com/vaadin/terminal/gwt/client/Util.java b/client/src/com/vaadin/terminal/gwt/client/Util.java index 571258dbe3..96344f0792 100644 --- a/client/src/com/vaadin/terminal/gwt/client/Util.java +++ b/client/src/com/vaadin/terminal/gwt/client/Util.java @@ -874,13 +874,13 @@ public class Util { } static void logVariableBurst(ApplicationConnection c, - ArrayList<MethodInvocation> loggedBurst) { + Collection<MethodInvocation> loggedBurst) { try { VConsole.log("Variable burst to be sent to server:"); String curId = null; ArrayList<MethodInvocation> invocations = new ArrayList<MethodInvocation>(); - for (int i = 0; i < loggedBurst.size(); i++) { - String id = loggedBurst.get(i).getConnectorId(); + for (MethodInvocation methodInvocation : loggedBurst) { + String id = methodInvocation.getConnectorId(); if (curId == null) { curId = id; @@ -889,7 +889,7 @@ public class Util { invocations.clear(); curId = id; } - invocations.add(loggedBurst.get(i)); + invocations.add(methodInvocation); } if (!invocations.isEmpty()) { printConnectorInvocations(invocations, curId, c); diff --git a/client/src/com/vaadin/terminal/gwt/client/communication/StateChangeEvent.java b/client/src/com/vaadin/terminal/gwt/client/communication/StateChangeEvent.java index e1847bdab7..8ed32bc94b 100644 --- a/client/src/com/vaadin/terminal/gwt/client/communication/StateChangeEvent.java +++ b/client/src/com/vaadin/terminal/gwt/client/communication/StateChangeEvent.java @@ -16,8 +16,11 @@ package com.vaadin.terminal.gwt.client.communication; import java.io.Serializable; +import java.util.Collections; +import java.util.Set; import com.google.gwt.event.shared.EventHandler; +import com.vaadin.terminal.gwt.client.ServerConnector; import com.vaadin.terminal.gwt.client.communication.StateChangeEvent.StateChangeHandler; public class StateChangeEvent extends @@ -27,12 +30,25 @@ public class StateChangeEvent extends */ public static final Type<StateChangeHandler> TYPE = new Type<StateChangeHandler>(); + private Set<String> changedProperties; + @Override public Type<StateChangeHandler> getAssociatedType() { return TYPE; } - public StateChangeEvent() { + /** + * Creates a new state change event. + * + * @param connector + * the event whose state has changed + * @param changedProperties + * a set of names of the changed properties + */ + public StateChangeEvent(ServerConnector connector, + Set<String> changedProperties) { + setConnector(connector); + this.changedProperties = changedProperties; } @Override @@ -40,7 +56,30 @@ public class StateChangeEvent extends listener.onStateChanged(this); } + /** + * Event handler that gets notified whenever any part of the state has been + * updated by the server. + * + * @author Vaadin Ltd + * @version @VERSION@ + * @since 7.0.0 + */ public interface StateChangeHandler extends Serializable, EventHandler { + /** + * Notifies the event handler that the state has changed. + * + * @param stateChangeEvent + * the state change event with details about the change + */ public void onStateChanged(StateChangeEvent stateChangeEvent); } + + /** + * Gets the properties that have changed. + * + * @return a set of names of the changed properties + */ + public Set<String> getChangedProperties() { + return Collections.unmodifiableSet(changedProperties); + } } diff --git a/client/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavaScriptManagerConnector.java b/client/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavaScriptManagerConnector.java index 5cc5911bb1..46578b0641 100644 --- a/client/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavaScriptManagerConnector.java +++ b/client/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavaScriptManagerConnector.java @@ -124,7 +124,7 @@ public class JavaScriptManagerConnector extends AbstractExtensionConnector { getConnection().addMethodInvocationToQueue( new MethodInvocation(getConnectorId(), "com.vaadin.ui.JavaScript$JavaScriptCallbackRpc", - "call", parameters), true); + "call", parameters), false, false); } @Override diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/AbstractConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/AbstractConnector.java index 514f63fdd8..435fff8a5b 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/AbstractConnector.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/AbstractConnector.java @@ -48,6 +48,7 @@ public abstract class AbstractConnector implements ServerConnector, private String id; private HandlerManager handlerManager; + private Map<String, HandlerManager> statePropertyHandlerManagers; private Map<String, Collection<ClientRpc>> rpcImplementations; private final boolean debugLogging = false; @@ -168,6 +169,17 @@ public abstract class AbstractConnector implements ServerConnector, if (handlerManager != null) { handlerManager.fireEvent(event); } + if (statePropertyHandlerManagers != null + && event instanceof StateChangeEvent) { + for (String property : ((StateChangeEvent) event) + .getChangedProperties()) { + HandlerManager manager = statePropertyHandlerManagers + .get(property); + if (manager != null) { + manager.fireEvent(event); + } + } + } } protected HandlerManager ensureHandlerManager() { @@ -185,6 +197,25 @@ public abstract class AbstractConnector implements ServerConnector, } @Override + public HandlerRegistration addStateChangeHandler(String propertyName, + StateChangeHandler handler) { + return ensureHandlerManager(propertyName).addHandler( + StateChangeEvent.TYPE, handler); + } + + private HandlerManager ensureHandlerManager(String propertyName) { + if (statePropertyHandlerManagers == null) { + statePropertyHandlerManagers = new HashMap<String, HandlerManager>(); + } + HandlerManager manager = statePropertyHandlerManagers.get(propertyName); + if (manager == null) { + manager = new HandlerManager(this); + statePropertyHandlerManagers.put(propertyName, manager); + } + return manager; + } + + @Override public void onStateChanged(StateChangeEvent stateChangeEvent) { if (debugLogging) { VConsole.log("State change event for " diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/VOverlay.java b/client/src/com/vaadin/terminal/gwt/client/ui/VOverlay.java index aef21ac737..97201de297 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/VOverlay.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/VOverlay.java @@ -42,6 +42,14 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { public static class PositionAndSize { private int left, top, width, height; + public PositionAndSize(int left, int top, int width, int height) { + super(); + setLeft(left); + setTop(top); + setWidth(width); + setHeight(height); + } + public int getLeft() { return left; } @@ -63,6 +71,10 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { } public void setWidth(int width) { + if (width < 0) { + width = 0; + } + this.width = width; } @@ -71,6 +83,10 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { } public void setHeight(int height) { + if (height < 0) { + height = 0; + } + this.height = height; } @@ -192,7 +208,7 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { return shadow != null; } - private void removeShim() { + private void removeShimElement() { if (shimElement != null) { shimElement.removeFromParent(); } @@ -211,7 +227,7 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { return isShadowEnabled() && shadow.getParentElement() != null; } - private boolean isShimAttached() { + private boolean isShimElementAttached() { return shimElement != null && shimElement.hasParentElement(); } @@ -242,11 +258,11 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { style.setMarginLeft(-adjustByRelativeLeftBodyMargin(), Unit.PX); style.setMarginTop(-adjustByRelativeTopBodyMargin(), Unit.PX); super.setPopupPosition(left, top); - sizeOrPositionUpdated(isAnimationEnabled() ? 0 : 1); + positionOrSizeUpdated(isAnimationEnabled() ? 0 : 1); } private IFrameElement getShimElement() { - if (shimElement == null) { + if (shimElement == null && needsShimElement()) { shimElement = Document.get().createIFrameElement(); // Insert shim iframe before the main overlay element. It does not @@ -318,7 +334,7 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { if (isAnimationEnabled()) { new ResizeAnimation().run(POPUP_PANEL_ANIMATION_DURATION); } else { - sizeOrPositionUpdated(1.0); + positionOrSizeUpdated(1.0); } } @@ -328,7 +344,7 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { // Always ensure shadow is removed when the overlay is removed. removeShadowIfPresent(); - removeShim(); + removeShimElement(); } @Override @@ -343,13 +359,13 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { @Override public void setWidth(String width) { super.setWidth(width); - sizeOrPositionUpdated(1.0); + positionOrSizeUpdated(1.0); } @Override public void setHeight(String height) { super.setHeight(height); - sizeOrPositionUpdated(1.0); + positionOrSizeUpdated(1.0); } /** @@ -374,8 +390,16 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { * 'setHeight(String)' methods (if not calling super.setWidth/Height). * */ - public void sizeOrPositionUpdated() { - sizeOrPositionUpdated(1.0); + public void positionOrSizeUpdated() { + positionOrSizeUpdated(1.0); + } + + /** + * @deprecated Call {@link #positionOrSizeUpdated()} instead. + */ + @Deprecated + protected void updateShadowSizeAndPosition() { + positionOrSizeUpdated(); } /** @@ -388,7 +412,7 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { * A value between 0.0 and 1.0, indicating the progress of the * animation (0=start, 1=end). */ - private void sizeOrPositionUpdated(final double progress) { + private void positionOrSizeUpdated(final double progress) { // Don't do anything if overlay element is not attached if (!isAttached()) { return; @@ -413,18 +437,8 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { getOffsetWidth(); } - PositionAndSize positionAndSize = new PositionAndSize(); - positionAndSize.left = getActualLeft(); - positionAndSize.top = getActualTop(); - positionAndSize.width = getOffsetWidth(); - positionAndSize.height = getOffsetHeight(); - - if (positionAndSize.width < 0) { - positionAndSize.width = 0; - } - if (positionAndSize.height < 0) { - positionAndSize.height = 0; - } + PositionAndSize positionAndSize = new PositionAndSize(getActualLeft(), + getActualTop(), getOffsetWidth(), getOffsetHeight()); // Animate the size positionAndSize.setAnimationFromCenterProgress(progress); @@ -441,29 +455,31 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { // Update correct values if (isShadowEnabled()) { - updateSizeAndPosition(shadow, positionAndSize); + updatePositionAndSize(shadow, positionAndSize); DOM.setStyleAttribute(shadow, "zIndex", zIndex); DOM.setStyleAttribute(shadow, "display", progress < 0.9 ? "none" : ""); } - updateSizeAndPosition((Element) Element.as(getShimElement()), - positionAndSize); + if (needsShimElement()) { + updatePositionAndSize((Element) Element.as(getShimElement()), + positionAndSize); + } // Opera fix, part 2 (ticket #2704) if (BrowserInfo.get().isOpera() && isShadowEnabled()) { // We'll fix the height of all the middle elements DOM.getChild(shadow, 3) - .getStyle() - .setPropertyPx("height", - DOM.getChild(shadow, 3).getOffsetHeight()); + .getStyle() + .setPropertyPx("height", + DOM.getChild(shadow, 3).getOffsetHeight()); DOM.getChild(shadow, 4) - .getStyle() - .setPropertyPx("height", - DOM.getChild(shadow, 4).getOffsetHeight()); + .getStyle() + .setPropertyPx("height", + DOM.getChild(shadow, 4).getOffsetHeight()); DOM.getChild(shadow, 5) - .getStyle() - .setPropertyPx("height", - DOM.getChild(shadow, 5).getOffsetHeight()); + .getStyle() + .setPropertyPx("height", + DOM.getChild(shadow, 5).getOffsetHeight()); } // Attach to dom if not there already @@ -471,25 +487,37 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { RootPanel.get().getElement().insertBefore(shadow, getElement()); sinkShadowEvents(); } - if (!isShimAttached()) { + if (needsShimElement() && !isShimElementAttached()) { RootPanel.get().getElement() - .insertBefore(shimElement, getElement()); + .insertBefore(getShimElement(), getElement()); } } - private void updateSizeAndPosition(Element e, + /** + * Returns true if we should add a shim iframe below the overlay to deal + * with zindex issues with PDFs and applets. Can be overriden to disable + * shim iframes if they are not needed. + * + * @return true if a shim iframe should be added, false otherwise + */ + protected boolean needsShimElement() { + BrowserInfo info = BrowserInfo.get(); + return info.isIE() && info.isBrowserVersionNewerOrEqual(8, 0); + } + + private void updatePositionAndSize(Element e, PositionAndSize positionAndSize) { - e.getStyle().setLeft(positionAndSize.left, Unit.PX); - e.getStyle().setTop(positionAndSize.top, Unit.PX); - e.getStyle().setWidth(positionAndSize.width, Unit.PX); - e.getStyle().setHeight(positionAndSize.height, Unit.PX); + e.getStyle().setLeft(positionAndSize.getLeft(), Unit.PX); + e.getStyle().setTop(positionAndSize.getTop(), Unit.PX); + e.getStyle().setWidth(positionAndSize.getWidth(), Unit.PX); + e.getStyle().setHeight(positionAndSize.getHeight(), Unit.PX); } protected class ResizeAnimation extends Animation { @Override protected void onUpdate(double progress) { - sizeOrPositionUpdated(progress); + positionOrSizeUpdated(progress); } } diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/button/ButtonConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/button/ButtonConnector.java index 59e187014c..59f90a9840 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/button/ButtonConnector.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/button/ButtonConnector.java @@ -16,6 +16,8 @@ package com.vaadin.terminal.gwt.client.ui.button; +import java.util.Set; + import com.google.gwt.event.dom.client.BlurEvent; import com.google.gwt.event.dom.client.BlurHandler; import com.google.gwt.event.dom.client.ClickEvent; @@ -34,6 +36,7 @@ import com.vaadin.terminal.gwt.client.EventHelper; import com.vaadin.terminal.gwt.client.MouseEventDetailsBuilder; import com.vaadin.terminal.gwt.client.communication.RpcProxy; import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; +import com.vaadin.terminal.gwt.client.communication.StateChangeEvent.StateChangeHandler; import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector; import com.vaadin.terminal.gwt.client.ui.Icon; import com.vaadin.ui.Button; @@ -59,6 +62,47 @@ public class ButtonConnector extends AbstractComponentConnector implements super.init(); getWidget().addClickHandler(this); getWidget().client = getConnection(); + addStateChangeHandler("errorMessage", new StateChangeHandler() { + @Override + public void onStateChanged(StateChangeEvent stateChangeEvent) { + if (null != getState().getErrorMessage()) { + if (getWidget().errorIndicatorElement == null) { + getWidget().errorIndicatorElement = DOM.createSpan(); + getWidget().errorIndicatorElement + .setClassName("v-errorindicator"); + } + getWidget().wrapper.insertBefore( + getWidget().errorIndicatorElement, + getWidget().captionElement); + + } else if (getWidget().errorIndicatorElement != null) { + getWidget().wrapper + .removeChild(getWidget().errorIndicatorElement); + getWidget().errorIndicatorElement = null; + } + } + }); + + addStateChangeHandler("icon", new StateChangeHandler() { + @Override + public void onStateChanged(StateChangeEvent stateChangeEvent) { + if (getState().getIcon() != null) { + if (getWidget().icon == null) { + getWidget().icon = new Icon(getConnection()); + getWidget().wrapper.insertBefore( + getWidget().icon.getElement(), + getWidget().captionElement); + } + getWidget().icon.setUri(getState().getIcon().getURL()); + } else { + if (getWidget().icon != null) { + getWidget().wrapper.removeChild(getWidget().icon + .getElement()); + getWidget().icon = null; + } + } + } + }); } @Override @@ -68,39 +112,15 @@ public class ButtonConnector extends AbstractComponentConnector implements focusHandlerRegistration); blurHandlerRegistration = EventHelper.updateBlurHandler(this, blurHandlerRegistration); - // Set text - if (getState().isHtmlContentAllowed()) { - getWidget().setHtml(getState().getCaption()); - } else { - getWidget().setText(getState().getCaption()); - } - // handle error - if (null != getState().getErrorMessage()) { - if (getWidget().errorIndicatorElement == null) { - getWidget().errorIndicatorElement = DOM.createSpan(); - getWidget().errorIndicatorElement - .setClassName("v-errorindicator"); - } - getWidget().wrapper.insertBefore(getWidget().errorIndicatorElement, - getWidget().captionElement); - - } else if (getWidget().errorIndicatorElement != null) { - getWidget().wrapper.removeChild(getWidget().errorIndicatorElement); - getWidget().errorIndicatorElement = null; - } - - if (getState().getIcon() != null) { - if (getWidget().icon == null) { - getWidget().icon = new Icon(getConnection()); - getWidget().wrapper.insertBefore(getWidget().icon.getElement(), - getWidget().captionElement); - } - getWidget().icon.setUri(getState().getIcon().getURL()); - } else { - if (getWidget().icon != null) { - getWidget().wrapper.removeChild(getWidget().icon.getElement()); - getWidget().icon = null; + Set<String> changedProperties = stateChangeEvent.getChangedProperties(); + if (changedProperties.contains("caption") + || changedProperties.contains("htmlContentAllowed")) { + // Set text + if (getState().isHtmlContentAllowed()) { + getWidget().setHtml(getState().getCaption()); + } else { + getWidget().setText(getState().getCaption()); } } diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/csslayout/CssLayoutConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/csslayout/CssLayoutConnector.java index 47c2049a67..2e51d717a4 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/csslayout/CssLayoutConnector.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/csslayout/CssLayoutConnector.java @@ -23,7 +23,6 @@ import com.google.gwt.user.client.Element; import com.google.gwt.user.client.ui.Widget; import com.vaadin.shared.ui.Connect; import com.vaadin.shared.ui.LayoutClickRpc; -import com.vaadin.shared.ui.VMarginInfo; import com.vaadin.shared.ui.csslayout.CssLayoutServerRpc; import com.vaadin.shared.ui.csslayout.CssLayoutState; import com.vaadin.terminal.gwt.client.BrowserInfo; @@ -75,9 +74,6 @@ public class CssLayoutConnector extends AbstractLayoutConnector { public void onStateChanged(StateChangeEvent stateChangeEvent) { super.onStateChanged(stateChangeEvent); - getWidget().setMarginStyles( - new VMarginInfo(getState().getMarginsBitmask())); - for (ComponentConnector child : getChildComponents()) { if (!getState().getChildCss().containsKey(child)) { continue; diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/csslayout/VCssLayout.java b/client/src/com/vaadin/terminal/gwt/client/ui/csslayout/VCssLayout.java index 813e95e3ed..e66b1c4208 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/csslayout/VCssLayout.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/csslayout/VCssLayout.java @@ -21,8 +21,6 @@ import com.google.gwt.user.client.Element; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.Widget; -import com.vaadin.shared.ui.VMarginInfo; -import com.vaadin.terminal.gwt.client.StyleConstants; public class VCssLayout extends SimplePanel { public static final String TAGNAME = "csslayout"; @@ -64,21 +62,4 @@ public class VCssLayout extends SimplePanel { } - /** - * Sets CSS classes for margin based on the given parameters. - * - * @param margins - * A {@link VMarginInfo} object that provides info on - * top/left/bottom/right margins - */ - protected void setMarginStyles(VMarginInfo margins) { - setStyleName(margin, VCssLayout.CLASSNAME + "-" - + StyleConstants.MARGIN_TOP, margins.hasTop()); - setStyleName(margin, VCssLayout.CLASSNAME + "-" - + StyleConstants.MARGIN_RIGHT, margins.hasRight()); - setStyleName(margin, VCssLayout.CLASSNAME + "-" - + StyleConstants.MARGIN_BOTTOM, margins.hasBottom()); - setStyleName(margin, VCssLayout.CLASSNAME + "-" - + StyleConstants.MARGIN_LEFT, margins.hasLeft()); - } } diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/formlayout/FormLayoutConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/formlayout/FormLayoutConnector.java index 7d5edfadf5..cbe06244af 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/formlayout/FormLayoutConnector.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/formlayout/FormLayoutConnector.java @@ -18,7 +18,7 @@ package com.vaadin.terminal.gwt.client.ui.formlayout; import com.google.gwt.dom.client.Element; import com.google.gwt.user.client.ui.Widget; import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.VMarginInfo; +import com.vaadin.shared.ui.MarginInfo; import com.vaadin.shared.ui.orderedlayout.AbstractOrderedLayoutState; import com.vaadin.terminal.gwt.client.ComponentConnector; import com.vaadin.terminal.gwt.client.ConnectorHierarchyChangeEvent; @@ -46,7 +46,7 @@ public class FormLayoutConnector extends AbstractLayoutConnector { VFormLayoutTable formLayoutTable = getWidget().table; - formLayoutTable.setMargins(new VMarginInfo(getState() + formLayoutTable.setMargins(new MarginInfo(getState() .getMarginsBitmask())); formLayoutTable.setSpacing(getState().isSpacing()); diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/formlayout/VFormLayout.java b/client/src/com/vaadin/terminal/gwt/client/ui/formlayout/VFormLayout.java index d3ce6f3d3f..7f211aaf9c 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/formlayout/VFormLayout.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/formlayout/VFormLayout.java @@ -29,7 +29,7 @@ import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.Widget; import com.vaadin.shared.ComponentState; -import com.vaadin.shared.ui.VMarginInfo; +import com.vaadin.shared.ui.MarginInfo; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.BrowserInfo; import com.vaadin.terminal.gwt.client.ComponentConnector; @@ -112,7 +112,7 @@ public class VFormLayout extends SimplePanel { } } - public void setMargins(VMarginInfo margins) { + public void setMargins(MarginInfo margins) { Element margin = getElement(); setStyleName(margin, CLASSNAME + "-" + StyleConstants.MARGIN_TOP, margins.hasTop()); diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/gridlayout/GridLayoutConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/gridlayout/GridLayoutConnector.java index 520afb778d..9a2732e408 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/gridlayout/GridLayoutConnector.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/gridlayout/GridLayoutConnector.java @@ -22,7 +22,7 @@ import com.google.gwt.user.client.ui.Widget; import com.vaadin.shared.ui.AlignmentInfo; import com.vaadin.shared.ui.Connect; import com.vaadin.shared.ui.LayoutClickRpc; -import com.vaadin.shared.ui.VMarginInfo; +import com.vaadin.shared.ui.MarginInfo; import com.vaadin.shared.ui.gridlayout.GridLayoutServerRpc; import com.vaadin.shared.ui.gridlayout.GridLayoutState; import com.vaadin.terminal.gwt.client.ApplicationConnection; @@ -163,7 +163,7 @@ public class GridLayoutConnector extends AbstractComponentContainerConnector layout.colExpandRatioArray = uidl.getIntArrayAttribute("colExpand"); layout.rowExpandRatioArray = uidl.getIntArrayAttribute("rowExpand"); - layout.updateMarginStyleNames(new VMarginInfo(getState() + layout.updateMarginStyleNames(new MarginInfo(getState() .getMarginsBitmask())); layout.updateSpacingStyleName(getState().isSpacing()); diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/gridlayout/VGridLayout.java b/client/src/com/vaadin/terminal/gwt/client/ui/gridlayout/VGridLayout.java index 25d7de6ee6..ef44964da7 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/gridlayout/VGridLayout.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/gridlayout/VGridLayout.java @@ -29,7 +29,7 @@ import com.google.gwt.user.client.Element; import com.google.gwt.user.client.ui.ComplexPanel; import com.google.gwt.user.client.ui.Widget; import com.vaadin.shared.ui.AlignmentInfo; -import com.vaadin.shared.ui.VMarginInfo; +import com.vaadin.shared.ui.MarginInfo; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.ComponentConnector; import com.vaadin.terminal.gwt.client.ConnectorMap; @@ -677,7 +677,7 @@ public class VGridLayout extends ComplexPanel { } } - void updateMarginStyleNames(VMarginInfo marginInfo) { + void updateMarginStyleNames(MarginInfo marginInfo) { togglePrefixedStyleName("margin-top", marginInfo.hasTop()); togglePrefixedStyleName("margin-right", marginInfo.hasRight()); togglePrefixedStyleName("margin-bottom", marginInfo.hasBottom()); diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/link/LinkConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/link/LinkConnector.java index c4bbcd34f7..f2b8361f2b 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/link/LinkConnector.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/link/LinkConnector.java @@ -17,6 +17,7 @@ package com.vaadin.terminal.gwt.client.ui.link; import com.google.gwt.user.client.DOM; +import com.vaadin.shared.ui.BorderStyle; import com.vaadin.shared.ui.Connect; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.Paintable; @@ -57,12 +58,12 @@ public class LinkConnector extends AbstractComponentConnector implements if (uidl.hasAttribute("border")) { if ("none".equals(uidl.getStringAttribute("border"))) { - getWidget().borderStyle = VLink.BORDER_STYLE_NONE; + getWidget().borderStyle = BorderStyle.NONE; } else { - getWidget().borderStyle = VLink.BORDER_STYLE_MINIMAL; + getWidget().borderStyle = BorderStyle.MINIMAL; } } else { - getWidget().borderStyle = VLink.BORDER_STYLE_DEFAULT; + getWidget().borderStyle = BorderStyle.DEFAULT; } getWidget().targetHeight = uidl.hasAttribute("targetHeight") ? uidl diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/link/VLink.java b/client/src/com/vaadin/terminal/gwt/client/ui/link/VLink.java index e312d4d489..b0e44c9d13 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/link/VLink.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/link/VLink.java @@ -23,6 +23,7 @@ import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.HTML; +import com.vaadin.shared.ui.BorderStyle; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.Util; import com.vaadin.terminal.gwt.client.ui.Icon; @@ -31,15 +32,20 @@ public class VLink extends HTML implements ClickHandler { public static final String CLASSNAME = "v-link"; - protected static final int BORDER_STYLE_DEFAULT = 0; - protected static final int BORDER_STYLE_MINIMAL = 1; - protected static final int BORDER_STYLE_NONE = 2; + @Deprecated + protected static final BorderStyle BORDER_STYLE_DEFAULT = BorderStyle.DEFAULT; + + @Deprecated + protected static final BorderStyle BORDER_STYLE_MINIMAL = BorderStyle.MINIMAL; + + @Deprecated + protected static final BorderStyle BORDER_STYLE_NONE = BorderStyle.NONE; protected String src; protected String target; - protected int borderStyle = BORDER_STYLE_DEFAULT; + protected BorderStyle borderStyle = BorderStyle.DEFAULT; protected boolean enabled; @@ -73,10 +79,10 @@ public class VLink extends HTML implements ClickHandler { } String features; switch (borderStyle) { - case BORDER_STYLE_NONE: + case NONE: features = "menubar=no,location=no,status=no"; break; - case BORDER_STYLE_MINIMAL: + case MINIMAL: features = "menubar=yes,location=no,status=no"; break; default: diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/menubar/VMenuBar.java b/client/src/com/vaadin/terminal/gwt/client/ui/menubar/VMenuBar.java index 9f17b81691..fe47fcca66 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/menubar/VMenuBar.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/menubar/VMenuBar.java @@ -56,8 +56,8 @@ import com.vaadin.terminal.gwt.client.ui.VLazyExecutor; import com.vaadin.terminal.gwt.client.ui.VOverlay; public class VMenuBar extends SimpleFocusablePanel implements - CloseHandler<PopupPanel>, KeyPressHandler, KeyDownHandler, - FocusHandler, SubPartAware { +CloseHandler<PopupPanel>, KeyPressHandler, KeyDownHandler, +FocusHandler, SubPartAware { // The hierarchy of VMenuBar is a bit weird as VMenuBar is the Paintable, // used for the root menu but also used for the sub menus. @@ -94,11 +94,11 @@ public class VMenuBar extends SimpleFocusablePanel implements private VLazyExecutor iconLoadedExecutioner = new VLazyExecutor(100, new ScheduledCommand() { - @Override - public void execute() { - iLayout(true); - } - }); + @Override + public void execute() { + iLayout(true); + } + }); boolean openRootOnHover; @@ -188,7 +188,7 @@ public class VMenuBar extends SimpleFocusablePanel implements itemHTML.append("<img src=\"" + Util.escapeAttribute(client.translateVaadinUri(item .getStringAttribute("icon"))) + "\" class=\"" - + Icon.CLASSNAME + "\" alt=\"\" />"); + + Icon.CLASSNAME + "\" alt=\"\" />"); } String itemText = item.getStringAttribute("text"); if (!htmlContentAllowed) { @@ -606,7 +606,7 @@ public class VMenuBar extends SimpleFocusablePanel implements // popup style.setWidth(contentWidth + Util.getNativeScrollbarSize(), Unit.PX); - popup.sizeOrPositionUpdated(); + popup.positionOrSizeUpdated(); } } return top; diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/notification/VNotification.java b/client/src/com/vaadin/terminal/gwt/client/ui/notification/VNotification.java index 451e6badbe..6e253c9137 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/notification/VNotification.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/notification/VNotification.java @@ -168,7 +168,7 @@ public class VNotification extends VOverlay { super.show(); notifications.add(this); setPosition(position); - sizeOrPositionUpdated(); + positionOrSizeUpdated(); /** * Android 4 fails to render notifications correctly without a little * nudge (#8551) diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java index 5da01bf127..122547ddb4 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java @@ -23,7 +23,7 @@ import com.google.gwt.user.client.Element; import com.google.gwt.user.client.ui.Widget; import com.vaadin.shared.ui.AlignmentInfo; import com.vaadin.shared.ui.LayoutClickRpc; -import com.vaadin.shared.ui.VMarginInfo; +import com.vaadin.shared.ui.MarginInfo; import com.vaadin.shared.ui.orderedlayout.AbstractOrderedLayoutServerRpc; import com.vaadin.shared.ui.orderedlayout.AbstractOrderedLayoutState; import com.vaadin.terminal.gwt.client.ComponentConnector; @@ -133,9 +133,8 @@ public abstract class AbstractOrderedLayoutConnector extends slot.setExpandRatio(expandRatio); } - layout.updateMarginStyleNames(new VMarginInfo(getState() + layout.updateMarginStyleNames(new MarginInfo(getState() .getMarginsBitmask())); - layout.updateSpacingStyleName(getState().isSpacing()); getLayoutManager().setNeedsLayout(this); diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VMeasuringOrderedLayout.java b/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VMeasuringOrderedLayout.java index ec2c4afa97..ee55bc07ba 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VMeasuringOrderedLayout.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VMeasuringOrderedLayout.java @@ -27,7 +27,7 @@ import com.google.gwt.user.client.Element; import com.google.gwt.user.client.ui.ComplexPanel; import com.google.gwt.user.client.ui.Widget; import com.google.gwt.user.client.ui.WidgetCollection; -import com.vaadin.shared.ui.VMarginInfo; +import com.vaadin.shared.ui.MarginInfo; import com.vaadin.terminal.gwt.client.VCaption; import com.vaadin.terminal.gwt.client.ui.layout.VLayoutSlot; @@ -75,7 +75,7 @@ public class VMeasuringOrderedLayout extends ComplexPanel { } } - void updateMarginStyleNames(VMarginInfo marginInfo) { + void updateMarginStyleNames(MarginInfo marginInfo) { togglePrefixedStyleName("margin-top", marginInfo.hasTop()); togglePrefixedStyleName("margin-right", marginInfo.hasRight()); togglePrefixedStyleName("margin-bottom", marginInfo.hasBottom()); diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/root/RootConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/root/RootConnector.java index 39702e6ba0..1759889a1b 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/root/RootConnector.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/root/RootConnector.java @@ -23,6 +23,8 @@ import com.google.gwt.core.client.Scheduler; import com.google.gwt.dom.client.NativeEvent; import com.google.gwt.dom.client.Style; import com.google.gwt.dom.client.Style.Position; +import com.google.gwt.event.logical.shared.ResizeEvent; +import com.google.gwt.event.logical.shared.ResizeHandler; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Event; @@ -84,6 +86,16 @@ public class RootConnector extends AbstractComponentContainerConnector com.google.gwt.user.client.Window.setTitle(title); } }); + getWidget().addResizeHandler(new ResizeHandler() { + @Override + public void onResize(ResizeEvent event) { + rpc.resize(event.getHeight(), event.getWidth(), + Window.getClientWidth(), Window.getClientHeight()); + if (getState().isImmediate()) { + getConnection().sendPendingVariableChanges(); + } + } + }); } @Override diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java b/client/src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java index a473bf4846..162e7c55a8 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import com.google.gwt.core.client.Scheduler.ScheduledCommand; import com.google.gwt.dom.client.Element; +import com.google.gwt.event.logical.shared.HasResizeHandlers; import com.google.gwt.event.logical.shared.ResizeEvent; import com.google.gwt.event.logical.shared.ResizeHandler; import com.google.gwt.event.logical.shared.ValueChangeEvent; @@ -50,7 +51,8 @@ import com.vaadin.terminal.gwt.client.ui.textfield.VTextField; * */ public class VRoot extends SimplePanel implements ResizeHandler, - Window.ClosingHandler, ShortcutActionHandlerOwner, Focusable { + Window.ClosingHandler, ShortcutActionHandlerOwner, Focusable, + HasResizeHandlers { private static final String CLASSNAME = "v-view"; @@ -401,16 +403,7 @@ public class VRoot extends SimplePanel implements ResizeHandler, int viewHeight = parentElement.getClientHeight(); int viewWidth = parentElement.getClientWidth(); - connection.updateVariable(id, "height", viewHeight, false); - connection.updateVariable(id, "width", viewWidth, false); - - int windowWidth = Window.getClientWidth(); - int windowHeight = Window.getClientHeight(); - - connection.updateVariable(id, RootConstants.BROWSER_WIDTH_VAR, - windowWidth, false); - connection.updateVariable(id, RootConstants.BROWSER_HEIGHT_VAR, - windowHeight, immediate); + ResizeEvent.fire(this, viewWidth, viewHeight); } public native static void goTo(String url) @@ -458,4 +451,9 @@ public class VRoot extends SimplePanel implements ResizeHandler, touchScrollHandler.addElement(getElement()); } + @Override + public HandlerRegistration addResizeHandler(ResizeHandler resizeHandler) { + return addHandler(resizeHandler, ResizeEvent.getType()); + } + } diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/table/VScrollTable.java b/client/src/com/vaadin/terminal/gwt/client/ui/table/VScrollTable.java index aa7da488d8..345eebc8aa 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/table/VScrollTable.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/table/VScrollTable.java @@ -4122,8 +4122,10 @@ public class VScrollTable extends FlowPanel implements HasWidgets, row.addStyleName("v-selected"); } tBodyElement.appendChild(row.getElement()); - adopt(row); + // Add to renderedRows before adopt so iterator() will return also + // this row if called in an attach handler (#9264) renderedRows.add(row); + adopt(row); } private void insertRowAt(VScrollTableRow row, int index) { @@ -5780,16 +5782,39 @@ public class VScrollTable extends FlowPanel implements HasWidgets, // Hey IE, are you really sure about this? availW = scrollBody.getAvailableWidth(); int visibleCellCount = tHead.getVisibleCellCount(); - availW -= scrollBody.getCellExtraWidth() * visibleCellCount; + int totalExtraWidth = scrollBody.getCellExtraWidth() + * visibleCellCount; if (willHaveScrollbars()) { - availW -= Util.getNativeScrollbarSize(); + totalExtraWidth += Util.getNativeScrollbarSize(); } + availW -= totalExtraWidth; + int forceScrollBodyWidth = -1; int extraSpace = availW - usedMinimumWidth; if (extraSpace < 0) { + if (getTotalRows() == 0) { + /* + * Too wide header combined with no rows in the table. + * + * No horizontal scrollbars would be displayed because + * there's no rows that grows too wide causing the + * scrollBody container div to overflow. Must explicitely + * force a width to a scrollbar. (see #9187) + */ + forceScrollBodyWidth = usedMinimumWidth + totalExtraWidth; + } extraSpace = 0; } + if (forceScrollBodyWidth > 0) { + scrollBody.container.getStyle().setWidth(forceScrollBodyWidth, + Unit.PX); + } else { + // Clear width that might have been set to force horizontal + // scrolling if there are no rows + scrollBody.container.getStyle().clearWidth(); + } + int totalUndefinedNaturalWidths = usedMinimumWidth - totalExplicitColumnsWidths; diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/textarea/VTextArea.java b/client/src/com/vaadin/terminal/gwt/client/ui/textarea/VTextArea.java index e061cda1fa..e1df1ba0db 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/textarea/VTextArea.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/textarea/VTextArea.java @@ -19,6 +19,10 @@ package com.vaadin.terminal.gwt.client.ui.textarea; import com.google.gwt.core.client.Scheduler; import com.google.gwt.dom.client.Style.Overflow; import com.google.gwt.dom.client.TextAreaElement; +import com.google.gwt.event.dom.client.ChangeEvent; +import com.google.gwt.event.dom.client.ChangeHandler; +import com.google.gwt.event.dom.client.KeyUpEvent; +import com.google.gwt.event.dom.client.KeyUpHandler; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Event; @@ -38,10 +42,17 @@ import com.vaadin.terminal.gwt.client.ui.textfield.VTextField; public class VTextArea extends VTextField { public static final String CLASSNAME = "v-textarea"; private boolean wordwrap = true; + private MaxLengthHandler maxLengthHandler = new MaxLengthHandler(); + private boolean browserSupportsMaxLengthAttribute = browserSupportsMaxLengthAttribute(); public VTextArea() { super(DOM.createTextArea()); setStyleName(CLASSNAME); + if (!browserSupportsMaxLengthAttribute) { + addKeyUpHandler(maxLengthHandler); + addChangeHandler(maxLengthHandler); + sinkEvents(Event.ONPASTE); + } } public TextAreaElement getTextAreaElement() { @@ -52,22 +63,28 @@ public class VTextArea extends VTextField { getTextAreaElement().setRows(rows); } - @Override - protected void setMaxLength(int newMaxLength) { - super.setMaxLength(newMaxLength); + private class MaxLengthHandler implements KeyUpHandler, ChangeHandler { - boolean hasMaxLength = (newMaxLength >= 0); + @Override + public void onKeyUp(KeyUpEvent event) { + enforceMaxLength(); + } - if (hasMaxLength) { - sinkEvents(Event.ONKEYUP); - } else { - unsinkEvents(Event.ONKEYUP); + public void onPaste(Event event) { + enforceMaxLength(); } + + @Override + public void onChange(ChangeEvent event) { + // Opera does not support paste events so this enforces max length + // for Opera. + enforceMaxLength(); + } + } - @Override - public void onBrowserEvent(Event event) { - if (getMaxLength() >= 0 && event.getTypeInt() == Event.ONKEYUP) { + protected void enforceMaxLength() { + if (getMaxLength() >= 0) { Scheduler.get().scheduleDeferred(new Command() { @Override public void execute() { @@ -77,9 +94,45 @@ public class VTextArea extends VTextField { } }); } + } + + protected boolean browserSupportsMaxLengthAttribute() { + BrowserInfo info = BrowserInfo.get(); + if (info.isFirefox() && info.isBrowserVersionNewerOrEqual(4, 0)) { + return true; + } + if (info.isSafari() && info.isBrowserVersionNewerOrEqual(5, 0)) { + return true; + } + if (info.isIE() && info.isBrowserVersionNewerOrEqual(10, 0)) { + return true; + } + if (info.isAndroid() && info.isBrowserVersionNewerOrEqual(2, 3)) { + return true; + } + return false; + } + + @Override + protected void updateMaxLength(int maxLength) { + if (browserSupportsMaxLengthAttribute) { + super.updateMaxLength(maxLength); + } else { + // Events handled by MaxLengthHandler. This call enforces max length + // when the max length value has changed + enforceMaxLength(); + } + } + + @Override + public void onBrowserEvent(Event event) { super.onBrowserEvent(event); + if (event.getTypeInt() == Event.ONPASTE) { + maxLengthHandler.onPaste(event); + } } + @Override public int getCursorPos() { // This is needed so that TextBoxImplIE6 is used to return the correct diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/textfield/VTextField.java b/client/src/com/vaadin/terminal/gwt/client/ui/textfield/VTextField.java index b00210cdd2..8f07c67c96 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/textfield/VTextField.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/textfield/VTextField.java @@ -44,7 +44,7 @@ import com.vaadin.terminal.gwt.client.ui.Field; * */ public class VTextField extends TextBoxBase implements Field, ChangeHandler, - FocusHandler, BlurHandler, KeyDownHandler { +FocusHandler, BlurHandler, KeyDownHandler { /** * The input node CSS classname. @@ -114,7 +114,7 @@ public class VTextField extends TextBoxBase implements Field, ChangeHandler, if (listenTextChangeEvents && (event.getTypeInt() & TEXTCHANGE_EVENTS) == event - .getTypeInt()) { + .getTypeInt()) { deferTextChangeEvent(); } @@ -261,12 +261,32 @@ public class VTextField extends TextBoxBase implements Field, ChangeHandler, } protected void setMaxLength(int newMaxLength) { - if (newMaxLength >= 0) { + if (newMaxLength >= 0 && newMaxLength != maxLength) { maxLength = newMaxLength; - } else { + updateMaxLength(maxLength); + } else if (maxLength != -1) { maxLength = -1; + updateMaxLength(maxLength); + } + + } + + /** + * This method is reponsible for updating the DOM or otherwise ensuring that + * the given max length is enforced. Called when the max length for the + * field has changed. + * + * @param maxLength + * The new max length + */ + protected void updateMaxLength(int maxLength) { + if (maxLength >= 0) { + getElement().setPropertyInt("maxLength", maxLength); + } else { + getElement().removeAttribute("maxLength"); + } - setMaxLengthToElement(newMaxLength); + setMaxLengthToElement(maxLength); } protected void setMaxLengthToElement(int newMaxLength) { diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/tree/VTree.java b/client/src/com/vaadin/terminal/gwt/client/ui/tree/VTree.java index 9fbaa1d8bf..40c5e4b8af 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/tree/VTree.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/tree/VTree.java @@ -79,8 +79,8 @@ import com.vaadin.terminal.gwt.client.ui.dd.VTransferable; * */ public class VTree extends FocusElementPanel implements VHasDropHandler, - FocusHandler, BlurHandler, KeyPressHandler, KeyDownHandler, - SubPartAware, ActionOwner { +FocusHandler, BlurHandler, KeyPressHandler, KeyDownHandler, +SubPartAware, ActionOwner { public static final String CLASSNAME = "v-tree"; @@ -137,12 +137,12 @@ public class VTree extends FocusElementPanel implements VHasDropHandler, public VLazyExecutor iconLoaded = new VLazyExecutor(50, new ScheduledCommand() { - @Override - public void execute() { - Util.notifyParentOfSizeChange(VTree.this, true); - } + @Override + public void execute() { + Util.notifyParentOfSizeChange(VTree.this, true); + } - }); + }); public VTree() { super(); @@ -601,7 +601,8 @@ public class VTree extends FocusElementPanel implements VHasDropHandler, focus(); } - ScheduledCommand command = new ScheduledCommand() { + executeEventCommand(new ScheduledCommand() { + @Override public void execute() { @@ -636,17 +637,7 @@ public class VTree extends FocusElementPanel implements VHasDropHandler, } } } - }; - - if (BrowserInfo.get().isWebkit() && !treeHasFocus) { - /* - * Safari may need to wait for focus. See FocusImplSafari. - */ - // VConsole.log("Deferring click handling to let webkit gain focus..."); - Scheduler.get().scheduleDeferred(command); - } else { - command.execute(); - } + }); return true; } @@ -677,7 +668,7 @@ public class VTree extends FocusElementPanel implements VHasDropHandler, && client.hasEventListeners(VTree.this, TreeConstants.ITEM_CLICK_EVENT_ID) - && (type == Event.ONDBLCLICK || type == Event.ONMOUSEUP)) { + && (type == Event.ONDBLCLICK || type == Event.ONMOUSEUP)) { fireClick(event); } if (type == Event.ONCLICK) { @@ -709,7 +700,7 @@ public class VTree extends FocusElementPanel implements VHasDropHandler, .getEventTarget().cast())) { if (dragMode > 0 && (type == Event.ONTOUCHSTART || event - .getButton() == NativeEvent.BUTTON_LEFT)) { + .getButton() == NativeEvent.BUTTON_LEFT)) { mouseDownEvent = event; // save event for possible // dd operation if (type == Event.ONMOUSEDOWN) { @@ -790,9 +781,12 @@ public class VTree extends FocusElementPanel implements VHasDropHandler, focus(); } } + final MouseEventDetails details = MouseEventDetailsBuilder .buildMouseEventDetails(evt); - ScheduledCommand command = new ScheduledCommand() { + + executeEventCommand(new ScheduledCommand() { + @Override public void execute() { // Determine if we should send the event immediately to the @@ -820,14 +814,18 @@ public class VTree extends FocusElementPanel implements VHasDropHandler, client.updateVariable(paintableId, "clickEvent", details.toString(), sendClickEventNow); } - }; - if (treeHasFocus) { - command.execute(); - } else { - /* - * Webkits need a deferring due to FocusImplSafari uses timeout - */ + }); + } + + /* + * Must wait for Safari to focus before sending click and value change + * events (see #6373, #6374) + */ + private void executeEventCommand(ScheduledCommand command) { + if (BrowserInfo.get().isWebkit() && !treeHasFocus) { Scheduler.get().scheduleDeferred(command); + } else { + command.execute(); } } @@ -1723,7 +1721,7 @@ public class VTree extends FocusElementPanel implements VHasDropHandler, selectNode( focusedNode, (!isMultiselect || multiSelectMode == MULTISELECT_MODE_SIMPLE) - && selectable); + && selectable); } else { deselectNode(focusedNode); } diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/treetable/VTreeTable.java b/client/src/com/vaadin/terminal/gwt/client/ui/treetable/VTreeTable.java index a8621190ae..909acdf85f 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/treetable/VTreeTable.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/treetable/VTreeTable.java @@ -188,8 +188,7 @@ public class VTreeTable extends VScrollTable { if (isTreeCellAdded) { return false; } - return curColIndex == colIndexOfHierarchy - + (showRowHeaders ? 1 : 0); + return curColIndex == getHierarchyColumnIndex(); } @Override @@ -227,6 +226,23 @@ public class VTreeTable extends VScrollTable { super.onAttach(); if (getIndentWidth() < 0) { detectIndent(this); + // If we detect indent here then the size of the hierarchy + // column is still wrong as it has been set when the indent + // was not known. + int w = getCellWidthFromDom(getHierarchyColumnIndex()); + if (w >= 0) { + setColWidth(getHierarchyColumnIndex(), w); + } + } + } + + private int getCellWidthFromDom(int cellIndex) { + final Element cell = DOM.getChild(getElement(), cellIndex); + String w = cell.getStyle().getProperty("width"); + if (w == null || "".equals(w) || !w.endsWith("px")) { + return -1; + } else { + return Integer.parseInt(w.substring(0, w.length() - 2)); } } @@ -242,14 +258,21 @@ public class VTreeTable extends VScrollTable { @Override protected void setCellWidth(int cellIx, int width) { - if (cellIx == colIndexOfHierarchy + (showRowHeaders ? 1 : 0)) { + if (cellIx == getHierarchyColumnIndex()) { // take indentation padding into account if this is the // hierarchy column - width = Math.max(width - getIndent(), 0); + int indent = getIndent(); + if (indent != -1) { + width = Math.max(width - getIndent(), 0); + } } super.setCellWidth(cellIx, width); } + private int getHierarchyColumnIndex() { + return colIndexOfHierarchy + (showRowHeaders ? 1 : 0); + } + private int getIndent() { return (depth + 1) * getIndentWidth(); } diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/window/WindowConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/window/WindowConnector.java index a1bab91618..3ee266b944 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/window/WindowConnector.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/window/WindowConnector.java @@ -46,8 +46,8 @@ import com.vaadin.terminal.gwt.client.ui.layout.MayScrollChildren; @Connect(value = com.vaadin.ui.Window.class) public class WindowConnector extends AbstractComponentContainerConnector - implements Paintable, BeforeShortcutActionListener, - SimpleManagedLayout, PostLayoutListener, MayScrollChildren { +implements Paintable, BeforeShortcutActionListener, +SimpleManagedLayout, PostLayoutListener, MayScrollChildren { private ClickEventHandler clickEventHandler = new ClickEventHandler(this) { @Override @@ -102,7 +102,7 @@ public class WindowConnector extends AbstractComponentContainerConnector } if (!getWidget().isAttached()) { getWidget().setVisible(false); // hide until - // possible centering + // possible centering getWidget().show(); } if (getState().isResizable() != getWidget().resizable) { @@ -299,7 +299,7 @@ public class WindowConnector extends AbstractComponentContainerConnector if (window.centered) { window.center(); } - window.sizeOrPositionUpdated(); + window.positionOrSizeUpdated(); } @Override |