]> source.dussan.org Git - vaadin-framework.git/commitdiff
Moved shared classes out from connector to avoid class loader problems
authorArtur Signell <artur@vaadin.com>
Wed, 11 Apr 2012 16:13:34 +0000 (19:13 +0300)
committerArtur Signell <artur@vaadin.com>
Thu, 12 Apr 2012 06:58:17 +0000 (09:58 +0300)
14 files changed:
src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
src/com/vaadin/terminal/gwt/client/ComponentLocator.java
src/com/vaadin/terminal/gwt/client/VDebugConsole.java
src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java
src/com/vaadin/terminal/gwt/client/ui/RootConnector.java [deleted file]
src/com/vaadin/terminal/gwt/client/ui/VNotification.java
src/com/vaadin/terminal/gwt/client/ui/VView.java [deleted file]
src/com/vaadin/terminal/gwt/client/ui/WindowConnector.java
src/com/vaadin/terminal/gwt/client/ui/root/RootConnector.java [new file with mode: 0644]
src/com/vaadin/terminal/gwt/client/ui/root/RootServerRPC.java [new file with mode: 0644]
src/com/vaadin/terminal/gwt/client/ui/root/RootState.java [new file with mode: 0644]
src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java [new file with mode: 0644]
src/com/vaadin/terminal/gwt/widgetsetutils/WidgetMapGenerator.java
src/com/vaadin/ui/Root.java

index 6148988b7dffe886b02ce7dc17b9145dc1fafb12..6f3ff6db457699a04546f1c52b0700d3831df139 100644 (file)
@@ -45,12 +45,12 @@ import com.vaadin.terminal.gwt.client.communication.MethodInvocation;
 import com.vaadin.terminal.gwt.client.communication.RpcManager;
 import com.vaadin.terminal.gwt.client.communication.SharedState;
 import com.vaadin.terminal.gwt.client.communication.StateChangeEvent;
-import com.vaadin.terminal.gwt.client.ui.RootConnector;
 import com.vaadin.terminal.gwt.client.ui.VContextMenu;
 import com.vaadin.terminal.gwt.client.ui.VNotification;
 import com.vaadin.terminal.gwt.client.ui.VNotification.HideEvent;
 import com.vaadin.terminal.gwt.client.ui.WindowConnector;
 import com.vaadin.terminal.gwt.client.ui.dd.VDragAndDropManager;
+import com.vaadin.terminal.gwt.client.ui.root.RootConnector;
 import com.vaadin.terminal.gwt.server.AbstractCommunicationManager;
 
 /**
@@ -140,7 +140,7 @@ public class ApplicationConnection {
     private Timer loadTimer3;
     private Element loadElement;
 
-    private final RootConnector view;
+    private final RootConnector rootConnector;
 
     protected boolean applicationRunning = false;
 
@@ -192,7 +192,7 @@ public class ApplicationConnection {
     }
 
     public ApplicationConnection() {
-        view = GWT.create(RootConnector.class);
+        rootConnector = GWT.create(RootConnector.class);
         rpcManager = GWT.create(RpcManager.class);
         layoutManager = GWT.create(LayoutManager.class);
         layoutManager.setConnection(this);
@@ -224,7 +224,7 @@ public class ApplicationConnection {
 
         initializeClientHooks();
 
-        view.init(cnf.getRootPanelId(), this);
+        rootConnector.init(cnf.getRootPanelId(), this);
         showLoadingIndicator();
     }
 
@@ -856,7 +856,7 @@ public class ApplicationConnection {
         if (loadElement == null) {
             loadElement = DOM.createDiv();
             DOM.setStyleAttribute(loadElement, "position", "absolute");
-            DOM.appendChild(view.getWidget().getElement(), loadElement);
+            DOM.appendChild(rootConnector.getWidget().getElement(), loadElement);
             VConsole.log("inserting load indicator");
         }
         DOM.setElementProperty(loadElement, "className", "v-loading-indicator");
@@ -1032,7 +1032,7 @@ public class ApplicationConnection {
                     meta = json.getValueMap("meta");
                     if (meta.containsKey("repaintAll")) {
                         repaintAll = true;
-                        view.getWidget().clear();
+                        rootConnector.getWidget().clear();
                         getConnectorMap().clear();
                         if (meta.containsKey("invalidLayouts")) {
                             validatingLayouts = true;
@@ -1226,10 +1226,10 @@ public class ApplicationConnection {
                             if (!cc.getParent().getChildren().contains(cc)) {
                                 VConsole.error("ERROR: Connector is connected to a parent but the parent does not contain the connector");
                             }
-                        } else if ((cc instanceof RootConnector && cc == getView())) {
+                        } else if ((cc instanceof RootConnector && cc == getRootConnector())) {
                             // RootConnector for this connection, leave as-is
                         } else if (cc instanceof WindowConnector
-                                && getView().hasSubWindow((WindowConnector) cc)) {
+                                && getRootConnector().hasSubWindow((WindowConnector) cc)) {
                             // Sub window attached to this RootConnector, leave
                             // as-is
                         } else {
@@ -1279,8 +1279,8 @@ public class ApplicationConnection {
                             // RootConnector has been created but not
                             // initialized as the connector id has not been
                             // known
-                            connectorMap.registerConnector(connectorId, view);
-                            view.doInit(connectorId, ApplicationConnection.this);
+                            connectorMap.registerConnector(connectorId, rootConnector);
+                            rootConnector.doInit(connectorId, ApplicationConnection.this);
                         }
                     } catch (final Throwable e) {
                         VConsole.error(e);
@@ -2207,8 +2207,8 @@ public class ApplicationConnection {
 
         @Override
         public void run() {
-            VConsole.log("Running re-layout of " + view.getClass().getName());
-            runDescendentsLayout(view.getWidget());
+            VConsole.log("Running re-layout of " + rootConnector.getClass().getName());
+            runDescendentsLayout(rootConnector.getWidget());
             isPending = false;
         }
     };
@@ -2243,8 +2243,8 @@ public class ApplicationConnection {
      * 
      * @return the main view
      */
