]> source.dussan.org Git - vaadin-framework.git/commitdiff
Merge commit 'e085e'
authorJohannes Dahlström <johannesd@vaadin.com>
Mon, 11 Jun 2012 11:43:48 +0000 (14:43 +0300)
committerJohannes Dahlström <johannesd@vaadin.com>
Mon, 11 Jun 2012 11:43:48 +0000 (14:43 +0300)
Conflicts:
src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java
tests/testbench/com/vaadin/tests/integration/EmbedSizeTest.java

1  2 
src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java
src/com/vaadin/ui/Window.java
tests/testbench/com/vaadin/tests/integration/EmbedSizeTest.java

index 5f08f92cf06508632fe6833b3066fae948a2e532,0000000000000000000000000000000000000000..31e09660fe9a16a23d27cf00de7df0484d6fa55e
mode 100644,000000..100644
--- /dev/null
@@@ -1,356 -1,0 +1,362 @@@
-         int newViewHeight = parentElement.getClientHeight();
-         int newViewWidth = parentElement.getClientWidth();
-         // Send the view dimensions if they have changed
-         if (newViewHeight != viewHeight || newViewWidth != viewWidth) {
-             viewHeight = newViewHeight;
-             viewWidth = newViewWidth;
-             connection.updateVariable(id, "height", newViewHeight, false);
-             connection.updateVariable(id, "width", newViewWidth, immediate);
-         }
 +/*
 +@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.dom.client.Element;
 +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.ComponentConnector;
 +import com.vaadin.terminal.gwt.client.ConnectorMap;
 +import com.vaadin.terminal.gwt.client.Focusable;
 +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.TouchScrollDelegate;
 +import com.vaadin.terminal.gwt.client.ui.VLazyExecutor;
 +import com.vaadin.terminal.gwt.client.ui.textfield.VTextField;
 +
 +/**
 + *
 + */
 +public class VRoot extends SimplePanel implements ResizeHandler,
 +        Window.ClosingHandler, ShortcutActionHandlerOwner, Focusable {
 +
 +    public static final String FRAGMENT_VARIABLE = "fragment";
 +
++    public static final String BROWSER_HEIGHT_VAR = "browserHeight";
++
++    public static final String BROWSER_WIDTH_VAR = "browserWidth";
++
 +    private static final String CLASSNAME = "v-view";
 +
 +    public static final String NOTIFICATION_HTML_CONTENT_NOT_ALLOWED = "useplain";
 +
 +    String theme;
 +
 +    String id;
 +
 +    ShortcutActionHandler actionHandler;
 +
 +    /*
 +     * Last known window size used to detect whether VView should be layouted
 +     * again. Detection must be based on window size, because the VView size
 +     * might be fixed and thus not automatically adapt to changed window sizes.
 +     */
 +    private int windowWidth;
 +    private int windowHeight;
 +
 +    /*
 +     * Last know view size used to detect whether new dimensions should be sent
 +     * to the server.
 +     */
 +    private int viewWidth;
 +    private int viewHeight;
 +
 +    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>() {
 +        @Override
 +        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() {
 +                @Override
 +                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);
 +        TouchScrollDelegate.enableTouchScrolling(this, getElement());
 +    }
 +
 +    @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;
 +        ComponentConnector connector = ConnectorMap.get(connection)
 +                .getConnector(this);
 +        if (windowWidth != newWidth) {
 +            windowWidth = newWidth;
 +            changed = true;
 +            connector.getLayoutManager().reportOuterWidth(connector, newWidth);
 +            VConsole.log("New window width: " + windowWidth);
 +        }
 +        if (windowHeight != newHeight) {
 +            windowHeight = newHeight;
 +            changed = true;
 +            connector.getLayoutManager()
 +                    .reportOuterHeight(connector, newHeight);
 +            VConsole.log("New window height: " + windowHeight);
 +        }
 +        if (changed) {
 +            /*
 +             * If the window size has changed, layout the VView again and send
 +             * new size to the server if the size changed. (Just checking VView
 +             * size would cause us to ignore cases when a relatively sized VView
 +             * should shrink as the content's size is fixed and would thus not
 +             * automatically shrink.)
 +             */
 +            VConsole.log("Running layout functions due to window resize");
 +
 +            sendClientResized();
 +
 +            connector.getLayoutManager().layoutNow();
 +        }
 +    }
 +
 +    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)
 +     */
 +    @Override
 +    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() {
 +        Element parentElement = getElement().getParentElement();
++        int viewHeight = parentElement.getClientHeight();
++        int viewWidth = parentElement.getClientWidth();
++
++        connection.updateVariable(id, "height", viewHeight, false);
++        connection.updateVariable(id, "width", viewWidth, false);
++
++        int windowWidth = Window.getClientWidth();
++        int windowHeight = Window.getClientHeight();
++
++        connection.updateVariable(id, BROWSER_WIDTH_VAR, windowWidth, false);
++        connection.updateVariable(id, BROWSER_HEIGHT_VAR, windowHeight,
++                immediate);
 +    }
 +
 +    public native static void goTo(String url)
 +    /*-{
 +       $wnd.location = url;
 +     }-*/;
 +
 +    @Override
 +    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) {
 +            // $entry not needed as function is not exported
 +            list.@java.util.Collection::add(Ljava/lang/Object;)(j);
 +         }
 +     }-*/;
 +
 +    @Override
 +    public ShortcutActionHandler getShortcutActionHandler() {
 +        return actionHandler;
 +    }
 +
 +    @Override
 +    public void focus() {
 +        getElement().focus();
 +    }
 +
 +}
