diff options
author | John Ahlroos <john@vaadin.com> | 2012-08-28 09:41:55 +0300 |
---|---|---|
committer | John Ahlroos <john@vaadin.com> | 2012-08-28 09:41:55 +0300 |
commit | 435a2e735251464529f8329b0563c26d5b4cc6a9 (patch) | |
tree | 8bde89594f6b258f087a8518265418a02800cea2 /client/src/com | |
parent | 7b9e1566d6e36c10aef3566b20267449586a81cb (diff) | |
parent | c6d43cc88fb0ef4853e07be54fc76a6aa1dc9e23 (diff) | |
download | vaadin-framework-435a2e735251464529f8329b0563c26d5b4cc6a9.tar.gz vaadin-framework-435a2e735251464529f8329b0563c26d5b4cc6a9.zip |
Merge branch 'master' into layoutgraph
Conflicts:
tests/testbench/com/vaadin/tests/components/orderedlayout/OrderedLayoutCases.java
Diffstat (limited to 'client/src/com')
23 files changed, 978 insertions, 228 deletions
diff --git a/client/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java b/client/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java index 8bb4f37324..2eccd9bb8c 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java +++ b/client/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java @@ -31,6 +31,7 @@ import com.google.gwt.core.client.Scheduler.ScheduledCommand; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.Window; import com.vaadin.shared.ApplicationConstants; +import com.vaadin.shared.ui.ui.UIConstants; import com.vaadin.terminal.gwt.client.metadata.BundleLoadCallback; import com.vaadin.terminal.gwt.client.metadata.ConnectorBundleLoader; import com.vaadin.terminal.gwt.client.metadata.NoDataException; @@ -202,11 +203,12 @@ public class ApplicationConfiguration implements EntryPoint { private String id; private String themeUri; private String appUri; - private int rootId; + private int uiId; private boolean standalone; private ErrorMessage communicationError; private ErrorMessage authorizationError; private boolean useDebugIdInDom = true; + private int heartbeatInterval; private HashMap<Integer, String> unknownComponents; @@ -284,12 +286,20 @@ public class ApplicationConfiguration implements EntryPoint { /** * Gets the root if of this application instance. The root id should be * included in every request originating from this instance in order to - * associate it with the right Root instance on the server. + * associate it with the right UI instance on the server. * * @return the root id */ - public int getRootId() { - return rootId; + public int getUIId() { + return uiId; + } + + /** + * @return The interval in seconds between heartbeat requests, or a + * non-positive number if heartbeat is disabled. + */ + public int getHeartbeatInterval() { + return heartbeatInterval; } public JavaScriptObject getVersionInfoJSObject() { @@ -314,7 +324,8 @@ public class ApplicationConfiguration implements EntryPoint { appUri += '/'; } themeUri = jsoConfiguration.getConfigString("themeUri"); - rootId = jsoConfiguration.getConfigInteger("rootId").intValue(); + uiId = jsoConfiguration.getConfigInteger(UIConstants.UI_ID_PARAMETER) + .intValue(); // null -> true useDebugIdInDom = jsoConfiguration.getConfigBoolean("useDebugIdInDom") != Boolean.FALSE; @@ -322,6 +333,9 @@ public class ApplicationConfiguration implements EntryPoint { // null -> false standalone = jsoConfiguration.getConfigBoolean("standalone") == Boolean.TRUE; + heartbeatInterval = jsoConfiguration + .getConfigInteger("heartbeatInterval"); + communicationError = jsoConfiguration.getConfigError("comErrMsg"); authorizationError = jsoConfiguration.getConfigError("authErrMsg"); diff --git a/client/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/client/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java index 58357ae3fc..450972ddc6 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java +++ b/client/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java @@ -58,6 +58,7 @@ 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.ui.ui.UIConstants; import com.vaadin.terminal.gwt.client.ApplicationConfiguration.ErrorMessage; import com.vaadin.terminal.gwt.client.ResourceLoader.ResourceLoadEvent; import com.vaadin.terminal.gwt.client.ResourceLoader.ResourceLoadListener; @@ -68,13 +69,16 @@ import com.vaadin.terminal.gwt.client.communication.RpcManager; import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; import com.vaadin.terminal.gwt.client.extensions.AbstractExtensionConnector; import com.vaadin.terminal.gwt.client.metadata.ConnectorBundleLoader; +import com.vaadin.terminal.gwt.client.metadata.NoDataException; +import com.vaadin.terminal.gwt.client.metadata.Property; import com.vaadin.terminal.gwt.client.metadata.Type; +import com.vaadin.terminal.gwt.client.metadata.TypeData; import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector; import com.vaadin.terminal.gwt.client.ui.VContextMenu; +import com.vaadin.terminal.gwt.client.ui.UI.UIConnector; import com.vaadin.terminal.gwt.client.ui.dd.VDragAndDropManager; import com.vaadin.terminal.gwt.client.ui.notification.VNotification; import com.vaadin.terminal.gwt.client.ui.notification.VNotification.HideEvent; -import com.vaadin.terminal.gwt.client.ui.root.RootConnector; import com.vaadin.terminal.gwt.client.ui.window.WindowConnector; /** @@ -153,7 +157,7 @@ public class ApplicationConnection { private Timer loadTimer3; private Element loadElement; - private final RootConnector rootConnector; + private final UIConnector uIConnector; protected boolean applicationRunning = false; @@ -205,10 +209,10 @@ public class ApplicationConnection { } public ApplicationConnection() { - // Assuming Root data is eagerly loaded + // Assuming UI data is eagerly loaded ConnectorBundleLoader.get().loadBundle( ConnectorBundleLoader.EAGER_BUNDLE_NAME, null); - rootConnector = GWT.create(RootConnector.class); + uIConnector = GWT.create(UIConnector.class); rpcManager = GWT.create(RpcManager.class); layoutManager = GWT.create(LayoutManager.class); layoutManager.setConnection(this); @@ -240,8 +244,10 @@ public class ApplicationConnection { initializeClientHooks(); - rootConnector.init(cnf.getRootPanelId(), this); + uIConnector.init(cnf.getRootPanelId(), this); showLoadingIndicator(); + + scheduleHeartbeat(); } /** @@ -492,8 +498,8 @@ public class ApplicationConnection { if (extraParams != null && extraParams.length() > 0) { uri = addGetParameters(uri, extraParams); } - uri = addGetParameters(uri, ApplicationConstants.ROOT_ID_PARAMETER - + "=" + configuration.getRootId()); + uri = addGetParameters(uri, UIConstants.UI_ID_PARAMETER + "=" + + configuration.getUIId()); doUidlRequest(uri, payload, forceSync); @@ -906,7 +912,7 @@ public class ApplicationConnection { if (loadElement == null) { loadElement = DOM.createDiv(); DOM.setStyleAttribute(loadElement, "position", "absolute"); - DOM.appendChild(rootConnector.getWidget().getElement(), loadElement); + DOM.appendChild(uIConnector.getWidget().getElement(), loadElement); VConsole.log("inserting load indicator"); } DOM.setElementProperty(loadElement, "className", "v-loading-indicator"); @@ -1090,7 +1096,7 @@ public class ApplicationConnection { meta = json.getValueMap("meta"); if (meta.containsKey("repaintAll")) { repaintAll = true; - rootConnector.getWidget().clear(); + uIConnector.getWidget().clear(); getConnectorMap().clear(); if (meta.containsKey("invalidLayouts")) { validatingLayouts = true; @@ -1148,6 +1154,8 @@ public class ApplicationConnection { " * Hierarchy state change event processing completed", 10); + delegateToWidget(pendingStateChangeEvents); + // Fire state change events. sendStateChangeEvents(pendingStateChangeEvents); @@ -1264,6 +1272,62 @@ public class ApplicationConnection { } + private void delegateToWidget( + Collection<StateChangeEvent> pendingStateChangeEvents) { + VConsole.log(" * Running @DelegateToWidget"); + + for (StateChangeEvent sce : pendingStateChangeEvents) { + ServerConnector connector = sce.getConnector(); + if (connector instanceof ComponentConnector) { + ComponentConnector component = (ComponentConnector) connector; + Type type = TypeData.getType(component.getClass()); + + Type stateType; + try { + stateType = type.getMethod("getState") + .getReturnType(); + } catch (NoDataException e) { + throw new RuntimeException( + "Can not find the state type for " + + type.getSignature(), e); + } + + Set<String> changedProperties = sce + .getChangedProperties(); + for (String propertyName : changedProperties) { + Property property = stateType + .getProperty(propertyName); + String method = property + .getDelegateToWidgetMethodName(); + if (method != null) { + doDelegateToWidget(component, property, method); + } + } + + } + } + } + + private void doDelegateToWidget(ComponentConnector component, + Property property, String methodName) { + Type type = TypeData.getType(component.getClass()); + try { + Type widgetType = type.getMethod("getWidget") + .getReturnType(); + Widget widget = component.getWidget(); + + Object propertyValue = property.getValue(component + .getState()); + + widgetType.getMethod(methodName).invoke(widget, + propertyValue); + } catch (NoDataException e) { + throw new RuntimeException( + "Missing data needed to invoke @DelegateToWidget for " + + Util.getSimpleName(component), e); + } + } + /** * Sends the state change events created while updating the state * information. @@ -1300,17 +1364,17 @@ public class ApplicationConnection { if (!c.getParent().getChildren().contains(c)) { VConsole.error("ERROR: Connector is connected to a parent but the parent does not contain the connector"); } - } else if ((c instanceof RootConnector && c == getRootConnector())) { - // RootConnector for this connection, leave as-is + } else if ((c instanceof UIConnector && c == getRootConnector())) { + // UIConnector for this connection, leave as-is } else if (c instanceof WindowConnector && getRootConnector().hasSubWindow( (WindowConnector) c)) { - // Sub window attached to this RootConnector, leave + // Sub window attached to this UIConnector, leave // as-is } else { // The connector has been detached from the // hierarchy, unregister it and any possible - // children. The RootConnector should never be + // children. The UIConnector should never be // unregistered even though it has no parent. connectorMap.unregisterConnector(c); unregistered++; @@ -1345,17 +1409,17 @@ public class ApplicationConnection { .getConnectorClassByEncodedTag(connectorType); // Connector does not exist so we must create it - if (connectorClass != RootConnector.class) { + if (connectorClass != UIConnector.class) { // create, initialize and register the paintable getConnector(connectorId, connectorType); } else { - // First RootConnector update. Before this the - // RootConnector has been created but not + // First UIConnector update. Before this the + // UIConnector has been created but not // initialized as the connector id has not been // known connectorMap.registerConnector(connectorId, - rootConnector); - rootConnector.doInit(connectorId, + uIConnector); + uIConnector.doInit(connectorId, ApplicationConnection.this); } } catch (final Throwable e) { @@ -2416,8 +2480,8 @@ public class ApplicationConnection { * * @return the main view */ - public RootConnector getRootConnector() { - return rootConnector; + public UIConnector getRootConnector() { + return uIConnector; } /** @@ -2554,4 +2618,77 @@ public class ApplicationConnection { LayoutManager getLayoutManager() { return layoutManager; } + + /** + * Schedules a heartbeat request to occur after the configured heartbeat + * interval elapses if the interval is a positive number. Otherwise, does + * nothing. + * + * @see #sendHeartbeat() + * @see ApplicationConfiguration#getHeartbeatInterval() + */ + protected void scheduleHeartbeat() { + final int interval = getConfiguration().getHeartbeatInterval(); + if (interval > 0) { + VConsole.log("Scheduling heartbeat in " + interval + " seconds"); + new Timer() { + @Override + public void run() { + sendHeartbeat(); + } + }.schedule(interval * 1000); + } + } + + /** + * Sends a heartbeat request to the server. + * <p> + * Heartbeat requests are used to inform the server that the client-side is + * still alive. If the client page is closed or the connection lost, the + * server will eventually close the inactive Root. + * <p> + * <b>TODO</b>: Improved error handling, like in doUidlRequest(). + * + * @see #scheduleHeartbeat() + */ + protected void sendHeartbeat() { + final String uri = addGetParameters( + translateVaadinUri(ApplicationConstants.APP_PROTOCOL_PREFIX + + ApplicationConstants.HEARTBEAT_REQUEST_PATH), + UIConstants.UI_ID_PARAMETER + "=" + + getConfiguration().getUIId()); + + final RequestBuilder rb = new RequestBuilder(RequestBuilder.POST, uri); + + final RequestCallback callback = new RequestCallback() { + + @Override + public void onResponseReceived(Request request, Response response) { + int status = response.getStatusCode(); + if (status == Response.SC_OK) { + // TODO Permit retry in some error situations + VConsole.log("Heartbeat response OK"); + scheduleHeartbeat(); + } else { + VConsole.error("Heartbeat request failed with status code " + + status); + } + } + + @Override + public void onError(Request request, Throwable exception) { + VConsole.error("Heartbeat request resulted in exception"); + VConsole.error(exception); + } + }; + + rb.setCallback(callback); + + try { + VConsole.log("Sending heartbeat request..."); + rb.send(); + } catch (RequestException re) { + callback.onError(null, re); + } + } } diff --git a/client/src/com/vaadin/terminal/gwt/client/ComponentLocator.java b/client/src/com/vaadin/terminal/gwt/client/ComponentLocator.java index e515c2626c..7c75913126 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ComponentLocator.java +++ b/client/src/com/vaadin/terminal/gwt/client/ComponentLocator.java @@ -28,10 +28,10 @@ import com.vaadin.shared.ComponentState; import com.vaadin.shared.Connector; import com.vaadin.shared.communication.SharedState; import com.vaadin.terminal.gwt.client.ui.SubPartAware; +import com.vaadin.terminal.gwt.client.ui.UI.VUI; import com.vaadin.terminal.gwt.client.ui.gridlayout.VGridLayout; import com.vaadin.terminal.gwt.client.ui.orderedlayout.VBoxLayout; import com.vaadin.terminal.gwt.client.ui.orderedlayout.VMeasuringOrderedLayout; -import com.vaadin.terminal.gwt.client.ui.root.VRoot; import com.vaadin.terminal.gwt.client.ui.tabsheet.VTabsheetPanel; import com.vaadin.terminal.gwt.client.ui.window.VWindow; import com.vaadin.terminal.gwt.client.ui.window.WindowConnector; @@ -386,7 +386,7 @@ public class ComponentLocator { return null; } - if (w instanceof VRoot) { + if (w instanceof VUI) { return ""; } else if (w instanceof VWindow) { Connector windowConnector = ConnectorMap.get(client) diff --git a/client/src/com/vaadin/terminal/gwt/client/LayoutManager.java b/client/src/com/vaadin/terminal/gwt/client/LayoutManager.java index 5bd784d1c6..3deb581848 100644 --- a/client/src/com/vaadin/terminal/gwt/client/LayoutManager.java +++ b/client/src/com/vaadin/terminal/gwt/client/LayoutManager.java @@ -315,7 +315,7 @@ public class LayoutManager { try { cl.layoutHorizontally(); } catch (RuntimeException e) { - VConsole.log(e); + VConsole.error(e); } countLayout(layoutCounts, cl); } else { @@ -326,7 +326,7 @@ public class LayoutManager { try { rr.layout(); } catch (RuntimeException e) { - VConsole.log(e); + VConsole.error(e); } countLayout(layoutCounts, rr); } @@ -343,7 +343,7 @@ public class LayoutManager { try { cl.layoutVertically(); } catch (RuntimeException e) { - VConsole.log(e); + VConsole.error(e); } countLayout(layoutCounts, cl); } else { @@ -354,7 +354,7 @@ public class LayoutManager { try { rr.layout(); } catch (RuntimeException e) { - VConsole.log(e); + VConsole.error(e); } countLayout(layoutCounts, rr); } diff --git a/client/src/com/vaadin/terminal/gwt/client/VDebugConsole.java b/client/src/com/vaadin/terminal/gwt/client/VDebugConsole.java index 1e2a3062f1..022171f2bb 100644 --- a/client/src/com/vaadin/terminal/gwt/client/VDebugConsole.java +++ b/client/src/com/vaadin/terminal/gwt/client/VDebugConsole.java @@ -70,8 +70,8 @@ import com.google.gwt.user.client.ui.Widget; import com.vaadin.shared.Version; import com.vaadin.terminal.gwt.client.ui.VLazyExecutor; import com.vaadin.terminal.gwt.client.ui.VOverlay; +import com.vaadin.terminal.gwt.client.ui.UI.UIConnector; import com.vaadin.terminal.gwt.client.ui.notification.VNotification; -import com.vaadin.terminal.gwt.client.ui.root.RootConnector; import com.vaadin.terminal.gwt.client.ui.window.WindowConnector; /** @@ -924,7 +924,7 @@ public class VDebugConsole extends VOverlay implements Console { } protected void dumpConnectorInfo(ApplicationConnection a) { - RootConnector root = a.getRootConnector(); + UIConnector root = a.getRootConnector(); log("================"); log("Connector hierarchy for Root: " + root.getState().getCaption() + " (" + root.getConnectorId() + ")"); diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/Property.java b/client/src/com/vaadin/terminal/gwt/client/metadata/Property.java index 082d032e64..69e41ce75d 100644 --- a/client/src/com/vaadin/terminal/gwt/client/metadata/Property.java +++ b/client/src/com/vaadin/terminal/gwt/client/metadata/Property.java @@ -4,6 +4,8 @@ package com.vaadin.terminal.gwt.client.metadata; +import com.vaadin.shared.annotations.DelegateToWidget; + public class Property { private final Type bean; private final String name; @@ -21,15 +23,12 @@ public class Property { TypeDataStore.getSetter(this).invoke(bean, value); } - public String getDelegateToWidgetMethod() { + public String getDelegateToWidgetMethodName() { String value = TypeDataStore.getDelegateToWidget(this); if (value == null) { return null; - } else if (value.isEmpty()) { - return "set" + Character.toUpperCase(value.charAt(0)) - + value.substring(1); } else { - return value; + return DelegateToWidget.Helper.getDelegateTarget(getName(), value); } } diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/TypeDataStore.java b/client/src/com/vaadin/terminal/gwt/client/metadata/TypeDataStore.java index 55740f69da..9c19410c88 100644 --- a/client/src/com/vaadin/terminal/gwt/client/metadata/TypeDataStore.java +++ b/client/src/com/vaadin/terminal/gwt/client/metadata/TypeDataStore.java @@ -101,6 +101,12 @@ public class TypeDataStore { return get().delegateToWidget.get(property); } + public void setDelegateToWidget(Class<?> clazz, String propertyName, + String delegateValue) { + delegateToWidget.put(new Property(getType(clazz), propertyName), + delegateValue); + } + public void setReturnType(Class<?> type, String methodName, Type returnType) { returnTypes.put(new Method(getType(type), methodName), returnType); } diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java index a50dad0c2f..14d7f4007e 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java @@ -40,8 +40,8 @@ import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; import com.vaadin.terminal.gwt.client.metadata.NoDataException; import com.vaadin.terminal.gwt.client.metadata.Type; import com.vaadin.terminal.gwt.client.metadata.TypeData; +import com.vaadin.terminal.gwt.client.ui.UI.UIConnector; import com.vaadin.terminal.gwt.client.ui.datefield.PopupDateFieldConnector; -import com.vaadin.terminal.gwt.client.ui.root.RootConnector; public abstract class AbstractComponentConnector extends AbstractConnector implements ComponentConnector { @@ -151,7 +151,7 @@ public abstract class AbstractComponentConnector extends AbstractConnector ServerConnector parent = getParent(); if (parent instanceof ComponentContainerConnector) { ((ComponentContainerConnector) parent).updateCaption(this); - } else if (parent == null && !(this instanceof RootConnector)) { + } else if (parent == null && !(this instanceof UIConnector)) { VConsole.error("Parent of connector " + Util.getConnectorString(this) + " is null. This is typically an indication of a broken component hierarchy"); @@ -181,7 +181,7 @@ public abstract class AbstractComponentConnector extends AbstractConnector ServerConnector parent = getParent(); if (parent instanceof ComponentContainerConnector) { ((ComponentContainerConnector) parent).updateCaption(this); - } else if (parent == null && !(this instanceof RootConnector)) { + } else if (parent == null && !(this instanceof UIConnector)) { VConsole.error("Parent of connector " + Util.getConnectorString(this) + " is null. This is typically an indication of a broken component hierarchy"); diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/MediaBaseConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/MediaBaseConnector.java index 2f52971aeb..33d97f4ed8 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/MediaBaseConnector.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/MediaBaseConnector.java @@ -49,9 +49,6 @@ public abstract class MediaBaseConnector extends AbstractComponentConnector { public void onStateChanged(StateChangeEvent stateChangeEvent) { super.onStateChanged(stateChangeEvent); - getWidget().setControls(getState().isShowControls()); - getWidget().setAutoplay(getState().isAutoplay()); - getWidget().setMuted(getState().isMuted()); for (int i = 0; i < getState().getSources().size(); i++) { URLReference source = getState().getSources().get(i); String sourceType = getState().getSourceTypes().get(i); diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/root/RootConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/UI/UIConnector.java index b3490effa7..4e1bed1aa8 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/root/RootConnector.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/UI/UIConnector.java @@ -13,7 +13,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.vaadin.terminal.gwt.client.ui.root; +package com.vaadin.terminal.gwt.client.ui.UI; import java.util.ArrayList; import java.util.Iterator; @@ -36,10 +36,10 @@ import com.google.web.bindery.event.shared.HandlerRegistration; import com.vaadin.shared.MouseEventDetails; import com.vaadin.shared.ui.Connect; import com.vaadin.shared.ui.Connect.LoadStyle; -import com.vaadin.shared.ui.root.PageClientRpc; -import com.vaadin.shared.ui.root.RootConstants; -import com.vaadin.shared.ui.root.RootServerRpc; -import com.vaadin.shared.ui.root.RootState; +import com.vaadin.shared.ui.ui.PageClientRpc; +import com.vaadin.shared.ui.ui.UIConstants; +import com.vaadin.shared.ui.ui.UIServerRpc; +import com.vaadin.shared.ui.ui.UIState; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.BrowserInfo; import com.vaadin.terminal.gwt.client.ComponentConnector; @@ -58,13 +58,13 @@ import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler; import com.vaadin.terminal.gwt.client.ui.layout.MayScrollChildren; import com.vaadin.terminal.gwt.client.ui.notification.VNotification; import com.vaadin.terminal.gwt.client.ui.window.WindowConnector; -import com.vaadin.ui.Root; +import com.vaadin.ui.UI; -@Connect(value = Root.class, loadStyle = LoadStyle.EAGER) -public class RootConnector extends AbstractComponentContainerConnector +@Connect(value = UI.class, loadStyle = LoadStyle.EAGER) +public class UIConnector extends AbstractComponentContainerConnector implements Paintable, MayScrollChildren { - private RootServerRpc rpc = RpcProxy.create(RootServerRpc.class, this); + private UIServerRpc rpc = RpcProxy.create(UIServerRpc.class, this); private HandlerRegistration childStateChangeHandlerRegistration; @@ -107,7 +107,7 @@ public class RootConnector extends AbstractComponentContainerConnector getWidget().connection = client; getWidget().immediate = getState().isImmediate(); - getWidget().resizeLazy = uidl.hasAttribute(RootConstants.RESIZE_LAZY); + getWidget().resizeLazy = uidl.hasAttribute(UIConstants.RESIZE_LAZY); String newTheme = uidl.getStringAttribute("theme"); if (getWidget().theme != null && !newTheme.equals(getWidget().theme)) { // Complete page refresh is needed due css can affect layout @@ -151,14 +151,14 @@ public class RootConnector extends AbstractComponentContainerConnector Scheduler.get().scheduleDeferred(new Command() { @Override public void execute() { - VRoot.goTo(url); + VUI.goTo(url); } }); } else if ("_self".equals(target)) { // This window is closing (for sure). Only other opens are // relevant in this change. See #3558, #2144 isClosed = true; - VRoot.goTo(url); + VUI.goTo(url); } else { String options; if (open.hasAttribute("border")) { @@ -263,9 +263,9 @@ public class RootConnector extends AbstractComponentContainerConnector scrollIntoView(connector); } - if (uidl.hasAttribute(RootConstants.FRAGMENT_VARIABLE)) { + if (uidl.hasAttribute(UIConstants.FRAGMENT_VARIABLE)) { getWidget().currentFragment = uidl - .getStringAttribute(RootConstants.FRAGMENT_VARIABLE); + .getStringAttribute(UIConstants.FRAGMENT_VARIABLE); if (!getWidget().currentFragment.equals(History.getToken())) { History.newItem(getWidget().currentFragment, true); } @@ -276,7 +276,7 @@ public class RootConnector extends AbstractComponentContainerConnector // Include current fragment in the next request client.updateVariable(getWidget().id, - RootConstants.FRAGMENT_VARIABLE, + UIConstants.FRAGMENT_VARIABLE, getWidget().currentFragment, false); } @@ -333,8 +333,8 @@ public class RootConnector extends AbstractComponentContainerConnector } @Override - public VRoot getWidget() { - return (VRoot) super.getWidget(); + public VUI getWidget() { + return (VUI) super.getWidget(); } protected ComponentConnector getContent() { @@ -359,7 +359,7 @@ public class RootConnector extends AbstractComponentContainerConnector } /** - * Checks if the given sub window is a child of this Root Connector + * Checks if the given sub window is a child of this UI Connector * * @deprecated Should be replaced by a more generic mechanism for getting * non-ComponentConnector children @@ -388,8 +388,8 @@ public class RootConnector extends AbstractComponentContainerConnector } @Override - public RootState getState() { - return (RootState) super.getState(); + public UIState getState() { + return (UIState) super.getState(); } @Override @@ -453,5 +453,4 @@ public class RootConnector extends AbstractComponentContainerConnector } }); } - } diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java b/client/src/com/vaadin/terminal/gwt/client/ui/UI/VUI.java index 162e7c55a8..1c4b69a3b9 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/UI/VUI.java @@ -14,7 +14,7 @@ * the License. */ -package com.vaadin.terminal.gwt.client.ui.root; +package com.vaadin.terminal.gwt.client.ui.UI; import java.util.ArrayList; @@ -33,7 +33,7 @@ import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.SimplePanel; import com.vaadin.shared.ApplicationConstants; -import com.vaadin.shared.ui.root.RootConstants; +import com.vaadin.shared.ui.ui.UIConstants; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.BrowserInfo; import com.vaadin.terminal.gwt.client.ComponentConnector; @@ -50,7 +50,7 @@ import com.vaadin.terminal.gwt.client.ui.textfield.VTextField; /** * */ -public class VRoot extends SimplePanel implements ResizeHandler, +public class VUI extends SimplePanel implements ResizeHandler, Window.ClosingHandler, ShortcutActionHandlerOwner, Focusable, HasResizeHandlers { @@ -130,7 +130,7 @@ public class VRoot extends SimplePanel implements ResizeHandler, // Send the new fragment to the server if it has changed if (!newFragment.equals(currentFragment) && connection != null) { currentFragment = newFragment; - connection.updateVariable(id, RootConstants.FRAGMENT_VARIABLE, + connection.updateVariable(id, UIConstants.FRAGMENT_VARIABLE, newFragment, true); } } @@ -146,7 +146,7 @@ public class VRoot extends SimplePanel implements ResizeHandler, }); - public VRoot() { + public VUI() { super(); setStyleName(CLASSNAME); diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/embeddedbrowser/EmbeddedBrowserConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/embeddedbrowser/EmbeddedBrowserConnector.java new file mode 100644 index 0000000000..61231c4fba --- /dev/null +++ b/client/src/com/vaadin/terminal/gwt/client/ui/embeddedbrowser/EmbeddedBrowserConnector.java @@ -0,0 +1,38 @@ +package com.vaadin.terminal.gwt.client.ui.embeddedbrowser; + +import com.vaadin.shared.ui.Connect; +import com.vaadin.shared.ui.embeddedbrowser.EmbeddedBrowserState; +import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; +import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector; + +@Connect(com.vaadin.ui.EmbeddedBrowser.class) +public class EmbeddedBrowserConnector extends AbstractComponentConnector { + + @Override + protected void init() { + super.init(); + } + + @Override + public VEmbeddedBrowser getWidget() { + return (VEmbeddedBrowser) super.getWidget(); + } + + @Override + public EmbeddedBrowserState getState() { + return (EmbeddedBrowserState) super.getState(); + } + + @Override + public void onStateChanged(StateChangeEvent stateChangeEvent) { + + super.onStateChanged(stateChangeEvent); + + getWidget().setAlternateText(getState().getAlternateText()); + getWidget().setSource( + getState().getSource() != null ? getState().getSource() + .getURL() : null); + getWidget().setName(getConnectorId()); + } + +} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/embeddedbrowser/VEmbeddedBrowser.java b/client/src/com/vaadin/terminal/gwt/client/ui/embeddedbrowser/VEmbeddedBrowser.java new file mode 100644 index 0000000000..fffbff049e --- /dev/null +++ b/client/src/com/vaadin/terminal/gwt/client/ui/embeddedbrowser/VEmbeddedBrowser.java @@ -0,0 +1,120 @@ +package com.vaadin.terminal.gwt.client.ui.embeddedbrowser; + +import com.google.gwt.dom.client.Document; +import com.google.gwt.dom.client.Element; +import com.google.gwt.dom.client.IFrameElement; +import com.google.gwt.user.client.ui.Widget; + +public class VEmbeddedBrowser extends Widget { + + protected IFrameElement iframe; + protected Element altElement; + protected String altText; + + public VEmbeddedBrowser() { + Element root = Document.get().createDivElement(); + setElement(root); + + setStylePrimaryName("v-embeddedbrowser"); + + createAltTextElement(); + } + + /** + * Always creates new iframe inside widget. Will replace previous iframe. + * + * @return + */ + protected IFrameElement createIFrameElement(String src) { + String name = null; + + // Remove alt text + if (altElement != null) { + getElement().removeChild(altElement); + altElement = null; + } + + // Remove old iframe + if (iframe != null) { + name = iframe.getAttribute("name"); + getElement().removeChild(iframe); + iframe = null; + } + + iframe = Document.get().createIFrameElement(); + iframe.setSrc(src); + iframe.setFrameBorder(0); + iframe.setAttribute("width", "100%"); + iframe.setAttribute("height", "100%"); + iframe.setAttribute("allowTransparency", "true"); + + getElement().appendChild(iframe); + + // Reset old attributes (except src) + if (name != null) { + iframe.setName(name); + } + + return iframe; + } + + protected void createAltTextElement() { + if (iframe != null) { + return; + } + + if (altElement == null) { + altElement = Document.get().createSpanElement(); + getElement().appendChild(altElement); + } + + if (altText != null) { + altElement.setInnerText(altText); + } else { + altElement.setInnerText(""); + } + } + + public void setAlternateText(String altText) { + if (this.altText != altText) { + this.altText = altText; + if (altElement != null) { + if (altText != null) { + altElement.setInnerText(altText); + } else { + altElement.setInnerText(""); + } + } + } + } + + /** + * Set the source (the "src" attribute) of iframe. Will replace old iframe + * with new. + * + * @param source + * Source of iframe. + */ + public void setSource(String source) { + + if (source == null) { + if (iframe != null) { + getElement().removeChild(iframe); + iframe = null; + } + createAltTextElement(); + setAlternateText(altText); + return; + } + + if (iframe == null || iframe.getSrc() != source) { + createIFrameElement(source); + } + } + + public void setName(String name) { + if (iframe != null) { + iframe.setName(name); + } + } +} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/flash/FlashConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/flash/FlashConnector.java new file mode 100644 index 0000000000..a9e7a71013 --- /dev/null +++ b/client/src/com/vaadin/terminal/gwt/client/ui/flash/FlashConnector.java @@ -0,0 +1,44 @@ +package com.vaadin.terminal.gwt.client.ui.flash; + +import com.vaadin.shared.ui.Connect; +import com.vaadin.shared.ui.flash.FlashState; +import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; +import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector; + +@Connect(com.vaadin.ui.Flash.class) +public class FlashConnector extends AbstractComponentConnector { + + @Override + protected void init() { + super.init(); + } + + @Override + public VFlash getWidget() { + return (VFlash) super.getWidget(); + } + + @Override + public FlashState getState() { + return (FlashState) super.getState(); + } + + @Override + public void onStateChanged(StateChangeEvent stateChangeEvent) { + + super.onStateChanged(stateChangeEvent); + + getWidget().setSource( + getState().getSource() != null ? getState().getSource() + .getURL() : null); + getWidget().setArchive(getState().getArchive()); + getWidget().setClassId(getState().getClassId()); + getWidget().setCodebase(getState().getCodebase()); + getWidget().setCodetype(getState().getCodetype()); + getWidget().setStandby(getState().getStandby()); + getWidget().setAlternateText(getState().getAlternateText()); + getWidget().setEmbedParams(getState().getEmbedParams()); + + getWidget().rebuildIfNeeded(); + } +} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/flash/VFlash.java b/client/src/com/vaadin/terminal/gwt/client/ui/flash/VFlash.java new file mode 100644 index 0000000000..5d60dc66aa --- /dev/null +++ b/client/src/com/vaadin/terminal/gwt/client/ui/flash/VFlash.java @@ -0,0 +1,228 @@ +package com.vaadin.terminal.gwt.client.ui.flash; + +import java.util.HashMap; +import java.util.Map; + +import com.google.gwt.user.client.ui.HTML; +import com.vaadin.terminal.gwt.client.Util; + +public class VFlash extends HTML { + + protected String source; + protected String altText; + protected String classId; + protected String codebase; + protected String codetype; + protected String standby; + protected String archive; + protected Map<String, String> embedParams = new HashMap<String, String>(); + protected boolean needsRebuild = false; + protected String width; + protected String height; + + public VFlash() { + setStylePrimaryName("v-flash"); + } + + public void setSource(String source) { + if (this.source != source) { + this.source = source; + needsRebuild = true; + } + } + + public void setAlternateText(String altText) { + if (this.altText != altText) { + this.altText = altText; + needsRebuild = true; + } + } + + public void setClassId(String classId) { + if (this.classId != classId) { + this.classId = classId; + needsRebuild = true; + } + } + + public void setCodebase(String codebase) { + if (this.codebase != codebase) { + this.codebase = codebase; + needsRebuild = true; + } + } + + public void setCodetype(String codetype) { + if (this.codetype != codetype) { + this.codetype = codetype; + needsRebuild = true; + } + } + + public void setStandby(String standby) { + if (this.standby != standby) { + this.standby = standby; + needsRebuild = true; + } + } + + public void setArchive(String archive) { + if (this.archive != archive) { + this.archive = archive; + needsRebuild = true; + } + } + + /** + * Call this after changing values of widget. It will rebuild embedding + * structure if needed. + */ + public void rebuildIfNeeded() { + if (needsRebuild) { + needsRebuild = false; + this.setHTML(createFlashEmbed()); + } + } + + @Override + public void setWidth(String width) { + // super.setWidth(height); + + if (this.width != width) { + this.width = width; + needsRebuild = true; + } + } + + @Override + public void setHeight(String height) { + // super.setHeight(height); + + if (this.height != height) { + this.height = height; + needsRebuild = true; + } + } + + public void setEmbedParams(Map<String, String> params) { + if (params == null) { + if (!embedParams.isEmpty()) { + embedParams.clear(); + needsRebuild = true; + } + return; + } + + if (!embedParams.equals(params)) { + embedParams = new HashMap<String, String>(params); + needsRebuild = true; + } + } + + protected String createFlashEmbed() { + /* + * To ensure cross-browser compatibility we are using the twice-cooked + * method to embed flash i.e. we add a OBJECT tag for IE ActiveX and + * inside it a EMBED for all other browsers. + */ + + StringBuilder html = new StringBuilder(); + + // Start the object tag + html.append("<object "); + + /* + * Add classid required for ActiveX to recognize the flash. This is a + * predefined value which ActiveX recognizes and must be the given + * value. More info can be found on + * http://kb2.adobe.com/cps/415/tn_4150.html. Allow user to override + * this by setting his own classid. + */ + if (classId != null) { + html.append("classid=\"" + Util.escapeAttribute(classId) + "\" "); + } else { + html.append("classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" "); + } + + /* + * Add codebase required for ActiveX and must be exactly this according + * to http://kb2.adobe.com/cps/415/tn_4150.html to work with the above + * given classid. Again, see more info on + * http://kb2.adobe.com/cps/415/tn_4150.html. Limiting Flash version to + * 6.0.0.0 and above. Allow user to override this by setting his own + * codebase + */ + if (codebase != null) { + html.append("codebase=\"" + Util.escapeAttribute(codebase) + "\" "); + } else { + html.append("codebase=\"http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0\" "); + } + + // Add width and height + html.append("width=\"" + Util.escapeAttribute(width) + "\" "); + html.append("height=\"" + Util.escapeAttribute(height) + "\" "); + html.append("type=\"application/x-shockwave-flash\" "); + + // Codetype + if (codetype != null) { + html.append("codetype=\"" + Util.escapeAttribute(codetype) + "\" "); + } + + // Standby + if (standby != null) { + html.append("standby=\"" + Util.escapeAttribute(standby) + "\" "); + } + + // Archive + if (archive != null) { + html.append("archive=\"" + Util.escapeAttribute(archive) + "\" "); + } + + // End object tag + html.append(">"); + + // Ensure we have an movie parameter + if (embedParams.get("movie") == null) { + embedParams.put("movie", source); + } + + // Add parameters to OBJECT + for (String name : embedParams.keySet()) { + html.append("<param "); + html.append("name=\"" + Util.escapeAttribute(name) + "\" "); + html.append("value=\"" + + Util.escapeAttribute(embedParams.get(name)) + "\" "); + html.append("/>"); + } + + // Build inner EMBED tag + html.append("<embed "); + html.append("src=\"" + Util.escapeAttribute(source) + "\" "); + html.append("width=\"" + Util.escapeAttribute(width) + "\" "); + html.append("height=\"" + Util.escapeAttribute(height) + "\" "); + html.append("type=\"application/x-shockwave-flash\" "); + + // Add the parameters to the Embed + for (String name : embedParams.keySet()) { + html.append(Util.escapeAttribute(name)); + html.append("="); + html.append("\"" + Util.escapeAttribute(embedParams.get(name)) + + "\""); + } + + // End embed tag + html.append("></embed>"); + + if (altText != null) { + html.append("<noembed>"); + html.append(altText); + html.append("</noembed>"); + } + + // End object tag + html.append("</object>"); + + return html.toString(); + } + +} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/image/ImageConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/image/ImageConnector.java new file mode 100644 index 0000000000..d36e224a03 --- /dev/null +++ b/client/src/com/vaadin/terminal/gwt/client/ui/image/ImageConnector.java @@ -0,0 +1,67 @@ +package com.vaadin.terminal.gwt.client.ui.image; + +import com.google.gwt.dom.client.NativeEvent; +import com.google.gwt.event.dom.client.LoadEvent; +import com.google.gwt.event.dom.client.LoadHandler; +import com.vaadin.shared.MouseEventDetails; +import com.vaadin.shared.ui.Connect; +import com.vaadin.shared.ui.image.ImageServerRpc; +import com.vaadin.shared.ui.image.ImageState; +import com.vaadin.terminal.gwt.client.communication.RpcProxy; +import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; +import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector; +import com.vaadin.terminal.gwt.client.ui.ClickEventHandler; + +@Connect(com.vaadin.ui.Image.class) +public class ImageConnector extends AbstractComponentConnector { + + ImageServerRpc rpc; + + @Override + protected void init() { + super.init(); + rpc = RpcProxy.create(ImageServerRpc.class, this); + getWidget().addHandler(new LoadHandler() { + + @Override + public void onLoad(LoadEvent event) { + getLayoutManager().setNeedsMeasure(ImageConnector.this); + } + + }, LoadEvent.getType()); + } + + @Override + public VImage getWidget() { + return (VImage) super.getWidget(); + } + + @Override + public ImageState getState() { + return (ImageState) super.getState(); + } + + @Override + public void onStateChanged(StateChangeEvent stateChangeEvent) { + super.onStateChanged(stateChangeEvent); + + clickEventHandler.handleEventHandlerRegistration(); + + getWidget().setUrl( + getState().getSource() != null ? getState().getSource() + .getURL() : null); + getWidget().setAltText(getState().getAlternateText()); + } + + protected final ClickEventHandler clickEventHandler = new ClickEventHandler( + this) { + + @Override + protected void fireClick(NativeEvent event, + MouseEventDetails mouseDetails) { + rpc.click(mouseDetails); + } + + }; + +} diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/image/VImage.java b/client/src/com/vaadin/terminal/gwt/client/ui/image/VImage.java new file mode 100644 index 0000000000..7e6b77ed4a --- /dev/null +++ b/client/src/com/vaadin/terminal/gwt/client/ui/image/VImage.java @@ -0,0 +1,10 @@ +package com.vaadin.terminal.gwt.client.ui.image; + +import com.google.gwt.user.client.ui.Image; + +public class VImage extends Image { + + public VImage() { + setStylePrimaryName("v-image"); + } +} 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 b4cea2dc72..b668c9a88c 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 @@ -30,7 +30,7 @@ import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.Widget; import com.vaadin.shared.Position; -import com.vaadin.shared.ui.root.RootConstants; +import com.vaadin.shared.ui.ui.UIConstants; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.BrowserInfo; import com.vaadin.terminal.gwt.client.UIDL; @@ -384,19 +384,19 @@ public class VNotification extends VOverlay { public static void showNotification(ApplicationConnection client, final UIDL notification) { boolean onlyPlainText = notification - .hasAttribute(RootConstants.NOTIFICATION_HTML_CONTENT_NOT_ALLOWED); + .hasAttribute(UIConstants.NOTIFICATION_HTML_CONTENT_NOT_ALLOWED); String html = ""; if (notification - .hasAttribute(RootConstants.ATTRIBUTE_NOTIFICATION_ICON)) { + .hasAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_ICON)) { final String parsedUri = client .translateVaadinUri(notification - .getStringAttribute(RootConstants.ATTRIBUTE_NOTIFICATION_ICON)); + .getStringAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_ICON)); html += "<img src=\"" + Util.escapeAttribute(parsedUri) + "\" />"; } if (notification - .hasAttribute(RootConstants.ATTRIBUTE_NOTIFICATION_CAPTION)) { + .hasAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_CAPTION)) { String caption = notification - .getStringAttribute(RootConstants.ATTRIBUTE_NOTIFICATION_CAPTION); + .getStringAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_CAPTION); if (onlyPlainText) { caption = Util.escapeHTML(caption); caption = caption.replaceAll("\\n", "<br />"); @@ -404,9 +404,9 @@ public class VNotification extends VOverlay { html += "<h1>" + caption + "</h1>"; } if (notification - .hasAttribute(RootConstants.ATTRIBUTE_NOTIFICATION_MESSAGE)) { + .hasAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_MESSAGE)) { String message = notification - .getStringAttribute(RootConstants.ATTRIBUTE_NOTIFICATION_MESSAGE); + .getStringAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_MESSAGE); if (onlyPlainText) { message = Util.escapeHTML(message); message = message.replaceAll("\\n", "<br />"); @@ -415,16 +415,16 @@ public class VNotification extends VOverlay { } final String style = notification - .hasAttribute(RootConstants.ATTRIBUTE_NOTIFICATION_STYLE) ? notification - .getStringAttribute(RootConstants.ATTRIBUTE_NOTIFICATION_STYLE) + .hasAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_STYLE) ? notification + .getStringAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_STYLE) : null; final int pos = notification - .getIntAttribute(RootConstants.ATTRIBUTE_NOTIFICATION_POSITION); + .getIntAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_POSITION); Position position = Position.values()[pos]; final int delay = notification - .getIntAttribute(RootConstants.ATTRIBUTE_NOTIFICATION_DELAY); + .getIntAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_DELAY); createNotification(delay).show(html, position, style); } diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/slider/SliderConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/slider/SliderConnector.java index 7e0617b7dc..53f3b8874b 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/slider/SliderConnector.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/slider/SliderConnector.java @@ -15,70 +15,61 @@ */ package com.vaadin.terminal.gwt.client.ui.slider; -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.user.client.Command; +import com.google.gwt.event.logical.shared.ValueChangeEvent; +import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.vaadin.shared.ui.Connect; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.Paintable; -import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.shared.ui.slider.SliderServerRpc; +import com.vaadin.shared.ui.slider.SliderState; +import com.vaadin.terminal.gwt.client.communication.RpcProxy; +import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; import com.vaadin.terminal.gwt.client.ui.AbstractFieldConnector; import com.vaadin.ui.Slider; @Connect(Slider.class) public class SliderConnector extends AbstractFieldConnector implements - Paintable { + ValueChangeHandler<Double> { - @Override - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - - getWidget().client = client; - getWidget().id = uidl.getId(); - - if (!isRealUpdate(uidl)) { - return; - } + protected SliderServerRpc rpc = RpcProxy + .create(SliderServerRpc.class, this); - getWidget().immediate = getState().isImmediate(); - getWidget().disabled = !isEnabled(); - getWidget().readonly = isReadOnly(); + @Override + public void init() { + super.init(); + getWidget().setConnection(getConnection()); + getWidget().addValueChangeHandler(this); + } - getWidget().vertical = uidl.hasAttribute("vertical"); + @Override + public VSlider getWidget() { + return (VSlider) super.getWidget(); + } - // TODO should style names be used? + @Override + public SliderState getState() { + return (SliderState) super.getState(); + } - if (getWidget().vertical) { - getWidget().addStyleName(VSlider.CLASSNAME + "-vertical"); - } else { - getWidget().removeStyleName(VSlider.CLASSNAME + "-vertical"); - } + @Override + public void onValueChange(ValueChangeEvent<Double> event) { + rpc.valueChanged(event.getValue()); + } - getWidget().min = uidl.getDoubleAttribute("min"); - getWidget().max = uidl.getDoubleAttribute("max"); - getWidget().resolution = uidl.getIntAttribute("resolution"); - getWidget().value = new Double(uidl.getDoubleVariable("value")); + @Override + public void onStateChanged(StateChangeEvent stateChangeEvent) { + super.onStateChanged(stateChangeEvent); - getWidget().setFeedbackValue(getWidget().value); + getWidget().setId(getConnectorId()); + getWidget().setImmediate(getState().isImmediate()); + getWidget().setDisabled(!isEnabled()); + getWidget().setReadOnly(isReadOnly()); + getWidget().setOrientation(getState().getOrientation()); + getWidget().setMinValue(getState().getMinValue()); + getWidget().setMaxValue(getState().getMaxValue()); + getWidget().setResolution(getState().getResolution()); + getWidget().setValue(getState().getValue(), false); + getWidget().setFeedbackValue(getState().getValue()); getWidget().buildBase(); - - if (!getWidget().vertical) { - // Draw handle with a delay to allow base to gain maximum width - Scheduler.get().scheduleDeferred(new Command() { - @Override - public void execute() { - getWidget().buildHandle(); - getWidget().setValue(getWidget().value, false); - } - }); - } else { - getWidget().buildHandle(); - getWidget().setValue(getWidget().value, false); - } - } - - @Override - public VSlider getWidget() { - return (VSlider) super.getWidget(); } } diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/slider/VSlider.java b/client/src/com/vaadin/terminal/gwt/client/ui/slider/VSlider.java index 9667522eb3..d9801626b4 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/slider/VSlider.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/slider/VSlider.java @@ -19,12 +19,17 @@ package com.vaadin.terminal.gwt.client.ui.slider; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.ScheduledCommand; import com.google.gwt.event.dom.client.KeyCodes; +import com.google.gwt.event.logical.shared.ValueChangeEvent; +import com.google.gwt.event.logical.shared.ValueChangeHandler; +import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.DOM; 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.google.gwt.user.client.ui.HasValue; +import com.vaadin.shared.ui.slider.SliderOrientation; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.BrowserInfo; import com.vaadin.terminal.gwt.client.ContainerResizedListener; @@ -36,7 +41,7 @@ import com.vaadin.terminal.gwt.client.ui.VLazyExecutor; import com.vaadin.terminal.gwt.client.ui.VOverlay; public class VSlider extends SimpleFocusablePanel implements Field, - ContainerResizedListener { + ContainerResizedListener, HasValue<Double> { public static final String CLASSNAME = "v-slider"; @@ -46,20 +51,22 @@ public class VSlider extends SimpleFocusablePanel implements Field, */ private static final int MIN_SIZE = 50; - ApplicationConnection client; + protected ApplicationConnection client; - String id; + protected String id; - boolean immediate; - boolean disabled; - boolean readonly; + protected boolean immediate; + protected boolean disabled; + protected boolean readonly; private int acceleration = 1; - double min; - double max; - int resolution; - Double value; - boolean vertical; + protected double min; + protected double max; + protected int resolution; + protected Double value; + protected SliderOrientation orientation = SliderOrientation.HORIZONTAL; + + private boolean valueChangeHandlerInitialized = false; private final HTML feedback = new HTML("", false); private final VOverlay feedbackPopup = new VOverlay(true, false, true) { @@ -92,7 +99,7 @@ public class VSlider extends SimpleFocusablePanel implements Field, @Override public void execute() { - updateValueToServer(); + fireValueChanged(); acceleration = 1; } }); @@ -137,7 +144,7 @@ public class VSlider extends SimpleFocusablePanel implements Field, } private void updateFeedbackPosition() { - if (vertical) { + if (isVertical()) { feedbackPopup.setPopupPosition( DOM.getAbsoluteLeft(handle) + handle.getOffsetWidth(), DOM.getAbsoluteTop(handle) + handle.getOffsetHeight() / 2 @@ -152,16 +159,17 @@ public class VSlider extends SimpleFocusablePanel implements Field, } void buildBase() { - final String styleAttribute = vertical ? "height" : "width"; - final String oppositeStyleAttribute = vertical ? "width" : "height"; - final String domProperty = vertical ? "offsetHeight" : "offsetWidth"; + final String styleAttribute = isVertical() ? "height" : "width"; + final String oppositeStyleAttribute = isVertical() ? "width" : "height"; + final String domProperty = isVertical() ? "offsetHeight" + : "offsetWidth"; // clear unnecessary opposite style attribute DOM.setStyleAttribute(base, oppositeStyleAttribute, ""); final Element p = DOM.getParent(getElement()); if (DOM.getElementPropertyInt(p, domProperty) > 50) { - if (vertical) { + if (isVertical()) { setHeight(); } else { DOM.setStyleAttribute(base, styleAttribute, ""); @@ -176,7 +184,7 @@ public class VSlider extends SimpleFocusablePanel implements Field, public void execute() { final Element p = DOM.getParent(getElement()); if (DOM.getElementPropertyInt(p, domProperty) > (MIN_SIZE + 5)) { - if (vertical) { + if (isVertical()) { setHeight(); } else { DOM.setStyleAttribute(base, styleAttribute, ""); @@ -188,12 +196,27 @@ public class VSlider extends SimpleFocusablePanel implements Field, }); } + if (!isVertical()) { + // Draw handle with a delay to allow base to gain maximum width + Scheduler.get().scheduleDeferred(new Command() { + @Override + public void execute() { + buildHandle(); + setValue(value, false); + } + }); + } else { + buildHandle(); + setValue(value, false); + } + // TODO attach listeners for focusing and arrow keys } void buildHandle() { - final String handleAttribute = vertical ? "marginTop" : "marginLeft"; - final String oppositeHandleAttribute = vertical ? "marginLeft" + final String handleAttribute = isVertical() ? "marginTop" + : "marginLeft"; + final String oppositeHandleAttribute = isVertical() ? "marginLeft" : "marginTop"; DOM.setStyleAttribute(handle, handleAttribute, "0"); @@ -206,59 +229,6 @@ public class VSlider extends SimpleFocusablePanel implements Field, } - void setValue(Double value, boolean updateToServer) { - if (value == null) { - return; - } - - if (value < min) { - value = min; - } else if (value > max) { - value = max; - } - - // Update handle position - final String styleAttribute = vertical ? "marginTop" : "marginLeft"; - final String domProperty = vertical ? "offsetHeight" : "offsetWidth"; - final int handleSize = Integer.parseInt(DOM.getElementProperty(handle, - domProperty)); - final int baseSize = Integer.parseInt(DOM.getElementProperty(base, - domProperty)) - (2 * BASE_BORDER_WIDTH); - - final int range = baseSize - handleSize; - double v = value.doubleValue(); - - // Round value to resolution - if (resolution > 0) { - v = Math.round(v * Math.pow(10, resolution)); - v = v / Math.pow(10, resolution); - } else { - v = Math.round(v); - } - final double valueRange = max - min; - double p = 0; - if (valueRange > 0) { - p = range * ((v - min) / valueRange); - } - if (p < 0) { - p = 0; - } - if (vertical) { - p = range - p; - } - final double pos = p; - - DOM.setStyleAttribute(handle, styleAttribute, (Math.round(pos)) + "px"); - - // Update value - this.value = new Double(v); - setFeedbackValue(v); - - if (updateToServer) { - updateValueToServer(); - } - } - @Override public void onBrowserEvent(Event event) { if (disabled || readonly) { @@ -386,7 +356,7 @@ public class VSlider extends SimpleFocusablePanel implements Field, final int coord = getEventPosition(event); final int handleSize, baseSize, baseOffset; - if (vertical) { + if (isVertical()) { handleSize = handle.getOffsetHeight(); baseSize = base.getOffsetHeight(); baseOffset = base.getAbsoluteTop() - Window.getScrollTop() @@ -398,7 +368,7 @@ public class VSlider extends SimpleFocusablePanel implements Field, + handleSize / 2; } - if (vertical) { + if (isVertical()) { v = ((baseSize - (coord - baseOffset)) / (double) (baseSize - handleSize)) * (max - min) + min; } else { @@ -423,7 +393,7 @@ public class VSlider extends SimpleFocusablePanel implements Field, * @return */ protected int getEventPosition(Event event) { - if (vertical) { + if (isVertical()) { return Util.getTouchOrMouseClientY(event); } else { return Util.getTouchOrMouseClientX(event); @@ -432,7 +402,7 @@ public class VSlider extends SimpleFocusablePanel implements Field, @Override public void iLayout() { - if (vertical) { + if (isVertical()) { setHeight(); } // Update handle position @@ -451,8 +421,8 @@ public class VSlider extends SimpleFocusablePanel implements Field, DOM.setStyleAttribute(base, "overflow", ""); } - private void updateValueToServer() { - client.updateVariable(id, "value", value.doubleValue(), immediate); + private void fireValueChanged() { + ValueChangeEvent.fire(VSlider.this, value); } /** @@ -469,8 +439,8 @@ public class VSlider extends SimpleFocusablePanel implements Field, return false; } - if ((keycode == getNavigationUpKey() && vertical) - || (keycode == getNavigationRightKey() && !vertical)) { + if ((keycode == getNavigationUpKey() && isVertical()) + || (keycode == getNavigationRightKey() && !isVertical())) { if (shift) { for (int a = 0; a < acceleration; a++) { increaseValue(false); @@ -480,8 +450,8 @@ public class VSlider extends SimpleFocusablePanel implements Field, increaseValue(false); } return true; - } else if (keycode == getNavigationDownKey() && vertical - || (keycode == getNavigationLeftKey() && !vertical)) { + } else if (keycode == getNavigationDownKey() && isVertical() + || (keycode == getNavigationLeftKey() && !isVertical())) { if (shift) { for (int a = 0; a < acceleration; a++) { decreaseValue(false); @@ -539,4 +509,119 @@ public class VSlider extends SimpleFocusablePanel implements Field, protected int getNavigationRightKey() { return KeyCodes.KEY_RIGHT; } + + public void setConnection(ApplicationConnection client) { + this.client = client; + } + + public void setId(String id) { + this.id = id; + } + + public void setImmediate(boolean immediate) { + this.immediate = immediate; + } + + public void setDisabled(boolean disabled) { + this.disabled = disabled; + } + + public void setReadOnly(boolean readonly) { + this.readonly = readonly; + } + + private boolean isVertical() { + return orientation == SliderOrientation.VERTICAL; + } + + public void setOrientation(SliderOrientation orientation) { + if (this.orientation != orientation) { + this.orientation = orientation; + + if (isVertical()) { + addStyleName(VSlider.CLASSNAME + "-vertical"); + } else { + removeStyleName(VSlider.CLASSNAME + "-vertical"); + } + } + } + + public void setMinValue(double value) { + min = value; + } + + public void setMaxValue(double value) { + max = value; + } + + public void setResolution(int resolution) { + this.resolution = resolution; + } + + public HandlerRegistration addValueChangeHandler( + ValueChangeHandler<Double> handler) { + return addHandler(handler, ValueChangeEvent.getType()); + } + + public Double getValue() { + return value; + } + + public void setValue(Double value) { + if (value < min) { + value = min; + } else if (value > max) { + value = max; + } + + // Update handle position + final String styleAttribute = isVertical() ? "marginTop" : "marginLeft"; + final String domProperty = isVertical() ? "offsetHeight" + : "offsetWidth"; + final int handleSize = Integer.parseInt(DOM.getElementProperty(handle, + domProperty)); + final int baseSize = Integer.parseInt(DOM.getElementProperty(base, + domProperty)) - (2 * BASE_BORDER_WIDTH); + + final int range = baseSize - handleSize; + double v = value.doubleValue(); + + // Round value to resolution + if (resolution > 0) { + v = Math.round(v * Math.pow(10, resolution)); + v = v / Math.pow(10, resolution); + } else { + v = Math.round(v); + } + final double valueRange = max - min; + double p = 0; + if (valueRange > 0) { + p = range * ((v - min) / valueRange); + } + if (p < 0) { + p = 0; + } + if (isVertical()) { + p = range - p; + } + final double pos = p; + + DOM.setStyleAttribute(handle, styleAttribute, (Math.round(pos)) + "px"); + + // Update value + this.value = new Double(v); + setFeedbackValue(v); + } + + public void setValue(Double value, boolean fireEvents) { + if (value == null) { + return; + } + + setValue(value); + + if (fireEvents) { + fireValueChanged(); + } + } } diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelConnector.java index 9f4df02380..912f9a7c83 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelConnector.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelConnector.java @@ -138,9 +138,6 @@ public abstract class AbstractSplitPanelConnector extends // Splitter updates SplitterState splitterState = getState().getSplitterState(); - getWidget().setLocked(splitterState.isLocked()); - getWidget().setPositionReversed(splitterState.isPositionReversed()); - getWidget().setStylenames(); getWidget().minimumPosition = splitterState.getMinPosition() 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 345eebc8aa..eda3f7090f 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 @@ -5256,6 +5256,27 @@ public class VScrollTable extends FlowPanel implements HasWidgets, return false; } + /** + * Checks if the row represented by the row key has been selected + * + * @param key + * The generated row key + */ + private boolean rowKeyIsSelected(int rowKey) { + // Check single selections + if (selectedRowKeys.contains("" + rowKey)) { + return true; + } + + // Check range selections + for (SelectionRange r : selectedRowRanges) { + if (r.inRange(getRenderedRowByKey("" + rowKey))) { + return true; + } + } + return false; + } + protected void startRowDrag(Event event, final int type, Element targetTdOrTr) { VTransferable transferable = new VTransferable(); @@ -5274,17 +5295,23 @@ public class VScrollTable extends FlowPanel implements HasWidgets, VDragEvent ev = VDragAndDropManager.get().startDrag( transferable, event, true); if (dragmode == DRAGMODE_MULTIROW && isMultiSelectModeAny() - && selectedRowKeys.contains("" + rowKey)) { + && rowKeyIsSelected(rowKey)) { + + // Create a drag image of ALL rows ev.createDragImage( (Element) scrollBody.tBodyElement.cast(), true); + + // Hide rows which are not selected Element dragImage = ev.getDragImage(); int i = 0; for (Iterator<Widget> iterator = scrollBody.iterator(); iterator .hasNext();) { VScrollTableRow next = (VScrollTableRow) iterator .next(); + Element child = (Element) dragImage.getChild(i++); - if (!selectedRowKeys.contains("" + next.rowKey)) { + + if (!rowKeyIsSelected(next.rowKey)) { child.getStyle().setVisibility(Visibility.HIDDEN); } } diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/textarea/TextAreaConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/textarea/TextAreaConnector.java index 5fb7f97044..d5abed4fa9 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/textarea/TextAreaConnector.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/textarea/TextAreaConnector.java @@ -18,7 +18,6 @@ package com.vaadin.terminal.gwt.client.ui.textarea; import com.vaadin.shared.ui.Connect; import com.vaadin.shared.ui.textarea.TextAreaState; -import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; import com.vaadin.terminal.gwt.client.ui.textfield.TextFieldConnector; import com.vaadin.ui.TextArea; @@ -31,14 +30,6 @@ public class TextAreaConnector extends TextFieldConnector { } @Override - public void onStateChanged(StateChangeEvent stateChangeEvent) { - super.onStateChanged(stateChangeEvent); - - getWidget().setRows(getState().getRows()); - getWidget().setWordwrap(getState().isWordwrap()); - } - - @Override public VTextArea getWidget() { return (VTextArea) super.getWidget(); } |