-    public RootConnector getView() {
-        return view;
+    public RootConnector getRootConnector() {
+        return rootConnector;
     }
 
     /**
index 9e5ed709c7206497642e42f57bc1d8b6a510b88e..82268605336875d04a6a81aa2b3151d1e965ba19 100644 (file)
@@ -16,9 +16,9 @@ import com.vaadin.terminal.gwt.client.ui.SubPartAware;
 import com.vaadin.terminal.gwt.client.ui.VGridLayout;
 import com.vaadin.terminal.gwt.client.ui.VMeasuringOrderedLayout;
 import com.vaadin.terminal.gwt.client.ui.VTabsheetPanel;
-import com.vaadin.terminal.gwt.client.ui.VView;
 import com.vaadin.terminal.gwt.client.ui.VWindow;
 import com.vaadin.terminal.gwt.client.ui.WindowConnector;
+import com.vaadin.terminal.gwt.client.ui.root.VRoot;
 
 /**
  * ComponentLocator provides methods for generating a String locator for a given
@@ -370,12 +370,12 @@ public class ComponentLocator {
             return null;
         }
 
-        if (w instanceof VView) {
+        if (w instanceof VRoot) {
             return "";
         } else if (w instanceof VWindow) {
             Connector windowConnector = ConnectorMap.get(client)
                     .getConnector(w);
-            List<WindowConnector> subWindowList = client.getView()
+            List<WindowConnector> subWindowList = client.getRootConnector()
                     .getSubWindows();
             int indexOfSubWindow = subWindowList.indexOf(windowConnector);
             return PARENTCHILD_SEPARATOR + "VWindow[" + indexOfSubWindow + "]";
@@ -436,7 +436,7 @@ public class ComponentLocator {
             if (part.equals(ROOT_ID)) {
                 w = RootPanel.get();
             } else if (part.equals("")) {
-                w = client.getView().getWidget();
+                w = client.getRootConnector().getWidget();
             } else if (w == null) {
                 String id = part;
                 // Must be old static pid (PID_S*)
@@ -445,7 +445,7 @@ public class ComponentLocator {
                 if (connector == null) {
                     // Lookup by debugId
                     // TODO Optimize this
-                    connector = findConnectorById(client.getView(),
+                    connector = findConnectorById(client.getRootConnector(),
                             id.substring(5));
                 }
 
@@ -541,7 +541,7 @@ public class ComponentLocator {
                  * compatibility
                  */
                 if (widgetClassName.equals("VWindow")) {
-                    List<WindowConnector> windows = client.getView()
+                    List<WindowConnector> windows = client.getRootConnector()
                             .getSubWindows();
                     List<VWindow> windowWidgets = new ArrayList<VWindow>(
                             windows.size());
index f815dc29fc590fddd26ebc02c43ad46b78494b83..ddf007ef373bbf021f1f3b384fcad00b447d3ed1 100644 (file)
@@ -52,11 +52,11 @@ import com.google.gwt.user.client.ui.Panel;
 import com.google.gwt.user.client.ui.RootPanel;
 import com.google.gwt.user.client.ui.VerticalPanel;
 import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ui.RootConnector;
 import com.vaadin.terminal.gwt.client.ui.VLazyExecutor;
 import com.vaadin.terminal.gwt.client.ui.VNotification;
 import com.vaadin.terminal.gwt.client.ui.VOverlay;
 import com.vaadin.terminal.gwt.client.ui.WindowConnector;
+import com.vaadin.terminal.gwt.client.ui.root.RootConnector;
 
 /**
  * A helper console for client side development. The debug console can also be
@@ -100,7 +100,7 @@ public class VDebugConsole extends VOverlay implements Console {
                 for (ApplicationConnection a : ApplicationConfiguration
                         .getRunningApplications()) {
                     ComponentConnector connector = Util.getConnectorForElement(
-                            a, a.getView().getWidget(), eventTarget);
+                            a, a.getRootConnector().getWidget(), eventTarget);
                     if (connector == null) {
                         connector = Util.getConnectorForElement(a,
                                 RootPanel.get(), eventTarget);
@@ -129,7 +129,7 @@ public class VDebugConsole extends VOverlay implements Console {
                 for (ApplicationConnection a : ApplicationConfiguration
                         .getRunningApplications()) {
                     ComponentConnector paintable = Util.getConnectorForElement(
-                            a, a.getView().getWidget(), eventTarget);
+                            a, a.getRootConnector().getWidget(), eventTarget);
                     if (paintable == null) {
                         paintable = Util.getConnectorForElement(a,
                                 RootPanel.get(), eventTarget);
@@ -841,7 +841,7 @@ public class VDebugConsole extends VOverlay implements Console {
     }
 
     protected void dumpConnectorInfo(ApplicationConnection a) {
-        RootConnector root = a.getView();
+        RootConnector root = a.getRootConnector();
         log("================");
         log("Connector hierarchy for Root: " + root.getState().getCaption()
                 + " (" + root.getConnectorId() + ")");
index 9ea03381c4b878b1695d8028d99ca0154ee49d70..57ee8a0bce3560c16d8f09618b863190a89606a4 100644 (file)
@@ -22,6 +22,7 @@ import com.vaadin.terminal.gwt.client.VConsole;
 import com.vaadin.terminal.gwt.client.communication.ServerRpc;
 import com.vaadin.terminal.gwt.client.communication.SharedState;
 import com.vaadin.terminal.gwt.client.communication.StateChangeEvent;
+import com.vaadin.terminal.gwt.client.ui.root.RootConnector;
 
 public abstract class AbstractComponentConnector extends AbstractConnector
         implements ComponentConnector {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/RootConnector.java b/src/com/vaadin/terminal/gwt/client/ui/RootConnector.java
deleted file mode 100644 (file)
index 21942ed..0000000
+++ /dev/null
@@ -1,417 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.client.ui;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import com.google.gwt.core.client.GWT;
-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.shared.HandlerRegistration;
-import com.google.gwt.user.client.Command;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.History;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.ui.RootPanel;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.BrowserInfo;
-import com.vaadin.terminal.gwt.client.ComponentConnector;
-import com.vaadin.terminal.gwt.client.ComponentState;
-import com.vaadin.terminal.gwt.client.Connector;
-import com.vaadin.terminal.gwt.client.ConnectorHierarchyChangeEvent;
-import com.vaadin.terminal.gwt.client.ConnectorMap;
-import com.vaadin.terminal.gwt.client.Focusable;
-import com.vaadin.terminal.gwt.client.MouseEventDetails;
-import com.vaadin.terminal.gwt.client.Paintable;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.Util;
-import com.vaadin.terminal.gwt.client.VConsole;
-import com.vaadin.terminal.gwt.client.communication.RpcProxy;
-import com.vaadin.terminal.gwt.client.communication.ServerRpc;
-import com.vaadin.terminal.gwt.client.communication.StateChangeEvent;
-import com.vaadin.terminal.gwt.client.communication.StateChangeEvent.StateChangeHandler;
-import com.vaadin.terminal.gwt.client.ui.Component.LoadStyle;
-import com.vaadin.ui.Root;
-
-@Component(value = Root.class, loadStyle = LoadStyle.EAGER)
-public class RootConnector extends AbstractComponentContainerConnector
-        implements Paintable {
-
-    public static class RootState extends ComponentState {
-        private Connector content;
-
-        public Connector getContent() {
-            return content;
-        }
-
-        public void setContent(Connector content) {
-            this.content = content;
-        }
-
-    }
-
-    public interface RootServerRPC extends ClickRPC, ServerRpc {
-
-    }
-
-    private RootServerRPC rpc;
-
-    private HandlerRegistration childStateChangeHandlerRegistration;
-
-    private final StateChangeHandler childStateChangeHandler = new StateChangeHandler() {
-        public void onStateChanged(StateChangeEvent stateChangeEvent) {
-            // TODO Should use a more specific handler that only reacts to
-            // size changes
-            onChildSizeChange();
-        }
-    };
-
-    @Override
-    protected void init() {
-        super.init();
-        rpc = RpcProxy.create(RootServerRPC.class, this);
-    }
-
-    public void updateFromUIDL(final UIDL uidl, ApplicationConnection client) {
-        ConnectorMap paintableMap = ConnectorMap.get(getConnection());
-        getWidget().rendering = true;
-        getWidget().id = getConnectorId();
-        boolean firstPaint = getWidget().connection == null;
-        getWidget().connection = client;
-
-        getWidget().immediate = getState().isImmediate();
-        getWidget().resizeLazy = uidl.hasAttribute(VView.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
-            // calculations etc
-            getWidget().reloadHostPage();
-        } else {
-            getWidget().theme = newTheme;
-        }
-        // this also implicitly removes old styles
-        String styles = "";
-        styles += getWidget().getStylePrimaryName() + " ";
-        if (getState().hasStyles()) {
-            for (String style : getState().getStyles()) {
-                styles += style + " ";
-            }
-        }
-        if (!client.getConfiguration().isStandalone()) {
-            styles += getWidget().getStylePrimaryName() + "-embedded";
-        }
-        getWidget().setStyleName(styles.trim());
-
-        clickEventHandler.handleEventHandlerRegistration();
-
-        if (!getWidget().isEmbedded() && getState().getCaption() != null) {
-            // only change window title if we're in charge of the whole page
-            com.google.gwt.user.client.Window.setTitle(getState().getCaption());
-        }
-
-        // Process children
-        int childIndex = 0;
-
-        // Open URL:s
-        boolean isClosed = false; // was this window closed?
-        while (childIndex < uidl.getChildCount()
-                && "open".equals(uidl.getChildUIDL(childIndex).getTag())) {
-            final UIDL open = uidl.getChildUIDL(childIndex);
-            final String url = client.translateVaadinUri(open
-                    .getStringAttribute("src"));
-            final String target = open.getStringAttribute("name");
-            if (target == null) {
-                // source will be opened to this browser window, but we may have
-                // to finish rendering this window in case this is a download
-                // (and window stays open).
-                Scheduler.get().scheduleDeferred(new Command() {
-                    public void execute() {
-                        VView.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;
-                VView.goTo(url);
-            } else {
-                String options;
-                if (open.hasAttribute("border")) {
-                    if (open.getStringAttribute("border").equals("minimal")) {
-                        options = "menubar=yes,location=no,status=no";
-                    } else {
-                        options = "menubar=no,location=no,status=no";
-                    }
-
-                } else {
-                    options = "resizable=yes,menubar=yes,toolbar=yes,directories=yes,location=yes,scrollbars=yes,status=yes";
-                }
-
-                if (open.hasAttribute("width")) {
-                    int w = open.getIntAttribute("width");
-                    options += ",width=" + w;
-                }
-                if (open.hasAttribute("height")) {
-                    int h = open.getIntAttribute("height");
-                    options += ",height=" + h;
-                }
-
-                Window.open(url, target, options);
-            }
-            childIndex++;
-        }
-        if (isClosed) {
-            // don't render the content, something else will be opened to this
-            // browser view
-            getWidget().rendering = false;
-            return;
-        }
-
-        // Handle other UIDL children
-        UIDL childUidl;
-        while ((childUidl = uidl.getChildUIDL(++childIndex)) != null) {
-            String tag = childUidl.getTag().intern();
-            if (tag == "actions") {
-                if (getWidget().actionHandler == null) {
-                    getWidget().actionHandler = new ShortcutActionHandler(
-                            getWidget().id, client);
-                }
-                getWidget().actionHandler.updateActionMap(childUidl);
-            } else if (tag == "execJS") {
-                String script = childUidl.getStringAttribute("script");
-                VView.eval(script);
-            } else if (tag == "notifications") {
-                for (final Iterator<?> it = childUidl.getChildIterator(); it
-                        .hasNext();) {
-                    final UIDL notification = (UIDL) it.next();
-                    VNotification.showNotification(client, notification);
-                }
-            }
-        }
-
-        if (uidl.hasAttribute("focused")) {
-            // set focused component when render phase is finished
-            Scheduler.get().scheduleDeferred(new Command() {
-                public void execute() {
-                    ComponentConnector paintable = (ComponentConnector) uidl
-                            .getPaintableAttribute("focused", getConnection());
-
-                    final Widget toBeFocused = paintable.getWidget();
-                    /*
-                     * Two types of Widgets can be focused, either implementing
-                     * GWT HasFocus of a thinner Vaadin specific Focusable
-                     * interface.
-                     */
-                    if (toBeFocused instanceof com.google.gwt.user.client.ui.Focusable) {
-                        final com.google.gwt.user.client.ui.Focusable toBeFocusedWidget = (com.google.gwt.user.client.ui.Focusable) toBeFocused;
-                        toBeFocusedWidget.setFocus(true);
-                    } else if (toBeFocused instanceof Focusable) {
-                        ((Focusable) toBeFocused).focus();
-                    } else {
-                        VConsole.log("Could not focus component");
-                    }
-                }
-            });
-        }
-
-        // Add window listeners on first paint, to prevent premature
-        // variablechanges
-        if (firstPaint) {
-            Window.addWindowClosingHandler(getWidget());
-            Window.addResizeHandler(getWidget());
-        }
-
-        // finally set scroll position from UIDL
-        if (uidl.hasVariable("scrollTop")) {
-            getWidget().scrollable = true;
-            getWidget().scrollTop = uidl.getIntVariable("scrollTop");
-            DOM.setElementPropertyInt(getWidget().getElement(), "scrollTop",
-                    getWidget().scrollTop);
-            getWidget().scrollLeft = uidl.getIntVariable("scrollLeft");
-            DOM.setElementPropertyInt(getWidget().getElement(), "scrollLeft",
-                    getWidget().scrollLeft);
-        } else {
-            getWidget().scrollable = false;
-        }
-
-        // Safari workaround must be run after scrollTop is updated as it sets
-        // scrollTop using a deferred command.
-        if (BrowserInfo.get().isSafari()) {
-            Util.runWebkitOverflowAutoFix(getWidget().getElement());
-        }
-
-        getWidget().scrollIntoView(uidl);
-
-        if (uidl.hasAttribute(VView.FRAGMENT_VARIABLE)) {
-            getWidget().currentFragment = uidl
-                    .getStringAttribute(VView.FRAGMENT_VARIABLE);
-            if (!getWidget().currentFragment.equals(History.getToken())) {
-                History.newItem(getWidget().currentFragment, true);
-            }
-        } else {
-            // Initial request for which the server doesn't yet have a fragment
-            // (and haven't shown any interest in getting one)
-            getWidget().currentFragment = History.getToken();
-
-            // Include current fragment in the next request
-            client.updateVariable(getWidget().id, VView.FRAGMENT_VARIABLE,
-                    getWidget().currentFragment, false);
-        }
-
-        getWidget().rendering = false;
-    }
-
-    public void init(String rootPanelId,
-            ApplicationConnection applicationConnection) {
-        DOM.sinkEvents(getWidget().getElement(), Event.ONKEYDOWN
-                | Event.ONSCROLL);
-
-        // iview is focused when created so element needs tabIndex
-        // 1 due 0 is at the end of natural tabbing order
-        DOM.setElementProperty(getWidget().getElement(), "tabIndex", "1");
-
-        RootPanel root = RootPanel.get(rootPanelId);
-
-        // Remove the v-app-loading or any splash screen added inside the div by
-        // the user
-        root.getElement().setInnerHTML("");
-
-        root.addStyleName("v-theme-"
-                + applicationConnection.getConfiguration().getThemeName());
-
-        root.add(getWidget());
-
-        if (applicationConnection.getConfiguration().isStandalone()) {
-            // set focus to iview element by default to listen possible keyboard
-            // shortcuts. For embedded applications this is unacceptable as we
-            // don't want to steal focus from the main page nor we don't want
-            // side-effects from focusing (scrollIntoView).
-            getWidget().getElement().focus();
-        }
-    }
-
-    private ClickEventHandler clickEventHandler = new ClickEventHandler(this) {
-
-        @Override
-        protected void fireClick(NativeEvent event,
-                MouseEventDetails mouseDetails) {
-            rpc.click(mouseDetails);
-        }
-
-    };
-
-    public void updateCaption(ComponentConnector component) {
-        // NOP The main view never draws caption for its layout
-    }
-
-    @Override
-    public VView getWidget() {
-        return (VView) super.getWidget();
-    }
-
-    @Override
-    protected Widget createWidget() {
-        return GWT.create(VView.class);
-    }
-
-    protected void onChildSizeChange() {
-        ComponentConnector child = (ComponentConnector) getState().getContent();
-        Style childStyle = child.getWidget().getElement().getStyle();
-        /*
-         * Must set absolute position if the child has relative height and
-         * there's a chance of horizontal scrolling as some browsers will
-         * otherwise not take the scrollbar into account when calculating the
-         * height. Assuming v-view does not have an undefined width for now, see
-         * #8460.
-         */
-        if (child.isRelativeHeight() && !BrowserInfo.get().isIE9()) {
-            childStyle.setPosition(Position.ABSOLUTE);
-        } else {
-            childStyle.clearPosition();
-        }
-    }
-
-    /**
-     * Checks if the given sub window is a child of this Root Connector
-     * 
-     * @deprecated Should be replaced by a more generic mechanism for getting
-     *             non-ComponentConnector children
-     * @param wc
-     * @return
-     */
-    @Deprecated
-    public boolean hasSubWindow(WindowConnector wc) {
-        return getChildren().contains(wc);
-    }
-
-    /**
-     * Return an iterator for current subwindows. This method is meant for
-     * testing purposes only.
-     * 
-     * @return
-     */
-    public List<WindowConnector> getSubWindows() {
-        ArrayList<WindowConnector> windows = new ArrayList<WindowConnector>();
-        for (ComponentConnector child : getChildren()) {
-            if (child instanceof WindowConnector) {
-                windows.add((WindowConnector) child);
-            }
-        }
-        return windows;
-    }
-
-    @Override
-    public RootState getState() {
-        return (RootState) super.getState();
-    }
-
-    @Override
-    public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) {
-        super.onConnectorHierarchyChange(event);
-
-        ComponentConnector oldChild = null;
-        ComponentConnector newChild = (ComponentConnector) getState()
-                .getContent();
-
-        for (ComponentConnector c : event.getOldChildren()) {
-            if (!(c instanceof WindowConnector)) {
-                oldChild = c;
-                break;
-            }
-        }
-
-        if (oldChild != newChild) {
-            if (childStateChangeHandlerRegistration != null) {
-                childStateChangeHandlerRegistration.removeHandler();
-                childStateChangeHandlerRegistration = null;
-            }
-            getWidget().setWidget(newChild.getWidget());
-            childStateChangeHandlerRegistration = newChild
-                    .addStateChangeHandler(childStateChangeHandler);
-            // Must handle new child here as state change events are already
-            // fired
-            onChildSizeChange();
-        }
-
-        for (ComponentConnector c : getChildren()) {
-            if (c instanceof WindowConnector) {
-                WindowConnector wc = (WindowConnector) c;
-                wc.setWindowOrderAndPosition();
-            }
-        }
-
-        // Close removed sub windows
-        for (ComponentConnector c : event.getOldChildren()) {
-            if (c.getParent() != this && c instanceof WindowConnector) {
-                ((WindowConnector) c).getWidget().hide();
-            }
-        }
-    }
-}
index cf62bb2de859f2cb875163ee0f32259f2f8820b1..1fc63e6a56b905c5de1efe3ba54634aee9ec4c62 100644 (file)
@@ -21,6 +21,7 @@ import com.vaadin.terminal.gwt.client.ApplicationConnection;
 import com.vaadin.terminal.gwt.client.BrowserInfo;
 import com.vaadin.terminal.gwt.client.UIDL;
 import com.vaadin.terminal.gwt.client.Util;
