diff options
Diffstat (limited to 'server/src/com/vaadin/ui')
-rw-r--r-- | server/src/com/vaadin/ui/AbstractComponent.java | 22 | ||||
-rw-r--r-- | server/src/com/vaadin/ui/AbstractEmbedded.java | 84 | ||||
-rw-r--r-- | server/src/com/vaadin/ui/Button.java | 4 | ||||
-rw-r--r-- | server/src/com/vaadin/ui/Component.java | 16 | ||||
-rw-r--r-- | server/src/com/vaadin/ui/ConnectorTracker.java | 51 | ||||
-rw-r--r-- | server/src/com/vaadin/ui/EmbeddedBrowser.java | 19 | ||||
-rw-r--r-- | server/src/com/vaadin/ui/Flash.java | 136 | ||||
-rw-r--r-- | server/src/com/vaadin/ui/Image.java | 94 | ||||
-rw-r--r-- | server/src/com/vaadin/ui/LoginForm.java | 4 | ||||
-rw-r--r-- | server/src/com/vaadin/ui/Select.java | 14 | ||||
-rw-r--r-- | server/src/com/vaadin/ui/Slider.java | 172 | ||||
-rw-r--r-- | server/src/com/vaadin/ui/UI.java (renamed from server/src/com/vaadin/ui/Root.java) | 388 | ||||
-rw-r--r-- | server/src/com/vaadin/ui/Window.java | 28 |
13 files changed, 715 insertions, 317 deletions
diff --git a/server/src/com/vaadin/ui/AbstractComponent.java b/server/src/com/vaadin/ui/AbstractComponent.java index b1393488f7..a52a07f266 100644 --- a/server/src/com/vaadin/ui/AbstractComponent.java +++ b/server/src/com/vaadin/ui/AbstractComponent.java @@ -557,16 +557,6 @@ public abstract class AbstractComponent extends AbstractClientConnector } /* - * Gets the parent window of the component. Don't add a JavaDoc comment - * here, we use the default documentation from implemented interface. - */ - @Override - public Root getRoot() { - // Just make method from implemented Component interface public - return super.getRoot(); - } - - /* * Notify the component that it's attached to a window. Don't add a JavaDoc * comment here, we use the default documentation from implemented * interface. @@ -588,9 +578,9 @@ public abstract class AbstractComponent extends AbstractClientConnector public void detach() { super.detach(); if (actionManager != null) { - // Remove any existing viewer. Root cast is just to make the + // Remove any existing viewer. UI cast is just to make the // compiler happy - actionManager.setViewer((Root) null); + actionManager.setViewer((UI) null); } } @@ -601,7 +591,7 @@ public abstract class AbstractComponent extends AbstractClientConnector if (this instanceof Focusable) { final Application app = getApplication(); if (app != null) { - getRoot().setFocusedComponent((Focusable) this); + getUI().setFocusedComponent((Focusable) this); delayedFocus = false; } else { delayedFocus = true; @@ -1304,19 +1294,19 @@ public abstract class AbstractComponent extends AbstractClientConnector /** * Set a viewer for the action manager to be the parent sub window (if the - * component is in a window) or the root (otherwise). This is still a + * component is in a window) or the UI (otherwise). This is still a * simplification of the real case as this should be handled by the parent * VOverlay (on the client side) if the component is inside an VOverlay * component. */ private void setActionManagerViewer() { - if (actionManager != null && getRoot() != null) { + if (actionManager != null && getUI() != null) { // Attached and has action manager Window w = findAncestor(Window.class); if (w != null) { actionManager.setViewer(w); } else { - actionManager.setViewer(getRoot()); + actionManager.setViewer(getUI()); } } diff --git a/server/src/com/vaadin/ui/AbstractEmbedded.java b/server/src/com/vaadin/ui/AbstractEmbedded.java new file mode 100644 index 0000000000..9396af5c44 --- /dev/null +++ b/server/src/com/vaadin/ui/AbstractEmbedded.java @@ -0,0 +1,84 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.ui; + +import com.vaadin.shared.ui.AbstractEmbeddedState; +import com.vaadin.terminal.Resource; +import com.vaadin.terminal.gwt.server.ResourceReference; + +/** + * Abstract base for embedding components. + * + * @author Vaadin Ltd. + * @version + * @VERSION@ + * @since 7.0 + */ +@SuppressWarnings("serial") +public abstract class AbstractEmbedded extends AbstractComponent { + + @Override + public AbstractEmbeddedState getState() { + return (AbstractEmbeddedState) super.getState(); + } + + /** + * Sets the object source resource. The dimensions are assumed if possible. + * The type is guessed from resource. + * + * @param source + * the source to set. + */ + public void setSource(Resource source) { + if (source == null) { + getState().setSource(null); + } else { + getState().setSource(new ResourceReference(source)); + } + requestRepaint(); + } + + /** + * Get the object source resource. + * + * @return the source + */ + public Resource getSource() { + ResourceReference ref = ((ResourceReference) getState().getSource()); + if (ref == null) { + return null; + } else { + return ref.getResource(); + } + } + + /** + * Sets this component's alternate text that can be presented instead of the + * component's normal content for accessibility purposes. + * + * @param altText + * A short, human-readable description of this component's + * content. + */ + public void setAlternateText(String altText) { + if (altText != getState().getAlternateText() + || (altText != null && !altText.equals(getState() + .getAlternateText()))) { + getState().setAlternateText(altText); + requestRepaint(); + } + } + + /** + * Gets this component's alternate text that can be presented instead of the + * component's normal content for accessibility purposes. + * + * @returns Alternate text + */ + public String getAlternateText() { + return getState().getAlternateText(); + } + +} diff --git a/server/src/com/vaadin/ui/Button.java b/server/src/com/vaadin/ui/Button.java index 8546d8f830..68b9f1392f 100644 --- a/server/src/com/vaadin/ui/Button.java +++ b/server/src/com/vaadin/ui/Button.java @@ -472,6 +472,10 @@ public class Button extends AbstractComponent implements * Determines if a button is automatically disabled when clicked. If this is * set to true the button will be automatically disabled when clicked, * typically to prevent (accidental) extra clicks on a button. + * <p> + * Note that this is only used when the click comes from the user, not when + * calling {@link #click()}. + * </p> * * @param disableOnClick * true to disable button when it is clicked, false otherwise diff --git a/server/src/com/vaadin/ui/Component.java b/server/src/com/vaadin/ui/Component.java index 89e282d4e1..400dd66cac 100644 --- a/server/src/com/vaadin/ui/Component.java +++ b/server/src/com/vaadin/ui/Component.java @@ -507,18 +507,18 @@ public interface Component extends ClientConnector, Sizeable, Serializable { public void setIcon(Resource icon); /** - * Gets the Root the component is attached to. + * Gets the UI the component is attached to. * * <p> - * If the component is not attached to a Root through a component + * If the component is not attached to a UI through a component * containment hierarchy, <code>null</code> is returned. * </p> * - * @return the Root of the component or <code>null</code> if it is not - * attached to a Root + * @return the UI of the component or <code>null</code> if it is not + * attached to a UI */ @Override - public Root getRoot(); + public UI getUI(); /** * Gets the application object to which the component is attached. @@ -548,7 +548,7 @@ public interface Component extends ClientConnector, Sizeable, Serializable { * <p> * Reimplementing the {@code attach()} method is useful for tasks that need * to get a reference to the parent, window, or application object with the - * {@link #getParent()}, {@link #getRoot()}, and {@link #getApplication()} + * {@link #getParent()}, {@link #getUI()}, and {@link #getApplication()} * methods. A component does not yet know these objects in the constructor, * so in such case, the methods will return {@code null}. For example, the * following is invalid: @@ -574,8 +574,8 @@ public interface Component extends ClientConnector, Sizeable, Serializable { * {@link #setParent(Component)}. * </p> * <p> - * This method must call {@link Root#componentAttached(Component)} to let - * the Root know that a new Component has been attached. + * This method must call {@link UI#componentAttached(Component)} to let + * the UI know that a new Component has been attached. * </p> * * diff --git a/server/src/com/vaadin/ui/ConnectorTracker.java b/server/src/com/vaadin/ui/ConnectorTracker.java index 72879e0a25..b44189f838 100644 --- a/server/src/com/vaadin/ui/ConnectorTracker.java +++ b/server/src/com/vaadin/ui/ConnectorTracker.java @@ -26,11 +26,12 @@ import java.util.logging.Level; import java.util.logging.Logger; import com.vaadin.terminal.AbstractClientConnector; +import com.vaadin.terminal.gwt.server.AbstractCommunicationManager; import com.vaadin.terminal.gwt.server.ClientConnector; /** * A class which takes care of book keeping of {@link ClientConnector}s for a - * Root. + * UI. * <p> * Provides {@link #getConnector(String)} which can be used to lookup a * connector from its id. This is for framework use only and should not be @@ -54,7 +55,7 @@ public class ConnectorTracker implements Serializable { private Set<ClientConnector> dirtyConnectors = new HashSet<ClientConnector>(); private Set<ClientConnector> uninitializedConnectors = new HashSet<ClientConnector>(); - private Root root; + private UI uI; private Map<ClientConnector, Object> diffStates = new HashMap<ClientConnector, Object>(); /** @@ -68,15 +69,15 @@ public class ConnectorTracker implements Serializable { } /** - * Creates a new ConnectorTracker for the given root. A tracker is always - * attached to a root and the root cannot be changed during the lifetime of - * a {@link ConnectorTracker}. + * Creates a new ConnectorTracker for the given uI. A tracker is always + * attached to a uI and the uI cannot be changed during the lifetime of a + * {@link ConnectorTracker}. * - * @param root - * The root to attach to. Cannot be null. + * @param uI + * The uI to attach to. Cannot be null. */ - public ConnectorTracker(Root root) { - this.root = root; + public ConnectorTracker(UI uI) { + this.uI = uI; } /** @@ -210,8 +211,8 @@ public class ConnectorTracker implements Serializable { while (iterator.hasNext()) { String connectorId = iterator.next(); ClientConnector connector = connectorIdToConnector.get(connectorId); - if (getRootForConnector(connector) != root) { - // If connector is no longer part of this root, + if (getUIForConnector(connector) != uI) { + // If connector is no longer part of this uI, // remove it from the map. If it is re-attached to the // application at some point it will be re-added through // registerConnector(connector) @@ -226,28 +227,36 @@ public class ConnectorTracker implements Serializable { uninitializedConnectors.remove(connector); diffStates.remove(connector); iterator.remove(); + } else if (!AbstractCommunicationManager.isVisible(connector) + && !uninitializedConnectors.contains(connector)) { + uninitializedConnectors.add(connector); + diffStates.remove(connector); + getLogger().fine( + "cleanConnectorMap removed state for " + + getConnectorAndParentInfo(connector) + + " as it is not visible"); } } } /** - * Finds the root that the connector is attached to. + * Finds the uI that the connector is attached to. * * @param connector * The connector to lookup - * @return The root the connector is attached to or null if it is not - * attached to any root. + * @return The uI the connector is attached to or null if it is not attached + * to any uI. */ - private Root getRootForConnector(ClientConnector connector) { + private UI getUIForConnector(ClientConnector connector) { if (connector == null) { return null; } if (connector instanceof Component) { - return ((Component) connector).getRoot(); + return ((Component) connector).getUI(); } - return getRootForConnector(connector.getParent()); + return getUIForConnector(connector.getParent()); } /** @@ -330,15 +339,15 @@ public class ConnectorTracker implements Serializable { } /** - * Mark all connectors in this root as dirty. + * Mark all connectors in this uI as dirty. */ public void markAllConnectorsDirty() { - markConnectorsDirtyRecursively(root); + markConnectorsDirtyRecursively(uI); getLogger().fine("All connectors are now dirty"); } /** - * Mark all connectors in this root as clean. + * Mark all connectors in this uI as clean. */ public void markAllConnectorsClean() { dirtyConnectors.clear(); @@ -370,7 +379,7 @@ public class ConnectorTracker implements Serializable { * client in the following request. * </p> * - * @return A collection of all dirty connectors for this root. This list may + * @return A collection of all dirty connectors for this uI. This list may * contain invisible connectors. */ public Collection<ClientConnector> getDirtyConnectors() { diff --git a/server/src/com/vaadin/ui/EmbeddedBrowser.java b/server/src/com/vaadin/ui/EmbeddedBrowser.java new file mode 100644 index 0000000000..4e2ae18de8 --- /dev/null +++ b/server/src/com/vaadin/ui/EmbeddedBrowser.java @@ -0,0 +1,19 @@ +package com.vaadin.ui; + +import com.vaadin.shared.ui.embeddedbrowser.EmbeddedBrowserState; + +/** + * Component for embedding browser "iframe". + * + * @author Vaadin Ltd. + * @version + * @VERSION@ + * @since 7.0 + */ +public class EmbeddedBrowser extends AbstractEmbedded { + + @Override + public EmbeddedBrowserState getState() { + return (EmbeddedBrowserState) super.getState(); + } +} diff --git a/server/src/com/vaadin/ui/Flash.java b/server/src/com/vaadin/ui/Flash.java new file mode 100644 index 0000000000..0e6cf63a91 --- /dev/null +++ b/server/src/com/vaadin/ui/Flash.java @@ -0,0 +1,136 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.ui; + +import java.util.HashMap; + +import com.vaadin.shared.ui.flash.FlashState; + +/** + * Component for embedding flash objects. + * + * @author Vaadin Ltd. + * @version + * @VERSION@ + * @since 7.0 + */ +@SuppressWarnings("serial") +public class Flash extends AbstractEmbedded { + + @Override + public FlashState getState() { + return (FlashState) super.getState(); + } + + /** + * This attribute specifies the base path used to resolve relative URIs + * specified by the classid, data, and archive attributes. When absent, its + * default value is the base URI of the current document. + * + * @param codebase + * The base path + */ + public void setCodebase(String codebase) { + if (codebase != getState().getCodebase() + || (codebase != null && !codebase.equals(getState() + .getCodebase()))) { + getState().setCodebase(codebase); + requestRepaint(); + } + } + + /** + * This attribute specifies the content type of data expected when + * downloading the object specified by classid. This attribute is optional + * but recommended when classid is specified since it allows the user agent + * to avoid loading information for unsupported content types. When absent, + * it defaults to the value of the type attribute. + * + * @param codetype + * the codetype to set. + */ + public void setCodetype(String codetype) { + if (codetype != getState().getCodetype() + || (codetype != null && !codetype.equals(getState() + .getCodetype()))) { + getState().setCodetype(codetype); + requestRepaint(); + } + } + + /** + * This attribute may be used to specify a space-separated list of URIs for + * archives containing resources relevant to the object, which may include + * the resources specified by the classid and data attributes. Preloading + * archives will generally result in reduced load times for objects. + * Archives specified as relative URIs should be interpreted relative to the + * codebase attribute. + * + * @param archive + * Space-separated list of URIs with resources relevant to the + * object + */ + public void setArchive(String archive) { + if (archive != getState().getArchive() + || (archive != null && !archive.equals(getState().getArchive()))) { + getState().setArchive(archive); + requestRepaint(); + } + } + + public void setStandby(String standby) { + if (standby != getState().getStandby() + || (standby != null && !standby.equals(getState().getStandby()))) { + getState().setStandby(standby); + requestRepaint(); + } + } + + /** + * Sets an object parameter. Parameters are optional information, and they + * are passed to the instantiated object. Parameters are are stored as name + * value pairs. This overrides the previous value assigned to this + * parameter. + * + * @param name + * the name of the parameter. + * @param value + * the value of the parameter. + */ + public void setParameter(String name, String value) { + if (getState().getEmbedParams() == null) { + getState().setEmbedParams(new HashMap<String, String>()); + } + getState().getEmbedParams().put(name, value); + requestRepaint(); + } + + /** + * Gets the value of an object parameter. Parameters are optional + * information, and they are passed to the instantiated object. Parameters + * are are stored as name value pairs. + * + * @return the Value of parameter or null if not found. + */ + public String getParameter(String name) { + return getState().getEmbedParams() != null ? getState() + .getEmbedParams().get(name) : null; + } + + /** + * Removes an object parameter from the list. + * + * @param name + * the name of the parameter to remove. + */ + public void removeParameter(String name) { + if (getState().getEmbedParams() == null) { + return; + } + getState().getEmbedParams().remove(name); + requestRepaint(); + } + +} diff --git a/server/src/com/vaadin/ui/Image.java b/server/src/com/vaadin/ui/Image.java new file mode 100644 index 0000000000..b0dbc9e629 --- /dev/null +++ b/server/src/com/vaadin/ui/Image.java @@ -0,0 +1,94 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.ui; + +import com.vaadin.event.MouseEvents.ClickEvent; +import com.vaadin.event.MouseEvents.ClickListener; +import com.vaadin.shared.EventId; +import com.vaadin.shared.MouseEventDetails; +import com.vaadin.shared.ui.image.ImageServerRpc; +import com.vaadin.shared.ui.image.ImageState; +import com.vaadin.terminal.Resource; + +/** + * Component for embedding images. + * + * @author Vaadin Ltd. + * @version + * @VERSION@ + * @since 7.0 + */ +@SuppressWarnings("serial") +public class Image extends AbstractEmbedded { + + protected ImageServerRpc rpc = new ImageServerRpc() { + @Override + public void click(MouseEventDetails mouseDetails) { + fireEvent(new ClickEvent(Image.this, mouseDetails)); + } + }; + + /** + * Creates a new empty Image. + */ + public Image() { + registerRpc(rpc); + } + + /** + * Creates a new empty Image with caption. + * + * @param caption + */ + public Image(String caption) { + this(); + setCaption(caption); + } + + /** + * Creates a new Image whose contents is loaded from given resource. The + * dimensions are assumed if possible. The type is guessed from resource. + * + * @param caption + * @param source + * the Source of the embedded object. + */ + public Image(String caption, Resource source) { + this(caption); + setSource(source); + } + + @Override + public ImageState getState() { + return (ImageState) super.getState(); + } + + /** + * Add a click listener to the component. The listener is called whenever + * the user clicks inside the component. Depending on the content the event + * may be blocked and in that case no event is fired. + * + * Use {@link #removeListener(ClickListener)} to remove the listener. + * + * @param listener + * The listener to add + */ + public void addListener(ClickListener listener) { + addListener(EventId.CLICK_EVENT_IDENTIFIER, ClickEvent.class, listener, + ClickListener.clickMethod); + } + + /** + * Remove a click listener from the component. The listener should earlier + * have been added using {@link #addListener(ClickListener)}. + * + * @param listener + * The listener to remove + */ + public void removeListener(ClickListener listener) { + removeListener(EventId.CLICK_EVENT_IDENTIFIER, ClickEvent.class, + listener); + } +} diff --git a/server/src/com/vaadin/ui/LoginForm.java b/server/src/com/vaadin/ui/LoginForm.java index bb7767084c..1c154699d8 100644 --- a/server/src/com/vaadin/ui/LoginForm.java +++ b/server/src/com/vaadin/ui/LoginForm.java @@ -99,8 +99,8 @@ public class LoginForm extends CustomComponent { throws IOException { String requestPathInfo = request.getRequestPathInfo(); if ("/loginHandler".equals(requestPathInfo)) { - // Ensure Root.getCurrent() works in listeners - Root.setCurrent(getRoot()); + // Ensure UI.getCurrent() works in listeners + UI.setCurrent(getUI()); response.setCacheTime(-1); response.setContentType("text/html; charset=utf-8"); diff --git a/server/src/com/vaadin/ui/Select.java b/server/src/com/vaadin/ui/Select.java index 20345b55e0..6ff7c9c9bc 100644 --- a/server/src/com/vaadin/ui/Select.java +++ b/server/src/com/vaadin/ui/Select.java @@ -654,7 +654,7 @@ public class Select extends AbstractSelect implements AbstractSelect.Filtering, if (filterstring != null) { filterstring = filterstring.toLowerCase(); } - optionRepaint(); + requestRepaint(); } else if (isNewItemsAllowed()) { // New option entered (and it is allowed) final String newitem = (String) variables.get("newitem"); @@ -682,18 +682,6 @@ public class Select extends AbstractSelect implements AbstractSelect.Filtering, } @Override - public void markAsDirty() { - super.markAsDirty(); - optionRequest = false; - prevfilterstring = filterstring; - filterstring = null; - } - - private void optionRepaint() { - super.markAsDirty(); - } - - @Override public void setFilteringMode(int filteringMode) { this.filteringMode = filteringMode; } diff --git a/server/src/com/vaadin/ui/Slider.java b/server/src/com/vaadin/ui/Slider.java index d4e2db4853..a0b1d01b01 100644 --- a/server/src/com/vaadin/ui/Slider.java +++ b/server/src/com/vaadin/ui/Slider.java @@ -16,11 +16,9 @@ package com.vaadin.ui; -import java.util.Map; - -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Vaadin6Component; +import com.vaadin.shared.ui.slider.SliderOrientation; +import com.vaadin.shared.ui.slider.SliderServerRpc; +import com.vaadin.shared.ui.slider.SliderState; /** * A component for selecting a numerical value within a range. @@ -41,9 +39,9 @@ import com.vaadin.terminal.Vaadin6Component; * vl.addComponent(volumeIndicator); * volumeIndicator.setValue("Current volume:" + 50.0); * slider.addListener(this); - * + * * } - * + * * public void setVolume(double d) { * volumeIndicator.setValue("Current volume: " + d); * } @@ -58,28 +56,29 @@ import com.vaadin.terminal.Vaadin6Component; * * @author Vaadin Ltd. */ -public class Slider extends AbstractField<Double> implements Vaadin6Component { - - public static final int ORIENTATION_HORIZONTAL = 0; - - public static final int ORIENTATION_VERTICAL = 1; +public class Slider extends AbstractField<Double> { - /** Minimum value of slider */ - private double min = 0; + private SliderServerRpc rpc = new SliderServerRpc() { - /** Maximum value of slider */ - private double max = 100; + @Override + public void valueChanged(double value) { - /** - * Resolution, how many digits are considered relevant after the decimal - * point. Must be a non-negative value - */ - private int resolution = 0; + try { + setValue(value, true); + } catch (final ValueOutOfBoundsException e) { + // Convert to nearest bound + double out = e.getValue().doubleValue(); + if (out < getState().getMinValue()) { + out = getState().getMinValue(); + } + if (out > getState().getMaxValue()) { + out = getState().getMaxValue(); + } + Slider.super.setValue(new Double(out), false); + } + } - /** - * Slider orientation (horizontal/vertical), defaults . - */ - private int orientation = ORIENTATION_HORIZONTAL; + }; /** * Default slider constructor. Sets all values to defaults and the slide @@ -88,7 +87,8 @@ public class Slider extends AbstractField<Double> implements Vaadin6Component { */ public Slider() { super(); - super.setValue(new Double(min)); + registerRpc(rpc); + super.setValue(new Double(getState().getMinValue())); } /** @@ -153,13 +153,18 @@ public class Slider extends AbstractField<Double> implements Vaadin6Component { setCaption(caption); } + @Override + public SliderState getState() { + return (SliderState) super.getState(); + } + /** * Gets the maximum slider value * * @return the largest value the slider can have */ public double getMax() { - return max; + return getState().getMaxValue(); } /** @@ -170,11 +175,10 @@ public class Slider extends AbstractField<Double> implements Vaadin6Component { * The new maximum slider value */ public void setMax(double max) { - this.max = max; + getState().setMaxValue(max); if (getValue() > max) { setValue(max); } - markAsDirty(); } /** @@ -183,7 +187,7 @@ public class Slider extends AbstractField<Double> implements Vaadin6Component { * @return the smallest value the slider can have */ public double getMin() { - return min; + return getState().getMinValue(); } /** @@ -194,33 +198,32 @@ public class Slider extends AbstractField<Double> implements Vaadin6Component { * The new minimum slider value */ public void setMin(double min) { - this.min = min; + getState().setMinValue(min); if (getValue() < min) { setValue(min); } - markAsDirty(); } /** * Get the current orientation of the slider (horizontal or vertical). * - * @return {@link #ORIENTATION_HORIZONTAL} or - * {@link #ORIENTATION_HORIZONTAL} + * @return {@link SliderOrientation#HORIZONTAL} or + * {@link SliderOrientation#VERTICAL} */ - public int getOrientation() { - return orientation; + public SliderOrientation getOrientation() { + return getState().getOrientation(); } /** * Set the orientation of the slider. * - * @param The - * new orientation, either {@link #ORIENTATION_HORIZONTAL} or - * {@link #ORIENTATION_VERTICAL} + * @param orientation + * The new orientation, either + * {@link SliderOrientation#HORIZONTAL} or + * {@link SliderOrientation#VERTICAL} */ - public void setOrientation(int orientation) { - this.orientation = orientation; - markAsDirty(); + public void setOrientation(SliderOrientation orientation) { + getState().setOrientation(orientation); } /** @@ -230,21 +233,24 @@ public class Slider extends AbstractField<Double> implements Vaadin6Component { * @return resolution */ public int getResolution() { - return resolution; + return getState().getResolution(); } /** * Set a new resolution for the slider. The resolution is the number of * digits after the decimal point. * + * @throws IllegalArgumentException + * if resolution is negative. + * * @param resolution */ public void setResolution(int resolution) { if (resolution < 0) { - return; + throw new IllegalArgumentException( + "Cannot set a negative resolution to Slider"); } - this.resolution = resolution; - markAsDirty(); + getState().setResolution(resolution); } /** @@ -261,87 +267,36 @@ public class Slider extends AbstractField<Double> implements Vaadin6Component { @Override protected void setValue(Double value, boolean repaintIsNotNeeded) { final double v = value.doubleValue(); + final int resolution = getResolution(); double newValue; + if (resolution > 0) { // Round up to resolution newValue = (int) (v * Math.pow(10, resolution)); newValue = newValue / Math.pow(10, resolution); - if (min > newValue || max < newValue) { + if (getMin() > newValue || getMax() < newValue) { throw new ValueOutOfBoundsException(value); } } else { newValue = (int) v; - if (min > newValue || max < newValue) { + if (getMin() > newValue || getMax() < newValue) { throw new ValueOutOfBoundsException(value); } } + + getState().setValue(newValue); super.setValue(newValue, repaintIsNotNeeded); } @Override - public void setValue(Object newFieldValue) - throws com.vaadin.data.Property.ReadOnlyException { - if (newFieldValue != null && newFieldValue instanceof Number - && !(newFieldValue instanceof Double)) { + public void setValue(Object newFieldValue) { + if (newFieldValue instanceof Number) { // Support setting all types of Numbers newFieldValue = ((Number) newFieldValue).doubleValue(); } - - super.setValue(newFieldValue); - } - - @Override - public void paintContent(PaintTarget target) throws PaintException { - - target.addAttribute("min", min); - if (max > min) { - target.addAttribute("max", max); - } else { - target.addAttribute("max", min); - } - target.addAttribute("resolution", resolution); - - if (resolution > 0) { - target.addVariable(this, "value", getValue().doubleValue()); - } else { - target.addVariable(this, "value", getValue().intValue()); - } - - if (orientation == ORIENTATION_VERTICAL) { - target.addAttribute("vertical", true); - } - - } - - /** - * Invoked when the value of a variable has changed. Slider listeners are - * notified if the slider value has changed. - * - * @param source - * @param variables - */ - @Override - public void changeVariables(Object source, Map<String, Object> variables) { - if (variables.containsKey("value")) { - final Object value = variables.get("value"); - final Double newValue = new Double(value.toString()); - if (newValue != null && newValue != getValue() - && !newValue.equals(getValue())) { - try { - setValue(newValue, true); - } catch (final ValueOutOfBoundsException e) { - // Convert to nearest bound - double out = e.getValue().doubleValue(); - if (out < min) { - out = min; - } - if (out > max) { - out = max; - } - super.setValue(new Double(out), false); - } - } - } + setValue(newFieldValue); + // The cast is safe if the above call returned without throwing + getState().setValue((Double) newFieldValue); } /** @@ -373,7 +328,6 @@ public class Slider extends AbstractField<Double> implements Vaadin6Component { public Double getValue() { return value; } - } @Override diff --git a/server/src/com/vaadin/ui/Root.java b/server/src/com/vaadin/ui/UI.java index 67f2e04a65..17a028bcdf 100644 --- a/server/src/com/vaadin/ui/Root.java +++ b/server/src/com/vaadin/ui/UI.java @@ -16,11 +16,13 @@ package com.vaadin.ui; +import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.EventListener; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Map; @@ -35,9 +37,9 @@ import com.vaadin.event.MouseEvents.ClickListener; import com.vaadin.shared.EventId; import com.vaadin.shared.MouseEventDetails; import com.vaadin.shared.ui.BorderStyle; -import com.vaadin.shared.ui.root.RootConstants; -import com.vaadin.shared.ui.root.RootServerRpc; -import com.vaadin.shared.ui.root.RootState; +import com.vaadin.shared.ui.ui.UIConstants; +import com.vaadin.shared.ui.ui.UIServerRpc; +import com.vaadin.shared.ui.ui.UIState; import com.vaadin.terminal.Page; import com.vaadin.terminal.Page.BrowserWindowResizeEvent; import com.vaadin.terminal.Page.BrowserWindowResizeListener; @@ -47,27 +49,28 @@ import com.vaadin.terminal.Resource; import com.vaadin.terminal.Vaadin6Component; import com.vaadin.terminal.WrappedRequest; import com.vaadin.terminal.WrappedRequest.BrowserDetails; -import com.vaadin.ui.Window.CloseListener; +import com.vaadin.terminal.gwt.server.AbstractApplicationServlet; +import com.vaadin.tools.ReflectTools; /** - * 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 + * 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. * <p> - * The root is the server side entry point for various client side features that + * 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. * </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. + * When a new UI instance is needed, typically because the user opens a URL in a + * browser window which points to {@link AbstractApplicationServlet}, + * {@link Application#getUIForRequest(WrappedRequest)} is invoked to get a UI. + * That method does by default create a UI according to the + * {@value Application#UI_PARAMETER} parameter from web.xml. * </p> * <p> - * After a root has been created by the application, it is initialized using + * After a UI 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 @@ -76,27 +79,27 @@ import com.vaadin.ui.Window.CloseListener; * </p> * <p> * If a {@link EagerInit} annotation is present on a class extending - * <code>Root</code>, the framework will use a faster initialization method - * which will not ensure that {@link BrowserDetails} are present in the + * <code>UI</code>, the framework will use a faster initialization method which + * will not ensure that {@link BrowserDetails} are present in the * {@link WrappedRequest} passed to the init method. * </p> * * @see #init(WrappedRequest) - * @see Application#getRoot(WrappedRequest) + * @see Application#getUI(WrappedRequest) * * @since 7.0 */ -public abstract class Root extends AbstractComponentContainer implements +public abstract class UI extends AbstractComponentContainer implements Action.Container, Action.Notifier, Vaadin6Component { /** - * Helper class to emulate the main window from Vaadin 6 using roots. This + * Helper class to emulate the main window from Vaadin 6 using UIs. This * class should be used in the same way as Window used as a browser level * window in Vaadin 6 with {@link com.vaadin.Application.LegacyApplication} */ @Deprecated @EagerInit - public static class LegacyWindow extends Root { + public static class LegacyWindow extends UI { private String name; /** @@ -210,11 +213,11 @@ public abstract class Root extends AbstractComponentContainer implements } /** - * Opens the given resource in this root. The contents of this Root is + * Opens the given resource in this UI. The contents of this UI is * replaced by the {@code Resource}. * * @param resource - * the resource to show in this root + * the resource to show in this UI * * @deprecated As of 7.0, use getPage().open instead */ @@ -294,9 +297,9 @@ public abstract class Root extends AbstractComponentContainer implements } /** - * Adds a new {@link BrowserWindowResizeListener} to this root. The + * Adds a new {@link BrowserWindowResizeListener} to this UI. The * listener will be notified whenever the browser window within which - * this root resides is resized. + * this UI resides is resized. * * @param resizeListener * the listener to add @@ -312,7 +315,7 @@ public abstract class Root extends AbstractComponentContainer implements } /** - * Removes a {@link BrowserWindowResizeListener} from this root. The + * Removes a {@link BrowserWindowResizeListener} from this UI. The * listener will no longer be notified when the browser window is * resized. * @@ -326,7 +329,7 @@ public abstract class Root extends AbstractComponentContainer implements } /** - * Gets the last known height of the browser window in which this root + * Gets the last known height of the browser window in which this UI * resides. * * @return the browser window height in pixels @@ -338,7 +341,7 @@ public abstract class Root extends AbstractComponentContainer implements } /** - * Gets the last known width of the browser window in which this root + * Gets the last known width of the browser window in which this UI * resides. * * @return the browser window width in pixels @@ -389,12 +392,48 @@ public abstract class Root extends AbstractComponentContainer implements } /** - * The application to which this root belongs + * Event fired when a UI is removed from the application. + */ + public static class CloseEvent extends Event { + + private static final String CLOSE_EVENT_IDENTIFIER = "uiClose"; + + public CloseEvent(UI source) { + super(source); + } + + public UI getUI() { + return (UI) getSource(); + } + } + + /** + * Interface for listening {@link UI.CloseEvent UI close events}. + * + */ + public interface CloseListener extends EventListener { + + public static final Method closeMethod = ReflectTools.findMethod( + CloseListener.class, "click", CloseEvent.class); + + /** + * Called when a CloseListener is notified of a CloseEvent. + * {@link UI#getCurrent()} returns <code>event.getUI()</code> within + * this method. + * + * @param event + * The close event that was fired. + */ + public void close(CloseEvent event); + } + + /** + * The application to which this UI belongs */ private Application application; /** - * List of windows in this root. + * List of windows in this UI. */ private final LinkedHashSet<Window> windows = new LinkedHashSet<Window>(); @@ -405,13 +444,13 @@ public abstract class Root extends AbstractComponentContainer implements 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. + * The id of this UI, used to find the server side instance of the UI form + * which a request originates. A negative value indicates that the UI id has + * not yet been assigned by the Application. * - * @see Application#nextRootId + * @see Application#nextUIId */ - private int rootId = -1; + private int uiId = -1; /** * Keeps track of the Actions added to this component, and manages the @@ -420,19 +459,19 @@ public abstract class Root extends AbstractComponentContainer implements protected ActionManager actionManager; /** - * Thread local for keeping track of the current root. + * Thread local for keeping track of the current UI. */ - private static final ThreadLocal<Root> currentRoot = new ThreadLocal<Root>(); + private static final ThreadLocal<UI> currentUI = new ThreadLocal<UI>(); /** Identifies the click event */ private ConnectorTracker connectorTracker = new ConnectorTracker(this); private Page page = new Page(this); - private RootServerRpc rpc = new RootServerRpc() { + private UIServerRpc rpc = new UIServerRpc() { @Override public void click(MouseEventDetails mouseDetails) { - fireEvent(new ClickEvent(Root.this, mouseDetails)); + fireEvent(new ClickEvent(UI.this, mouseDetails)); } @Override @@ -444,80 +483,89 @@ public abstract class Root extends AbstractComponentContainer implements }; /** - * Creates a new empty root without a caption. This root will have a + * Timestamp keeping track of the last heartbeat of this UI. Updated to the + * current time whenever the application receives a heartbeat or UIDL + * request from the client for this UI. + */ + private long lastHeartbeat = System.currentTimeMillis(); + + private long lastUidlRequest = System.currentTimeMillis(); + + /** + * Creates a new empty UI without a caption. This UI will have a * {@link VerticalLayout} with margins enabled as its content. */ - public Root() { + public UI() { this((ComponentContainer) null); } /** - * Creates a new root with the given component container as its content. + * Creates a new UI with the given component container as its content. * * @param content - * the content container to use as this roots content. + * the content container to use as this UIs content. * * @see #setContent(ComponentContainer) */ - public Root(ComponentContainer content) { + public UI(ComponentContainer content) { registerRpc(rpc); setSizeFull(); setContent(content); } /** - * Creates a new empty root with the given caption. This root will have a + * Creates a new empty UI with the given caption. This UI 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 + * the caption of the UI, used as the page title if there's * nothing but the application on the web page * * @see #setCaption(String) */ - public Root(String caption) { + public UI(String caption) { this((ComponentContainer) null); setCaption(caption); } /** - * Creates a new root with the given caption and content. + * Creates a new UI with the given caption and content. * * @param caption - * the caption of the root, used as the page title if there's + * the caption of the UI, 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. + * the content container to use as this UIs content. * * @see #setContent(ComponentContainer) * @see #setCaption(String) */ - public Root(String caption, ComponentContainer content) { + public UI(String caption, ComponentContainer content) { this(content); setCaption(caption); } @Override - protected RootState getState() { - return (RootState) super.getState(); + protected UIState getState() { + return (UIState) super.getState(); } @Override - public Class<? extends RootState> getStateType() { + public Class<? extends UIState> getStateType() { // This is a workaround for a problem with creating the correct state // object during build - return RootState.class; + return UIState.class; } /** * Overridden to return a value instead of referring to the parent. * - * @return this root + * @return this UI * - * @see com.vaadin.ui.AbstractComponent#getRoot() + * @see com.vaadin.ui.AbstractComponent#getUI() */ @Override - public Root getRoot() { + public UI getUI() { return this; } @@ -542,9 +590,9 @@ public abstract class Root extends AbstractComponentContainer implements if (pendingFocus != null) { // ensure focused component is still attached to this main window - if (pendingFocus.getRoot() == this - || (pendingFocus.getRoot() != null && pendingFocus - .getRoot().getParent() == this)) { + if (pendingFocus.getUI() == this + || (pendingFocus.getUI() != null && pendingFocus.getUI() + .getParent() == this)) { target.addAttribute("focused", pendingFocus); } pendingFocus = null; @@ -555,7 +603,7 @@ public abstract class Root extends AbstractComponentContainer implements } if (isResizeLazy()) { - target.addAttribute(RootConstants.RESIZE_LAZY, true); + target.addAttribute(UIConstants.RESIZE_LAZY, true); } } @@ -571,6 +619,16 @@ public abstract class Root extends AbstractComponentContainer implements fireEvent(new ClickEvent(this, mouseDetails)); } + /** + * For internal use only. + */ + public void fireCloseEvent() { + UI current = UI.getCurrent(); + UI.setCurrent(this); + fireEvent(new CloseEvent(this)); + UI.setCurrent(current); + } + @Override @SuppressWarnings("unchecked") public void changeVariables(Object source, Map<String, Object> variables) { @@ -584,9 +642,9 @@ public abstract class Root extends AbstractComponentContainer implements actionManager.handleActions(variables, this); } - if (variables.containsKey(RootConstants.FRAGMENT_VARIABLE)) { + if (variables.containsKey(UIConstants.FRAGMENT_VARIABLE)) { String fragment = (String) variables - .get(RootConstants.FRAGMENT_VARIABLE); + .get(UIConstants.FRAGMENT_VARIABLE); getPage().setFragment(fragment, true); } } @@ -622,7 +680,7 @@ public abstract class Root extends AbstractComponentContainer implements } /** - * Sets the application to which this root is assigned. It is not legal to + * Sets the application to which this UI is assigned. It is not legal to * change the application once it has been set nor to set a * <code>null</code> application. * <p> @@ -652,46 +710,46 @@ public abstract class Root extends AbstractComponentContainer implements } /** - * Sets the id of this root within its application. The root id is used to - * route requests to the right root. + * Sets the id of this UI within its application. The UI id is used to route + * requests to the right UI. * <p> * This method is mainly intended for internal use by the framework. * </p> * - * @param rootId - * the id of this root + * @param uiId + * the id of this UI * * @throws IllegalStateException - * if the root id has already been set + * if the UI id has already been set * - * @see #getRootId() + * @see #getUIId() */ - public void setRootId(int rootId) { - if (this.rootId != -1) { - throw new IllegalStateException("Root id has already been defined"); + public void setUIId(int uiId) { + if (this.uiId != -1) { + throw new IllegalStateException("UI id has already been defined"); } - this.rootId = rootId; + this.uiId = uiId; } /** - * 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. + * 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 Application#getUIForRequest(WrappedRequest)} uses this id to find + * the route to which the request belongs. * * @return */ - public int getRootId() { - return rootId; + public int getUIId() { + return uiId; } /** - * 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 + * Adds a window as a subwindow inside this UI. 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. + * {@link Application#getUI(WrappedRequest)} returns an appropriate UI for + * the request. * * @param window * @throws IllegalArgumentException @@ -727,7 +785,7 @@ public abstract class Root extends AbstractComponentContainer implements } /** - * Remove the given subwindow from this root. + * Remove the given subwindow from this UI. * * Since Vaadin 6.5, {@link CloseListener}s are called also when explicitly * removing a window by calling this method. @@ -741,7 +799,7 @@ public abstract class Root extends AbstractComponentContainer implements */ public boolean removeWindow(Window window) { if (!windows.remove(window)) { - // Window window is not a subwindow of this root. + // Window window is not a subwindow of this UI. return false; } window.setParent(null); @@ -752,7 +810,7 @@ public abstract class Root extends AbstractComponentContainer implements } /** - * Gets all the windows added to this root. + * Gets all the windows added to this UI. * * @return an unmodifiable collection of windows */ @@ -792,28 +850,28 @@ public abstract class Root extends AbstractComponentContainer implements } /** - * Scrolls any component between the component and root to a suitable - * position so the component is visible to the user. The given component - * must belong to this root. + * Scrolls any component between the component and UI to a suitable position + * so the component is visible to the user. The given component must belong + * to this UI. * * @param component * the component to be scrolled into view * @throws IllegalArgumentException - * if {@code component} does not belong to this root + * if {@code component} does not belong to this UI */ public void scrollIntoView(Component component) throws IllegalArgumentException { - if (component.getRoot() != this) { + if (component.getUI() != this) { throw new IllegalArgumentException( - "The component where to scroll must belong to this root."); + "The component where to scroll must belong to this UI."); } scrollIntoView = component; markAsDirty(); } /** - * 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. + * Gets the content of this UI. The content is a component container that + * serves as the outermost item of the visual contents of this UI. * * @return a component container to use as content * @@ -837,15 +895,15 @@ public abstract class Root extends AbstractComponentContainer implements } /** - * 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 + * Sets the content of this UI. The content is a component container that + * serves as the outermost item of the visual contents of this UI. 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 #UI(ComponentContainer) * @see #createDefaultLayout() */ public void setContent(ComponentContainer content) { @@ -863,11 +921,11 @@ public abstract class Root extends AbstractComponentContainer implements } /** - * Adds a component to this root. The component is not added directly to the - * root, but instead to the content container ({@link #getContent()}). + * Adds a component to this UI. The component is not added directly to the + * UI, but instead to the content container ({@link #getContent()}). * * @param component - * the component to add to this root + * the component to add to this UI * * @see #getContent() */ @@ -878,7 +936,7 @@ public abstract class Root extends AbstractComponentContainer implements /** * This implementation removes the component from the content container ( - * {@link #getContent()}) instead of from the actual root. + * {@link #getContent()}) instead of from the actual UI. */ @Override public void removeComponent(Component component) { @@ -887,7 +945,7 @@ public abstract class Root extends AbstractComponentContainer implements /** * This implementation removes the components from the content container ( - * {@link #getContent()}) instead of from the actual root. + * {@link #getContent()}) instead of from the actual UI. */ @Override public void removeAllComponents() { @@ -910,56 +968,55 @@ public abstract class Root extends AbstractComponentContainer implements } /** - * Initializes this root. This method is intended to be overridden by + * 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 root is not properly set up when the constructor is invoked. + * state of the UI 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 + * request that caused this UI to be created. By default, the * {@link BrowserDetails} will be available in the request. If the browser * details are not required, loading the application in the browser can take * some shortcuts giving a faster initial rendering. This can be indicated - * by adding the {@link EagerInit} annotation to the Root class. + * by adding the {@link EagerInit} annotation to the UI class. * </p> * * @param request - * the wrapped request that caused this root to be created + * the wrapped request that caused this UI to be created */ protected abstract void init(WrappedRequest request); /** - * Sets the thread local for the current root. This method is used by the + * 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. * <p> * The application developer can also use this method to define the current - * root outside the normal request handling, e.g. when initiating custom + * UI outside the normal request handling, e.g. when initiating custom * background threads. * </p> * - * @param root - * the root to register as the current root + * @param uI + * the UI to register as the current UI * * @see #getCurrent() * @see ThreadLocal */ - public static void setCurrent(Root root) { - currentRoot.set(root); + public static void setCurrent(UI ui) { + currentUI.set(ui); } /** - * 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. + * 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. * - * @return the current root instance if available, otherwise - * <code>null</code> + * @return the current UI instance if available, otherwise <code>null</code> * - * @see #setCurrent(Root) + * @see #setCurrent(UI) */ - public static Root getCurrent() { - return currentRoot.get(); + public static UI getCurrent() { + return currentUI.get(); } public void setScrollTop(int scrollTop) { @@ -1027,10 +1084,10 @@ public abstract class Root extends AbstractComponentContainer implements } /** - * Add a click listener to the Root. The listener is called whenever the - * user clicks inside the Root. Also when the click targets a component - * inside the Root, provided the targeted component does not prevent the - * click event from propagating. + * 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. * * Use {@link #removeListener(ClickListener)} to remove the listener. * @@ -1043,7 +1100,7 @@ public abstract class Root extends AbstractComponentContainer implements } /** - * Remove a click listener from the Root. The listener should earlier have + * Remove a click listener from the UI. The listener should earlier have * been added using {@link #addListener(ClickListener)}. * * @param listener @@ -1054,9 +1111,33 @@ public abstract class Root extends AbstractComponentContainer implements listener); } + /** + * Adds a close listener to the UI. The listener is called when the UI is + * removed from the application. + * + * @param listener + * The listener to add. + */ + public void addListener(CloseListener listener) { + addListener(CloseEvent.CLOSE_EVENT_IDENTIFIER, CloseEvent.class, + listener, CloseListener.closeMethod); + } + + /** + * Removes a close listener from the UI if it has previously been added with + * {@link #addListener(ClickListener)}. Otherwise, has no effect. + * + * @param listener + * The listener to remove. + */ + public void removeListener(CloseListener listener) { + removeListener(CloseEvent.CLOSE_EVENT_IDENTIFIER, CloseEvent.class, + listener); + } + @Override public boolean isConnectorEnabled() { - // TODO How can a Root be invisible? What does it mean? + // TODO How can a UI be invisible? What does it mean? return isVisible() && isEnabled(); } @@ -1069,7 +1150,7 @@ public abstract class Root extends AbstractComponentContainer implements } /** - * Setting the caption of a Root is not supported. To set the title of the + * 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.0, use {@link Page#setTitle(String)} @@ -1078,11 +1159,11 @@ public abstract class Root extends AbstractComponentContainer implements @Deprecated public void setCaption(String caption) { throw new IllegalStateException( - "You can not set the title of a Root. To set the title of the HTML page, use Page.setTitle"); + "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 root. The message + * 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 @@ -1105,7 +1186,7 @@ public abstract class Root extends AbstractComponentContainer implements } /** - * Shows a notification message the root. The position and behavior of the + * 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. * @@ -1132,8 +1213,8 @@ public abstract class Root extends AbstractComponentContainer implements /** * Shows a notification consisting of a bigger caption and a smaller - * description on the middle of the root. The message automatically - * disappears ("humanized message"). + * 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. @@ -1238,4 +1319,43 @@ public abstract class Root extends AbstractComponentContainer implements getPage().showNotification(notification); } + /** + * Returns the timestamp (milliseconds since the epoch) of the last received + * heartbeat for this UI. + * + * @see #heartbeat() + * @see Application#closeInactiveUIs() + * + * @return The time the last heartbeat request occurred. + */ + public long getLastHeartbeatTime() { + return lastHeartbeat; + } + + /** + * Returns the timestamp (milliseconds since the epoch) of the last received + * UIDL request for this UI. + * + * @return + */ + public long getLastUidlRequestTime() { + return lastUidlRequest; + } + + /** + * Sets the last heartbeat request timestamp for this UI. Called by the + * framework whenever the application receives a valid heartbeat request for + * this UI. + */ + public void setLastHeartbeatTime(long lastHeartbeat) { + this.lastHeartbeat = lastHeartbeat; + } + + /** + * Sets the last UIDL request timestamp for this UI. Called by the framework + * whenever the application receives a valid UIDL request for this UI. + */ + public void setLastUidlRequestTime(long lastUidlRequest) { + this.lastUidlRequest = lastUidlRequest; + } } diff --git a/server/src/com/vaadin/ui/Window.java b/server/src/com/vaadin/ui/Window.java index d79588cc63..6102350566 100644 --- a/server/src/com/vaadin/ui/Window.java +++ b/server/src/com/vaadin/ui/Window.java @@ -40,8 +40,8 @@ import com.vaadin.terminal.Vaadin6Component; /** * A component that represents a floating popup window that can be added to a - * {@link Root}. A window is added to a {@code Root} using - * {@link Root#addWindow(Window)}. </p> + * {@link UI}. A window is added to a {@code UI} using + * {@link UI#addWindow(Window)}. </p> * <p> * The contents of a window is set using {@link #setContent(ComponentContainer)} * or by using the {@link #Window(String, ComponentContainer)} constructor. The @@ -57,7 +57,7 @@ import com.vaadin.terminal.Vaadin6Component; * </p> * <p> * In Vaadin versions prior to 7.0.0, Window was also used as application level - * windows. This function is now covered by the {@link Root} class. + * windows. This function is now covered by the {@link UI} class. * </p> * * @author Vaadin Ltd. @@ -222,14 +222,14 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier, * </p> */ public void close() { - Root root = getRoot(); + UI uI = getUI(); - // Don't do anything if not attached to a root - if (root != null) { + // Don't do anything if not attached to a UI + if (uI != null) { // focus is restored to the parent window - root.focus(); - // subwindow is removed from the root - root.removeWindow(this); + uI.focus(); + // subwindow is removed from the UI + uI.removeWindow(this); } } @@ -470,22 +470,22 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier, * If there are currently several windows visible, calling this method makes * this window topmost. * <p> - * This method can only be called if this window connected a root. Else an + * This method can only be called if this window connected a UI. Else an * illegal state exception is thrown. Also if there are modal windows and * this window is not modal, and illegal state exception is thrown. * <p> */ public void bringToFront() { - Root root = getRoot(); - if (root == null) { + UI uI = getUI(); + if (uI == null) { throw new IllegalStateException( "Window must be attached to parent before calling bringToFront method."); } int maxBringToFront = -1; - for (Window w : root.getWindows()) { + for (Window w : uI.getWindows()) { if (!isModal() && w.isModal()) { throw new IllegalStateException( - "The root contains modal windows, non-modal window cannot be brought to front."); + "The UI contains modal windows, non-modal window cannot be brought to front."); } if (w.bringToFront != null) { maxBringToFront = Math.max(maxBringToFront, |