aboutsummaryrefslogtreecommitdiffstats
path: root/src/com/vaadin/ui
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/vaadin/ui')
-rw-r--r--src/com/vaadin/ui/AbstractJavaScriptComponent.java161
-rw-r--r--src/com/vaadin/ui/AbstractJavascriptComponent.java19
-rw-r--r--src/com/vaadin/ui/AbstractSelect.java5
-rw-r--r--src/com/vaadin/ui/AbstractSplitPanel.java128
-rw-r--r--src/com/vaadin/ui/Button.java2
-rw-r--r--src/com/vaadin/ui/HelloWorldExtension.java2
-rw-r--r--src/com/vaadin/ui/JavaScript.java146
-rw-r--r--src/com/vaadin/ui/JavaScriptCallback.java41
-rw-r--r--src/com/vaadin/ui/JavascriptCallback.java14
-rw-r--r--src/com/vaadin/ui/JavascriptManager.java58
-rw-r--r--src/com/vaadin/ui/Link.java7
-rw-r--r--src/com/vaadin/ui/Notification.java115
-rw-r--r--src/com/vaadin/ui/Root.java1065
-rw-r--r--src/com/vaadin/ui/TabSheet.java88
-rw-r--r--src/com/vaadin/ui/Table.java164
-rw-r--r--src/com/vaadin/ui/Tree.java5
-rw-r--r--src/com/vaadin/ui/TreeTable.java12
-rw-r--r--src/com/vaadin/ui/UniqueSerializable.java30
-rw-r--r--src/com/vaadin/ui/Window.java39
-rw-r--r--src/com/vaadin/ui/themes/ChameleonTheme.java2
20 files changed, 1186 insertions, 917 deletions
diff --git a/src/com/vaadin/ui/AbstractJavaScriptComponent.java b/src/com/vaadin/ui/AbstractJavaScriptComponent.java
new file mode 100644
index 0000000000..95c45f55f9
--- /dev/null
+++ b/src/com/vaadin/ui/AbstractJavaScriptComponent.java
@@ -0,0 +1,161 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.ui;
+
+import com.vaadin.terminal.JavaScriptCallbackHelper;
+import com.vaadin.terminal.gwt.client.ui.JavaScriptComponentState;
+import com.vaadin.terminal.gwt.client.ui.JavaScriptWidget;
+
+/**
+ * Base class for Components with all client-side logic implemented using
+ * JavaScript.
+ * <p>
+ * When a new JavaScript component is initialized in the browser, the framework
+ * will look for a globally defined JavaScript function that will initialize the
+ * component. The name of the initialization function is formed by replacing .
+ * with _ in the name of the server-side class. If no such function is defined,
+ * each super class is used in turn until a match is found. The framework will
+ * thus first attempt with <code>com_example_MyComponent</code> for the
+ * server-side
+ * <code>com.example.MyComponent extends AbstractJavaScriptComponent</code>
+ * class. If MyComponent instead extends <code>com.example.SuperComponent</code>
+ * , then <code>com_example_SuperComponent</code> will also be attempted if
+ * <code>com_example_MyComponent</code> has not been defined.
+ * <p>
+ * JavaScript components have a very simple GWT widget ({@link JavaScriptWidget}
+ * ) just consisting of a <code>div</code> element to which the JavaScript code
+ * should initialize its own user interface.
+ * <p>
+ * The initialization function will be called with <code>this</code> pointing to
+ * a connector wrapper object providing integration to Vaadin with the following
+ * functions:
+ * <ul>
+ * <li><code>getConnectorId()</code> - returns a string with the id of the
+ * connector.</li>
+ * <li><code>getParentId([connectorId])</code> - returns a string with the id of
+ * the connector's parent. If <code>connectorId</code> is provided, the id of
+ * the parent of the corresponding connector with the passed id is returned
+ * instead.</li>
+ * <li><code>getWidgetElement([connectorId])</code> - returns the DOM Element
+ * that is the root of a connector's widget. <code>null</code> is returned if
+ * the connector can not be found or if the connector doesn't have a widget. If
+ * <code>connectorId</code> is not provided, the connector id of the current
+ * connector will be used.</li>
+ * <li><code>getState()</code> - returns an object corresponding to the shared
+ * state defined on the server. The scheme for conversion between Java and
+ * JavaScript types is described bellow.</li>
+ * <li><code>registerRpc([name, ] rpcObject)</code> - registers the
+ * <code>rpcObject</code> as a RPC handler. <code>rpcObject</code> should be an
+ * object with field containing functions for all eligible RPC functions. If
+ * <code>name</code> is provided, the RPC handler will only used for RPC calls
+ * for the RPC interface with the same fully qualified Java name. If no
+ * <code>name</code> is provided, the RPC handler will be used for all incoming
+ * RPC invocations where the RPC method name is defined as a function field in
+ * the handler. The scheme for conversion between Java types in the RPC
+ * interface definition and the JavaScript values passed as arguments to the
+ * handler functions is described bellow.</li>
+ * <li><code>getRpcProxy([name])</code> - returns an RPC proxy object. If
+ * <code>name</code> is provided, the proxy object will contain functions for
+ * all methods in the RPC interface with the same fully qualified name, provided
+ * a RPC handler has been registered by the server-side code. If no
+ * <code>name</code> is provided, the returned RPC proxy object will contain
+ * functions for all methods in all RPC interfaces registered for the connector
+ * on the server. If the same method name is present in multiple registered RPC
+ * interfaces, the corresponding function in the RPC proxy object will throw an
+ * exception when called. The scheme for conversion between Java types in the
+ * RPC interface and the JavaScript values that should be passed to the
+ * functions is described bellow.</li>
+ * </ul>
+ * The connector wrapper also supports these special functions:
+ * <ul>
+ * <li><code>onStateChange</code> - If the JavaScript code assigns a function to
+ * the field, that function is called whenever the contents of the shared state
+ * is changed.</li>
+ * <li>Any field name corresponding to a call to
+ * {@link #registerCallback(String, JavaScriptCallback)} on the server will
+ * automatically be present as a function that triggers the registered callback
+ * on the server.</li>
+ * <li>Any field name referred to using
+ * {@link #invokeCallback(String, Object...)} on the server will be called if a
+ * function has been assigned to the field.</li>
+ * </ul>
+ * <p>
+ *
+ * Values in the Shared State and in RPC calls are converted between Java and
+ * JavaScript using the following conventions:
+ * <ul>
+ * <li>Primitive Java numbers (byte, char, int, long, float, double) and their
+ * boxed types (Byte, Character, Integer, Long, Float, Double) are represented
+ * by JavaScript numbers.</li>
+ * <li>The primitive Java boolean and the boxed Boolean are represented by
+ * JavaScript booleans.</li>
+ * <li>Java Strings are represented by JavaScript strings.</li>
+ * <li>List, Set and all arrays in Java are represented by JavaScript arrays.</li>
+ * <li>Map<String, ?> in Java is represented by JavaScript object with fields
+ * corresponding to the map keys.</li>
+ * <li>Any other Java Map is represented by a JavaScript array containing two
+ * arrays, the first contains the keys and the second contains the values in the
+ * same order.</li>
+ * <li>A Java Bean is represented by a JavaScript object with fields
+ * corresponding to the bean's properties.</li>
+ * <li>A Java Connector is represented by a JavaScript string containing the
+ * connector's id.</li>
+ * <li>A pluggable serialization mechanism is provided for types not described
+ * here. Please refer to the documentation for specific types for serialization
+ * information.</li>
+ * </ul>
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public class AbstractJavaScriptComponent extends AbstractComponent {
+ private JavaScriptCallbackHelper callbackHelper = new JavaScriptCallbackHelper(
+ this);
+
+ @Override
+ protected <T> void registerRpc(T implementation, Class<T> rpcInterfaceType) {
+ super.registerRpc(implementation, rpcInterfaceType);
+ callbackHelper.registerRpc(rpcInterfaceType);
+ }
+
+ /**
+ * Register a {@link JavaScriptCallback} that can be called from the
+ * JavaScript using the provided name. A JavaScript function with the
+ * provided name will be added to the connector wrapper object (initially
+ * available as <code>this</code>). Calling that JavaScript function will
+ * cause the call method in the registered {@link JavaScriptCallback} to be
+ * invoked with the same arguments.
+ *
+ * @param functionName
+ * the name that should be used for client-side callback
+ * @param javaScriptCallback
+ * the callback object that will be invoked when the JavaScript
+ * function is called
+ */
+ protected void registerCallback(String functionName,
+ JavaScriptCallback javaScriptCallback) {
+ callbackHelper.registerCallback(functionName, javaScriptCallback);
+ }
+
+ /**
+ * Invoke a named function that the connector JavaScript has added to the
+ * JavaScript connector wrapper object. The arguments should only contain
+ * data types that can be represented in JavaScript, including primitive
+ * boxing types, arrays, String, List, Set, Map, Connector and JavaBeans.
+ *
+ * @param name
+ * the name of the function
+ * @param arguments
+ * function arguments
+ */
+ protected void invokeCallback(String name, Object... arguments) {
+ callbackHelper.invokeCallback(name, arguments);
+ }
+
+ @Override
+ public JavaScriptComponentState getState() {
+ return (JavaScriptComponentState) super.getState();
+ }
+}
diff --git a/src/com/vaadin/ui/AbstractJavascriptComponent.java b/src/com/vaadin/ui/AbstractJavascriptComponent.java
deleted file mode 100644
index 0a26c10239..0000000000
--- a/src/com/vaadin/ui/AbstractJavascriptComponent.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.ui;
-
-import com.vaadin.terminal.JavascriptRpcHelper;
-
-public class AbstractJavascriptComponent extends AbstractComponent {
- private JavascriptRpcHelper rpcHelper = new JavascriptRpcHelper(this);
-
- protected void registerCallback(String functionName,
- JavascriptCallback javascriptCallback) {
- rpcHelper.registerCallback(functionName, javascriptCallback);
- }
-
- protected void invokeCallback(String name, Object... arguments) {
- rpcHelper.invokeCallback(name, arguments);
- }
-}
diff --git a/src/com/vaadin/ui/AbstractSelect.java b/src/com/vaadin/ui/AbstractSelect.java
index e586810b2d..6a927251af 100644
--- a/src/com/vaadin/ui/AbstractSelect.java
+++ b/src/com/vaadin/ui/AbstractSelect.java
@@ -24,7 +24,6 @@ import com.vaadin.event.Transferable;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.DropTarget;
import com.vaadin.event.dd.TargetDetailsImpl;
-import com.vaadin.event.dd.acceptcriteria.ClientCriterion;
import com.vaadin.event.dd.acceptcriteria.ClientSideCriterion;
import com.vaadin.event.dd.acceptcriteria.ContainsDataFlavor;
import com.vaadin.event.dd.acceptcriteria.TargetDetailIs;
@@ -33,8 +32,6 @@ import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.terminal.Resource;
import com.vaadin.terminal.Vaadin6Component;
-import com.vaadin.terminal.gwt.client.ui.dd.VIsOverId;
-import com.vaadin.terminal.gwt.client.ui.dd.VItemIdIs;
import com.vaadin.terminal.gwt.client.ui.dd.VerticalDropLocation;
import com.vaadin.ui.AbstractSelect.ItemCaptionMode;
@@ -1800,7 +1797,6 @@ public abstract class AbstractSelect extends AbstractField<Object> implements
*
* @since 6.3
*/
- @ClientCriterion(VIsOverId.class)
public static class TargetItemIs extends AbstractItemSetCriterion {
/**
@@ -1867,7 +1863,6 @@ public abstract class AbstractSelect extends AbstractField<Object> implements
*
* @since 6.3
*/
- @ClientCriterion(VItemIdIs.class)
public static class AcceptItem extends AbstractItemSetCriterion {
/**
diff --git a/src/com/vaadin/ui/AbstractSplitPanel.java b/src/com/vaadin/ui/AbstractSplitPanel.java
index 5205952621..876d39f2ae 100644
--- a/src/com/vaadin/ui/AbstractSplitPanel.java
+++ b/src/com/vaadin/ui/AbstractSplitPanel.java
@@ -22,7 +22,7 @@ import com.vaadin.tools.ReflectTools;
* AbstractSplitPanel.
*
* <code>AbstractSplitPanel</code> is base class for a component container that
- * can contain two components. The comopnents are split by a divider element.
+ * can contain two components. The components are split by a divider element.
*
* @author Vaadin Ltd.
* @version
@@ -31,7 +31,10 @@ import com.vaadin.tools.ReflectTools;
*/
public abstract class AbstractSplitPanel extends AbstractComponentContainer {
+ // TODO use Unit in AbstractSplitPanelState and remove these
private Unit posUnit;
+ private Unit posMinUnit;
+ private Unit posMaxUnit;
private AbstractSplitPanelRpc rpc = new AbstractSplitPanelRpc() {
@@ -41,13 +44,14 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
}
public void setSplitterPosition(float position) {
- getState().getSplitterState().setPosition(position);
+ getSplitterState().setPosition(position);
}
};
public AbstractSplitPanel() {
registerRpc(rpc);
setSplitPosition(50, Unit.PERCENTAGE, false);
+ setSplitPositionLimits(0, Unit.PERCENTAGE, 100, Unit.PERCENTAGE);
}
/**
@@ -101,6 +105,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
* @param c
* the component to be added.
*/
+
@Override
public void addComponent(Component c) {
if (getFirstComponent() == null) {
@@ -188,6 +193,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
* @param c
* the component to be removed.
*/
+
@Override
public void removeComponent(Component c) {
super.removeComponent(c);
@@ -204,6 +210,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
*
* @see com.vaadin.ui.ComponentContainer#getComponentIterator()
*/
+
public Iterator<Component> getComponentIterator() {
return new ComponentIterator();
}
@@ -214,6 +221,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
*
* @return the number of contained components (zero, one or two)
*/
+
public int getComponentCount() {
int count = 0;
if (getFirstComponent() != null) {
@@ -226,6 +234,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
}
/* Documented in superclass */
+
public void replaceComponent(Component oldComponent, Component newComponent) {
if (oldComponent == getFirstComponent()) {
setFirstComponent(newComponent);
@@ -297,7 +306,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
if (unit != Unit.PERCENTAGE) {
pos = Math.round(pos);
}
- SplitterState splitterState = getState().getSplitterState();
+ SplitterState splitterState = getSplitterState();
splitterState.setPosition(pos);
splitterState.setPositionUnit(unit.getSymbol());
splitterState.setPositionReversed(reverse);
@@ -313,7 +322,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
* @return position of the splitter
*/
public float getSplitPosition() {
- return getState().getSplitterState().getPosition();
+ return getSplitterState().getPosition();
}
/**
@@ -326,6 +335,110 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
}
/**
+ * Sets the minimum split position to the given position and unit. If the
+ * split position is reversed, maximum and minimum are also reversed.
+ *
+ * @param pos
+ * the minimum position of the split
+ * @param unit
+ * the unit (from {@link Sizeable}) in which the size is given.
+ * Allowed units are UNITS_PERCENTAGE and UNITS_PIXELS
+ */
+ public void setMinSplitPosition(int pos, Unit unit) {
+ setSplitPositionLimits(pos, unit, getSplitterState().getMaxPosition(),
+ posMaxUnit);
+ }
+
+ /**
+ * Returns the current minimum position of the splitter, in
+ * {@link #getMinSplitPositionUnit()} units.
+ *
+ * @return the minimum position of the splitter
+ */
+ public float getMinSplitPosition() {
+ return getSplitterState().getMinPosition();
+ }
+
+ /**
+ * Returns the unit of the minimum position of the splitter.
+ *
+ * @return the unit of the minimum position of the splitter
+ */
+ public Unit getMinSplitPositionUnit() {
+ return posMinUnit;
+ }
+
+ /**
+ * Sets the maximum split position to the given position and unit. If the
+ * split position is reversed, maximum and minimum are also reversed.
+ *
+ * @param pos
+ * the maximum position of the split
+ * @param unit
+ * the unit (from {@link Sizeable}) in which the size is given.
+ * Allowed units are UNITS_PERCENTAGE and UNITS_PIXELS
+ */
+ public void setMaxSplitPosition(float pos, Unit unit) {
+ setSplitPositionLimits(getSplitterState().getMinPosition(), posMinUnit,
+ pos, unit);
+ }
+
+ /**
+ * Returns the current maximum position of the splitter, in
+ * {@link #getMaxSplitPositionUnit()} units.
+ *
+ * @return the maximum position of the splitter
+ */
+ public float getMaxSplitPosition() {
+ return getSplitterState().getMaxPosition();
+ }
+
+ /**
+ * Returns the unit of the maximum position of the splitter
+ *
+ * @return the unit of the maximum position of the splitter
+ */
+ public Unit getMaxSplitPositionUnit() {
+ return posMaxUnit;
+ }
+
+ /**
+ * Sets the maximum and minimum position of the splitter. If the split
+ * position is reversed, maximum and minimum are also reversed.
+ *
+ * @param minPos
+ * the new minimum position
+ * @param minPosUnit
+ * the unit (from {@link Sizeable}) in which the minimum position
+ * is given.
+ * @param maxPos
+ * the new maximum position
+ * @param maxPosUnit
+ * the unit (from {@link Sizeable}) in which the maximum position
+ * is given.
+ */
+ private void setSplitPositionLimits(float minPos, Unit minPosUnit,
+ float maxPos, Unit maxPosUnit) {
+ if ((minPosUnit != Unit.PERCENTAGE && minPosUnit != Unit.PIXELS)
+ || (maxPosUnit != Unit.PERCENTAGE && maxPosUnit != Unit.PIXELS)) {
+ throw new IllegalArgumentException(
+ "Only percentage and pixel units are allowed");
+ }
+
+ SplitterState state = getSplitterState();
+
+ state.setMinPosition(minPos);
+ state.setMinPositionUnit(minPosUnit.getSymbol());
+ posMinUnit = minPosUnit;
+
+ state.setMaxPosition(maxPos);
+ state.setMaxPositionUnit(maxPosUnit.getSymbol());
+ posMaxUnit = maxPosUnit;
+
+ requestRepaint();
+ }
+
+ /**
* Lock the SplitPanels position, disabling the user from dragging the split
* handle.
*
@@ -333,7 +446,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
* Set <code>true</code> if locked, <code>false</code> otherwise.
*/
public void setLocked(boolean locked) {
- getState().getSplitterState().setLocked(locked);
+ getSplitterState().setLocked(locked);
requestRepaint();
}
@@ -344,7 +457,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
* @return <code>true</code> if locked, <code>false</code> otherwise.
*/
public boolean isLocked() {
- return getState().getSplitterState().isLocked();
+ return getSplitterState().isLocked();
}
/**
@@ -394,4 +507,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
return (AbstractSplitPanelState) super.getState();
}
+ private SplitterState getSplitterState() {
+ return getState().getSplitterState();
+ }
}
diff --git a/src/com/vaadin/ui/Button.java b/src/com/vaadin/ui/Button.java
index 876fe593e2..8e504d828b 100644
--- a/src/com/vaadin/ui/Button.java
+++ b/src/com/vaadin/ui/Button.java
@@ -38,6 +38,7 @@ public class Button extends AbstractComponent implements
Action.ShortcutNotifier {
private ButtonServerRpc rpc = new ButtonServerRpc() {
+
public void click(MouseEventDetails mouseEventDetails) {
fireClick(mouseEventDetails);
}
@@ -50,6 +51,7 @@ public class Button extends AbstractComponent implements
};
FocusAndBlurServerRpcImpl focusBlurRpc = new FocusAndBlurServerRpcImpl(this) {
+
@Override
protected void fireEvent(Event event) {
Button.this.fireEvent(event);
diff --git a/src/com/vaadin/ui/HelloWorldExtension.java b/src/com/vaadin/ui/HelloWorldExtension.java
index 6d9ce9bcf1..e705954f2e 100644
--- a/src/com/vaadin/ui/HelloWorldExtension.java
+++ b/src/com/vaadin/ui/HelloWorldExtension.java
@@ -13,7 +13,7 @@ public class HelloWorldExtension extends AbstractExtension {
public HelloWorldExtension() {
registerRpc(new HelloWorldRpc() {
public void onMessageSent(String message) {
- getRoot().showNotification(message);
+ Notification.show(message);
}
});
}
diff --git a/src/com/vaadin/ui/JavaScript.java b/src/com/vaadin/ui/JavaScript.java
new file mode 100644
index 0000000000..d256717711
--- /dev/null
+++ b/src/com/vaadin/ui/JavaScript.java
@@ -0,0 +1,146 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.ui;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.vaadin.external.json.JSONArray;
+import com.vaadin.external.json.JSONException;
+import com.vaadin.terminal.AbstractExtension;
+import com.vaadin.terminal.Page;
+import com.vaadin.terminal.gwt.client.communication.ServerRpc;
+import com.vaadin.terminal.gwt.client.extensions.javascriptmanager.ExecuteJavaScriptRpc;
+import com.vaadin.terminal.gwt.client.extensions.javascriptmanager.JavaScriptManagerState;
+
+/**
+ * Provides access to JavaScript functionality in the web browser. To get an
+ * instance of JavaScript, either use Page.getJavaScript() or
+ * JavaScript.getCurrent() as a shorthand for getting the JavaScript object
+ * corresponding to the current Page.
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public class JavaScript extends AbstractExtension {
+ private Map<String, JavaScriptCallback> callbacks = new HashMap<String, JavaScriptCallback>();
+
+ // Can not be defined in client package as this JSONArray is not available
+ // in GWT
+ public interface JavaScriptCallbackRpc extends ServerRpc {
+ public void call(String name, JSONArray arguments);
+ }
+
+ /**
+ * Creates a new JavaScript object. You should typically not this, but
+ * instead use the JavaScript object already associated with your Page
+ * object.
+ */
+ public JavaScript() {
+ registerRpc(new JavaScriptCallbackRpc() {
+ public void call(String name, JSONArray arguments) {
+ JavaScriptCallback callback = callbacks.get(name);
+ // TODO handle situation if name is not registered
+ try {
+ callback.call(arguments);
+ } catch (JSONException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+ });
+ }
+
+ @Override
+ public JavaScriptManagerState getState() {
+ return (JavaScriptManagerState) super.getState();
+ }
+
+ /**
+ * Add a new function to the global JavaScript namespace (i.e. the window
+ * object). The <code>call</code> method in the passed
+ * {@link JavaScriptCallback} object will be invoked with the same
+ * parameters whenever the JavaScript function is called in the browser.
+ *
+ * A callback added with the name <code>"myCallback"</code> can thus be
+ * invoked with the following JavaScript code:
+ * <code>window.myCallback(argument1, argument2)</code>.
+ *
+ * If the name parameter contains dots, simple objects are created on demand
+ * to allow calling the function using the same name (e.g.
+ * <code>window.myObject.myFunction</code>).
+ *
+ * @param name
+ * the name that the callback function should get in the global
+ * JavaScript namespace.
+ * @param callback
+ * the JavaScriptCallback that will be invoked if the JavaScript
+ * function is called.
+ */
+ public void addCallback(String name, JavaScriptCallback callback) {
+ callbacks.put(name, callback);
+ if (getState().getNames().add(name)) {
+ requestRepaint();
+ }
+ }
+
+ /**
+ * Removes a JavaScripCallback from the browser's global JavaScript
+ * namespace.
+ *
+ * If the name contains dots and intermediate were created by
+ * {@link #addCallback(String, JavaScriptCallback)}addCallback, these
+ * objects will not be removed when the callback is removed.
+ *
+ * @param name
+ * the name of the callback to remove
+ */
+ public void removeCallback(String name) {
+ callbacks.remove(name);
+ if (getState().getNames().remove(name)) {
+ requestRepaint();
+ }
+ }
+
+ /**
+ * Executes the given JavaScript code in the browser.
+ *
+ * @param script
+ * The JavaScript code to run.
+ */
+ public void execute(String script) {
+ getRpcProxy(ExecuteJavaScriptRpc.class).executeJavaScript(script);
+ }
+
+ /**
+ * Get the JavaScript object for the current Page, or null if there is no
+ * current page.
+ *
+ * @see Page#getCurrent()
+ *
+ * @return the JavaScript object corresponding to the current Page, or
+ * <code>null</code> if there is no current page.
+ */
+ public static JavaScript getCurrent() {
+ Page page = Page.getCurrent();
+ if (page == null) {
+ return null;
+ }
+ return page.getJavaScript();
+ }
+
+ /**
+ * JavaScript is not designed to be removed.
+ *
+ * @throws UnsupportedOperationException
+ * when invoked
+ */
+ @Override
+ public void removeFromTarget() {
+ throw new UnsupportedOperationException(
+ "JavaScript is not designed to be removed.");
+ }
+
+}
diff --git a/src/com/vaadin/ui/JavaScriptCallback.java b/src/com/vaadin/ui/JavaScriptCallback.java
new file mode 100644
index 0000000000..49f7695e89
--- /dev/null
+++ b/src/com/vaadin/ui/JavaScriptCallback.java
@@ -0,0 +1,41 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.ui;
+
+import java.io.Serializable;
+
+import com.vaadin.external.json.JSONArray;
+import com.vaadin.external.json.JSONException;
+import com.vaadin.terminal.AbstractJavaScriptExtension;
+
+/**
+ * Defines a method that is called by a client-side JavaScript function. When
+ * the corresponding JavaScript function is called, the {@link #call(JSONArray)}
+ * method is invoked.
+ *
+ * @see JavaScript#addCallback(String, JavaScriptCallback)
+ * @see AbstractJavaScriptComponent#registerCallback(String, JavaScriptCallback)
+ * @see AbstractJavaScriptExtension#registerCallback(String, JavaScriptCallback)
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public interface JavaScriptCallback extends Serializable {
+ /**
+ * Invoked whenever the corresponding JavaScript function is called in the
+ * browser.
+ * <p>
+ * Because of the asynchronous nature of the communication between client
+ * and server, no return value can be sent back to the browser.
+ *
+ * @param arguments
+ * an array with JSON representations of the arguments with which
+ * the JavaScript function was called.
+ * @throws JSONException
+ * if the arguments can not be interpreted
+ */
+ public void call(JSONArray arguments) throws JSONException;
+}
diff --git a/src/com/vaadin/ui/JavascriptCallback.java b/src/com/vaadin/ui/JavascriptCallback.java
deleted file mode 100644
index 89700b3faf..0000000000
--- a/src/com/vaadin/ui/JavascriptCallback.java
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.ui;
-
-import java.io.Serializable;
-
-import com.vaadin.external.json.JSONArray;
-import com.vaadin.external.json.JSONException;
-
-public interface JavascriptCallback extends Serializable {
- public void call(JSONArray arguments) throws JSONException;
-}
diff --git a/src/com/vaadin/ui/JavascriptManager.java b/src/com/vaadin/ui/JavascriptManager.java
deleted file mode 100644
index 72295dce2b..0000000000
--- a/src/com/vaadin/ui/JavascriptManager.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-
-package com.vaadin.ui;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import com.vaadin.external.json.JSONArray;
-import com.vaadin.external.json.JSONException;
-import com.vaadin.terminal.AbstractExtension;
-import com.vaadin.terminal.gwt.client.communication.ServerRpc;
-import com.vaadin.terminal.gwt.client.extensions.javascriptmanager.JavascriptManagerState;
-
-public class JavascriptManager extends AbstractExtension {
- private Map<String, JavascriptCallback> callbacks = new HashMap<String, JavascriptCallback>();
-
- // Can not be defined in client package as this JSONArray is not available
- // in GWT
- public interface JavascriptCallbackRpc extends ServerRpc {
- public void call(String name, JSONArray arguments);
- }
-
- public JavascriptManager() {
- registerRpc(new JavascriptCallbackRpc() {
- public void call(String name, JSONArray arguments) {
- JavascriptCallback callback = callbacks.get(name);
- // TODO handle situation if name is not registered
- try {
- callback.call(arguments);
- } catch (JSONException e) {
- throw new IllegalArgumentException(e);
- }
- }
- });
- }
-
- @Override
- public JavascriptManagerState getState() {
- return (JavascriptManagerState) super.getState();
- }
-
- public void addCallback(String name, JavascriptCallback javascriptCallback) {
- callbacks.put(name, javascriptCallback);
- if (getState().getNames().add(name)) {
- requestRepaint();
- }
- }
-
- public void removeCallback(String name) {
- callbacks.remove(name);
- if (getState().getNames().remove(name)) {
- requestRepaint();
- }
- }
-
-}
diff --git a/src/com/vaadin/ui/Link.java b/src/com/vaadin/ui/Link.java
index ed5ffbba3a..db0dc58e6b 100644
--- a/src/com/vaadin/ui/Link.java
+++ b/src/com/vaadin/ui/Link.java
@@ -6,6 +6,7 @@ package com.vaadin.ui;
import java.util.Map;
+import com.vaadin.terminal.Page;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.terminal.Resource;
@@ -23,13 +24,13 @@ import com.vaadin.terminal.Vaadin6Component;
public class Link extends AbstractComponent implements Vaadin6Component {
/* Target window border type constant: No window border */
- public static final int TARGET_BORDER_NONE = Root.BORDER_NONE;
+ public static final int TARGET_BORDER_NONE = Page.BORDER_NONE;
/* Target window border type constant: Minimal window border */
- public static final int TARGET_BORDER_MINIMAL = Root.BORDER_MINIMAL;
+ public static final int TARGET_BORDER_MINIMAL = Page.BORDER_MINIMAL;
/* Target window border type constant: Default window border */
- public static final int TARGET_BORDER_DEFAULT = Root.BORDER_DEFAULT;
+ public static final int TARGET_BORDER_DEFAULT = Page.BORDER_DEFAULT;
private Resource resource = null;
diff --git a/src/com/vaadin/ui/Notification.java b/src/com/vaadin/ui/Notification.java
index bb1f874635..075ab50196 100644
--- a/src/com/vaadin/ui/Notification.java
+++ b/src/com/vaadin/ui/Notification.java
@@ -6,6 +6,7 @@ package com.vaadin.ui;
import java.io.Serializable;
+import com.vaadin.terminal.Page;
import com.vaadin.terminal.Resource;
/**
@@ -318,4 +319,118 @@ public class Notification implements Serializable {
public boolean isHtmlContentAllowed() {
return htmlContentAllowed;
}
+
+ public void show() {
+ Page.getCurrent().showNotification(this);
+ }
+
+ /**
+ * Shows a notification message on the middle of the current page. 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
+ */
+ public static void show(String caption) {
+ new Notification(caption).show();
+ }
+
+ /**
+ * Shows a notification message the current page. 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
+ */
+ public static void show(String caption, int type) {
+ new Notification(caption, type).show();
+ }
+
+ /**
+ * Shows a notification consisting of a bigger caption and a smaller
+ * description on the middle of the current page. 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
+ *
+ */
+ public static void show(String caption, String description) {
+ new Notification(caption, description).show();
+ }
+
+ /**
+ * 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
+ */
+ public static void show(String caption, String description, int type) {
+
+ new Notification(caption, description, type).show();
+ }
+
+ /**
+ * 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
+ */
+ public static void show(String caption, String description, int type,
+ boolean htmlContentAllowed) {
+ new Notification(caption, description, type, htmlContentAllowed).show();
+ }
} \ No newline at end of file
diff --git a/src/com/vaadin/ui/Root.java b/src/com/vaadin/ui/Root.java
index 9814084cbc..50ad99571e 100644
--- a/src/com/vaadin/ui/Root.java
+++ b/src/com/vaadin/ui/Root.java
@@ -4,8 +4,6 @@
package com.vaadin.ui;
-import java.io.Serializable;
-import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
@@ -13,8 +11,6 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
-import java.util.LinkedList;
-import java.util.List;
import java.util.Map;
import com.vaadin.Application;
@@ -24,6 +20,9 @@ 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.terminal.Page;
+import com.vaadin.terminal.Page.BrowserWindowResizeEvent;
+import com.vaadin.terminal.Page.BrowserWindowResizeListener;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.terminal.Resource;
@@ -31,11 +30,9 @@ import com.vaadin.terminal.Vaadin6Component;
import com.vaadin.terminal.WrappedRequest;
import com.vaadin.terminal.WrappedRequest.BrowserDetails;
import com.vaadin.terminal.gwt.client.MouseEventDetails;
-import com.vaadin.terminal.gwt.client.ui.notification.VNotification;
import com.vaadin.terminal.gwt.client.ui.root.RootServerRpc;
import com.vaadin.terminal.gwt.client.ui.root.RootState;
import com.vaadin.terminal.gwt.client.ui.root.VRoot;
-import com.vaadin.tools.ReflectTools;
import com.vaadin.ui.Window.CloseListener;
/**
@@ -79,121 +76,6 @@ public abstract class Root extends AbstractComponentContainer implements
Action.Container, Action.Notifier, Vaadin6Component {
/**
- * Listener that gets notified when the size of the browser window
- * containing the root has changed.
- *
- * @see Root#addListener(BrowserWindowResizeListener)
- */
- public interface BrowserWindowResizeListener extends Serializable {
- /**
- * Invoked when the browser window containing a Root has been resized.
- *
- * @param event
- * a browser window resize event
- */
- public void browserWindowResized(BrowserWindowResizeEvent event);
- }
-
- /**
- * Event that is fired when a browser window containing a root is resized.
- */
- public class BrowserWindowResizeEvent extends Component.Event {
-
- private final int width;
- private final int height;
-
- /**
- * Creates a new event
- *
- * @param source
- * the root for which the browser window has been resized
- * @param width
- * the new width of the browser window
- * @param height
- * the new height of the browser window
- */
- public BrowserWindowResizeEvent(Root source, int width, int height) {
- super(source);
- this.width = width;
- this.height = height;
- }
-
- @Override
- public Root getSource() {
- return (Root) super.getSource();
- }
-
- /**
- * Gets the new browser window height
- *
- * @return an integer with the new pixel height of the browser window
- */
- public int getHeight() {
- return height;
- }
-
- /**
- * Gets the new browser window width
- *
- * @return an integer with the new pixel width of the browser window
- */
- public int getWidth() {
- return width;
- }
- }
-
- private static final Method BROWSWER_RESIZE_METHOD = ReflectTools
- .findMethod(BrowserWindowResizeListener.class,
- "browserWindowResized", BrowserWindowResizeEvent.class);
-
- /**
- * Listener that listens changes in URI fragment.
- */
- public interface FragmentChangedListener extends Serializable {
- public void fragmentChanged(FragmentChangedEvent event);
- }
-
- /**
- * Event fired when uri fragment changes.
- */
- public class FragmentChangedEvent extends Component.Event {
-
- /**
- * The new uri fragment
- */
- private final String fragment;
-
- /**
- * Creates a new instance of UriFragmentReader change event.
- *
- * @param source
- * the Source of the event.
- */
- public FragmentChangedEvent(Root source, String fragment) {
- super(source);
- this.fragment = fragment;
- }
-
- /**
- * Gets the root in which the fragment has changed.
- *
- * @return the root in which the fragment has changed
- */
- public Root getRoot() {
- return (Root) getComponent();
- }
-
- /**
- * Get the new fragment
- *
- * @return the new fragment
- */
- public String getFragment() {
- return fragment;
- }
- }
-
- /**
* Helper class to emulate the main window from Vaadin 6 using roots. 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}
@@ -312,55 +194,337 @@ public abstract class Root extends AbstractComponentContainer implements
"Internal problem getting window URL, please report");
}
}
- }
- private static final Method FRAGMENT_CHANGED_METHOD;
-
- static {
- try {
- FRAGMENT_CHANGED_METHOD = FragmentChangedListener.class
- .getDeclaredMethod("fragmentChanged",
- new Class[] { FragmentChangedEvent.class });
- } catch (final java.lang.NoSuchMethodException e) {
- // This should never happen
- throw new java.lang.RuntimeException(
- "Internal error finding methods in FragmentChangedListener");
+ /**
+ * 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 root
+ *
+ * @deprecated As of 7.0, use getPage().open instead
+ */
+ @Deprecated
+ public void open(Resource resource) {
+ getPage().open(resource);
}
- }
- /**
- * A border style used for opening resources in a window without a border.
- */
- public static final int BORDER_NONE = 0;
+ /* ********************************************************************* */
- /**
- * A border style used for opening resources in a window with a minimal
- * border.
- */
- public static final int BORDER_MINIMAL = 1;
+ /**
+ * Opens the given resource in a window with the given name.
+ * <p>
+ * The supplied {@code windowName} is used as the target name in a
+ * window.open call in the client. This means that special values such
+ * as "_blank", "_self", "_top", "_parent" have special meaning. An
+ * empty or <code>null</code> window name is also a special case.
+ * </p>
+ * <p>
+ * "", null and "_self" as {@code windowName} all causes the resource to
+ * be opened in the current window, replacing any old contents. For
+ * downloadable content you should avoid "_self" as "_self" causes the
+ * client to skip rendering of any other changes as it considers them
+ * irrelevant (the page will be replaced by the resource). This can
+ * speed up the opening of a resource, but it might also put the client
+ * side into an inconsistent state if the window content is not
+ * completely replaced e.g., if the resource is downloaded instead of
+ * displayed in the browser.
+ * </p>
+ * <p>
+ * "_blank" as {@code windowName} causes the resource to always be
+ * opened in a new window or tab (depends on the browser and browser
+ * settings).
+ * </p>
+ * <p>
+ * "_top" and "_parent" as {@code windowName} works as specified by the
+ * HTML standard.
+ * </p>
+ * <p>
+ * Any other {@code windowName} will open the resource in a window with
+ * that name, either by opening a new window/tab in the browser or by
+ * replacing the contents of an existing window with that name.
+ * </p>
+ *
+ * @param resource
+ * the resource.
+ * @param windowName
+ * the name of the window.
+ * @deprecated As of 7.0, use getPage().open instead
+ */
+ @Deprecated
+ public void open(Resource resource, String windowName) {
+ getPage().open(resource, windowName);
+ }
- /**
- * A border style that indicates that the default border style should be
- * used when opening resources.
- */
- public static final int BORDER_DEFAULT = 2;
+ /**
+ * Opens the given resource in a window with the given size, border and
+ * name. For more information on the meaning of {@code windowName}, see
+ * {@link #open(Resource, String)}.
+ *
+ * @param resource
+ * the resource.
+ * @param windowName
+ * the name of the window.
+ * @param width
+ * the width of the window in pixels
+ * @param height
+ * the height of the window in pixels
+ * @param border
+ * the border style of the window. See {@link #BORDER_NONE
+ * Window.BORDER_* constants}
+ * @deprecated As of 7.0, use getPage().open instead
+ */
+ @Deprecated
+ public void open(Resource resource, String windowName, int width,
+ int height, int border) {
+ getPage().open(resource, windowName, width, height, border);
+ }
- /**
- * The application to which this root belongs
- */
- private Application application;
+ /**
+ * Adds a new {@link BrowserWindowResizeListener} to this root. The
+ * listener will be notified whenever the browser window within which
+ * this root resides is resized.
+ *
+ * @param resizeListener
+ * the listener to add
+ *
+ * @see BrowserWindowResizeListener#browserWindowResized(BrowserWindowResizeEvent)
+ * @see #setResizeLazy(boolean)
+ *
+ * @deprecated As of 7.0, use the similarly named api in Page instead
+ */
+ @Deprecated
+ public void addListener(BrowserWindowResizeListener resizeListener) {
+ getPage().addListener(resizeListener);
+ }
- /**
- * A list of notifications that are waiting to be sent to the client.
- * Cleared (set to null) when the notifications have been sent.
- */
- private List<Notification> notifications;
+ /**
+ * Removes a {@link BrowserWindowResizeListener} from this root. The
+ * listener will no longer be notified when the browser window is
+ * resized.
+ *
+ * @param resizeListener
+ * the listener to remove
+ * @deprecated As of 7.0, use the similarly named api in Page instead
+ */
+ @Deprecated
+ public void removeListener(BrowserWindowResizeListener resizeListener) {
+ getPage().removeListener(resizeListener);
+ }
+
+ /**
+ * Gets the last known height of the browser window in which this root
+ * resides.
+ *
+ * @return the browser window height in pixels
+ * @deprecated As of 7.0, use the similarly named api in Page instead
+ */
+ @Deprecated
+ public int getBrowserWindowHeight() {
+ return getPage().getBrowserWindowHeight();
+ }
+
+ /**
+ * Gets the last known width of the browser window in which this root
+ * resides.
+ *
+ * @return the browser window width in pixels
+ *
+ * @deprecated As of 7.0, use the similarly named api in Page instead
+ */
+ @Deprecated
+ public int getBrowserWindowWidth() {
+ return getPage().getBrowserWindowWidth();
+ }
+
+ /**
+ * 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(Notification)
+ * @see Notification
+ *
+ * @param caption
+ * The message
+ *
+ * @deprecated As of 7.0, use Notification.show instead
+ */
+ @Deprecated
+ public void showNotification(String caption) {
+ getPage().showNotification(new Notification(caption));
+ }
+
+ /**
+ * 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(Notification)
+ * @see Notification
+ *
+ * @param caption
+ * The message
+ * @param type
+ * The message type
+ *
+ * @deprecated As of 7.0, use Notification.show instead
+ */
+ @Deprecated
+ public void showNotification(String caption, int type) {
+ getPage().showNotification(new Notification(caption, type));
+ }
+
+ /**
+ * Shows a notification consisting of a bigger caption and a smaller
+ * 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(Notification)
+ * @see Notification
+ *
+ * @param caption
+ * The caption of the message
+ * @param description
+ * The message description
+ *
+ * @deprecated As of 7.0, use Notification.show instead
+ */
+ @Deprecated
+ public void showNotification(String caption, String description) {
+ getPage().showNotification(new Notification(caption, description));
+ }
+
+ /**
+ * 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 Notification.show instead
+ */
+ @Deprecated
+ public void showNotification(String caption, String description,
+ int type) {
+ getPage().showNotification(
+ new Notification(caption, description, type));
+ }
+
+ /**
+ * 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 Notification.show instead
+ */
+ @Deprecated
+ public void showNotification(String caption, String description,
+ int 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);
+ }
+
+ /**
+ * Executes JavaScript in this window.
+ *
+ * <p>
+ * This method allows one to inject javascript from the server to
+ * client. A client implementation is not required to implement this
+ * functionality, but currently all web-based clients do implement this.
+ * </p>
+ *
+ * <p>
+ * Executing javascript this way often leads to cross-browser
+ * compatibility issues and regressions that are hard to resolve. Use of
+ * this method should be avoided and instead it is recommended to create
+ * new widgets with GWT. For more info on creating own, reusable
+ * client-side widgets in Java, read the corresponding chapter in Book
+ * of Vaadin.
+ * </p>
+ *
+ * @param script
+ * JavaScript snippet that will be executed.
+ *
+ * @deprecated as of 7.0, use JavaScript.getCurrent().execute(String)
+ * instead
+ */
+ @Deprecated
+ public void executeJavaScript(String script) {
+ getPage().getJavaScript().execute(script);
+ }
+
+ @Override
+ public void setCaption(String caption) {
+ // Override to provide backwards compatibility
+ getState().setCaption(caption);
+ getPage().setTitle(caption);
+ }
+
+ }
/**
- * A list of javascript commands that are waiting to be sent to the client.
- * Cleared (set to null) when the commands have been sent.
+ * The application to which this root belongs
*/
- private List<String> jsExecQueue = null;
+ private Application application;
/**
* List of windows in this root.
@@ -368,12 +532,6 @@ public abstract class Root extends AbstractComponentContainer implements
private final LinkedHashSet<Window> windows = new LinkedHashSet<Window>();
/**
- * Resources to be opened automatically on next repaint. The list is
- * automatically cleared when it has been sent to the client.
- */
- private final LinkedList<OpenResource> openList = new LinkedList<OpenResource>();
-
- /**
* The component that should be scrolled into view after the next repaint.
* Null if nothing should be scrolled into view.
*/
@@ -399,16 +557,13 @@ public abstract class Root extends AbstractComponentContainer implements
*/
private static final ThreadLocal<Root> currentRoot = new ThreadLocal<Root>();
- private int browserWindowWidth = -1;
- private int browserWindowHeight = -1;
-
/** Identifies the click event */
private static final String CLICK_EVENT_ID = VRoot.CLICK_EVENT_ID;
private DirtyConnectorTracker dirtyConnectorTracker = new DirtyConnectorTracker(
this);
- private JavascriptManager javascriptManager;
+ private Page page = new Page(this);
private RootServerRpc rpc = new RootServerRpc() {
public void click(MouseEventDetails mouseDetails) {
@@ -504,68 +659,7 @@ public abstract class Root extends AbstractComponentContainer implements
}
public void paintContent(PaintTarget target) throws PaintException {
- // Open requested resource
- synchronized (openList) {
- if (!openList.isEmpty()) {
- for (final Iterator<OpenResource> i = openList.iterator(); i
- .hasNext();) {
- (i.next()).paintContent(target);
- }
- openList.clear();
- }
- }
-
- // Paint notifications
- if (notifications != null) {
- target.startTag("notifications");
- for (final Iterator<Notification> it = notifications.iterator(); it
- .hasNext();) {
- final Notification n = it.next();
- target.startTag("notification");
- if (n.getCaption() != null) {
- target.addAttribute(
- VNotification.ATTRIBUTE_NOTIFICATION_CAPTION,
- n.getCaption());
- }
- if (n.getDescription() != null) {
- target.addAttribute(
- VNotification.ATTRIBUTE_NOTIFICATION_MESSAGE,
- n.getDescription());
- }
- if (n.getIcon() != null) {
- target.addAttribute(
- VNotification.ATTRIBUTE_NOTIFICATION_ICON,
- n.getIcon());
- }
- if (!n.isHtmlContentAllowed()) {
- target.addAttribute(
- VRoot.NOTIFICATION_HTML_CONTENT_NOT_ALLOWED, true);
- }
- target.addAttribute(
- VNotification.ATTRIBUTE_NOTIFICATION_POSITION,
- n.getPosition());
- target.addAttribute(VNotification.ATTRIBUTE_NOTIFICATION_DELAY,
- n.getDelayMsec());
- if (n.getStyleName() != null) {
- target.addAttribute(
- VNotification.ATTRIBUTE_NOTIFICATION_STYLE,
- n.getStyleName());
- }
- target.endTag("notification");
- }
- target.endTag("notifications");
- notifications = null;
- }
-
- // Add executable javascripts if needed
- if (jsExecQueue != null) {
- for (String script : jsExecQueue) {
- target.startTag("execJS");
- target.addAttribute("script", script);
- target.endTag("execJS");
- }
- jsExecQueue = null;
- }
+ page.paintContent(target);
if (scrollIntoView != null) {
target.addAttribute("scrollTo", scrollIntoView);
@@ -586,10 +680,6 @@ public abstract class Root extends AbstractComponentContainer implements
actionManager.paintActions(null, target);
}
- if (fragment != null) {
- target.addAttribute(VRoot.FRAGMENT_VARIABLE, fragment);
- }
-
if (isResizeLazy()) {
target.addAttribute(VRoot.RESIZE_LAZY, true);
}
@@ -620,23 +710,14 @@ public abstract class Root extends AbstractComponentContainer implements
if (variables.containsKey(VRoot.FRAGMENT_VARIABLE)) {
String fragment = (String) variables.get(VRoot.FRAGMENT_VARIABLE);
- setFragment(fragment, true);
+ getPage().setFragment(fragment, true);
}
- boolean sendResizeEvent = false;
- if (variables.containsKey("height")) {
- browserWindowHeight = ((Integer) variables.get("height"))
- .intValue();
- sendResizeEvent = true;
- }
- if (variables.containsKey("width")) {
- browserWindowWidth = ((Integer) variables.get("width")).intValue();
- sendResizeEvent = true;
- }
- if (sendResizeEvent) {
- fireEvent(new BrowserWindowResizeEvent(this, browserWindowWidth,
- browserWindowHeight));
+ if (variables.containsKey("height") || variables.containsKey("width")) {
+ getPage().setBrowserWindowSize((Integer) variables.get("width"),
+ (Integer) variables.get("height"));
}
+
}
/*
@@ -817,11 +898,6 @@ public abstract class Root extends AbstractComponentContainer implements
*/
private Focusable pendingFocus;
- /**
- * The current URI fragment.
- */
- private String fragment;
-
private boolean resizeLazy = false;
/**
@@ -843,175 +919,6 @@ public abstract class Root extends AbstractComponentContainer implements
}
/**
- * 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(Notification)
- * @see Notification
- *
- * @param caption
- * The message
- */
- public void showNotification(String caption) {
- addNotification(new Notification(caption));
- }
-
- /**
- * 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(Notification)
- * @see Notification
- *
- * @param caption
- * The message
- * @param type
- * The message type
- */
- public void showNotification(String caption, int type) {
- addNotification(new Notification(caption, type));
- }
-
- /**
- * Shows a notification consisting of a bigger caption and a smaller
- * 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(Notification)
- * @see Notification
- *
- * @param caption
- * The caption of the message
- * @param description
- * The message description
- *
- */
- public void showNotification(String caption, String description) {
- addNotification(new Notification(caption, description));
- }
-
- /**
- * 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
- */
- public void showNotification(String caption, String description, int type) {
- addNotification(new Notification(caption, description, type));
- }
-
- /**
- * 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
- */
- public void showNotification(String caption, String description, int type,
- boolean htmlContentAllowed) {
- addNotification(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
- */
- public void showNotification(Notification notification) {
- 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>();
- }
- notifications.add(notification);
- requestRepaint();
- }
-
- /**
- * Executes JavaScript in this root.
- *
- * <p>
- * This method allows one to inject javascript from the server to client. A
- * client implementation is not required to implement this functionality,
- * but currently all web-based clients do implement this.
- * </p>
- *
- * <p>
- * Executing javascript this way often leads to cross-browser compatibility
- * issues and regressions that are hard to resolve. Use of this method
- * should be avoided and instead it is recommended to create new widgets
- * with GWT. For more info on creating own, reusable client-side widgets in
- * Java, read the corresponding chapter in Book of Vaadin.
- * </p>
- *
- * @param script
- * JavaScript snippet that will be executed.
- */
- public void executeJavaScript(String script) {
- if (jsExecQueue == null) {
- jsExecQueue = new ArrayList<String>();
- }
-
- jsExecQueue.add(script);
-
- requestRepaint();
- }
-
- /**
* 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.
@@ -1125,10 +1032,7 @@ public abstract class Root extends AbstractComponentContainer implements
* the initialization request
*/
public void doInit(WrappedRequest request) {
- BrowserDetails browserDetails = request.getBrowserDetails();
- if (browserDetails != null) {
- fragment = browserDetails.getUriFragment();
- }
+ getPage().init(request);
// Call the init overridden by the application developer
init(request);
@@ -1187,186 +1091,6 @@ public abstract class Root extends AbstractComponentContainer implements
return currentRoot.get();
}
- /**
- * 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 root
- */
- public void open(Resource resource) {
- synchronized (openList) {
- if (!openList.contains(resource)) {
- openList.add(new OpenResource(resource, null, -1, -1,
- BORDER_DEFAULT));
- }
- }
- requestRepaint();
- }
-
- /* ********************************************************************* */
-
- /**
- * Opens the given resource in a window with the given name.
- * <p>
- * The supplied {@code windowName} is used as the target name in a
- * window.open call in the client. This means that special values such as
- * "_blank", "_self", "_top", "_parent" have special meaning. An empty or
- * <code>null</code> window name is also a special case.
- * </p>
- * <p>
- * "", null and "_self" as {@code windowName} all causes the resource to be
- * opened in the current window, replacing any old contents. For
- * downloadable content you should avoid "_self" as "_self" causes the
- * client to skip rendering of any other changes as it considers them
- * irrelevant (the page will be replaced by the resource). This can speed up
- * the opening of a resource, but it might also put the client side into an
- * inconsistent state if the window content is not completely replaced e.g.,
- * if the resource is downloaded instead of displayed in the browser.
- * </p>
- * <p>
- * "_blank" as {@code windowName} causes the resource to always be opened in
- * a new window or tab (depends on the browser and browser settings).
- * </p>
- * <p>
- * "_top" and "_parent" as {@code windowName} works as specified by the HTML
- * standard.
- * </p>
- * <p>
- * Any other {@code windowName} will open the resource in a window with that
- * name, either by opening a new window/tab in the browser or by replacing
- * the contents of an existing window with that name.
- * </p>
- *
- * @param resource
- * the resource.
- * @param windowName
- * the name of the window.
- */
- public void open(Resource resource, String windowName) {
- synchronized (openList) {
- if (!openList.contains(resource)) {
- openList.add(new OpenResource(resource, windowName, -1, -1,
- BORDER_DEFAULT));
- }
- }
- requestRepaint();
- }
-
- /**
- * Opens the given resource in a window with the given size, border and
- * name. For more information on the meaning of {@code windowName}, see
- * {@link #open(Resource, String)}.
- *
- * @param resource
- * the resource.
- * @param windowName
- * the name of the window.
- * @param width
- * the width of the window in pixels
- * @param height
- * the height of the window in pixels
- * @param border
- * the border style of the window. See {@link #BORDER_NONE
- * Window.BORDER_* constants}
- */
- public void open(Resource resource, String windowName, int width,
- int height, int border) {
- synchronized (openList) {
- if (!openList.contains(resource)) {
- openList.add(new OpenResource(resource, windowName, width,
- height, border));
- }
- }
- requestRepaint();
- }
-
- /**
- * Private class for storing properties related to opening resources.
- */
- private class OpenResource implements Serializable {
-
- /**
- * The resource to open
- */
- private final Resource resource;
-
- /**
- * The name of the target window
- */
- private final String name;
-
- /**
- * The width of the target window
- */
- private final int width;
-
- /**
- * The height of the target window
- */
- private final int height;
-
- /**
- * The border style of the target window
- */
- private final int border;
-
- /**
- * Creates a new open resource.
- *
- * @param resource
- * The resource to open
- * @param name
- * The name of the target window
- * @param width
- * The width of the target window
- * @param height
- * The height of the target window
- * @param border
- * The border style of the target window
- */
- private OpenResource(Resource resource, String name, int width,
- int height, int border) {
- this.resource = resource;
- this.name = name;
- this.width = width;
- this.height = height;
- this.border = border;
- }
-
- /**
- * Paints the open request. Should be painted inside the window.
- *
- * @param target
- * the paint target
- * @throws PaintException
- * if the paint operation fails
- */
- private void paintContent(PaintTarget target) throws PaintException {
- target.startTag("open");
- target.addAttribute("src", resource);
- if (name != null && name.length() > 0) {
- target.addAttribute("name", name);
- }
- if (width >= 0) {
- target.addAttribute("width", width);
- }
- if (height >= 0) {
- target.addAttribute("height", height);
- }
- switch (border) {
- case BORDER_MINIMAL:
- target.addAttribute("border", "minimal");
- break;
- case BORDER_NONE:
- target.addAttribute("border", "none");
- break;
- }
-
- target.endTag("open");
- }
- }
-
public void setScrollTop(int scrollTop) {
throw new RuntimeException("Not yet implemented");
}
@@ -1454,110 +1178,6 @@ public abstract class Root extends AbstractComponentContainer implements
removeListener(CLICK_EVENT_ID, ClickEvent.class, listener);
}
- public void addListener(FragmentChangedListener listener) {
- addListener(FragmentChangedEvent.class, listener,
- FRAGMENT_CHANGED_METHOD);
- }
-
- public void removeListener(FragmentChangedListener listener) {
- removeListener(FragmentChangedEvent.class, listener,
- FRAGMENT_CHANGED_METHOD);
- }
-
- /**
- * Sets URI fragment. Optionally fires a {@link FragmentChangedEvent}
- *
- * @param newFragment
- * id of the new fragment
- * @param fireEvent
- * true to fire event
- * @see FragmentChangedEvent
- * @see FragmentChangedListener
- */
- public void setFragment(String newFragment, boolean fireEvents) {
- if (newFragment == null) {
- throw new NullPointerException("The fragment may not be null");
- }
- if (!newFragment.equals(fragment)) {
- fragment = newFragment;
- if (fireEvents) {
- fireEvent(new FragmentChangedEvent(this, newFragment));
- }
- requestRepaint();
- }
- }
-
- /**
- * Sets URI fragment. This method fires a {@link FragmentChangedEvent}
- *
- * @param newFragment
- * id of the new fragment
- * @see FragmentChangedEvent
- * @see FragmentChangedListener
- */
- public void setFragment(String newFragment) {
- setFragment(newFragment, true);
- }
-
- /**
- * Gets currently set URI fragment.
- * <p>
- * To listen changes in fragment, hook a {@link FragmentChangedListener}.
- *
- * @return the current fragment in browser uri or null if not known
- */
- public String getFragment() {
- return fragment;
- }
-
- /**
- * Adds a new {@link BrowserWindowResizeListener} to this root. The listener
- * will be notified whenever the browser window within which this root
- * resides is resized.
- *
- * @param resizeListener
- * the listener to add
- *
- * @see BrowserWindowResizeListener#browserWindowResized(BrowserWindowResizeEvent)
- * @see #setResizeLazy(boolean)
- */
- public void addListener(BrowserWindowResizeListener resizeListener) {
- addListener(BrowserWindowResizeEvent.class, resizeListener,
- BROWSWER_RESIZE_METHOD);
- }
-
- /**
- * Removes a {@link BrowserWindowResizeListener} from this root. The
- * listener will no longer be notified when the browser window is resized.
- *
- * @param resizeListener
- * the listener to remove
- */
- public void removeListener(BrowserWindowResizeListener resizeListener) {
- removeListener(BrowserWindowResizeEvent.class, resizeListener,
- BROWSWER_RESIZE_METHOD);
- }
-
- /**
- * Gets the last known height of the browser window in which this root
- * resides.
- *
- * @return the browser window height in pixels
- */
- public int getBrowserWindowHeight() {
- return browserWindowHeight;
- }
-
- /**
- * Gets the last known width of the browser window in which this root
- * resides.
- *
- * @return the browser window width in pixels
- */
- public int getBrowserWindowWidth() {
- return browserWindowWidth;
- }
-
/**
* Notifies the child components and windows that the root is attached to
* the application.
@@ -1592,14 +1212,21 @@ public abstract class Root extends AbstractComponentContainer implements
return dirtyConnectorTracker;
}
- public JavascriptManager getJavascriptManager() {
- if (javascriptManager == null) {
- // Create and attach on first use
- javascriptManager = new JavascriptManager();
- addExtension(javascriptManager);
- }
+ public Page getPage() {
+ return page;
+ }
- return javascriptManager;
+ /**
+ * Setting the caption of a Root 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)}
+ */
+ @Override
+ @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");
}
}
diff --git a/src/com/vaadin/ui/TabSheet.java b/src/com/vaadin/ui/TabSheet.java
index 23dee15359..061809de67 100644
--- a/src/com/vaadin/ui/TabSheet.java
+++ b/src/com/vaadin/ui/TabSheet.java
@@ -108,6 +108,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
setWidth(100, UNITS_PERCENTAGE);
setImmediate(true);
setCloseHandler(new CloseHandler() {
+
public void onTabClose(TabSheet tabsheet, Component c) {
tabsheet.removeComponent(c);
}
@@ -120,6 +121,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
*
* @return the unmodifiable Iterator of the tab content components
*/
+
public Iterator<Component> getComponentIterator() {
return Collections.unmodifiableList(components).iterator();
}
@@ -130,6 +132,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
*
* @return the number of contained components
*/
+
public int getComponentCount() {
return components.size();
}
@@ -143,6 +146,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
* @param c
* the component to be removed.
*/
+
@Override
public void removeComponent(Component c) {
if (c != null && components.contains(c)) {
@@ -193,6 +197,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
* @param c
* the component to be added.
*/
+
@Override
public void addComponent(Component c) {
addTab(c);
@@ -334,6 +339,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
* @param source
* the container components are removed from.
*/
+
@Override
public void moveComponentsFrom(ComponentContainer source) {
for (final Iterator<Component> i = source.getComponentIterator(); i
@@ -359,6 +365,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
* @throws PaintException
* if the paint operation failed.
*/
+
public void paintContent(PaintTarget target) throws PaintException {
if (areTabsHidden()) {
@@ -683,6 +690,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
}
// inherits javadoc
+
public void changeVariables(Object source, Map<String, Object> variables) {
if (variables.containsKey("selected")) {
setSelectedTab(keyMapper.get((String) variables.get("selected")));
@@ -719,6 +727,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
*
* {@inheritDoc}
*/
+
public void replaceComponent(Component oldComponent, Component newComponent) {
if (selected == oldComponent) {
@@ -729,25 +738,6 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
Tab newTab = tabs.get(newComponent);
Tab oldTab = tabs.get(oldComponent);
- // Gets the captions
- String oldCaption = null;
- Resource oldIcon = null;
- String newCaption = null;
- Resource newIcon = null;
-
- if (oldTab != null) {
- oldCaption = oldTab.getCaption();
- oldIcon = oldTab.getIcon();
- }
-
- if (newTab != null) {
- newCaption = newTab.getCaption();
- newIcon = newTab.getIcon();
- } else {
- newCaption = newComponent.getCaption();
- newIcon = newComponent.getIcon();
- }
-
// Gets the locations
int oldLocation = -1;
int newLocation = -1;
@@ -769,35 +759,21 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
addComponent(newComponent);
} else if (newLocation == -1) {
removeComponent(oldComponent);
- keyMapper.remove(oldComponent);
- newTab = addTab(newComponent);
- components.remove(newComponent);
- components.add(oldLocation, newComponent);
- newTab.setCaption(oldCaption);
- newTab.setIcon(oldIcon);
+ newTab = addTab(newComponent, oldLocation);
+ // Copy all relevant metadata to the new tab (#8793)
+ // TODO Should reuse the old tab instance instead?
+ copyTabMetadata(oldTab, newTab);
} else {
- if (oldLocation > newLocation) {
- components.remove(oldComponent);
- components.add(newLocation, oldComponent);
- components.remove(newComponent);
- components.add(oldLocation, newComponent);
- } else {
- components.remove(newComponent);
- components.add(oldLocation, newComponent);
- components.remove(oldComponent);
- components.add(newLocation, oldComponent);
- }
+ components.set(oldLocation, newComponent);
+ components.set(newLocation, oldComponent);
- if (newTab != null) {
- // This should always be true
- newTab.setCaption(oldCaption);
- newTab.setIcon(oldIcon);
- }
- if (oldTab != null) {
- // This should always be true
- oldTab.setCaption(newCaption);
- oldTab.setIcon(newIcon);
- }
+ // Tab associations are not changed, but metadata is swapped between
+ // the instances
+ // TODO Should reassociate the instances instead?
+ Tab tmp = new TabSheetTabImpl(null, null);
+ copyTabMetadata(newTab, tmp);
+ copyTabMetadata(oldTab, newTab);
+ copyTabMetadata(tmp, oldTab);
requestRepaint();
}
@@ -1106,6 +1082,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
/**
* Returns the tab caption. Can never be null.
*/
+
public String getCaption() {
return caption;
}
@@ -1300,4 +1277,23 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
public boolean isComponentVisible(Component childComponent) {
return childComponent == getSelectedTab();
}
+
+ /**
+ * Copies properties from one Tab to another.
+ *
+ * @param from
+ * The tab whose data to copy.
+ * @param to
+ * The tab to which copy the data.
+ */
+ private static void copyTabMetadata(Tab from, Tab to) {
+ to.setCaption(from.getCaption());
+ to.setIcon(from.getIcon());
+ to.setDescription(from.getDescription());
+ to.setVisible(from.isVisible());
+ to.setEnabled(from.isEnabled());
+ to.setClosable(from.isClosable());
+ to.setStyleName(from.getStyleName());
+ to.setComponentError(from.getComponentError());
+ }
}
diff --git a/src/com/vaadin/ui/Table.java b/src/com/vaadin/ui/Table.java
index fc736bfa93..5d4f919704 100644
--- a/src/com/vaadin/ui/Table.java
+++ b/src/com/vaadin/ui/Table.java
@@ -39,7 +39,6 @@ import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.DragSource;
import com.vaadin.event.dd.DropHandler;
import com.vaadin.event.dd.DropTarget;
-import com.vaadin.event.dd.acceptcriteria.ClientCriterion;
import com.vaadin.event.dd.acceptcriteria.ServerSideCriterion;
import com.vaadin.terminal.KeyMapper;
import com.vaadin.terminal.LegacyPaint;
@@ -47,7 +46,6 @@ import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.terminal.Resource;
import com.vaadin.terminal.gwt.client.MouseEventDetails;
-import com.vaadin.terminal.gwt.client.ui.dd.VLazyInitItemIdentifiers;
import com.vaadin.terminal.gwt.client.ui.table.VScrollTable;
/**
@@ -78,8 +76,7 @@ public class Table extends AbstractSelect implements Action.Container,
Container.Ordered, Container.Sortable, ItemClickNotifier, DragSource,
DropTarget, HasComponents {
- private static final Logger logger = Logger
- .getLogger(Table.class.getName());
+ private transient Logger logger = null;
/**
* Modes that Table support as drag sourse.
@@ -331,7 +328,8 @@ public class Table extends AbstractSelect implements Action.Container,
private static final double CACHE_RATE_DEFAULT = 2;
private static final String ROW_HEADER_COLUMN_KEY = "0";
- private static final Object ROW_HEADER_FAKE_PROPERTY_ID = new Object();
+ private static final Object ROW_HEADER_FAKE_PROPERTY_ID = new UniqueSerializable() {
+ };
/* Private table extensions to Select */
@@ -356,6 +354,11 @@ public class Table extends AbstractSelect implements Action.Container,
private LinkedList<Object> visibleColumns = new LinkedList<Object>();
/**
+ * Holds noncollapsible columns.
+ */
+ private HashSet<Object> noncollapsibleColumns = new HashSet<Object>();
+
+ /**
* Holds propertyIds of currently collapsed columns.
*/
private final HashSet<Object> collapsedColumns = new HashSet<Object>();
@@ -1248,6 +1251,9 @@ public class Table extends AbstractSelect implements Action.Container,
if (!isColumnCollapsingAllowed()) {
throw new IllegalStateException("Column collapsing not allowed!");
}
+ if (collapsed && noncollapsibleColumns.contains(propertyId)) {
+ throw new IllegalStateException("The column is noncollapsible!");
+ }
if (collapsed) {
collapsedColumns.add(propertyId);
@@ -1287,6 +1293,41 @@ public class Table extends AbstractSelect implements Action.Container,
}
/**
+ * Sets whether the given column is collapsible. Note that collapsible
+ * columns can only be actually collapsed (via UI or with
+ * {@link #setColumnCollapsed(Object, boolean) setColumnCollapsed()}) if
+ * {@link #isColumnCollapsingAllowed()} is true. By default all columns are
+ * collapsible.
+ *
+ * @param propertyId
+ * the propertyID identifying the column.
+ * @param collapsible
+ * true if the column should be collapsible, false otherwise.
+ */
+ public void setColumnCollapsible(Object propertyId, boolean collapsible) {
+ if (collapsible) {
+ noncollapsibleColumns.remove(propertyId);
+ } else {
+ noncollapsibleColumns.add(propertyId);
+ collapsedColumns.remove(propertyId);
+ }
+ refreshRowCache();
+ }
+
+ /**
+ * Checks if the given column is collapsible. Note that even if this method
+ * returns <code>true</code>, the column can only be actually collapsed (via
+ * UI or with {@link #setColumnCollapsed(Object, boolean)
+ * setColumnCollapsed()}) if {@link #isColumnCollapsingAllowed()} is also
+ * true.
+ *
+ * @return true if the column can be collapsed; false otherwise.
+ */
+ public boolean isColumnCollapsible(Object propertyId) {
+ return !noncollapsibleColumns.contains(propertyId);
+ }
+
+ /**
* Checks if column reordering is allowed.
*
* @return true if columns can be reordered; false otherwise.
@@ -1569,6 +1610,13 @@ public class Table extends AbstractSelect implements Action.Container,
}
} else {
// initial load
+
+ // #8805 send one extra row in the beginning in case a partial
+ // row is shown on the UI
+ if (firstIndex > 0) {
+ firstIndex = firstIndex - 1;
+ rows = rows + 1;
+ }
firstToBeRenderedInClient = firstIndex;
}
if (totalRows > 0) {
@@ -1597,6 +1645,7 @@ public class Table extends AbstractSelect implements Action.Container,
* this method has been called. See {@link #refreshRowCache()} for forcing
* an update of the contents.
*/
+
@Override
public void requestRepaint() {
// Overridden only for javadoc
@@ -1714,8 +1763,9 @@ public class Table extends AbstractSelect implements Action.Container,
* @return
*/
private Object[][] getVisibleCellsInsertIntoCache(int firstIndex, int rows) {
- logger.finest("Insert " + rows + " rows at index " + firstIndex
- + " to existing page buffer requested");
+ getLogger().finest(
+ "Insert " + rows + " rows at index " + firstIndex
+ + " to existing page buffer requested");
// Page buffer must not become larger than pageLength*cacheRate before
// or after the current page
@@ -1818,11 +1868,14 @@ public class Table extends AbstractSelect implements Action.Container,
}
}
pageBuffer = newPageBuffer;
- logger.finest("Page Buffer now contains "
- + pageBuffer[CELL_ITEMID].length + " rows ("
- + pageBufferFirstIndex + "-"
- + (pageBufferFirstIndex + pageBuffer[CELL_ITEMID].length - 1)
- + ")");
+ getLogger().finest(
+ "Page Buffer now contains "
+ + pageBuffer[CELL_ITEMID].length
+ + " rows ("
+ + pageBufferFirstIndex
+ + "-"
+ + (pageBufferFirstIndex
+ + pageBuffer[CELL_ITEMID].length - 1) + ")");
return cells;
}
@@ -1839,8 +1892,9 @@ public class Table extends AbstractSelect implements Action.Container,
*/
private Object[][] getVisibleCellsNoCache(int firstIndex, int rows,
boolean replaceListeners) {
- logger.finest("Render visible cells for rows " + firstIndex + "-"
- + (firstIndex + rows - 1));
+ getLogger().finest(
+ "Render visible cells for rows " + firstIndex + "-"
+ + (firstIndex + rows - 1));
final Object[] colids = getVisibleColumns();
final int cols = colids.length;
@@ -2022,8 +2076,9 @@ public class Table extends AbstractSelect implements Action.Container,
}
protected void registerComponent(Component component) {
- logger.finest("Registered " + component.getClass().getSimpleName()
- + ": " + component.getCaption());
+ getLogger().finest(
+ "Registered " + component.getClass().getSimpleName() + ": "
+ + component.getCaption());
if (component.getParent() != this) {
component.setParent(this);
}
@@ -2054,8 +2109,9 @@ public class Table extends AbstractSelect implements Action.Container,
* @param count
*/
private void unregisterComponentsAndPropertiesInRows(int firstIx, int count) {
- logger.finest("Unregistering components in rows " + firstIx + "-"
- + (firstIx + count - 1));
+ getLogger().finest(
+ "Unregistering components in rows " + firstIx + "-"
+ + (firstIx + count - 1));
Object[] colids = getVisibleColumns();
if (pageBuffer != null && pageBuffer[CELL_ITEMID].length > 0) {
int bufSize = pageBuffer[CELL_ITEMID].length;
@@ -2135,8 +2191,9 @@ public class Table extends AbstractSelect implements Action.Container,
* a set of components that should be unregistered.
*/
protected void unregisterComponent(Component component) {
- logger.finest("Unregistered " + component.getClass().getSimpleName()
- + ": " + component.getCaption());
+ getLogger().finest(
+ "Unregistered " + component.getClass().getSimpleName() + ": "
+ + component.getCaption());
component.setParent(null);
/*
* Also remove property data sources to unregister listeners keeping the
@@ -2446,6 +2503,7 @@ public class Table extends AbstractSelect implements Action.Container,
* @see com.vaadin.ui.Select#changeVariables(java.lang.Object,
* java.util.Map)
*/
+
@Override
public void changeVariables(Object source, Map<String, Object> variables) {
@@ -2505,7 +2563,7 @@ public class Table extends AbstractSelect implements Action.Container,
.get("lastToBeRendered")).intValue();
} catch (Exception e) {
// FIXME: Handle exception
- logger.log(Level.FINER,
+ getLogger().log(Level.FINER,
"Could not parse the first and/or last rows.", e);
}
@@ -2525,8 +2583,9 @@ public class Table extends AbstractSelect implements Action.Container,
}
}
}
- logger.finest("Client wants rows " + reqFirstRowToPaint + "-"
- + (reqFirstRowToPaint + reqRowsToPaint - 1));
+ getLogger().finest(
+ "Client wants rows " + reqFirstRowToPaint + "-"
+ + (reqFirstRowToPaint + reqRowsToPaint - 1));
clientNeedsContentRefresh = true;
}
@@ -2572,7 +2631,7 @@ public class Table extends AbstractSelect implements Action.Container,
}
} catch (final Exception e) {
// FIXME: Handle exception
- logger.log(Level.FINER,
+ getLogger().log(Level.FINER,
"Could not determine column collapsing state", e);
}
clientNeedsContentRefresh = true;
@@ -2594,7 +2653,7 @@ public class Table extends AbstractSelect implements Action.Container,
}
} catch (final Exception e) {
// FIXME: Handle exception
- logger.log(Level.FINER,
+ getLogger().log(Level.FINER,
"Could not determine column reordering state", e);
}
clientNeedsContentRefresh = true;
@@ -2767,6 +2826,7 @@ public class Table extends AbstractSelect implements Action.Container,
* @see com.vaadin.ui.AbstractSelect#paintContent(com.vaadin.
* terminal.PaintTarget)
*/
+
@Override
public void paintContent(PaintTarget target) throws PaintException {
/*
@@ -2884,8 +2944,9 @@ public class Table extends AbstractSelect implements Action.Container,
target.startTag("prows");
if (!shouldHideAddedRows()) {
- logger.finest("Paint rows for add. Index: " + firstIx + ", count: "
- + count + ".");
+ getLogger().finest(
+ "Paint rows for add. Index: " + firstIx + ", count: "
+ + count + ".");
// Partial row additions bypass the normal caching mechanism.
Object[][] cells = getVisibleCellsInsertIntoCache(firstIx, count);
@@ -2908,8 +2969,9 @@ public class Table extends AbstractSelect implements Action.Container,
indexInRowbuffer, itemId);
}
} else {
- logger.finest("Paint rows for remove. Index: " + firstIx
- + ", count: " + count + ".");
+ getLogger().finest(
+ "Paint rows for remove. Index: " + firstIx + ", count: "
+ + count + ".");
removeRowsFromCacheAndFillBottom(firstIx, count);
target.addAttribute("hide", true);
}
@@ -3108,7 +3170,17 @@ public class Table extends AbstractSelect implements Action.Container,
}
}
target.addVariable(this, "collapsedcolumns", collapsedKeys);
+
+ final String[] noncollapsibleKeys = new String[noncollapsibleColumns
+ .size()];
+ nextColumn = 0;
+ for (Object colId : noncollapsibleColumns) {
+ noncollapsibleKeys[nextColumn++] = columnIdMap.key(colId);
+ }
+ target.addVariable(this, "noncollapsiblecolumns",
+ noncollapsibleKeys);
}
+
}
private void paintActions(PaintTarget target, final Set<Action> actionSet)
@@ -3613,6 +3685,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.event.Action.Container#addActionHandler(Action.Handler)
*/
+
public void addActionHandler(Action.Handler actionHandler) {
if (actionHandler != null) {
@@ -3639,6 +3712,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.event.Action.Container#removeActionHandler(Action.Handler)
*/
+
public void removeActionHandler(Action.Handler actionHandler) {
if (actionHandlers != null && actionHandlers.contains(actionHandler)) {
@@ -3678,6 +3752,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Property.ValueChangeListener#valueChange(Property.ValueChangeEvent)
*/
+
@Override
public void valueChange(Property.ValueChangeEvent event) {
if (event.getProperty() == this
@@ -3708,6 +3783,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.ui.Component#attach()
*/
+
@Override
public void attach() {
super.attach();
@@ -3720,6 +3796,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.ui.Component#detach()
*/
+
@Override
public void detach() {
super.detach();
@@ -3730,6 +3807,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container#removeAllItems()
*/
+
@Override
public boolean removeAllItems() {
currentPageFirstItemId = null;
@@ -3742,6 +3820,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container#removeItem(Object)
*/
+
@Override
public boolean removeItem(Object itemId) {
final Object nextItemId = nextItemId(itemId);
@@ -3760,6 +3839,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container#removeContainerProperty(Object)
*/
+
@Override
public boolean removeContainerProperty(Object propertyId)
throws UnsupportedOperationException {
@@ -3786,6 +3866,7 @@ public class Table extends AbstractSelect implements Action.Container,
* @see com.vaadin.data.Container#addContainerProperty(Object, Class,
* Object)
*/
+
@Override
public boolean addContainerProperty(Object propertyId, Class<?> type,
Object defaultValue) throws UnsupportedOperationException {
@@ -3941,6 +4022,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.ui.Select#getVisibleItemIds()
*/
+
@Override
public Collection<?> getVisibleItemIds() {
@@ -3964,6 +4046,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container.ItemSetChangeListener#containerItemSetChange(com.vaadin.data.Container.ItemSetChangeEvent)
*/
+
@Override
public void containerItemSetChange(Container.ItemSetChangeEvent event) {
super.containerItemSetChange(event);
@@ -3980,6 +4063,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container.PropertySetChangeListener#containerPropertySetChange(com.vaadin.data.Container.PropertySetChangeEvent)
*/
+
@Override
public void containerPropertySetChange(
Container.PropertySetChangeEvent event) {
@@ -4023,6 +4107,7 @@ public class Table extends AbstractSelect implements Action.Container,
* if set to true.
* @see com.vaadin.ui.Select#setNewItemsAllowed(boolean)
*/
+
@Override
public void setNewItemsAllowed(boolean allowNewOptions)
throws UnsupportedOperationException {
@@ -4036,6 +4121,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container.Ordered#nextItemId(java.lang.Object)
*/
+
public Object nextItemId(Object itemId) {
return ((Container.Ordered) items).nextItemId(itemId);
}
@@ -4046,6 +4132,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container.Ordered#prevItemId(java.lang.Object)
*/
+
public Object prevItemId(Object itemId) {
return ((Container.Ordered) items).prevItemId(itemId);
}
@@ -4055,6 +4142,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container.Ordered#firstItemId()
*/
+
public Object firstItemId() {
return ((Container.Ordered) items).firstItemId();
}
@@ -4064,6 +4152,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container.Ordered#lastItemId()
*/
+
public Object lastItemId() {
return ((Container.Ordered) items).lastItemId();
}
@@ -4074,6 +4163,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container.Ordered#isFirstId(java.lang.Object)
*/
+
public boolean isFirstId(Object itemId) {
return ((Container.Ordered) items).isFirstId(itemId);
}
@@ -4084,6 +4174,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container.Ordered#isLastId(java.lang.Object)
*/
+
public boolean isLastId(Object itemId) {
return ((Container.Ordered) items).isLastId(itemId);
}
@@ -4093,6 +4184,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container.Ordered#addItemAfter(java.lang.Object)
*/
+
public Object addItemAfter(Object previousItemId)
throws UnsupportedOperationException {
Object itemId = ((Container.Ordered) items)
@@ -4109,6 +4201,7 @@ public class Table extends AbstractSelect implements Action.Container,
* @see com.vaadin.data.Container.Ordered#addItemAfter(java.lang.Object,
* java.lang.Object)
*/
+
public Item addItemAfter(Object previousItemId, Object newItemId)
throws UnsupportedOperationException {
Item item = ((Container.Ordered) items).addItemAfter(previousItemId,
@@ -4201,6 +4294,7 @@ public class Table extends AbstractSelect implements Action.Container,
* boolean[])
*
*/
+
public void sort(Object[] propertyId, boolean[] ascending)
throws UnsupportedOperationException {
final Container c = getContainerDataSource();
@@ -4236,6 +4330,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container.Sortable#getSortableContainerPropertyIds()
*/
+
public Collection<?> getSortableContainerPropertyIds() {
final Container c = getContainerDataSource();
if (c instanceof Container.Sortable && !isSortDisabled()) {
@@ -4436,6 +4531,7 @@ public class Table extends AbstractSelect implements Action.Container,
}
// Identical to AbstractCompoenentContainer.setEnabled();
+
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
@@ -4560,7 +4656,6 @@ public class Table extends AbstractSelect implements Action.Container,
* initialized from server and no subsequent requests requests are needed
* during that drag and drop operation.
*/
- @ClientCriterion(VLazyInitItemIdentifiers.class)
public static abstract class TableDropCriterion extends ServerSideCriterion {
private Table table;
@@ -4574,6 +4669,7 @@ public class Table extends AbstractSelect implements Action.Container,
* com.vaadin.event.dd.acceptcriteria.ServerSideCriterion#getIdentifier
* ()
*/
+
@Override
protected String getIdentifier() {
return TableDropCriterion.class.getCanonicalName();
@@ -4605,6 +4701,7 @@ public class Table extends AbstractSelect implements Action.Container,
* com.vaadin.event.dd.acceptcriteria.AcceptCriterion#paintResponse(
* com.vaadin.terminal.PaintTarget)
*/
+
@Override
public void paintResponse(PaintTarget target) throws PaintException {
/*
@@ -5276,4 +5373,11 @@ public class Table extends AbstractSelect implements Action.Container,
public boolean isComponentVisible(Component childComponent) {
return true;
}
+
+ private final Logger getLogger() {
+ if (logger == null) {
+ logger = Logger.getLogger(Table.class.getName());
+ }
+ return logger;
+ }
}
diff --git a/src/com/vaadin/ui/Tree.java b/src/com/vaadin/ui/Tree.java
index db738fee58..dacb3a2027 100644
--- a/src/com/vaadin/ui/Tree.java
+++ b/src/com/vaadin/ui/Tree.java
@@ -34,7 +34,6 @@ import com.vaadin.event.dd.DragSource;
import com.vaadin.event.dd.DropHandler;
import com.vaadin.event.dd.DropTarget;
import com.vaadin.event.dd.TargetDetails;
-import com.vaadin.event.dd.acceptcriteria.ClientCriterion;
import com.vaadin.event.dd.acceptcriteria.ClientSideCriterion;
import com.vaadin.event.dd.acceptcriteria.ServerSideCriterion;
import com.vaadin.event.dd.acceptcriteria.TargetDetailIs;
@@ -43,8 +42,6 @@ import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.terminal.Resource;
import com.vaadin.terminal.gwt.client.MouseEventDetails;
-import com.vaadin.terminal.gwt.client.ui.dd.VLazyInitItemIdentifiers;
-import com.vaadin.terminal.gwt.client.ui.dd.VTargetInSubtree;
import com.vaadin.terminal.gwt.client.ui.dd.VerticalDropLocation;
import com.vaadin.terminal.gwt.client.ui.tree.TreeConnector;
import com.vaadin.terminal.gwt.client.ui.tree.VTree;
@@ -1396,7 +1393,6 @@ public class Tree extends AbstractSelect implements Container.Hierarchical,
* initialized from server and no subsequent requests requests are needed
* during that drag and drop operation.
*/
- @ClientCriterion(VLazyInitItemIdentifiers.class)
public static abstract class TreeDropCriterion extends ServerSideCriterion {
private Tree tree;
@@ -1513,7 +1509,6 @@ public class Tree extends AbstractSelect implements Container.Hierarchical,
* <p>
* The root items is also consider to be valid target.
*/
- @ClientCriterion(VTargetInSubtree.class)
public class TargetInSubtree extends ClientSideCriterion {
private Object rootId;
diff --git a/src/com/vaadin/ui/TreeTable.java b/src/com/vaadin/ui/TreeTable.java
index 9607add2c9..3294f6fab0 100644
--- a/src/com/vaadin/ui/TreeTable.java
+++ b/src/com/vaadin/ui/TreeTable.java
@@ -49,9 +49,6 @@ import com.vaadin.ui.Tree.ExpandListener;
@SuppressWarnings({ "serial" })
public class TreeTable extends Table implements Hierarchical {
- private static final Logger logger = Logger.getLogger(TreeTable.class
- .getName());
-
private interface ContainerStrategy extends Serializable {
public int size();
@@ -84,6 +81,7 @@ public class TreeTable extends Table implements Hierarchical {
* Consider adding getDepth to {@link Collapsible}, might help
* scalability with some container implementations.
*/
+
public int getDepth(Object itemId) {
int depth = 0;
Hierarchical hierarchicalContainer = getContainerDataSource();
@@ -222,9 +220,9 @@ public class TreeTable extends Table implements Hierarchical {
boolean removed = openItems.remove(itemId);
if (!removed) {
openItems.add(itemId);
- logger.finest("Item " + itemId + " is now expanded");
+ getLogger().finest("Item " + itemId + " is now expanded");
} else {
- logger.finest("Item " + itemId + " is now collapsed");
+ getLogger().finest("Item " + itemId + " is now collapsed");
}
clearPreorderCache();
}
@@ -789,4 +787,8 @@ public class TreeTable extends Table implements Hierarchical {
requestRepaint();
}
+ private static final Logger getLogger() {
+ return Logger.getLogger(TreeTable.class.getName());
+ }
+
}
diff --git a/src/com/vaadin/ui/UniqueSerializable.java b/src/com/vaadin/ui/UniqueSerializable.java
new file mode 100644
index 0000000000..828b285538
--- /dev/null
+++ b/src/com/vaadin/ui/UniqueSerializable.java
@@ -0,0 +1,30 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.ui;
+
+import java.io.Serializable;
+
+/**
+ * A base class for generating an unique object that is serializable.
+ * <p>
+ * This class is abstract but has no abstract methods to force users to create
+ * an anonymous inner class. Otherwise each instance will not be unique.
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0
+ *
+ */
+public abstract class UniqueSerializable implements Serializable {
+
+ @Override
+ public int hashCode() {
+ return getClass().hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return getClass() == obj.getClass();
+ }
+}
diff --git a/src/com/vaadin/ui/Window.java b/src/com/vaadin/ui/Window.java
index 3c17baf414..02556c9961 100644
--- a/src/com/vaadin/ui/Window.java
+++ b/src/com/vaadin/ui/Window.java
@@ -24,6 +24,7 @@ import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.terminal.Vaadin6Component;
import com.vaadin.terminal.gwt.client.MouseEventDetails;
+import com.vaadin.terminal.gwt.client.ui.root.VRoot;
import com.vaadin.terminal.gwt.client.ui.window.WindowServerRpc;
import com.vaadin.terminal.gwt.client.ui.window.WindowState;
@@ -83,6 +84,10 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
}
};
+ private int browserWindowWidth = -1;
+
+ private int browserWindowHeight = -1;
+
/**
* Creates a new unnamed window with a default layout.
*/
@@ -119,6 +124,7 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
*
* @see com.vaadin.ui.Panel#addComponent(com.vaadin.ui.Component)
*/
+
@Override
public void addComponent(Component c) {
if (c instanceof Window) {
@@ -136,6 +142,7 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
*
* @see com.vaadin.ui.Panel#paintContent(com.vaadin.terminal.PaintTarget)
*/
+
@Override
public synchronized void paintContent(PaintTarget target)
throws PaintException {
@@ -153,6 +160,7 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
*
* @see com.vaadin.ui.Panel#changeVariables(java.lang.Object, java.util.Map)
*/
+
@Override
public void changeVariables(Object source, Map<String, Object> variables) {
@@ -161,15 +169,29 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
// size is handled in super class, but resize events only in windows ->
// so detect if size change occurs before super.changeVariables()
if (variables.containsKey("height")
- && (getHeightUnits() != UNITS_PIXELS || (Integer) variables
+ && (getHeightUnits() != Unit.PIXELS || (Integer) variables
.get("height") != getHeight())) {
sizeHasChanged = true;
}
if (variables.containsKey("width")
- && (getWidthUnits() != UNITS_PIXELS || (Integer) variables
+ && (getWidthUnits() != Unit.PIXELS || (Integer) variables
.get("width") != getWidth())) {
sizeHasChanged = true;
}
+ Integer browserHeightVar = (Integer) variables
+ .get(VRoot.BROWSER_HEIGHT_VAR);
+ if (browserHeightVar != null
+ && browserHeightVar.intValue() != browserWindowHeight) {
+ browserWindowHeight = browserHeightVar.intValue();
+ sizeHasChanged = true;
+ }
+ Integer browserWidthVar = (Integer) variables
+ .get(VRoot.BROWSER_WIDTH_VAR);
+ if (browserWidthVar != null
+ && browserWidthVar.intValue() != browserWindowWidth) {
+ browserWindowWidth = browserWidthVar.intValue();
+ sizeHasChanged = true;
+ }
super.changeVariables(source, variables);
@@ -604,8 +626,13 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
}
/**
- * Request to center this window on the screen. <b>Note:</b> affects
- * sub-windows only.
+ * Sets this window to be centered relative to its parent window. Affects
+ * sub-windows only. If the window is resized as a result of the size of its
+ * content changing, it will keep itself centered as long as its position is
+ * not explicitly changed programmatically or by the user.
+ * <p>
+ * <b>NOTE:</b> This method has several issues as currently implemented.
+ * Please refer to http://dev.vaadin.com/ticket/8971 for details.
*/
public void center() {
getState().setCentered(true);
@@ -788,6 +815,7 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
*
* @see com.vaadin.event.FieldEvents.FocusNotifier#addListener(com.vaadin.event.FieldEvents.FocusListener)
*/
+
public void addListener(FocusListener listener) {
addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener,
FocusListener.focusMethod);
@@ -804,6 +832,7 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
*
* @see com.vaadin.event.FieldEvents.BlurNotifier#addListener(com.vaadin.event.FieldEvents.BlurListener)
*/
+
public void addListener(BlurListener listener) {
addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener,
BlurListener.blurMethod);
@@ -819,6 +848,7 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
* If the window is a sub-window focusing will cause the sub-window to be
* brought on top of other sub-windows on gain keyboard focus.
*/
+
@Override
public void focus() {
/*
@@ -834,5 +864,4 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
public WindowState getState() {
return (WindowState) super.getState();
}
-
}
diff --git a/src/com/vaadin/ui/themes/ChameleonTheme.java b/src/com/vaadin/ui/themes/ChameleonTheme.java
index bfb9686018..5ae8cd4e57 100644
--- a/src/com/vaadin/ui/themes/ChameleonTheme.java
+++ b/src/com/vaadin/ui/themes/ChameleonTheme.java
@@ -5,7 +5,7 @@ package com.vaadin.ui.themes;
public class ChameleonTheme extends BaseTheme {
- public static final String THEME_NAME = "Chameleon";
+ public static final String THEME_NAME = "chameleon";
/***************************************************************************
* Label styles