+import com.vaadin.terminal.gwt.client.ui.root.VRoot;
 
 public class VNotification extends VOverlay {
 
@@ -364,7 +365,7 @@ public class VNotification extends VOverlay {
     public static void showNotification(ApplicationConnection client,
             final UIDL notification) {
         boolean onlyPlainText = notification
-                .hasAttribute(VView.NOTIFICATION_HTML_CONTENT_NOT_ALLOWED);
+                .hasAttribute(VRoot.NOTIFICATION_HTML_CONTENT_NOT_ALLOWED);
         String html = "";
         if (notification.hasAttribute(ATTRIBUTE_NOTIFICATION_ICON)) {
             final String parsedUri = client.translateVaadinUri(notification
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VView.java b/src/com/vaadin/terminal/gwt/client/ui/VView.java
deleted file mode 100644 (file)
index 2cf446a..0000000
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.terminal.gwt.client.ui;
-
-import java.util.ArrayList;
-
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.core.client.Scheduler.ScheduledCommand;
-import com.google.gwt.event.logical.shared.ResizeEvent;
-import com.google.gwt.event.logical.shared.ResizeHandler;
-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.Event;
-import com.google.gwt.user.client.History;
-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.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.BrowserInfo;
-import com.vaadin.terminal.gwt.client.ComponentConnector;
-import com.vaadin.terminal.gwt.client.Focusable;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.Util;
-import com.vaadin.terminal.gwt.client.VConsole;
-import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.ShortcutActionHandlerOwner;
-
-/**
- *
- */
-public class VView extends SimplePanel implements ResizeHandler,
-        Window.ClosingHandler, ShortcutActionHandlerOwner, Focusable {
-
-    public static final String FRAGMENT_VARIABLE = "fragment";
-
-    private static final String CLASSNAME = "v-view";
-
-    public static final String NOTIFICATION_HTML_CONTENT_NOT_ALLOWED = "useplain";
-
-    String theme;
-
-    String id;
-
-    ShortcutActionHandler actionHandler;
-
-    /** stored width for IE resize optimization */
-    private int width;
-
-    /** stored height for IE resize optimization */
-    private int height;
-
-    ApplicationConnection connection;
-
-    /** Identifies the click event */
-    public static final String CLICK_EVENT_ID = "click";
-
-    /**
-     * We are postponing resize process with IE. IE bugs with scrollbars in some
-     * situations, that causes false onWindowResized calls. With Timer we will
-     * give IE some time to decide if it really wants to keep current size
-     * (scrollbars).
-     */
-    private Timer resizeTimer;
-
-    int scrollTop;
-
-    int scrollLeft;
-
-    boolean rendering;
-
-    boolean scrollable;
-
-    boolean immediate;
-
-    boolean resizeLazy = false;
-
-    /**
-     * Attribute name for the lazy resize setting .
-     */
-    public static final String RESIZE_LAZY = "rL";
-
-    private HandlerRegistration historyHandlerRegistration;
-
-    /**
-     * The current URI fragment, used to avoid sending updates if nothing has
-     * changed.
-     */
-    String currentFragment;
-
-    /**
-     * Listener for URI fragment changes. Notifies the server of the new value
-     * whenever the value changes.
-     */
-    private final ValueChangeHandler<String> historyChangeHandler = new ValueChangeHandler<String>() {
-        public void onValueChange(ValueChangeEvent<String> event) {
-            String newFragment = event.getValue();
-
-            // Send the new fragment to the server if it has changed
-            if (!newFragment.equals(currentFragment) && connection != null) {
-                currentFragment = newFragment;
-                connection.updateVariable(id, FRAGMENT_VARIABLE, newFragment,
-                        true);
-            }
-        }
-    };
-
-    private VLazyExecutor delayedResizeExecutor = new VLazyExecutor(200,
-            new ScheduledCommand() {
-                public void execute() {
-                    windowSizeMaybeChanged(Window.getClientWidth(),
-                            Window.getClientHeight());
-                }
-
-            });
-
-    public VView() {
-        super();
-        setStyleName(CLASSNAME);
-
-        // Allow focusing the view by using the focus() method, the view
-        // should not be in the document focus flow
-        getElement().setTabIndex(-1);
-    }
-
-    @Override
-    protected void onAttach() {
-        super.onAttach();
-        historyHandlerRegistration = History
-                .addValueChangeHandler(historyChangeHandler);
-        currentFragment = History.getToken();
-    }
-
-    @Override
-    protected void onDetach() {
-        super.onDetach();
-        historyHandlerRegistration.removeHandler();
-        historyHandlerRegistration = null;
-    }
-
-    /**
-     * Called when the window might have been resized.
-     * 
-     * @param newWidth
-     *            The new width of the window
-     * @param newHeight
-     *            The new height of the window
-     */
-    protected void windowSizeMaybeChanged(int newWidth, int newHeight) {
-        boolean changed = false;
-        if (width != newWidth) {
-            width = newWidth;
-            changed = true;
-            VConsole.log("New window width: " + width);
-        }
-        if (height != newHeight) {
-            height = newHeight;
-            changed = true;
-            VConsole.log("New window height: " + height);
-        }
-        if (changed) {
-            VConsole.log("Running layout functions due to window resize");
-            Util.runWebkitOverflowAutoFix(getElement());
-
-            sendClientResized();
-
-            connection.doLayout(false);
-        }
-    }
-
-    public String getTheme() {
-        return theme;
-    }
-
-    /**
-     * Used to reload host page on theme changes.
-     */
-    static native void reloadHostPage()
-    /*-{
-         $wnd.location.reload();
-     }-*/;
-
-    /**
-     * Evaluate the given script in the browser document.
-     * 
-     * @param script
-     *            Script to be executed.
-     */
-    static native void eval(String script)
-    /*-{
-      try {
-         if (script == null) return;
-         $wnd.eval(script);
-      } catch (e) {
-      }
-    }-*/;
-
-    /**
-     * Returns true if the body is NOT generated, i.e if someone else has made
-     * the page that we're running in. Otherwise we're in charge of the whole
-     * page.
-     * 
-     * @return true if we're running embedded
-     */
-    public boolean isEmbedded() {
-        return !getElement().getOwnerDocument().getBody().getClassName()
-                .contains(ApplicationConnection.GENERATED_BODY_CLASSNAME);
-    }
-
-    /**
-     * Tries to scroll paintable referenced from given UIDL snippet to be
-     * visible.
-     * 
-     * @param uidl
-     */
-    void scrollIntoView(final UIDL uidl) {
-        if (uidl.hasAttribute("scrollTo")) {
-            Scheduler.get().scheduleDeferred(new Command() {
-                public void execute() {
-                    final ComponentConnector paintable = (ComponentConnector) uidl
-                            .getPaintableAttribute("scrollTo", connection);
-                    paintable.getWidget().getElement().scrollIntoView();
-                }
-            });
-        }
-    }
-
-    @Override
-    public void onBrowserEvent(Event event) {
-        super.onBrowserEvent(event);
-        int type = DOM.eventGetType(event);
-        if (type == Event.ONKEYDOWN && actionHandler != null) {
-            actionHandler.handleKeyboardEvent(event);
-            return;
-        } else if (scrollable && type == Event.ONSCROLL) {
-            updateScrollPosition();
-        }
-    }
-
-    /**
-     * Updates scroll position from DOM and saves variables to server.
-     */
-    private void updateScrollPosition() {
-        int oldTop = scrollTop;
-        int oldLeft = scrollLeft;
-        scrollTop = DOM.getElementPropertyInt(getElement(), "scrollTop");
-        scrollLeft = DOM.getElementPropertyInt(getElement(), "scrollLeft");
-        if (connection != null && !rendering) {
-            if (oldTop != scrollTop) {
-                connection.updateVariable(id, "scrollTop", scrollTop, false);
-            }
-            if (oldLeft != scrollLeft) {
-                connection.updateVariable(id, "scrollLeft", scrollLeft, false);
-            }
-        }
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see
-     * com.google.gwt.event.logical.shared.ResizeHandler#onResize(com.google
-     * .gwt.event.logical.shared.ResizeEvent)
-     */
-    public void onResize(ResizeEvent event) {
-        onResize();
-    }
-
-    /**
-     * Called when a resize event is received.
-     */
-    void onResize() {
-        /*
-         * IE (pre IE9 at least) will give us some false resize events due to
-         * problems with scrollbars. Firefox 3 might also produce some extra
-         * events. We postpone both the re-layouting and the server side event
-         * for a while to deal with these issues.
-         * 
-         * We may also postpone these events to avoid slowness when resizing the
-         * browser window. Constantly recalculating the layout causes the resize
-         * operation to be really slow with complex layouts.
-         */
-        boolean lazy = resizeLazy || BrowserInfo.get().isIE8();
-
-        if (lazy) {
-            delayedResizeExecutor.trigger();
-        } else {
-            windowSizeMaybeChanged(Window.getClientWidth(),
-                    Window.getClientHeight());
-        }
-    }
-
-    /**
-     * Send new dimensions to the server.
-     */
-    private void sendClientResized() {
-        connection.updateVariable(id, "height", height, false);
-        connection.updateVariable(id, "width", width, immediate);
-    }
-
-    public native static void goTo(String url)
-    /*-{
-       $wnd.location = url;
-     }-*/;
-
-    public void onWindowClosing(Window.ClosingEvent event) {
-        // Change focus on this window in order to ensure that all state is
-        // collected from textfields
-        // TODO this is a naive hack, that only works with text fields and may
-        // cause some odd issues. Should be replaced with a decent solution, see
-        // also related BeforeShortcutActionListener interface. Same interface
-        // might be usable here.
-        VTextField.flushChangesFromFocusedTextField();
-    }
-
-    private native static void loadAppIdListFromDOM(ArrayList<String> list)
-    /*-{
-         var j;
-         for(j in $wnd.vaadin.vaadinConfigurations) {
-            list.@java.util.Collection::add(Ljava/lang/Object;)(j);
-         }
-     }-*/;
-
-    public ShortcutActionHandler getShortcutActionHandler() {
-        return actionHandler;
-    }
-
-    public void focus() {
-        getElement().focus();
-    }
-
-}
index 34a3f9a94f373caa808ca3c76f291e483f16a905..4cee6813c7dfc6a7f6b01c1cd9ad71f3915e0f48 100644 (file)
@@ -243,8 +243,6 @@ public class WindowConnector extends AbstractComponentContainerConnector
             getWidget().setHeight(Window.getClientHeight() + "px");
         }
 
-        client.getView().getWidget().scrollIntoView(uidl);
-
         if (uidl.hasAttribute("bringToFront")) {
             /*
              * Focus as a side-efect. Will be overridden by
diff --git a/src/com/vaadin/terminal/gwt/client/ui/root/RootConnector.java b/src/com/vaadin/terminal/gwt/client/ui/root/RootConnector.java
new file mode 100644 (file)
index 0000000..04bfbf2
--- /dev/null
@@ -0,0 +1,429 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.terminal.gwt.client.ui.root;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import com.google.gwt.core.client.GWT;
+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.shared.HandlerRegistration;
+import com.google.gwt.user.client.Command;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.History;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.RootPanel;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.terminal.gwt.client.ApplicationConnection;
+import com.vaadin.terminal.gwt.client.BrowserInfo;
+import com.vaadin.terminal.gwt.client.ComponentConnector;
+import com.vaadin.terminal.gwt.client.ConnectorHierarchyChangeEvent;
+import com.vaadin.terminal.gwt.client.ConnectorMap;
+import com.vaadin.terminal.gwt.client.Focusable;
+import com.vaadin.terminal.gwt.client.MouseEventDetails;
+import com.vaadin.terminal.gwt.client.Paintable;
+import com.vaadin.terminal.gwt.client.UIDL;
+import com.vaadin.terminal.gwt.client.Util;
+import com.vaadin.terminal.gwt.client.VConsole;
+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.AbstractComponentContainerConnector;
+import com.vaadin.terminal.gwt.client.ui.ClickEventHandler;
+import com.vaadin.terminal.gwt.client.ui.Component;
+import com.vaadin.terminal.gwt.client.ui.Component.LoadStyle;
+import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler;
+import com.vaadin.terminal.gwt.client.ui.VNotification;
+import com.vaadin.terminal.gwt.client.ui.WindowConnector;
+import com.vaadin.ui.Root;
+
+@Component(value = Root.class, loadStyle = LoadStyle.EAGER)
+public class RootConnector extends AbstractComponentContainerConnector
+        implements Paintable {
+
+    private RootServerRPC rpc = RpcProxy.create(RootServerRPC.class, this);
+
+    private HandlerRegistration childStateChangeHandlerRegistration;
+
+    private final StateChangeHandler childStateChangeHandler = new StateChangeHandler() {
+        public void onStateChanged(StateChangeEvent stateChangeEvent) {
+            // TODO Should use a more specific handler that only reacts to
+            // size changes
+            onChildSizeChange();
+        }
+    };
+
+    @Override
+    protected void init() {
+        super.init();
+    }
+
+    public void updateFromUIDL(final UIDL uidl, ApplicationConnection client) {
+        ConnectorMap paintableMap = ConnectorMap.get(getConnection());
+        getWidget().rendering = true;
+        getWidget().id = getConnectorId();
+        boolean firstPaint = getWidget().connection == null;
+        getWidget().connection = client;
+
+        getWidget().immediate = getState().isImmediate();
+        getWidget().resizeLazy = uidl.hasAttribute(VRoot.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
+            // calculations etc
+            getWidget().reloadHostPage();
+        } else {
+            getWidget().theme = newTheme;
+        }
+        // this also implicitly removes old styles
+        String styles = "";
+        styles += getWidget().getStylePrimaryName() + " ";
+        if (getState().hasStyles()) {
+            for (String style : getState().getStyles()) {
+                styles += style + " ";
+            }
+        }
+        if (!client.getConfiguration().isStandalone()) {
+            styles += getWidget().getStylePrimaryName() + "-embedded";
+        }
+        getWidget().setStyleName(styles.trim());
+
+        clickEventHandler.handleEventHandlerRegistration();
+
+        if (!getWidget().isEmbedded() && getState().getCaption() != null) {
+            // only change window title if we're in charge of the whole page
+            com.google.gwt.user.client.Window.setTitle(getState().getCaption());
+        }
+
+        // Process children
+        int childIndex = 0;
+
+        // Open URL:s
+        boolean isClosed = false; // was this window closed?
+        while (childIndex < uidl.getChildCount()
+                && "open".equals(uidl.getChildUIDL(childIndex).getTag())) {
+            final UIDL open = uidl.getChildUIDL(childIndex);
+            final String url = client.translateVaadinUri(open
+                    .getStringAttribute("src"));
+            final String target = open.getStringAttribute("name");
+            if (target == null) {
+                // source will be opened to this browser window, but we may have
+                // to finish rendering this window in case this is a download
+                // (and window stays open).
+                Scheduler.get().scheduleDeferred(new Command() {
+                    public void execute() {
+                        VRoot.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);
+            } else {
+                String options;
+                if (open.hasAttribute("border")) {
+                    if (open.getStringAttribute("border").equals("minimal")) {
+                        options = "menubar=yes,location=no,status=no";
+                    } else {
+                        options = "menubar=no,location=no,status=no";
+                    }
+
+                } else {
+                    options = "resizable=yes,menubar=yes,toolbar=yes,directories=yes,location=yes,scrollbars=yes,status=yes";
+                }
+
+                if (open.hasAttribute("width")) {
+                    int w = open.getIntAttribute("width");
+                    options += ",width=" + w;
+                }
+                if (open.hasAttribute("height")) {
+                    int h = open.getIntAttribute("height");
+                    options += ",height=" + h;
+                }
+
+                Window.open(url, target, options);
+            }
+            childIndex++;
+        }
+        if (isClosed) {
+            // don't render the content, something else will be opened to this
+            // browser view
+            getWidget().rendering = false;
+            return;
+        }
+
+        // Handle other UIDL children
+        UIDL childUidl;
+        while ((childUidl = uidl.getChildUIDL(++childIndex)) != null) {
+            String tag = childUidl.getTag().intern();
+            if (tag == "actions") {
+                if (getWidget().actionHandler == null) {
+                    getWidget().actionHandler = new ShortcutActionHandler(
+                            getWidget().id, client);
+                }
+                getWidget().actionHandler.updateActionMap(childUidl);
+            } else if (tag == "execJS") {
+                String script = childUidl.getStringAttribute("script");
+                VRoot.eval(script);
+            } else if (tag == "notifications") {
+                for (final Iterator<?> it = childUidl.getChildIterator(); it
+                        .hasNext();) {
+                    final UIDL notification = (UIDL) it.next();
+                    VNotification.showNotification(client, notification);
+                }
+            }
+        }
+
+        if (uidl.hasAttribute("focused")) {
+            // set focused component when render phase is finished
+            Scheduler.get().scheduleDeferred(new Command() {
+                public void execute() {
+                    ComponentConnector paintable = (ComponentConnector) uidl
+                            .getPaintableAttribute("focused", getConnection());
+
+                    final Widget toBeFocused = paintable.getWidget();
+                    /*
+                     * Two types of Widgets can be focused, either implementing
+                     * GWT HasFocus of a thinner Vaadin specific Focusable
+                     * interface.
+                     */
+                    if (toBeFocused instanceof com.google.gwt.user.client.ui.Focusable) {
+                        final com.google.gwt.user.client.ui.Focusable toBeFocusedWidget = (com.google.gwt.user.client.ui.Focusable) toBeFocused;
+                        toBeFocusedWidget.setFocus(true);
+                    } else if (toBeFocused instanceof Focusable) {
+                        ((Focusable) toBeFocused).focus();
+                    } else {
+                        VConsole.log("Could not focus component");
+                    }
+                }
+            });
+        }
+
+        // Add window listeners on first paint, to prevent premature
+        // variablechanges
+        if (firstPaint) {
+            Window.addWindowClosingHandler(getWidget());
+            Window.addResizeHandler(getWidget());
+        }
+
+        // finally set scroll position from UIDL
+        if (uidl.hasVariable("scrollTop")) {
+            getWidget().scrollable = true;
+            getWidget().scrollTop = uidl.getIntVariable("scrollTop");
+            DOM.setElementPropertyInt(getWidget().getElement(), "scrollTop",
+                    getWidget().scrollTop);
+            getWidget().scrollLeft = uidl.getIntVariable("scrollLeft");
+            DOM.setElementPropertyInt(getWidget().getElement(), "scrollLeft",
+                    getWidget().scrollLeft);
+        } else {
+            getWidget().scrollable = false;
+        }
+
+        // Safari workaround must be run after scrollTop is updated as it sets
+        // scrollTop using a deferred command.
+        if (BrowserInfo.get().isSafari()) {
+            Util.runWebkitOverflowAutoFix(getWidget().getElement());
+        }
+
+        if (uidl.hasAttribute("scrollTo")) {
+            final ComponentConnector connector = (ComponentConnector) uidl
+                    .getPaintableAttribute("scrollTo", getConnection());
+            scrollIntoView(connector);
+        }
+
+        if (uidl.hasAttribute(VRoot.FRAGMENT_VARIABLE)) {
+            getWidget().currentFragment = uidl
+                    .getStringAttribute(VRoot.FRAGMENT_VARIABLE);
+            if (!getWidget().currentFragment.equals(History.getToken())) {
+                History.newItem(getWidget().currentFragment, true);
+            }
+        } else {
+            // Initial request for which the server doesn't yet have a fragment
+            // (and haven't shown any interest in getting one)
+            getWidget().currentFragment = History.getToken();
+
+            // Include current fragment in the next request
+            client.updateVariable(getWidget().id, VRoot.FRAGMENT_VARIABLE,
+                    getWidget().currentFragment, false);
+        }
+
+        getWidget().rendering = false;
+    }
+
+    public void init(String rootPanelId,
+            ApplicationConnection applicationConnection) {
+        DOM.sinkEvents(getWidget().getElement(), Event.ONKEYDOWN
+                | Event.ONSCROLL);
+
+        // iview is focused when created so element needs tabIndex
+        // 1 due 0 is at the end of natural tabbing order
+        DOM.setElementProperty(getWidget().getElement(), "tabIndex", "1");
+
+        RootPanel root = RootPanel.get(rootPanelId);
+
+        // Remove the v-app-loading or any splash screen added inside the div by
+        // the user
+        root.getElement().setInnerHTML("");
+
+        root.addStyleName("v-theme-"
+                + applicationConnection.getConfiguration().getThemeName());
+
+        root.add(getWidget());
+
+        if (applicationConnection.getConfiguration().isStandalone()) {
+            // set focus to iview element by default to listen possible keyboard
+            // shortcuts. For embedded applications this is unacceptable as we
+            // don't want to steal focus from the main page nor we don't want
+            // side-effects from focusing (scrollIntoView).
+            getWidget().getElement().focus();
+        }
+    }
+
+    private ClickEventHandler clickEventHandler = new ClickEventHandler(this) {
+
+        @Override
+        protected void fireClick(NativeEvent event,
+                MouseEventDetails mouseDetails) {
+            rpc.click(mouseDetails);
+        }
+
+    };
+
+    public void updateCaption(ComponentConnector component) {
+        // NOP The main view never draws caption for its layout
+    }
+
+    @Override
+    public VRoot getWidget() {
+        return (VRoot) super.getWidget();
+    }
+
+    @Override
+    protected Widget createWidget() {
+        return GWT.create(VRoot.class);
+    }
+
+    protected ComponentConnector getContent() {
+        return (ComponentConnector) getState().getContent();
+    }
+
+    protected void onChildSizeChange() {
+        ComponentConnector child = getContent();
+        Style childStyle = child.getWidget().getElement().getStyle();
+        /*
+         * Must set absolute position if the child has relative height and
+         * there's a chance of horizontal scrolling as some browsers will
+         * otherwise not take the scrollbar into account when calculating the
+         * height. Assuming v-view does not have an undefined width for now, see
+         * #8460.
+         */
+        if (child.isRelativeHeight() && !BrowserInfo.get().isIE9()) {
+            childStyle.setPosition(Position.ABSOLUTE);
+        } else {
+            childStyle.clearPosition();
+        }
+    }
+
+    /**
+     * Checks if the given sub window is a child of this Root Connector
+     * 
+     * @deprecated Should be replaced by a more generic mechanism for getting
+     *             non-ComponentConnector children
+     * @param wc
+     * @return
+     */
+    @Deprecated
+    public boolean hasSubWindow(WindowConnector wc) {
+        return getChildren().contains(wc);
+    }
+
+    /**
+     * Return an iterator for current subwindows. This method is meant for
+     * testing purposes only.
+     * 
+     * @return
+     */
+    public List<WindowConnector> getSubWindows() {
+        ArrayList<WindowConnector> windows = new ArrayList<WindowConnector>();
+        for (ComponentConnector child : getChildren()) {
+            if (child instanceof WindowConnector) {
+                windows.add((WindowConnector) child);
+            }
+        }
+        return windows;
+    }
+
+    @Override
+    public RootState getState() {
+        return (RootState) super.getState();
+    }
+
+    @Override
+    public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) {
+        super.onConnectorHierarchyChange(event);
+
+        ComponentConnector oldChild = null;
+        ComponentConnector newChild = getContent();
+
+        for (ComponentConnector c : event.getOldChildren()) {
+            if (!(c instanceof WindowConnector)) {
+                oldChild = c;
+                break;
+            }
+        }
+
+        if (oldChild != newChild) {
+            if (childStateChangeHandlerRegistration != null) {
+                childStateChangeHandlerRegistration.removeHandler();
+                childStateChangeHandlerRegistration = null;
+            }
+            getWidget().setWidget(newChild.getWidget());
+            childStateChangeHandlerRegistration = newChild
+                    .addStateChangeHandler(childStateChangeHandler);
+            // Must handle new child here as state change events are already
+            // fired
+            onChildSizeChange();
+        }
+
+        for (ComponentConnector c : getChildren()) {
+            if (c instanceof WindowConnector) {
+                WindowConnector wc = (WindowConnector) c;
+                wc.setWindowOrderAndPosition();
+            }
+        }
+
+        // Close removed sub windows
+        for (ComponentConnector c : event.getOldChildren()) {
+            if (c.getParent() != this && c instanceof WindowConnector) {
+                ((WindowConnector) c).getWidget().hide();
+            }
+        }
+    }
+
+    /**
+     * Tries to scroll the viewport so that the given connector is in view.
+     * 
+     * @param componentConnector
+     *            The connector which should be visible
+     * 
+     */
+    public void scrollIntoView(final ComponentConnector componentConnector) {
+        if (componentConnector == null) {
+            return;
+        }
+
+        Scheduler.get().scheduleDeferred(new Command() {
+            public void execute() {
+                componentConnector.getWidget().getElement().scrollIntoView();
+            }
+        });
+    }
+
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/root/RootServerRPC.java b/src/com/vaadin/terminal/gwt/client/ui/root/RootServerRPC.java
new file mode 100644 (file)
index 0000000..734c624
--- /dev/null
@@ -0,0 +1,9 @@
+package com.vaadin.terminal.gwt.client.ui.root;
+
+import com.vaadin.terminal.gwt.client.communication.ServerRpc;
+import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector;
+import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector.ClickRPC;
+
+public interface RootServerRPC extends ClickRPC, ServerRpc {
+
+}
\ No newline at end of file
diff --git a/src/com/vaadin/terminal/gwt/client/ui/root/RootState.java b/src/com/vaadin/terminal/gwt/client/ui/root/RootState.java
new file mode 100644 (file)
index 0000000..0bd044c
--- /dev/null
@@ -0,0 +1,17 @@
+package com.vaadin.terminal.gwt.client.ui.root;
+
+import com.vaadin.terminal.gwt.client.ComponentState;
+import com.vaadin.terminal.gwt.client.Connector;
+
+public class RootState extends ComponentState {
+    private Connector content;
+
+    public Connector getContent() {
+        return content;
+    }
+
+    public void setContent(Connector content) {
+        this.content = content;
+    }
+
+}
\ No newline at end of file
diff --git a/src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java b/src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java
new file mode 100644 (file)
index 0000000..2026353
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client.ui.root;
+
+import java.util.ArrayList;
+
+import com.google.gwt.core.client.Scheduler.ScheduledCommand;
+import com.google.gwt.event.logical.shared.ResizeEvent;
+import com.google.gwt.event.logical.shared.ResizeHandler;
+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.DOM;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.History;
+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.terminal.gwt.client.ApplicationConnection;
+import com.vaadin.terminal.gwt.client.BrowserInfo;
+import com.vaadin.terminal.gwt.client.Focusable;
+import com.vaadin.terminal.gwt.client.Util;
+import com.vaadin.terminal.gwt.client.VConsole;
+import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler;
+import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.ShortcutActionHandlerOwner;
+import com.vaadin.terminal.gwt.client.ui.VLazyExecutor;
+import com.vaadin.terminal.gwt.client.ui.VTextField;
+
+/**
+ *
+ */
+public class VRoot extends SimplePanel implements ResizeHandler,
+        Window.ClosingHandler, ShortcutActionHandlerOwner, Focusable {
+
+    public static final String FRAGMENT_VARIABLE = "fragment";
+
+    private static final String CLASSNAME = "v-view";
+
+    public static final String NOTIFICATION_HTML_CONTENT_NOT_ALLOWED = "useplain";
+
+    String theme;
+
+    String id;
+
+    ShortcutActionHandler actionHandler;
+
+    /** stored width for IE resize optimization */
+    private int width;
+
+    /** stored height for IE resize optimization */
+    private int height;
+
+    ApplicationConnection connection;
+
+    /** Identifies the click event */
+    public static final String CLICK_EVENT_ID = "click";
+
+    /**
+     * We are postponing resize process with IE. IE bugs with scrollbars in some
+     * situations, that causes false onWindowResized calls. With Timer we will
+     * give IE some time to decide if it really wants to keep current size
+     * (scrollbars).
+     */
+    private Timer resizeTimer;
+
+    int scrollTop;
+
+    int scrollLeft;
+
+    boolean rendering;
+
+    boolean scrollable;
+
+    boolean immediate;
+
+    boolean resizeLazy = false;
+
+    /**
+     * Attribute name for the lazy resize setting .
+     */
+    public static final String RESIZE_LAZY = "rL";
+
+    private HandlerRegistration historyHandlerRegistration;
+
+    /**
+     * The current URI fragment, used to avoid sending updates if nothing has
+     * changed.
+     */
+    String currentFragment;
+
+    /**
+     * Listener for URI fragment changes. Notifies the server of the new value
+     * whenever the value changes.
+     */
+    private final ValueChangeHandler<String> historyChangeHandler = new ValueChangeHandler<String>() {
+        public void onValueChange(ValueChangeEvent<String> event) {
+            String newFragment = event.getValue();
+
+            // Send the new fragment to the server if it has changed
+            if (!newFragment.equals(currentFragment) && connection != null) {
+                currentFragment = newFragment;
+                connection.updateVariable(id, FRAGMENT_VARIABLE, newFragment,
+                        true);
+            }
+        }
+    };
+
+    private VLazyExecutor delayedResizeExecutor = new VLazyExecutor(200,
+            new ScheduledCommand() {
+                public void execute() {
+                    windowSizeMaybeChanged(Window.getClientWidth(),
+                            Window.getClientHeight());
+                }
+
+            });
+
+    public VRoot() {
+        super();
+        setStyleName(CLASSNAME);
+
+        // Allow focusing the view by using the focus() method, the view
+        // should not be in the document focus flow
+        getElement().setTabIndex(-1);
+    }
+
+    @Override
+    protected void onAttach() {
+        super.onAttach();
+        historyHandlerRegistration = History
+                .addValueChangeHandler(historyChangeHandler);
+        currentFragment = History.getToken();
+    }
+
+    @Override
+    protected void onDetach() {
+        super.onDetach();
+        historyHandlerRegistration.removeHandler();
+        historyHandlerRegistration = null;
+    }
+
+    /**
+     * Called when the window might have been resized.
+     * 
+     * @param newWidth
+     *            The new width of the window
+     * @param newHeight
+     *            The new height of the window
+     */
+    protected void windowSizeMaybeChanged(int newWidth, int newHeight) {
+        boolean changed = false;
+        if (width != newWidth) {
+            width = newWidth;
+            changed = true;
+            VConsole.log("New window width: " + width);
+        }
+        if (height != newHeight) {
+            height = newHeight;
+            changed = true;
+            VConsole.log("New window height: " + height);
+        }
+        if (changed) {
+            VConsole.log("Running layout functions due to window resize");
+            Util.runWebkitOverflowAutoFix(getElement());
+
+            sendClientResized();
+
+            connection.doLayout(false);
+        }
+    }
+
+    public String getTheme() {
+        return theme;
+    }
+
+    /**
+     * Used to reload host page on theme changes.
+     */
+    static native void reloadHostPage()
+    /*-{
+         $wnd.location.reload();
+     }-*/;
+
+    /**
+     * Evaluate the given script in the browser document.
+     * 
+     * @param script
+     *            Script to be executed.
+     */
+    static native void eval(String script)
+    /*-{
+      try {
+         if (script == null) return;
+         $wnd.eval(script);
+      } catch (e) {
+      }
+    }-*/;
+
+    /**
+     * Returns true if the body is NOT generated, i.e if someone else has made
+     * the page that we're running in. Otherwise we're in charge of the whole
+     * page.
+     * 
+     * @return true if we're running embedded
+     */
+    public boolean isEmbedded() {
+        return !getElement().getOwnerDocument().getBody().getClassName()
+                .contains(ApplicationConnection.GENERATED_BODY_CLASSNAME);
+    }
+
+    @Override
+    public void onBrowserEvent(Event event) {
+        super.onBrowserEvent(event);
+        int type = DOM.eventGetType(event);
+        if (type == Event.ONKEYDOWN && actionHandler != null) {
+            actionHandler.handleKeyboardEvent(event);
+            return;
+        } else if (scrollable && type == Event.ONSCROLL) {
+            updateScrollPosition();
+        }
+    }
+
+    /**
+     * Updates scroll position from DOM and saves variables to server.
+     */
+    private void updateScrollPosition() {
+        int oldTop = scrollTop;
+        int oldLeft = scrollLeft;
+        scrollTop = DOM.getElementPropertyInt(getElement(), "scrollTop");
+        scrollLeft = DOM.getElementPropertyInt(getElement(), "scrollLeft");
+        if (connection != null && !rendering) {
+            if (oldTop != scrollTop) {
+                connection.updateVariable(id, "scrollTop", scrollTop, false);
+            }
+            if (oldLeft != scrollLeft) {
+                connection.updateVariable(id, "scrollLeft", scrollLeft, false);
+            }
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * com.google.gwt.event.logical.shared.ResizeHandler#onResize(com.google
+     * .gwt.event.logical.shared.ResizeEvent)
+     */
+    public void onResize(ResizeEvent event) {
+        onResize();
+    }
+
+    /**
+     * Called when a resize event is received.
+     */
+    void onResize() {
+        /*
+         * IE (pre IE9 at least) will give us some false resize events due to
+         * problems with scrollbars. Firefox 3 might also produce some extra
+         * events. We postpone both the re-layouting and the server side event
+         * for a while to deal with these issues.
+         * 
+         * We may also postpone these events to avoid slowness when resizing the
+         * browser window. Constantly recalculating the layout causes the resize
+         * operation to be really slow with complex layouts.
+         */
+        boolean lazy = resizeLazy || BrowserInfo.get().isIE8();
+
+        if (lazy) {
+            delayedResizeExecutor.trigger();
+        } else {
+            windowSizeMaybeChanged(Window.getClientWidth(),
+                    Window.getClientHeight());
+        }
+    }
+
+    /**
+     * Send new dimensions to the server.
+     */
+    private void sendClientResized() {
+        connection.updateVariable(id, "height", height, false);
+        connection.updateVariable(id, "width", width, immediate);
+    }
+
+    public native static void goTo(String url)
+    /*-{
+       $wnd.location = url;
+     }-*/;
+
+    public void onWindowClosing(Window.ClosingEvent event) {
+        // Change focus on this window in order to ensure that all state is
+        // collected from textfields
+        // TODO this is a naive hack, that only works with text fields and may
+        // cause some odd issues. Should be replaced with a decent solution, see
+        // also related BeforeShortcutActionListener interface. Same interface
+        // might be usable here.
+        VTextField.flushChangesFromFocusedTextField();
+    }
+
+    private native static void loadAppIdListFromDOM(ArrayList<String> list)
+    /*-{
+         var j;
+         for(j in $wnd.vaadin.vaadinConfigurations) {
+            list.@java.util.Collection::add(Ljava/lang/Object;)(j);
+         }
+     }-*/;
+
+    public ShortcutActionHandler getShortcutActionHandler() {
+        return actionHandler;
+    }
+
+    public void focus() {
+        getElement().focus();
+    }
+
+}
index 8552168753750f065ae57388006fdb2fd50ec93c..2db68ebca2d2d00bd13e69c3aec4f7c5f8b92b65 100644 (file)
@@ -26,7 +26,7 @@ import com.vaadin.terminal.gwt.client.ComponentConnector;
 import com.vaadin.terminal.gwt.client.Connector;
 import com.vaadin.terminal.gwt.client.ui.Component;
 import com.vaadin.terminal.gwt.client.ui.Component.LoadStyle;
-import com.vaadin.terminal.gwt.client.ui.RootConnector;
+import com.vaadin.terminal.gwt.client.ui.root.RootConnector;
 import com.vaadin.terminal.gwt.client.ui.UnknownComponentConnector;
 import com.vaadin.terminal.gwt.server.ClientConnector;
 
index 6850c88a817359e7f114b927ca135932a555a8d7..aab4c1b6e9dae0e7205ffc517e98053c5b92af82 100644 (file)
@@ -31,10 +31,10 @@ import com.vaadin.terminal.Vaadin6Component;
 import com.vaadin.terminal.WrappedRequest;
 import com.vaadin.terminal.WrappedRequest.BrowserDetails;
 import com.vaadin.terminal.gwt.client.MouseEventDetails;
-import com.vaadin.terminal.gwt.client.ui.RootConnector.RootServerRPC;
-import com.vaadin.terminal.gwt.client.ui.RootConnector.RootState;
 import com.vaadin.terminal.gwt.client.ui.VNotification;
-import com.vaadin.terminal.gwt.client.ui.VView;
+import com.vaadin.terminal.gwt.client.ui.root.RootServerRPC;
+import com.vaadin.terminal.gwt.client.ui.root.RootState;
+import com.vaadin.terminal.gwt.client.ui.root.VRoot;
 import com.vaadin.tools.ReflectTools;
 import com.vaadin.ui.Window.CloseListener;
 
@@ -403,7 +403,7 @@ public abstract class Root extends AbstractComponentContainer implements
     private int browserWindowHeight = -1;
 
     /** Identifies the click event */
-    private static final String CLICK_EVENT_ID = VView.CLICK_EVENT_ID;
+    private static final String CLICK_EVENT_ID = VRoot.CLICK_EVENT_ID;
 
     private DirtyConnectorTracker dirtyConnectorTracker = new DirtyConnectorTracker(
             this);
@@ -530,7 +530,7 @@ public abstract class Root extends AbstractComponentContainer implements
                 }
                 if (!n.isHtmlContentAllowed()) {
                     target.addAttribute(
-                            VView.NOTIFICATION_HTML_CONTENT_NOT_ALLOWED, true);
+                            VRoot.NOTIFICATION_HTML_CONTENT_NOT_ALLOWED, true);
                 }
                 target.addAttribute(
                         VNotification.ATTRIBUTE_NOTIFICATION_POSITION,
@@ -578,11 +578,11 @@ public abstract class Root extends AbstractComponentContainer implements
         }
 
         if (fragment != null) {
-            target.addAttribute(VView.FRAGMENT_VARIABLE, fragment);
+            target.addAttribute(VRoot.FRAGMENT_VARIABLE, fragment);
         }
 
         if (isResizeLazy()) {
-            target.addAttribute(VView.RESIZE_LAZY, true);
+            target.addAttribute(VRoot.RESIZE_LAZY, true);
         }
     }
 
@@ -609,8 +609,8 @@ public abstract class Root extends AbstractComponentContainer implements
             actionManager.handleActions(variables, this);
         }
 
-        if (variables.containsKey(VView.FRAGMENT_VARIABLE)) {
-            String fragment = (String) variables.get(VView.FRAGMENT_VARIABLE);
+        if (variables.containsKey(VRoot.FRAGMENT_VARIABLE)) {
+            String fragment = (String) variables.get(VRoot.FRAGMENT_VARIABLE);
             setFragment(fragment, true);
         }