public class ApplicationConfiguration implements EntryPoint {
+ /**
+ * Helper class for reading configuration options from the bootstap
+ * javascript
+ *
+ * @since 7.0
+ */
private static class JsoConfiguration extends JavaScriptObject {
protected JsoConfiguration() {
// JSO Constructor
}
+ /**
+ * Reads a configuration parameter as a string. Please note that the
+ * javascript value of the parameter should also be a string, or else an
+ * undefined exception may be thrown.
+ *
+ * @param name
+ * name of the configuration parameter
+ * @return value of the configuration parameter, or <code>null</code> if
+ * not defined
+ */
private native String getConfigString(String name)
/*-{
var value = this.getConfig(name);
}
}-*/;
+ /**
+ * Reads a configuration parameter as a boolean object. Please note that
+ * the javascript value of the parameter should also be a boolean, or
+ * else an undefined exception may be thrown.
+ *
+ * @param name
+ * name of the configuration parameter
+ * @return boolean value of the configuration paramter, or
+ * <code>null</code> if no value is defined
+ */
private native Boolean getConfigBoolean(String name)
/*-{
var value = this.getConfig(name);
}
}-*/;
+ /**
+ * Reads a configuration parameter as an integer object. Please note
+ * that the javascript value of the parameter should also be an integer,
+ * or else an undefined exception may be thrown.
+ *
+ * @param name
+ * name of the configuration parameter
+ * @return integer value of the configuration paramter, or
+ * <code>null</code> if no value is defined
+ */
private native Integer getConfigInteger(String name)
/*-{
var value = this.getConfig(name);
}
}-*/;
+ /**
+ * Reads a configuration parameter as an {@link ErrorMessage} object.
+ * Please note that the javascript value of the parameter should also be
+ * an object with appropriate fields, or else an undefined exception may
+ * be thrown when calling this method or when calling methods on the
+ * returned object.
+ *
+ * @param name
+ * name of the configuration parameter
+ * @return error message with the given name, or <code>null</code> if no
+ * value is defined
+ */
private native ErrorMessage getConfigError(String name)
/*-{
return this.getConfig(name);
}-*/;
+ /**
+ * Returns a native javascript object containing version information
+ * from the server.
+ *
+ * @return a javascript object with the version information
+ */
private native JavaScriptObject getVersionInfoJSObject()
/*-{
return this.getConfig("versionInfo");
}-*/;
+ /**
+ * Gets the version of the Vaadin framework used on the server.
+ *
+ * @return a string with the version
+ *
+ * @see com.vaadin.terminal.gwt.server.AbstractApplicationServlet#VERSION
+ */
private native String getVaadinVersion()
/*-{
return this.getConfig("versionInfo").vaadinVersion;
}-*/;
+ /**
+ * Gets the version of the application running on the server.
+ *
+ * @return a string with the application version
+ *
+ * @see com.vaadin.Application#getVersion()
+ */
private native String getApplicationVersion()
/*-{
return this.getConfig("versionInfo").applicationVersion;
}-*/;
}
+ /**
+ * Wraps a native javascript object containing fields for an error message
+ *
+ * @since 7.0
+ */
public static final class ErrorMessage extends JavaScriptObject {
protected ErrorMessage() {
return standalone;
}
+ /**
+ * Gets the root if of this application instance. The root id should be
+ * included in every request originating from this instance in order to
+ * associate it with the right Root instance on the server.
+ *
+ * @return the root id
+ */
public int getRootId() {
return rootId;
}
return authorizationError;
}
+ /**
+ * Reads the configuration values defined by the bootstrap javascript.
+ */
private void loadFromDOM() {
JsoConfiguration jsoConfiguration = getJsoConfiguration(id);
appUri = jsoConfiguration.getConfigString("appUri");
}
+ /**
+ * Starts the application with a given id by reading the configuration
+ * options stored by the bootstrap javascript.
+ *
+ * @param applicationId
+ * id of the application to load, this is also the id of the html
+ * element into which the application should be rendered.
+ */
public static void startApplication(final String applicationId) {
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
public void execute() {
return runningApplications;
}
+ /**
+ * Gets the configuration object for a specific application from the
+ * bootstrap javascript.
+ *
+ * @param appId
+ * the id of the application to get configuration data for
+ * @return a native javascript object containing the configuration data
+ */
private native static JsoConfiguration getJsoConfiguration(String appId)
/*-{
return $wnd.vaadin.getApp(appId);
deferredWidgetLoader = new DeferredWidgetLoader();
}
+ /**
+ * Registers that callback that the bootstrap javascript uses to start
+ * applications once the widgetset is loaded and all required information is
+ * available
+ *
+ * @param widgetsetName
+ * the name of this widgetset
+ */
public native static void registerCallback(String widgetsetName)
/*-{
var callbackHandler = @com.vaadin.terminal.gwt.client.ApplicationConfiguration::startApplication(Ljava/lang/String;);
import java.util.Map;
import com.vaadin.Application;
+import com.vaadin.Application.LegacyApplication;
+import com.vaadin.annotations.RootInitRequiresBrowserDetals;
import com.vaadin.event.Action;
import com.vaadin.event.Action.Handler;
import com.vaadin.event.ActionManager;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.terminal.Resource;
-import com.vaadin.terminal.Terminal;
import com.vaadin.terminal.WrappedRequest;
+import com.vaadin.terminal.WrappedRequest.BrowserDetails;
import com.vaadin.terminal.gwt.client.ui.VPanel;
import com.vaadin.terminal.gwt.client.ui.VView;
import com.vaadin.ui.Window.CloseListener;
import com.vaadin.ui.Window.ResizeListener;
+/**
+ * The topmost component in any component hierarchy. There is one root for every
+ * Vaadin instance in a browser window. A root may either represent an entire
+ * browser window (or tab) or some part of a html page where a Vaadin
+ * application is embedded.
+ * <p>
+ * The root is the server side entry point for various client side features that
+ * are not represented as components added to a layout, e.g notifications, sub
+ * windows, and executing javascript in the browser.
+ * </p>
+ * <p>
+ * When a new application instance is needed, typically because the user opens
+ * the application in a browser window,
+ * {@link Application#gerRoot(WrappedRequest)} is invoked to get a root. That
+ * method does by default create a root according to the
+ * {@value Application#ROOT_PARAMETER} parameter from web.xml.
+ * </p>
+ * <p>
+ * After a root has been created by the application, it is initialized using
+ * {@link #init(WrappedRequest)}. This method is intended to be overridden by
+ * the developer to add components to the user interface and initialize
+ * non-component functionality. The component hierarchy is initialized by
+ * passing a {@link ComponentContainer} with the main layout of the view to
+ * {@link #setContent(ComponentContainer)}.
+ * </p>
+ * <p>
+ * If a {@link RootInitRequiresBrowserDetals} annotation is present on a class
+ * extending <code>Root</code>, the framework will ensure {@link BrowserDetails}
+ * are present in the {@link WrappedRequest} passed to the init method.
+ * </p>
+ *
+ * @see #init(WrappedRequest)
+ * @see Application#getRoot(WrappedRequest)
+ *
+ * @since 7.0
+ */
@ClientWidget(VView.class)
public class Root extends AbstractComponentContainer implements
- com.vaadin.event.Action.Container {
+ Action.Container, Action.Notifier {
+
/**
* A border style used for opening resources in a window without a border.
*/
*/
public static final int BORDER_DEFAULT = 2;
+ /**
+ * The container in which the component hierarchy of the root starts.
+ */
private ComponentContainer content;
- private Terminal terminal;
+
+ /**
+ * The application to which this root belongs
+ */
private Application application;
/**
*/
private Component scrollIntoView;
+ /**
+ * The id of this root, used to find the server side instance of the root
+ * form which a request originates. A negative value indicates that the root
+ * id has not yet been assigned by the Application.
+ *
+ * @see Application#nextRootId
+ */
private int rootId = -1;
/**
*/
protected ActionManager actionManager;
+ /**
+ * Thread local for keeping track of the current root.
+ */
private static final ThreadLocal<Root> currentRoot = new ThreadLocal<Root>();
+ /**
+ * Creates a new empty root without a caption. This root will have a
+ * {@link VerticalLayout} with margins enabled as its content.
+ */
public Root() {
// Nothing to do here?
}
+ /**
+ * Creates a new root with the given component container as its content.
+ *
+ * @param content
+ * the content container to use as this roots content.
+ *
+ * @see #setContent(ComponentContainer)
+ */
public Root(ComponentContainer content) {
setContent(content);
}
+ /**
+ * Creates a new empty root with the given caption. This root will have a
+ * {@link VerticalLayout} with margins enabled as its content.
+ *
+ * @param caption
+ * the caption of the root, used as the page title if there's
+ * nothing but the application on the web page
+ *
+ * @see #setCaption(String)
+ */
public Root(String caption) {
setCaption(caption);
}
+ /**
+ * Creates a new root with the given caption and content.
+ *
+ * @param caption
+ * the caption of the root, used as the page title if there's
+ * nothing but the application on the web page
+ * @param content
+ * the content container to use as this roots content.
+ *
+ * @see #setContent(ComponentContainer)
+ * @see #setCaption(String)
+ */
public Root(String caption, ComponentContainer content) {
this(content);
setCaption(caption);
}
+ /**
+ * Overridden to return a value instead of referring to the parent.
+ *
+ * @return this root
+ *
+ * @see com.vaadin.ui.AbstractComponent#getRoot()
+ */
@Override
public Root getRoot() {
return this;
return Collections.singleton((Component) getContent()).iterator();
}
+ /**
+ * Sets the application to which this root is assigned. It is not legal to
+ * change the application once it has been set nor to set a
+ * <code>null</code> application.
+ * <p>
+ * This method is mainly intended for internal use by the framework.
+ * </p>
+ *
+ * @param application
+ * the application to set
+ *
+ * @throws IllegalStateException
+ * if the application has already been set
+ *
+ * @see #getApplication()
+ */
public void setApplication(Application application) {
if (application == null) {
throw new NullPointerException("application");
}
}
+ /**
+ * Sets the id of this root within its application. The root id is used to
+ * route requests to the right root.
+ * <p>
+ * This method is mainly intended for internal use by the framework.
+ * </p>
+ *
+ * @param rootId
+ * the id of this root
+ *
+ * @throws IllegalStateException
+ * if the root id has already been set
+ *
+ * @see #getRootId()
+ */
public void setRootId(int rootId) {
if (this.rootId != -1) {
throw new IllegalStateException("Root id has already been defined");
this.rootId = rootId;
}
+ /**
+ * Gets the id of the root, used to identify this root within its
+ * application when processing requests. The root id should be present in
+ * every request to the server that originates from this root.
+ * {@link Application#getRootForRequest(WrappedRequest)} uses this id to
+ * find the route to which the request belongs.
+ *
+ * @return
+ */
public int getRootId() {
return rootId;
}
/**
- * Adds a window inside this root.
- *
- * <p>
- * Adding windows inside another window creates "subwindows". These windows
- * should not be added to application directly and are not accessible
- * directly with any url. Addding windows implicitly sets their parents.
- * </p>
- *
- * <p>
- * Only one level of subwindows are supported. Thus you can add windows
- * inside such windows whose parent is <code>null</code>.
- * </p>
+ * Adds a window as a subwindow inside this root. To open a new browser
+ * window or tab, you should instead use {@link open(Resource)} with an url
+ * pointing to this application and ensure
+ * {@link Application#getRoot(WrappedRequest)} returns an appropriate root
+ * for the request.
*
* @param window
* @throws IllegalArgumentException
- * if a window is added inside non-application level window.
+ * if the window is already added to an application
* @throws NullPointerException
* if the given <code>Window</code> is <code>null</code>.
*/
attachWindow(window);
}
+ /**
+ * Helper method to attach a window.
+ *
+ * @param w
+ * the window to add
+ */
private void attachWindow(Window w) {
windows.add(w);
w.setParent(this);
return true;
}
+ /**
+ * Gets all the windows added to this root.
+ *
+ * @return an unmodifiable collection of windows
+ */
public Collection<Window> getWindows() {
return Collections.unmodifiableCollection(windows);
}
}
/**
- * Shows a notification message on the middle of the window. The message
+ * Shows a notification message on the middle of the root. The message
* automatically disappears ("humanized message").
*
* Care should be taken to to avoid XSS vulnerabilities as the caption is
* rendered as html.
*
- * @see #showNotification(com.vaadin.ui.Window.Notification)
+ * @see #showNotification(Notification)
* @see Notification
*
* @param caption
}
/**
- * Shows a notification message the window. The position and behavior of the
+ * Shows a notification message the root. The position and behavior of the
* message depends on the type, which is one of the basic types defined in
* {@link Notification}, for instance Notification.TYPE_WARNING_MESSAGE.
*
* Care should be taken to to avoid XSS vulnerabilities as the caption is
* rendered as html.
*
- * @see #showNotification(com.vaadin.ui.Window.Notification)
+ * @see #showNotification(Notification)
* @see Notification
*
* @param caption
/**
* Shows a notification consisting of a bigger caption and a smaller
- * description on the middle of the window. The message automatically
+ * description on the middle of the root. The message automatically
* disappears ("humanized message").
*
* Care should be taken to to avoid XSS vulnerabilities as the caption and
* description are rendered as html.
*
- * @see #showNotification(com.vaadin.ui.Window.Notification)
+ * @see #showNotification(Notification)
* @see Notification
*
* @param caption
* Care should be taken to to avoid XSS vulnerabilities as the caption and
* description are rendered as html.
*
- * @see #showNotification(com.vaadin.ui.Window.Notification)
+ * @see #showNotification(Notification)
* @see Notification
*
* @param caption
* Care should be taken to avoid XSS vulnerabilities if html content is
* allowed.
*
- * @see #showNotification(com.vaadin.ui.Window.Notification)
+ * @see #showNotification(Notification)
* @see Notification
*
* @param caption
addNotification(notification);
}
+ /**
+ * Internal helper method to actually add a notification.
+ *
+ * @param notification
+ * the notification to add
+ */
private void addNotification(Notification notification) {
if (notifications == null) {
notifications = new LinkedList<Notification>();
requestRepaint();
}
+ /**
+ * Gets the content of this root. The content is a component container that
+ * serves as the outermost item of the visual contents of this root.
+ *
+ * @return a component container to use as content
+ *
+ * @see #setContent(ComponentContainer)
+ * @see #createDefaultLayout()
+ */
public ComponentContainer getContent() {
if (content == null) {
setContent(createDefaultLayout());
return content;
}
- private VerticalLayout createDefaultLayout() {
+ /**
+ * Helper method to create the default content layout that is used if no
+ * content has not been explicitly defined.
+ *
+ * @return a newly created layout
+ */
+ private static VerticalLayout createDefaultLayout() {
VerticalLayout layout = new VerticalLayout();
layout.setMargin(true);
return layout;
}
+ /**
+ * Sets the content of this root. The content is a component container that
+ * serves as the outermost item of the visual contents of this root. If no
+ * content has been set, a {@link VerticalLayout} with margins enabled will
+ * be used by default - see {@link #createDefaultLayout()}. The content can
+ * also be set in a constructor.
+ *
+ * @return a component container to use as content
+ *
+ * @see #Root(ComponentContainer)
+ * @see #createDefaultLayout()
+ */
public void setContent(ComponentContainer content) {
if (this.content != null) {
super.removeComponent(this.content);
}
}
+ /**
+ * <b>Adding a component directly to a root is generally not supported.</b>
+ * To maintain backwards compatibility, adding components is still supported
+ * for roots in a {@link LegacyApplication}, where the component will be
+ * added to the content container.
+ *
+ * @see Window#addComponent(Component)
+ *
+ * @deprecated Add components to the content container (
+ * {@link #getContent()}) instead.
+ */
@Override
+ @Deprecated
public void addComponent(Component c) {
// Use the thread local as the instance field might not yet be inited
if (Application.getCurrentApplication() instanceof Application.LegacyApplication) {
}
}
+ /**
+ * <b>Removing a component from a root is generally not supported.</b> To
+ * maintain backwards compatibility, removing components is still supported
+ * for roots in a {@link LegacyApplication}, where the component will be
+ * removed from the content container.
+ *
+ * @see Window#removeComponent(Component)
+ *
+ * @deprecated Remove components from the content container (
+ * {@link #getContent()}) instead.
+ */
@Override
+ @Deprecated
public void removeComponent(Component c) {
// Use the thread local as the instance field might not yet be inited
if (Application.getCurrentApplication() instanceof Application.LegacyApplication) {
}
}
+ /**
+ * <b>Removing components from a root is generally not supported.</b> To
+ * maintain backwards compatibility, removing components is still supported
+ * for roots in a {@link LegacyApplication}, where the components will be
+ * removed from the content container.
+ *
+ * @see Window#removeAllComponents()
+ *
+ * @deprecated Remove components from the content container (
+ * {@link #getContent()}) instead.
+ */
@Override
+ @Deprecated
public void removeAllComponents() {
// Use the thread local as the instance field might not yet be inited
if (Application.getCurrentApplication() instanceof Application.LegacyApplication) {
}
}
+ /**
+ * 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
+ * state of the root is not properly set up when the constructor is invoked.
+ * <p>
+ * The {@link WrappedRequest} can be used to get information about the
+ * request that caused this root to be created. By default, the
+ * {@link BrowserDetails} are note guaranteed to be available in the
+ * request. Availability of the browser details can be requested by adding
+ * the {@link RootInitRequiresBrowserDetals} annotation to the class.
+ * </p>
+ *
+ * @param request
+ * the wrapped request that caused this root to be created
+ */
public void init(WrappedRequest request) {
-
+ // Default implementation doesn't do anything
}
+ /**
+ * Sets the thread local for the current root. 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.
+ * <p>
+ * The application developer can also use this method to define the current
+ * root outside the normal request handling, e.g. when initiating custom
+ * background threads.
+ * </p>
+ *
+ * @param root
+ * the root to register as the current root
+ *
+ * @see #getCurrentRoot()
+ * @see ThreadLocal
+ */
public static void setCurrentRoot(Root root) {
currentRoot.set(root);
}
+ /**
+ * Gets the currently used root. The current root is automatically defined
+ * when processing requests to the server. In other cases, (e.g. from
+ * background threads), the current root is not automatically defined.
+ *
+ * @return the current root instance if available, otherwise
+ * <code>null</code>
+ *
+ * @see #setCurrentRoot(Root)
+ */
public static Root getCurrentRoot() {
return currentRoot.get();
}
/**
- * Opens the given resource in this window. The contents of this Window is
+ * Opens the given resource in this root. The contents of this Root is
* replaced by the {@code Resource}.
*
* @param resource
- * the resource to show in this window
+ * the resource to show in this root
*/
public void open(Resource resource) {
synchronized (openList) {
}
}
+ /**
+ * Should resize operations be lazy, i.e. should there be a delay before
+ * layout sizes are recalculated. Speeds up resize operations in slow UIs
+ * with the penalty of slightly decreased usability.
+ *
+ * @param resizeLazy
+ * true to use a delay before recalculating sizes, false to
+ * calculate immediately.
+ */
public void setResizeLazy(boolean resizeLazy) {
throw new RuntimeException("Not yet implemented");
}