diff options
author | Johannes Dahlström <johannesd@vaadin.com> | 2014-03-19 17:29:45 +0200 |
---|---|---|
committer | Vaadin Code Review <review@vaadin.com> | 2014-03-31 08:39:15 +0000 |
commit | e4a50934a2cfb0e652b872376decf581bc0ab057 (patch) | |
tree | e7ea07ee5d1f13292ed6abcc9435c47892d8b10c /server/src | |
parent | 7a91d29097e606a7e2dc4440443cb21ae7dfa61b (diff) | |
download | vaadin-framework-e4a50934a2cfb0e652b872376decf581bc0ab057.tar.gz vaadin-framework-e4a50934a2cfb0e652b872376decf581bc0ab057.zip |
Add reinit method for preserve-on-refresh UIs (#12191)
UI.reinit() is now called when an existing, preserved UI is shown after a
browser reload of the current page. The default implementation is empty.
The browser window size and location are up to date in UI.reinit();
window resize and URI fragment listeners, if any, will be called after
returning from UI.reinit().
Change-Id: Ie7aa670aaecf8e0e1510c91325b2a137b41263af
Diffstat (limited to 'server/src')
-rw-r--r-- | server/src/com/vaadin/annotations/PreserveOnRefresh.java | 5 | ||||
-rw-r--r-- | server/src/com/vaadin/server/Page.java | 72 | ||||
-rw-r--r-- | server/src/com/vaadin/server/UIProvider.java | 5 | ||||
-rw-r--r-- | server/src/com/vaadin/server/communication/UIInitHandler.java | 7 | ||||
-rw-r--r-- | server/src/com/vaadin/ui/UI.java | 57 |
5 files changed, 127 insertions, 19 deletions
diff --git a/server/src/com/vaadin/annotations/PreserveOnRefresh.java b/server/src/com/vaadin/annotations/PreserveOnRefresh.java index 0b503b8c3f..801c1e78f2 100644 --- a/server/src/com/vaadin/annotations/PreserveOnRefresh.java +++ b/server/src/com/vaadin/annotations/PreserveOnRefresh.java @@ -22,6 +22,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import com.vaadin.server.UIProvider; +import com.vaadin.ui.UI; /** * Marks a UI that should be retained when the user refreshed the browser @@ -30,6 +31,10 @@ import com.vaadin.server.UIProvider; * adding this annotation to a UI class, the framework will instead reuse the * current UI instance when a reload is detected. * <p> + * Whenever a request is received that reloads a preserved UI, the UI's + * {@link UI#reinit(com.vaadin.server.VaadinRequest) reinit} method is invoked + * by the framework. + * <p> * By using * {@link UIProvider#isPreservedOnRefresh(com.vaadin.server.UICreateEvent)}, the * decision can also be made dynamically based on other parameters than only diff --git a/server/src/com/vaadin/server/Page.java b/server/src/com/vaadin/server/Page.java index 3b96ec2ee1..70b8306bc3 100644 --- a/server/src/com/vaadin/server/Page.java +++ b/server/src/com/vaadin/server/Page.java @@ -32,6 +32,7 @@ import com.vaadin.shared.ui.ui.PageClientRpc; import com.vaadin.shared.ui.ui.PageState; import com.vaadin.shared.ui.ui.UIConstants; import com.vaadin.shared.ui.ui.UIState; +import com.vaadin.shared.util.SharedUtil; import com.vaadin.ui.JavaScript; import com.vaadin.ui.LegacyWindow; import com.vaadin.ui.Link; @@ -635,6 +636,9 @@ public class Page implements Serializable { } public void init(VaadinRequest request) { + // NOTE: UI.reinit makes assumptions about the semantics of this method. + // It should be kept in sync if this method is changed. + // Extract special parameter sent by vaadinBootstrap.js String location = request.getParameter("v-loc"); String clientWidth = request.getParameter("v-cw"); @@ -676,28 +680,51 @@ public class Page implements Serializable { } /** - * Updates the internal state with the given values. Does not resize the - * Page or browser window. - * + * For internal use only. Updates the internal state with the given values. + * Does not resize the Page or browser window. + * + * @deprecated As of 7.2, use + * {@link #updateBrowserWindowSize(int, int, boolean)} instead. + * * @param width - * The new width + * the new browser window width * @param height - * The new height + * the new browse window height */ + @Deprecated public void updateBrowserWindowSize(int width, int height) { - boolean fireEvent = false; + updateBrowserWindowSize(width, height, true); + } + + /** + * For internal use only. Updates the internal state with the given values. + * Does not resize the Page or browser window. + * + * @since 7.2 + * + * @param width + * the new browser window width + * @param height + * the new browser window height + * @param fireEvents + * whether to fire {@link BrowserWindowResizeEvent} if the size + * changes + */ + public void updateBrowserWindowSize(int width, int height, + boolean fireEvents) { + boolean sizeChanged = false; if (width != browserWindowWidth) { browserWindowWidth = width; - fireEvent = true; + sizeChanged = true; } if (height != browserWindowHeight) { browserWindowHeight = height; - fireEvent = true; + sizeChanged = true; } - if (fireEvent) { + if (fireEvents && sizeChanged) { fireEvent(new BrowserWindowResizeEvent(this, browserWindowWidth, browserWindowHeight)); } @@ -917,14 +944,37 @@ public class Page implements Serializable { /** * For internal use only. Used to update the server-side location when the * client-side location changes. + * + * @deprecated As of 7.2, use {@link #updateLocation(String, boolean)} + * instead. + * + * @param location + * the new location URI */ + @Deprecated public void updateLocation(String location) { + updateLocation(location, true); + } + + /** + * For internal use only. Used to update the server-side location when the + * client-side location changes. + * + * @since 7.2 + * + * @param location + * the new location URI + * @param fireEvents + * whether to fire {@link UriFragmentChangedEvent} if the URI + * fragment changes + */ + public void updateLocation(String location, boolean fireEvents) { try { String oldUriFragment = this.location.getFragment(); this.location = new URI(location); String newUriFragment = this.location.getFragment(); - if (newUriFragment == null ? oldUriFragment != null - : !newUriFragment.equals(oldUriFragment)) { + if (fireEvents + && !SharedUtil.equals(oldUriFragment, newUriFragment)) { fireEvent(new UriFragmentChangedEvent(this, newUriFragment)); } } catch (URISyntaxException e) { diff --git a/server/src/com/vaadin/server/UIProvider.java b/server/src/com/vaadin/server/UIProvider.java index 3e7c85aea9..a76f396767 100644 --- a/server/src/com/vaadin/server/UIProvider.java +++ b/server/src/com/vaadin/server/UIProvider.java @@ -129,6 +129,11 @@ public abstract class UIProvider implements Serializable { * detect that the application is opened in a browser window where it has * previously been open. The framework attempts to discover this by checking * the value of window.name in the browser. + * <p> + * Whenever a preserved UI is reused, its + * {@link UI#reinit(com.vaadin.server.VaadinRequest) reinit} method is + * invoked by the framework first. + * * * @param event * the UI create event with information about the UI and the diff --git a/server/src/com/vaadin/server/communication/UIInitHandler.java b/server/src/com/vaadin/server/communication/UIInitHandler.java index 6ab9d9dc58..5dc44208d1 100644 --- a/server/src/com/vaadin/server/communication/UIInitHandler.java +++ b/server/src/com/vaadin/server/communication/UIInitHandler.java @@ -266,12 +266,7 @@ public abstract class UIInitHandler extends SynchronizedRequestHandler { */ private void reinitUI(UI ui, VaadinRequest request) { UI.setCurrent(ui); - - // Fire fragment change if the fragment has changed - String location = request.getParameter("v-loc"); - if (location != null) { - ui.getPage().updateLocation(location); - } + ui.doReinit(request); } /** diff --git a/server/src/com/vaadin/ui/UI.java b/server/src/com/vaadin/ui/UI.java index b3004e9ad2..2b2e773601 100644 --- a/server/src/com/vaadin/ui/UI.java +++ b/server/src/com/vaadin/ui/UI.java @@ -16,6 +16,7 @@ package com.vaadin.ui; +import java.net.URI; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -27,6 +28,7 @@ import java.util.concurrent.Future; import java.util.logging.Level; import java.util.logging.Logger; +import com.vaadin.annotations.PreserveOnRefresh; import com.vaadin.event.Action; import com.vaadin.event.Action.Handler; import com.vaadin.event.ActionManager; @@ -161,7 +163,7 @@ public abstract class UI extends AbstractSingleComponentContainer implements public void resize(int viewWidth, int viewHeight, int windowWidth, int windowHeight) { // TODO We're not doing anything with the view dimensions - getPage().updateBrowserWindowSize(windowWidth, windowHeight); + getPage().updateBrowserWindowSize(windowWidth, windowHeight, true); } @Override @@ -361,7 +363,7 @@ public abstract class UI extends AbstractSingleComponentContainer implements if (variables.containsKey(UIConstants.LOCATION_VARIABLE)) { String location = (String) variables .get(UIConstants.LOCATION_VARIABLE); - getPage().updateLocation(location); + getPage().updateLocation(location, true); } } @@ -660,6 +662,57 @@ public abstract class UI extends AbstractSingleComponentContainer implements protected abstract void init(VaadinRequest request); /** + * Internal reinitialization method, should not be overridden. + * + * @since 7.2 + * @param request + * the request that caused this UI to be reloaded + */ + public void doReinit(VaadinRequest request) { + // This is a horrible hack. We want to have the most recent location and + // browser window size available in reinit(), but we want to call + // listeners, if any, only after reinit(). So we momentarily assign the + // old values back before setting the new values again to ensure the + // events are properly fired. + + Page page = getPage(); + + URI oldLocation = page.getLocation(); + int oldWidth = page.getBrowserWindowWidth(); + int oldHeight = page.getBrowserWindowHeight(); + + page.init(request); + + reinit(request); + + URI newLocation = page.getLocation(); + int newWidth = page.getBrowserWindowWidth(); + int newHeight = page.getBrowserWindowHeight(); + + page.updateLocation(oldLocation.toString(), false); + page.updateBrowserWindowSize(oldWidth, oldHeight, false); + + page.updateLocation(newLocation.toString(), true); + page.updateBrowserWindowSize(newWidth, newHeight, true); + } + + /** + * Reinitializes this UI after a browser refresh if the UI is set to be + * preserved on refresh, typically using the {@link PreserveOnRefresh} + * annotation. This method is intended to be overridden by subclasses if + * needed; the default implementation is empty. + * <p> + * The {@link VaadinRequest} can be used to get information about the + * request that caused this UI to be reloaded. + * + * @since 7.2 + * @param request + * the request that caused this UI to be reloaded + */ + protected void reinit(VaadinRequest request) { + } + + /** * Sets the thread local for the current UI. This method is used by the * framework to set the current application whenever a new request is * processed and it is cleared when the request has been processed. |