diff options
author | Leif Åstrand <leif@vaadin.com> | 2011-12-07 16:34:59 +0200 |
---|---|---|
committer | Leif Åstrand <leif@vaadin.com> | 2011-12-07 16:34:59 +0200 |
commit | 94d133023f8b43e0e185b43d7c329c6eac3be4b8 (patch) | |
tree | 9a2d847b09d3fde69e94bcec26fca4f0da3b2b24 /src/com/vaadin/ui/Root.java | |
parent | 7491f0fd006b8ef26d7dd2a50bf18300d8b4e7e1 (diff) | |
download | vaadin-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.java | 152 |
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"); } |