/* * Copyright 2000-2016 Vaadin Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.vaadin.ui; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.URI; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; 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; import com.vaadin.event.MouseEvents.ClickEvent; import com.vaadin.event.MouseEvents.ClickListener; import com.vaadin.event.UIEvents.PollEvent; import com.vaadin.event.UIEvents.PollListener; import com.vaadin.event.UIEvents.PollNotifier; import com.vaadin.navigator.Navigator; import com.vaadin.server.ClientConnector; import com.vaadin.server.ComponentSizeValidator; import com.vaadin.server.ComponentSizeValidator.InvalidLayout; import com.vaadin.server.DefaultErrorHandler; import com.vaadin.server.ErrorHandler; import com.vaadin.server.ErrorHandlingRunnable; import com.vaadin.server.LocaleService; import com.vaadin.server.Page; import com.vaadin.server.PaintException; import com.vaadin.server.PaintTarget; import com.vaadin.server.UIProvider; import com.vaadin.server.VaadinRequest; import com.vaadin.server.VaadinService; import com.vaadin.server.VaadinServlet; import com.vaadin.server.VaadinSession; import com.vaadin.server.VaadinSession.State; import com.vaadin.server.communication.PushConnection; import com.vaadin.shared.Connector; import com.vaadin.shared.EventId; import com.vaadin.shared.MouseEventDetails; import com.vaadin.shared.Registration; import com.vaadin.shared.communication.PushMode; import com.vaadin.shared.ui.ui.DebugWindowClientRpc; import com.vaadin.shared.ui.ui.DebugWindowServerRpc; import com.vaadin.shared.ui.ui.ScrollClientRpc; import com.vaadin.shared.ui.ui.UIClientRpc; import com.vaadin.shared.ui.ui.UIConstants; import com.vaadin.shared.ui.ui.UIServerRpc; import com.vaadin.shared.ui.ui.UIState; import com.vaadin.ui.Component.Focusable; import com.vaadin.ui.declarative.Design; import com.vaadin.util.ConnectorHelper; import com.vaadin.util.CurrentInstance; /** * The topmost component in any component hierarchy. There is one UI for every * Vaadin instance in a browser window. A UI may either represent an entire * browser window (or tab) or some part of a html page where a Vaadin * application is embedded. *
* The UI 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. *
*
* When a new UI instance is needed, typically because the user opens a URL in a
* browser window which points to e.g. {@link VaadinServlet}, all
* {@link UIProvider}s registered to the current {@link VaadinSession} are
* queried for the UI class that should be used. The selection is by default
* based on the UI
init parameter from web.xml.
*
* After a UI has been created by the application, it is initialized using * {@link #init(VaadinRequest)}. 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 must be initialized by * passing a {@link Component} with the main layout or other content of the view * to {@link #setContent(Component)} or to the constructor of the UI. *
* * @see #init(VaadinRequest) * @see UIProvider * * @since 7.0 */ public abstract class UI extends AbstractSingleComponentContainer implements Action.Container, Action.Notifier, PollNotifier, LegacyComponent, Focusable { /** * The application to which this UI belongs */ private volatile VaadinSession session; /** * List of windows in this UI. */ private final LinkedHashSet* The method will return {@code null} if the component is not currently * attached to an application. *
* ** Getting a null value is often a problem in constructors of regular * components and in the initializers of custom composite components. A * standard workaround is to use {@link VaadinSession#getCurrent()} to * retrieve the application instance that the current request relates to. * Another way is to move the problematic initialization to * {@link #attach()}, as described in the documentation of the method. *
* * @return the parent application of the component ornull
.
* @see #attach()
*/
@Override
public VaadinSession getSession() {
return session;
}
@Override
public void paintContent(PaintTarget target) throws PaintException {
page.paintContent(target);
if (scrollIntoView != null) {
target.addAttribute("scrollTo", scrollIntoView);
scrollIntoView = null;
}
if (pendingFocus != null) {
// ensure focused component is still attached to this main window
if (equals(pendingFocus.getUI()) || (pendingFocus.getUI() != null
&& equals(pendingFocus.getUI().getParent()))) {
target.addAttribute("focused", pendingFocus);
}
pendingFocus = null;
}
if (actionManager != null) {
actionManager.paintActions(null, target);
}
if (isResizeLazy()) {
target.addAttribute(UIConstants.RESIZE_LAZY, true);
}
}
/**
* Fire a click event to all click listeners.
*
* @param object
* The raw "value" of the variable change from the client side.
*/
private void fireClick(Map* This method is for internal use by the framework. To explicitly close a * UI, see {@link #close()}. *
* * @param session * the session to set * * @throws IllegalStateException * if the session has already been set * * @see #getSession() */ public void setSession(VaadinSession session) { if (session == null && this.session == null) { throw new IllegalStateException( "Session should never be set to null when UI.session is already null"); } else if (session != null && this.session != null) { throw new IllegalStateException( "Session has already been set. Old session: " + getSessionDetails(this.session) + ". New session: " + getSessionDetails(session) + "."); } else { if (session == null) { try { detach(); } catch (Exception e) { getLogger().log(Level.WARNING, "Error while detaching UI from session", e); } // Disable push when the UI is detached. Otherwise the // push connection and possibly VaadinSession will live on. getPushConfiguration().setPushMode(PushMode.DISABLED); setPushConnection(null); } this.session = session; } if (session != null) { attach(); } } private static String getSessionDetails(VaadinSession session) { if (session == null) { return null; } else { return session.toString() + " for " + session.getService().getServiceName(); } } /** * Gets the id of the UI, used to identify this UI within its application * when processing requests. The UI id should be present in every request to * the server that originates from this UI. * {@link VaadinService#findUI(VaadinRequest)} uses this id to find the * route to which the request belongs. *
* This method is not intended to be overridden. If it is overridden, care
* should be taken since this method might be called in situations where
* {@link UI#getCurrent()} does not return this UI.
*
* @return the id of this UI
*/
public int getUIId() {
return uiId;
}
/**
* Adds a window as a subwindow inside this UI. To open a new browser window
* or tab, you should instead use a {@link UIProvider}.
*
* @param window
* @throws IllegalArgumentException
* if the window is already added to an application
* @throws NullPointerException
* if the given
* The {@link VaadinRequest} can be used to get information about the
* request that caused this UI to be created.
*
* 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 refresh(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.
*
* The application developer can also use this method to define the current
* UI outside the normal request handling, e.g. when initiating custom
* background threads.
*
* The UI is stored using a weak reference to avoid leaking memory in case
* it is not explicitly cleared.
*
* @param ui
* the UI to register as the current UI
*
* @see #getCurrent()
* @see ThreadLocal
*/
public static void setCurrent(UI ui) {
CurrentInstance.setInheritable(UI.class, ui);
}
/**
* Gets the currently used UI. The current UI is automatically defined when
* processing requests to the server. In other cases, (e.g. from background
* threads), the current UI is not automatically defined.
*
* The UI is stored using a weak reference to avoid leaking memory in case
* it is not explicitly cleared.
*
* @return the current UI instance if available, otherwise
* Default value:
* When there are active window resize listeners, lazy resize mode should be
* used to avoid a large number of events during resize.
*
* This method is not intended to be overridden. If it is overridden, care
* should be taken since this method might be called in situations where
* {@link UI#getCurrent()} does not return this UI.
*
* @see VaadinService#closeInactiveUIs(VaadinSession)
*
* @return The time the last heartbeat request occurred, in milliseconds
* since the epoch.
*/
public long getLastHeartbeatTimestamp() {
return lastHeartbeatTimestamp;
}
/**
* Sets the last heartbeat request timestamp for this UI. Called by the
* framework whenever the application receives a valid heartbeat request for
* this UI.
*
* This method is not intended to be overridden. If it is overridden, care
* should be taken since this method might be called in situations where
* {@link UI#getCurrent()} does not return this UI.
*
* @param lastHeartbeat
* The time the last heartbeat request occurred, in milliseconds
* since the epoch.
*/
public void setLastHeartbeatTimestamp(long lastHeartbeat) {
lastHeartbeatTimestamp = lastHeartbeat;
}
/**
* Gets the theme currently in use by this UI
*
* @return the theme name
*/
public String getTheme() {
return getState(false).theme;
}
/**
* Sets the theme currently in use by this UI
*
* Calling this method will remove the old theme (CSS file) from the
* application and add the new theme.
*
* Note that this method is NOT SAFE to call in a portal environment or
* other environment where there are multiple UIs on the same page. The old
* CSS file will be removed even if there are other UIs on the page which
* are still using it.
*
* @since 7.3
* @param theme
* The new theme name
*/
public void setTheme(String theme) {
if (theme == null) {
getState().theme = null;
} else {
getState().theme = VaadinServlet.stripSpecialChars(theme);
}
}
/**
* Marks this UI to be {@link #detach() detached} from the session at the
* end of the current request, or the next request if there is no current
* request (if called from a background thread, for instance.)
*
* The UI is detached after the response is sent, so in the current request
* it can still update the client side normally. However, after the response
* any new requests from the client side to this UI will cause an error, so
* usually the client should be asked, for instance, to reload the page
* (serving a fresh UI instance), to close the page, or to navigate
* somewhere else.
*
* Note that this method is strictly for users to explicitly signal the
* framework that the UI should be detached. Overriding it is not a reliable
* way to catch UIs that are to be detached. Instead, {@code UI.detach()}
* should be overridden or a {@link DetachListener} used.
*/
public void close() {
closing = true;
boolean sessionExpired = (session == null
|| session.getState() != State.OPEN);
getRpcProxy(UIClientRpc.class).uiClosed(sessionExpired);
if (getPushConnection() != null) {
// Push the Rpc to the client. The connection will be closed when
// the UI is detached and cleaned up.
// Can't use UI.push() directly since it checks for a valid session
if (session != null) {
session.getService().runPendingAccessTasks(session);
}
getPushConnection().push();
}
}
/**
* Returns whether this UI is marked as closed and is to be detached.
*
* This method is not intended to be overridden. If it is overridden, care
* should be taken since this method might be called in situations where
* {@link UI#getCurrent()} does not return this UI.
*
* @see #close()
*
* @return whether this UI is closing.
*/
public boolean isClosing() {
return closing;
}
/**
* Called after the UI is added to the session. A UI instance is attached
* exactly once, before its {@link #init(VaadinRequest) init} method is
* called.
*
* @see Component#attach
*/
@Override
public void attach() {
super.attach();
getLocaleService().addLocale(getLocale());
}
/**
* Called before the UI is removed from the session. A UI instance is
* detached exactly once, either:
*
* Note that when a UI is detached, any changes made in the {@code detach}
* methods of any children or {@link DetachListener}s that would be
* communicated to the client are silently ignored.
*/
@Override
public void detach() {
super.detach();
}
/*
* (non-Javadoc)
*
* @see
* com.vaadin.ui.AbstractSingleComponentContainer#setContent(com.vaadin.
* ui.Component)
*/
@Override
public void setContent(Component content) {
if (content instanceof Window) {
throw new IllegalArgumentException(
"A Window cannot be added using setContent. Use addWindow(Window window) instead");
}
super.setContent(content);
}
@Override
public void setTabIndex(int tabIndex) {
getState().tabIndex = tabIndex;
}
@Override
public int getTabIndex() {
return getState(false).tabIndex;
}
/**
* Locks the session of this UI and runs the provided Runnable right away.
*
* It is generally recommended to use {@link #access(Runnable)} instead of
* this method for accessing a session from a different thread as
* {@link #access(Runnable)} can be used while holding the lock of another
* session. To avoid causing deadlocks, this methods throws an exception if
* it is detected than another session is also locked by the current thread.
*
* This method behaves differently than {@link #access(Runnable)} in some
* situations:
*
* The given runnable is executed while holding the session lock to ensure
* exclusive access to this UI. If the session is not locked, the lock will
* be acquired and the runnable is run right away. If the session is
* currently locked, the runnable will be run before that lock is released.
*
* RPC handlers for components inside this UI do not need to use this method
* as the session is automatically locked by the framework during RPC
* handling.
*
* Please note that the runnable might be invoked on a different thread or
* later on the current thread, which means that custom thread locals might
* not have the expected values when the runnable is executed. Inheritable
* values in {@link CurrentInstance} will have the same values as when this
* method was invoked. {@link UI#getCurrent()},
* {@link VaadinSession#getCurrent()} and {@link VaadinService#getCurrent()}
* are set according to this UI before executing the runnable.
* Non-inheritable CurrentInstance values including
* {@link VaadinService#getCurrentRequest()} and
* {@link VaadinService#getCurrentResponse()} will not be defined.
*
* The returned future can be used to check for task completion and to
* cancel the task.
*
* If push is enabled, but the push connection is not currently open, the
* push will be done when the connection is established.
*
* As with all UI methods, the session must be locked when calling this
* method. It is also recommended that {@link UI#getCurrent()} is set up to
* return this UI since writing the response may invoke logic in any
* attached component or extension. The recommended way of fulfilling these
* conditions is to use {@link #access(Runnable)}.
*
* @throws IllegalStateException
* if push is disabled.
* @throws UIDetachedException
* if this UI is not attached to a session.
*
* @see #getPushConfiguration()
*
* @since 7.1
*/
public void push() {
VaadinSession session = getSession();
if (session == null) {
throw new UIDetachedException("Cannot push a detached UI");
}
assert session.hasLock();
if (!getPushConfiguration().getPushMode().isEnabled()) {
throw new IllegalStateException("Push not enabled");
}
assert pushConnection != null;
/*
* Purge the pending access queue as it might mark a connector as dirty
* when the push would otherwise be ignored because there are no changes
* to push.
*/
session.getService().runPendingAccessTasks(session);
if (!getConnectorTracker().hasDirtyConnectors()) {
// Do not push if there is nothing to push
return;
}
pushConnection.push();
}
/**
* Returns the internal push connection object used by this UI. This method
* should only be called by the framework.
*
* This method is not intended to be overridden. If it is overridden, care
* should be taken since this method might be called in situations where
* {@link UI#getCurrent()} does not return this UI.
*
* @return the push connection used by this UI, or {@code null} if push is
* not available.
*/
public PushConnection getPushConnection() {
assert !(getPushConfiguration().getPushMode().isEnabled()
&& pushConnection == null);
return pushConnection;
}
/**
* Sets the internal push connection object used by this UI. This method
* should only be called by the framework.
*
* The {@code pushConnection} argument must be non-null if and only if
* {@code getPushConfiguration().getPushMode().isEnabled()}.
*
* @param pushConnection
* the push connection to use for this UI
*/
public void setPushConnection(PushConnection pushConnection) {
// If pushMode is disabled then there should never be a pushConnection;
// if enabled there should always be
assert (pushConnection == null)
^ getPushConfiguration().getPushMode().isEnabled();
if (pushConnection == this.pushConnection) {
return;
}
if (this.pushConnection != null && this.pushConnection.isConnected()) {
this.pushConnection.disconnect();
}
this.pushConnection = pushConnection;
}
/**
* Sets the interval with which the UI should poll the server to see if
* there are any changes. Polling is disabled by default.
*
* Note that it is possible to enable push and polling at the same time but
* it should not be done to avoid excessive server traffic.
*
* Add-on developers should note that this method is only meant for the
* application developer. An add-on should not set the poll interval
* directly, rather instruct the user to set it.
*
* This is helpful for users of assistive devices, as this element is
* reachable for them.
* Window
is null
.
*/
public void addWindow(Window window)
throws IllegalArgumentException, NullPointerException {
if (window == null) {
throw new NullPointerException("Argument must not be null");
}
if (window.isAttached()) {
throw new IllegalArgumentException(
"Window is already attached to an application.");
}
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);
fireComponentAttachEvent(w);
markAsDirty();
}
/**
* Remove the given subwindow from this UI.
*
* Since Vaadin 6.5, {@link Window.CloseListener}s are called also when
* explicitly removing a window by calling this method.
*
* Since Vaadin 6.5, returns a boolean indicating if the window was removed
* or not.
*
* @param window
* Window to be removed.
* @return true if the subwindow was removed, false otherwise
*/
public boolean removeWindow(Window window) {
if (!windows.remove(window)) {
// Window window is not a subwindow of this UI.
return false;
}
window.setParent(null);
markAsDirty();
window.fireClose();
fireComponentDetachEvent(window);
return true;
}
/**
* Gets all the windows added to this UI.
*
* @return an unmodifiable collection of windows
*/
public Collectionnull
if no id is
* known
*
* @see #getUIId()
* @see #getEmbedId()
*/
public void doInit(VaadinRequest request, int uiId, String embedId) {
if (this.uiId != -1) {
String message = "This UI instance is already initialized (as UI id "
+ this.uiId
+ ") and can therefore not be initialized again (as UI id "
+ uiId + "). ";
if (getSession() != null
&& !getSession().equals(VaadinSession.getCurrent())) {
message += "Furthermore, it is already attached to another VaadinSession. ";
}
message += "Please make sure you are not accidentally reusing an old UI instance.";
throw new IllegalStateException(message);
}
this.uiId = uiId;
this.embedId = embedId;
// Actual theme - used for finding CustomLayout templates
setTheme(request.getParameter("theme"));
getPage().init(request);
// Call the init overridden by the application developer
init(request);
Navigator navigator = getNavigator();
if (navigator != null) {
// Kickstart navigation if a navigator was attached in init()
navigator.navigateTo(navigator.getState());
}
}
/**
* Initializes this UI. 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 UI is not properly set up when the constructor is invoked.
* null
*
* @see #setCurrent(UI)
*/
public static UI getCurrent() {
return CurrentInstance.get(UI.class);
}
/**
* Set top offset to which the UI should scroll to.
*
* @param scrollTop
*/
public void setScrollTop(int scrollTop) {
if (scrollTop < 0) {
throw new IllegalArgumentException(
"Scroll offset must be at least 0");
}
if (this.scrollTop != scrollTop) {
this.scrollTop = scrollTop;
getRpcProxy(ScrollClientRpc.class).setScrollTop(scrollTop);
}
}
public int getScrollTop() {
return scrollTop;
}
/**
* Set left offset to which the UI should scroll to.
*
* @param scrollLeft
*/
public void setScrollLeft(int scrollLeft) {
if (scrollLeft < 0) {
throw new IllegalArgumentException(
"Scroll offset must be at least 0");
}
if (this.scrollLeft != scrollLeft) {
this.scrollLeft = scrollLeft;
getRpcProxy(ScrollClientRpc.class).setScrollLeft(scrollLeft);
}
}
public int getScrollLeft() {
return scrollLeft;
}
@Override
protected ActionManager getActionManager() {
if (actionManager == null) {
actionManager = new ActionManager(this);
}
return actionManager;
}
@Override
public false
* true
if lazy resize is enabled, false
* if lazy resize is not enabled
*/
public boolean isResizeLazy() {
return resizeLazy;
}
/**
* Add a click listener to the UI. The listener is called whenever the user
* clicks inside the UI. Also when the click targets a component inside the
* UI, provided the targeted component does not prevent the click event from
* propagating.
*
* @see Registration
*
* @param listener
* The listener to add, not null
* @return a registration object for removing the listener
*/
public Registration addClickListener(ClickListener listener) {
return addListener(EventId.CLICK_EVENT_IDENTIFIER, ClickEvent.class,
listener, ClickListener.clickMethod);
}
/**
* Remove a click listener from the UI. The listener should earlier have
* been added using {@link #addListener(ClickListener)}.
*
* @param listener
* The listener to remove
*
* @deprecated As of 8.0, replaced by {@link Registration#remove()} in the
* registration object returned from
* {@link #removeClickListener(ClickListener)}.
*/
@Deprecated
public void removeClickListener(ClickListener listener) {
removeListener(EventId.CLICK_EVENT_IDENTIFIER, ClickEvent.class,
listener);
}
@Override
public boolean isConnectorEnabled() {
// TODO How can a UI be invisible? What does it mean?
return isVisible() && isEnabled();
}
public ConnectorTracker getConnectorTracker() {
return connectorTracker;
}
public Page getPage() {
return page;
}
/**
* Returns the navigator attached to this UI or null if there is no
* navigator.
*
* @return
*/
public Navigator getNavigator() {
return navigator;
}
/**
* For internal use only.
*
* @param navigator
*/
public void setNavigator(Navigator navigator) {
this.navigator = navigator;
}
/**
* Setting the caption of a UI is not supported. To set the title of the
* HTML page, use Page.setTitle
*
* @deprecated As of 7.0, use {@link Page#setTitle(String)}
*/
@Override
@Deprecated
public void setCaption(String caption) {
throw new UnsupportedOperationException(
"You can not set the title of a UI. To set the title of the HTML page, use Page.setTitle");
}
/**
* Shows a notification message on the middle of the UI. The message
* automatically disappears ("humanized message").
*
* Care should be taken to to avoid XSS vulnerabilities as the caption is
* rendered as html.
*
* @see #showNotification(Notification)
* @see Notification
*
* @param caption
* The message
*
* @deprecated As of 7.0, use Notification.show instead but be aware that
* Notification.show does not allow HTML.
*/
@Deprecated
public void showNotification(String caption) {
Notification notification = new Notification(caption);
notification.setHtmlContentAllowed(true);// Backwards compatibility
getPage().showNotification(notification);
}
/**
* Shows a notification message the UI. 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(Notification)
* @see Notification
*
* @param caption
* The message
* @param type
* The message type
*
* @deprecated As of 7.0, use Notification.show instead but be aware that
* Notification.show does not allow HTML.
*/
@Deprecated
public void showNotification(String caption, Notification.Type type) {
Notification notification = new Notification(caption, type);
notification.setHtmlContentAllowed(true);// Backwards compatibility
getPage().showNotification(notification);
}
/**
* Shows a notification consisting of a bigger caption and a smaller
* description on the middle of the UI. 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(Notification)
* @see Notification
*
* @param caption
* The caption of the message
* @param description
* The message description
*
* @deprecated As of 7.0, use new Notification(...).show(Page) instead but
* be aware that HTML by default not allowed.
*/
@Deprecated
public void showNotification(String caption, String description) {
Notification notification = new Notification(caption, description);
notification.setHtmlContentAllowed(true);// Backwards compatibility
getPage().showNotification(notification);
}
/**
* Shows a notification consisting of a bigger caption and a smaller
* description. 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 and
* description are rendered as html.
*
* @see #showNotification(Notification)
* @see Notification
*
* @param caption
* The caption of the message
* @param description
* The message description
* @param type
* The message type
*
* @deprecated As of 7.0, use new Notification(...).show(Page) instead but
* be aware that HTML by default not allowed.
*/
@Deprecated
public void showNotification(String caption, String description,
Notification.Type type) {
Notification notification = new Notification(caption, description,
type);
notification.setHtmlContentAllowed(true);// Backwards compatibility
getPage().showNotification(notification);
}
/**
* Shows a notification consisting of a bigger caption and a smaller
* description. 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 avoid XSS vulnerabilities if html content is
* allowed.
*
* @see #showNotification(Notification)
* @see Notification
*
* @param caption
* The message caption
* @param description
* The message description
* @param type
* The type of message
* @param htmlContentAllowed
* Whether html in the caption and description should be
* displayed as html or as plain text
*
* @deprecated As of 7.0, use new Notification(...).show(Page).
*/
@Deprecated
public void showNotification(String caption, String description,
Notification.Type type, boolean htmlContentAllowed) {
getPage().showNotification(new Notification(caption, description, type,
htmlContentAllowed));
}
/**
* Shows a notification message.
*
* @see Notification
* @see #showNotification(String)
* @see #showNotification(String, int)
* @see #showNotification(String, String)
* @see #showNotification(String, String, int)
*
* @param notification
* The notification message to show
*
* @deprecated As of 7.0, use Notification.show instead
*/
@Deprecated
public void showNotification(Notification notification) {
getPage().showNotification(notification);
}
/**
* Returns the timestamp of the last received heartbeat for this UI.
*
*
*
*
* window.name
DOM attribute of the browser window where the UI
* is displayed and the id of the div element where the UI is embedded.
*
* @since 7.2
* @return the embed id for this UI, or null
if no id known
*/
public String getEmbedId() {
return embedId;
}
/**
* Gets the last processed server message id.
*
* Used internally for communication tracking.
*
* @return lastProcessedServerMessageId the id of the last processed server
* message
* @since 7.6
*/
public int getLastProcessedClientToServerId() {
return lastProcessedClientToServerId;
}
/**
* Sets the last processed server message id.
*
* Used internally for communication tracking.
*
* @param lastProcessedServerMessageId
* the id of the last processed server message
* @since 7.6
*/
public void setLastProcessedClientToServerId(
int lastProcessedClientToServerId) {
this.lastProcessedClientToServerId = lastProcessedClientToServerId;
}
}