summaryrefslogtreecommitdiffstats
path: root/src/com/vaadin/ui/Root.java
diff options
context:
space:
mode:
authorLeif Åstrand <leif@vaadin.com>2011-12-07 16:34:59 +0200
committerLeif Åstrand <leif@vaadin.com>2011-12-07 16:34:59 +0200
commit94d133023f8b43e0e185b43d7c329c6eac3be4b8 (patch)
tree9a2d847b09d3fde69e94bcec26fca4f0da3b2b24 /src/com/vaadin/ui/Root.java
parent7491f0fd006b8ef26d7dd2a50bf18300d8b4e7e1 (diff)
downloadvaadin-framework-94d133023f8b43e0e185b43d7c329c6eac3be4b8.tar.gz
vaadin-framework-94d133023f8b43e0e185b43d7c329c6eac3be4b8.zip
URI fragment support in Root (#8048)
Diffstat (limited to 'src/com/vaadin/ui/Root.java')
-rw-r--r--src/com/vaadin/ui/Root.java152
1 files changed, 151 insertions, 1 deletions
diff --git a/src/com/vaadin/ui/Root.java b/src/com/vaadin/ui/Root.java
index bcc9c443c3..03bb1023ac 100644
--- a/src/com/vaadin/ui/Root.java
+++ b/src/com/vaadin/ui/Root.java
@@ -5,6 +5,7 @@
package com.vaadin.ui;
import java.io.Serializable;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -73,6 +74,67 @@ public class Root extends AbstractComponentContainer implements
Action.Container, Action.Notifier {
/**
+ * Listener that listens changes in URI fragment.
+ */
+ public interface FragmentChangedListener extends Serializable {
+ public void fragmentChanged(FragmentChangedEvent event);
+ }
+
+ /**
+ * Event fired when uri fragment changes.
+ */
+ public class FragmentChangedEvent extends Component.Event {
+
+ /**
+ * The new uri fragment
+ */
+ private final String fragment;
+
+ /**
+ * Creates a new instance of UriFragmentReader change event.
+ *
+ * @param source
+ * the Source of the event.
+ */
+ public FragmentChangedEvent(Root source, String fragment) {
+ super(source);
+ this.fragment = fragment;
+ }
+
+ /**
+ * Gets the root in which the fragment has changed.
+ *
+ * @return the root in which the fragment has changed
+ */
+ public Root getRoot() {
+ return (Root) getComponent();
+ }
+
+ /**
+ * Get the new fragment
+ *
+ * @return the new fragment
+ */
+ public String getFragment() {
+ return fragment;
+ }
+ }
+
+ private static final Method FRAGMENT_CHANGED_METHOD;
+
+ static {
+ try {
+ FRAGMENT_CHANGED_METHOD = FragmentChangedListener.class
+ .getDeclaredMethod("fragmentChanged",
+ new Class[] { FragmentChangedEvent.class });
+ } catch (final java.lang.NoSuchMethodException e) {
+ // This should never happen
+ throw new java.lang.RuntimeException(
+ "Internal error finding methods in FragmentChangedListener");
+ }
+ }
+
+ /**
* A border style used for opening resources in a window without a border.
*/
public static final int BORDER_NONE = 0;
@@ -303,6 +365,10 @@ public class Root extends AbstractComponentContainer implements
if (actionManager != null) {
actionManager.paintActions(null, target);
}
+
+ if (fragment != null) {
+ target.addAttribute(VView.FRAGMENT_VARIABLE, fragment);
+ }
}
@Override
@@ -313,6 +379,11 @@ public class Root extends AbstractComponentContainer implements
if (actionManager != null) {
actionManager.handleActions(variables, this);
}
+
+ if (variables.containsKey(VView.FRAGMENT_VARIABLE)) {
+ String fragment = (String) variables.get(VView.FRAGMENT_VARIABLE);
+ setFragment(fragment, true);
+ }
}
public Iterator<Component> getComponentIterator() {
@@ -466,6 +537,11 @@ public class Root extends AbstractComponentContainer implements
private Focusable pendingFocus;
/**
+ * The current URI fragment.
+ */
+ private String fragment;
+
+ /**
* This method is used by Component.Focusable objects to request focus to
* themselves. Focus renders must be handled at window level (instead of
* Component.Focusable) due we want the last focused component to be focused
@@ -792,6 +868,24 @@ public class Root extends AbstractComponentContainer implements
}
/**
+ * Internal initialization method, should not be overridden. This method is
+ * not declared as final because that would break compatibility with e.g.
+ * CDI.
+ *
+ * @param request
+ * the initialization request
+ */
+ public void doInit(WrappedRequest request) {
+ BrowserDetails browserDetails = request.getBrowserDetails();
+ if (browserDetails != null) {
+ fragment = browserDetails.getUriFragmet();
+ }
+
+ // Call the init overridden by the application developer
+ init(request);
+ }
+
+ /**
* Initializes this root. This method is intended to be overridden by
* subclasses to build the view and configure non-component functionality.
* Performing the initialization in a constructor is not suggested as the
@@ -807,7 +901,7 @@ public class Root extends AbstractComponentContainer implements
* @param request
* the wrapped request that caused this root to be created
*/
- public void init(WrappedRequest request) {
+ protected void init(WrappedRequest request) {
// Default implementation doesn't do anything
}
@@ -1100,6 +1194,62 @@ public class Root extends AbstractComponentContainer implements
listener);
}
+ public void addListener(FragmentChangedListener listener) {
+ addListener(FragmentChangedEvent.class, listener,
+ FRAGMENT_CHANGED_METHOD);
+ }
+
+ public void removeListener(FragmentChangedListener listener) {
+ removeListener(FragmentChangedEvent.class, listener,
+ FRAGMENT_CHANGED_METHOD);
+ }
+
+ /**
+ * Sets URI fragment. Optionally fires a {@link FragmentChangedEvent}
+ *
+ * @param newFragment
+ * id of the new fragment
+ * @param fireEvent
+ * true to fire event
+ * @see FragmentChangedEvent
+ * @see FragmentChangedListener
+ */
+ public void setFragment(String newFragment, boolean fireEvents) {
+ if (newFragment == null) {
+ throw new NullPointerException("The fragment may not be null");
+ }
+ if (!newFragment.equals(fragment)) {
+ fragment = newFragment;
+ if (fireEvents) {
+ fireEvent(new FragmentChangedEvent(this, newFragment));
+ }
+ requestRepaint();
+ }
+ }
+
+ /**
+ * Sets URI fragment. This method fires a {@link FragmentChangedEvent}
+ *
+ * @param newFragment
+ * id of the new fragment
+ * @see FragmentChangedEvent
+ * @see FragmentChangedListener
+ */
+ public void setFragment(String newFragment) {
+ setFragment(newFragment, true);
+ }
+
+ /**
+ * Gets currently set URI fragment.
+ * <p>
+ * To listen changes in fragment, hook a {@link FragmentChangedListener}.
+ *
+ * @return the current fragment in browser uri or null if not known
+ */
+ public String getFragment() {
+ return fragment;
+ }
+
public void addListener(ResizeListener resizeListener) {
throw new RuntimeException("Not yet implemented");
}