summaryrefslogtreecommitdiffstats
path: root/server/src
diff options
context:
space:
mode:
authorJohannes Dahlström <johannesd@vaadin.com>2014-03-19 17:29:45 +0200
committerVaadin Code Review <review@vaadin.com>2014-03-31 08:39:15 +0000
commite4a50934a2cfb0e652b872376decf581bc0ab057 (patch)
treee7ea07ee5d1f13292ed6abcc9435c47892d8b10c /server/src
parent7a91d29097e606a7e2dc4440443cb21ae7dfa61b (diff)
downloadvaadin-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.java5
-rw-r--r--server/src/com/vaadin/server/Page.java72
-rw-r--r--server/src/com/vaadin/server/UIProvider.java5
-rw-r--r--server/src/com/vaadin/server/communication/UIInitHandler.java7
-rw-r--r--server/src/com/vaadin/ui/UI.java57
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.