package org.vaadin.touchkit.ui;
import java.util.Iterator;
import java.util.LinkedList;
import org.vaadin.touchkit.gwt.client.vcom.navigation.NavigationViewServerRpc;
import org.vaadin.touchkit.gwt.client.vcom.navigation.NavigationViewState;
import com.vaadin.ui.AbstractComponentContainer;
import com.vaadin.ui.Component;
import com.vaadin.ui.CssLayout;
import com.vaadin.ui.Panel;
/**
* The NavigationView is a component container which integrates well with the
* {@link NavigationManager}. It consists of a {@link NavigationBar}, a content
* area, and optionally a {@link Toolbar}.
* <p>
* The content area is scrollable (i.e. no need to use a {@link Panel} in it).
* The {@link NavigationView} is most commonly used with a
* {@link NavigationManager} which provides smooth forward/back animations.
* <p>
* In addition to the main content area (set with {@link #setContent(Component)}
* ), a {@link NavigationView} can contain a secondary component which, by
* default, is positioned at the bottom of the layout. The secondary content is
* set with {@link #setToolbar(Component)}, and is usually a {@link Toolbar}.
*
*/
public class NavigationView extends AbstractComponentContainer {
private NavigationBar navigationBar = new NavigationBar();
private Component mainComponent;
private Component toolbar;
private NavigationViewServerRpc rpc = new NavigationViewServerRpc() {
@Override
public void updateScrollPosition(int position) {
setScrollPosition(position);
}
};
/**
* Constructs a NavigationView with the given content.
*
* @param content
*/
public NavigationView(Component content) {
this("", content);
}
/**
* Constructs a NavigationView with an empty {@link CssLayout} as its
* content.
*/
public NavigationView() {
this(new CssLayout());
}
/**
* Constructs a NavigationView with the given caption and an empty
* {@link CssLayout} as its content.
*
* @param caption
* the caption
*/
public NavigationView(String caption) {
this();
setCaption(caption);
}
/**
* Constructs a NavigationView with the given caption and content.
*
* @param caption
* the caption
* @param content
* the content
*/
public NavigationView(String caption, Component content) {
registerRpc(rpc);
mainComponent = content;
super.addComponent(getContent());
super.addComponent(getNavigationBar());
setCaption(caption);
}
/**
* Sets the main content of the NavigationView. If null, an empty
* {@link CssLayout} will be used.
*
* @param c
* the component to set as the content
*/
public void setContent(Component c) {
if (mainComponent == c) {
return;
}
if (mainComponent != null) {
super.removeComponent(mainComponent);
}
if (c == null) {
c = new CssLayout();
}
super.addComponent(c);
mainComponent = c;
markAsDirty();
}
/**
* @return the content of the navigation view.
*/
public Component getContent() {
return mainComponent;
}
/**
* @deprecated use setContent or setToolbar instead
*/
@Deprecated
@Override
public void addComponent(Component c) {
setContent(c);
}
/**
* The toolbar or content can be removed - other attempts will result in an
* {@link IllegalArgumentException}. If the content is removed, an empty
* {@link CssLayout} is set as the content.
*/
@Override
public void removeComponent(Component c) {
if (c == toolbar) {
super.removeComponent(c);
toolbar = null;
} else if (c == mainComponent) {
setContent(null);
} else {
throw new IllegalArgumentException(
" Only the toolbar or main content can be removed");
}
markAsDirty();
}
/**
* Removes the toolbar, and the current content (setting the content to an
* empty {@link CssLayout}).
*/
@Override
public void removeAllComponents() {
removeComponent(mainComponent);
removeComponent(toolbar);
}
/**
* @return the {@link NavigationBar}
*/
public NavigationBar getNavigationBar() {
return navigationBar;
}
/**
* Sets the component in the navigation bar's right slot.
*
* @param c
* the component to set in the right slot.
*/
public void setRightComponent(Component c) {
getNavigationBar().setRightComponent(c);
}
/**
* @return the component in the right slot of the navigation bar or null if
* not set
*/
public Component getRightComponent() {
return getNavigationBar().getRightComponent();
}
/**
* Sets the component in the navigation bar's left slot. Most commonly this
* component slot is automatically populated by the NavigationView (a back
* button).
*
* @param c
* the component to set in the left slot.
*/
public void setLeftComponent(Component c) {
getNavigationBar().setLeftComponent(c);
}
/**
* @return the component in the left slot of the navigation bar or null if
* not set
*/
public Component getLeftComponent() {
return getNavigationBar().getLeftComponent();
}
/**
* @see NavigationBar#getPreviousView()
*/
public Component getPreviousComponent() {
return getNavigationBar().getPreviousView();
}
/**
* @see NavigationBar#setPreviousView(Component)
*/
public void setPreviousComponent(Component component) {
getNavigationBar().setPreviousView(component);
}
@Override
public void setCaption(String caption) {
getNavigationBar().setCaption(caption);
}
@Override
public String getCaption() {
return getNavigationBar().getCaption();
}
/**
* Called by {@link NavigationManager} when the view is about to become
* visible.
*/
protected void onBecomingVisible() {
/*
* Due to limitations with Paintble references in UIDL, reset previous
* component to make sure back button renders its target view.
*/
Component previousComponent = getPreviousComponent();
if (previousComponent != null) {
setPreviousComponent(previousComponent);
}
}
/**
* The main content and the toolbar can be replaced - other attempts will
* result in an {@link IllegalArgumentException}
*/
@Override
public void replaceComponent(Component oldComponent, Component newComponent) {
if (mainComponent == oldComponent) {
setContent(newComponent);
} else if (toolbar == oldComponent) {
setToolbar(newComponent);
} else {
throw new IllegalArgumentException(
" Only the toolbar or main content can be replaced");
}
}
@Override
public Iterator<Component> getComponentIterator() {
LinkedList<Component> linkedList = new LinkedList<Component>();
if (navigationBar != null) {
linkedList.add(navigationBar);
}
if (mainComponent != null) {
linkedList.add(mainComponent);
}
if (toolbar != null) {
linkedList.add(toolbar);
}
return linkedList.iterator();
}
/**
* Sets the toolbar component, usually a {@link Toolbar}. If a previous
* toolbar is set, it is removed from the layout and forgotten.
*
* @param toolbar
* The component to put in the toolbar slot.
*/
public void setToolbar(Component toolbar) {
if (this.toolbar != null && this.toolbar != toolbar) {
super.removeComponent(this.toolbar);
}
this.toolbar = toolbar;
if (toolbar != null) {
super.addComponent(toolbar);
}
markAsDirty();
}
/**
* @return The component in the toolbar slot or null if no toolbar has been
* set
*/
public Component getToolbar() {
return toolbar;
}
@Override
public NavigationViewState getState() {
return (NavigationViewState) super.getState();
}
/**
* Scrolls the view to the specified position.
*
* @param scrollPosition
* the position to scroll to (y coordinate).
*/
public void setScrollPosition(int scrollPosition) {
getState().scrollPosition = scrollPosition;
}
/**
* @return The scroll position of the view.
*/
public int getScrollPosition() {
return getState().scrollPosition;
}
/**
* Gets the @link {@link NavigationManager} in which this view is contained.
*
* @return the parent {@link NavigationManager} or null if not inside one.
*/
public NavigationManager getNavigationManager() {
Component p = getParent();
if (p instanceof NavigationManager) {
return (NavigationManager) p;
}
return null;
}
@Override
public int getComponentCount() {
return toolbar != null ? 3 : 2;
}
@Override
public Iterator<Component> iterator() {
return getComponentIterator();
}
}