index 3c17baf41451e3120604d138b59a9062ea04591b,f20090feade975255968f3cba8c849342005e745..807b801155c10487d6ff0baaf374b312e50b66be
@@@ -73,16 -84,149 +73,20 @@@ import com.vaadin.terminal.gwt.client.u
   * @since 3.0
   */
  @SuppressWarnings("serial")
 -@ClientWidget(VWindow.class)
 -public class Window extends Panel implements URIHandler, ParameterHandler,
 -        FocusNotifier, BlurNotifier {
 +public class Window extends Panel implements FocusNotifier, BlurNotifier,
 +        Vaadin6Component {
  
 -    /**
 -     * <b>Application window only</b>. A border style used for opening resources
 -     * in a window without a border.
 -     */
 -    public static final int BORDER_NONE = 0;
 -
 -    /**
 -     * <b>Application window only</b>. A border style used for opening resources
 -     * in a window with a minimal border.
 -     */
 -    public static final int BORDER_MINIMAL = 1;
 -
 -    /**
 -     * <b>Application window only</b>. A border style that indicates that the
 -     * default border style should be used when opening resources.
 -     */
 -    public static final int BORDER_DEFAULT = 2;
 -
 -    /**
 -     * <b>Application window only</b>. The user terminal for this window.
 -     */
 -    private Terminal terminal = null;
 -
 -    /**
 -     * <b>Application window only</b>. The application this window is attached
 -     * to or null.
 -     */
 -    private Application application = null;
 -
 -    /**
 -     * <b>Application window only</b>. List of URI handlers for this window.
 -     */
 -    private LinkedList<URIHandler> uriHandlerList = null;
 -
 -    /**
 -     * <b>Application window only</b>. List of parameter handlers for this
 -     * window.
 -     */
 -    private LinkedList<ParameterHandler> parameterHandlerList = null;
 -
 -    /**
 -     * <b>Application window only</b>. List of sub windows in this window. A sub
 -     * window cannot have other sub windows.
 -     */
 -    private final LinkedHashSet<Window> subwindows = new LinkedHashSet<Window>();
 -
 -    /**
 -     * <b>Application window only</b>. Explicitly specified theme of this window
 -     * or null if the application theme should be used.
 -     */
 -    private String theme = null;
 -
 -    /**
 -     * <b>Application window only</b>. Resources to be opened automatically on
 -     * next repaint. The list is automatically cleared when it has been sent to
 -     * the client.
 -     */
 -    private final LinkedList<OpenResource> openList = new LinkedList<OpenResource>();
 -
 -    /**
 -     * <b>Application window only</b>. Unique name of the window used to
 -     * identify it.
 -     */
 -    private String name = null;
 -
 -    /**
 -     * <b>Application window only.</b> Border mode of the Window.
 -     */
 -    private int border = BORDER_DEFAULT;
 -
 -    /**
 -     * <b>Sub window only</b>. Top offset in pixels for the sub window (relative
 -     * to the parent application window) or -1 if unspecified.
 -     */
 -    private int positionY = -1;
 -
 -    /**
 -     * <b>Sub window only</b>. Left offset in pixels for the sub window
 -     * (relative to the parent application window) or -1 if unspecified.
 -     */
 -    private int positionX = -1;
 -
 -    /**
 -     * <b>Application window only</b>. A list of notifications that are waiting
 -     * to be sent to the client. Cleared (set to null) when the notifications
 -     * have been sent.
 -     */
 -    private LinkedList<Notification> notifications;
 -
 -    /**
 -     * <b>Sub window only</b>. Modality flag for sub window.
 -     */
 -    private boolean modal = false;
 +    private WindowServerRpc rpc = new WindowServerRpc() {
  
 -    /**
 -     * <b>Sub window only</b>. Controls if the end user can resize the window.
 -     */
 -    private boolean resizable = true;
 -
 -    /**
 -     * <b>Sub window only</b>. Controls if the end user can move the window by
 -     * dragging.
 -     */
 -    private boolean draggable = true;
 -
 -    /**
 -     * <b>Sub window only</b>. Flag which is true if the window is centered on
 -     * the screen.
 -     */
 -    private boolean centerRequested = false;
 -
 -    /**
 -     * Should resize recalculate layouts lazily (as opposed to immediately)
 -     */
 -    private boolean resizeLazy = false;
 -
 -    /**
 -     * Component that should be focused after the next repaint. Null if no focus
 -     * change should take place.
 -     */
 -    private Focusable pendingFocus;
 -
 -    /**
 -     * <b>Application window only</b>. A list of javascript commands that are
 -     * waiting to be sent to the client. Cleared (set to null) when the commands
 -     * have been sent.
 -     */
 -    private ArrayList<String> jsExecQueue = null;
 -
 -    /**
 -     * The component that should be scrolled into view after the next repaint.
 -     * Null if nothing should be scrolled into view.
 -     */
 -    private Component scrollIntoView;
 +        public void click(MouseEventDetails mouseDetails) {
 +            fireEvent(new ClickEvent(Window.this, mouseDetails));
 +        }
 +    };
  
+     private int browserWindowWidth = -1;
+     private int browserWindowHeight = -1;
      /**
       * Creates a new unnamed window with a default layout.
       */
       */
      @Override
      public void focus() {
 -        if (getParent() != null) {
 -            /*
 -             * When focusing a sub-window it basically means it should be
 -             * brought to the front. Instead of just moving the keyboard focus
 -             * we focus the window and bring it top-most.
 -             */
 -            bringToFront();
 -        } else {
 -            super.focus();
 -        }
 -    }
 -
 -    /**
 -     * Notifies the child components and subwindows that the window is attached
 -     * to the application.
 -     */
 -    @Override
 -    public void attach() {
 -        super.attach();
 -        for (Window w : subwindows) {
 -            w.attach();
 -        }
 +        /*
 +         * When focusing a sub-window it basically means it should be brought to
 +         * the front. Instead of just moving the keyboard focus we focus the
 +         * window and bring it top-most.
 +         */
 +        super.focus();
 +        bringToFront();
      }
  
 -    /**
 -     * Notifies the child components and subwindows that the window is detached
 -     * from the application.
 -     */
      @Override
 -    public void detach() {
 -        super.detach();
 -        for (Window w : subwindows) {
 -            w.detach();
 -        }
 +    public WindowState getState() {
 +        return (WindowState) super.getState();
      }
  
+     /**
+      * Gets the height of the viewport area of the browser window where this
+      * window is displayed.
+      * 
+      * @return the browser viewport height in pixels
+      */
+     public int getBrowserWindowHeight() {
+         // Size only reported by VView -> data only available from application
+         // level window
+         if (getParent() != null) {
+             return (getParent()).getBrowserWindowHeight();
+         }
+         return browserWindowHeight;
+     }
+     /**
+      * Gets the width of the viewport area of the browser window where this
+      * window is displayed.
+      * 
+      * @return the browser viewport width in pixels
+      */
+     public int getBrowserWindowWidth() {
+         // Size only reported by VView -> data only available from application
+         // level window
+         if (getParent() != null) {
+             return (getParent()).getBrowserWindowWidth();
+         }
+         return browserWindowWidth;
+     }
  }
index eb26faacc024885da3530c6c95a693d511415930,3524b3fce390b3444316e9a4cc2d2208f52be2e2..7ca73ef63dc46de7593268eeeaa930a39aeff1ae
@@@ -19,26 -19,27 +19,28 @@@ public class EmbedSizeTest extends Test
          mainWindow.getContent().setSizeUndefined();
          mainWindow.setImmediate(true);
  
 -        CheckBox lazyCheckBox = new CheckBox("Lazy resize",
 -                new Button.ClickListener() {
 -                    public void buttonClick(ClickEvent event) {
 -                        boolean resizeLazy = Boolean.TRUE == event.getButton()
 -                                .getValue();
 -                        getMainWindow().setResizeLazy(resizeLazy);
 -                        log.log("Resize lazy: " + resizeLazy);
 -                    }
 -                });
 +        CheckBox lazyCheckBox = new CheckBox("Lazy resize");
 +        lazyCheckBox.addListener(new ValueChangeListener() {
 +
++            @Override
 +            public void valueChange(ValueChangeEvent event) {
 +                CheckBox cb = (CheckBox) event.getProperty();
 +                Boolean resizeLazy = cb.getValue();
 +                getMainWindow().setResizeLazy(resizeLazy);
 +                log.log("Resize lazy: " + resizeLazy);
 +            }
 +        });
          lazyCheckBox.setValue(Boolean.FALSE);
          lazyCheckBox.setImmediate(true);
          addComponent(lazyCheckBox);
  
          addComponent(log);
 -        mainWindow.addListener(new Window.ResizeListener() {
 -            public void windowResized(ResizeEvent e) {
 -                Window window = e.getWindow();
 -                log.log("App: " + window.getWidth() + " x "
 -                        + window.getHeight() + ", Browser window: "
 -                        + window.getBrowserWindowWidth() + " x "
 -                        + window.getBrowserWindowHeight());
++
 +        mainWindow.addListener(new Root.BrowserWindowResizeListener() {
++            @Override
 +            public void browserWindowResized(BrowserWindowResizeEvent event) {
 +                log.log("Resize event: " + event.getWidth() + " x "
 +                        + event.getHeight());
              }
          });
      }