summaryrefslogtreecommitdiffstats
path: root/src/com
diff options
context:
space:
mode:
authorHenri Sara <hesara@vaadin.com>2012-06-28 16:57:40 +0300
committerHenri Sara <hesara@vaadin.com>2012-06-28 16:57:40 +0300
commit275b1734c34536d6cd07416b5a2c254509917f1f (patch)
tree2c8e7c9fab46eddcfeb77147fe6d7e4d8bb65cf8 /src/com
parent4ef99ec731c10d7c2e33b3bac68b7b6d3ff242ca (diff)
parente9b1233e49b66c97f5237538e8299ad75aa9c88b (diff)
downloadvaadin-framework-275b1734c34536d6cd07416b5a2c254509917f1f.tar.gz
vaadin-framework-275b1734c34536d6cd07416b5a2c254509917f1f.zip
Merge branch 'master' into gwt
Diffstat (limited to 'src/com')
-rw-r--r--src/com/vaadin/annotations/JavaScript.java32
-rw-r--r--src/com/vaadin/annotations/LoadScripts.java24
-rw-r--r--src/com/vaadin/annotations/StyleSheet.java32
-rw-r--r--src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java20
-rw-r--r--src/com/vaadin/terminal/gwt/client/ApplicationConnection.java174
-rw-r--r--src/com/vaadin/terminal/gwt/client/ComponentConnector.java11
-rw-r--r--src/com/vaadin/terminal/gwt/client/ConnectorMap.java38
-rw-r--r--src/com/vaadin/terminal/gwt/client/JavaScriptConnectorHelper.java4
-rw-r--r--src/com/vaadin/terminal/gwt/client/ResourceLoader.java529
-rw-r--r--src/com/vaadin/terminal/gwt/client/TooltipInfo.java19
-rw-r--r--src/com/vaadin/terminal/gwt/client/VCaption.java27
-rw-r--r--src/com/vaadin/terminal/gwt/client/VTooltip.java214
-rw-r--r--src/com/vaadin/terminal/gwt/client/WidgetLoader.java4
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java185
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/AbstractFieldConnector.java21
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/UnknownComponentConnector.java1
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/button/VButton.java5
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/checkbox/VCheckBox.java4
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/combobox/VFilterSelect.java22
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/datefield/AbstractDateFieldConnector.java14
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/datefield/PopupDateFieldConnector.java34
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/datefield/VDateField.java11
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/VDragAndDropWrapper.java12
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/embedded/EmbeddedConnector.java22
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/embedded/VEmbedded.java3
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/formlayout/FormLayoutConnector.java35
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/formlayout/VFormLayout.java21
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/label/ContentMode.java22
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/label/VLabel.java4
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/link/VLink.java5
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/listselect/TooltipListBox.java41
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/listselect/VListSelect.java15
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/menubar/VMenuBar.java30
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/nativebutton/VNativeButton.java6
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/nativeselect/VNativeSelect.java16
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java1
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/panel/PanelConnector.java1
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/panel/VPanel.java4
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/popupview/VPopupView.java10
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/slider/VSlider.java6
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/table/TableConnector.java25
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/table/VScrollTable.java70
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/tabsheet/TabsheetConnector.java30
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheet.java16
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/textfield/VTextField.java5
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/tree/TreeConnector.java47
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/tree/VTree.java21
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/upload/VUpload.java11
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/window/VWindow.java5
-rw-r--r--src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java27
-rw-r--r--src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java176
-rw-r--r--src/com/vaadin/terminal/gwt/server/BootstrapHandler.java53
-rw-r--r--src/com/vaadin/terminal/gwt/server/CommunicationManager.java3
-rw-r--r--src/com/vaadin/terminal/gwt/server/PortletCommunicationManager.java4
-rw-r--r--src/com/vaadin/tools/WidgetsetCompiler.java3
-rw-r--r--src/com/vaadin/ui/AbstractJavaScriptComponent.java2
-rw-r--r--src/com/vaadin/ui/AbstractMedia.java2
-rw-r--r--src/com/vaadin/ui/Component.java4
-rw-r--r--src/com/vaadin/ui/ConnectorTracker.java129
-rw-r--r--src/com/vaadin/ui/Label.java12
60 files changed, 1620 insertions, 704 deletions
diff --git a/src/com/vaadin/annotations/JavaScript.java b/src/com/vaadin/annotations/JavaScript.java
new file mode 100644
index 0000000000..065c37b78d
--- /dev/null
+++ b/src/com/vaadin/annotations/JavaScript.java
@@ -0,0 +1,32 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import com.vaadin.terminal.gwt.server.ClientConnector;
+
+/**
+ * If this annotation is present on a {@link ClientConnector} class, the
+ * framework ensures the referenced JavaScript files are loaded before the init
+ * method for the corresponding client-side connector is invoked.
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface JavaScript {
+ /**
+ * JavaScript files to load before initializing the client-side connector.
+ *
+ * @return an array of JavaScript file urls
+ */
+ public String[] value();
+}
diff --git a/src/com/vaadin/annotations/LoadScripts.java b/src/com/vaadin/annotations/LoadScripts.java
deleted file mode 100644
index 84ac2d2fb7..0000000000
--- a/src/com/vaadin/annotations/LoadScripts.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.annotations;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Temporary hack used for ensuring external javascript libraries are included.
- * To add a javascript, add this annotation to your Root class.
- *
- * @deprecated Will be removed in favor of a more robust solution before version
- * 7.0.0
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.TYPE)
-@Deprecated
-public @interface LoadScripts {
- public String[] value();
-
-}
diff --git a/src/com/vaadin/annotations/StyleSheet.java b/src/com/vaadin/annotations/StyleSheet.java
new file mode 100644
index 0000000000..f8bf635474
--- /dev/null
+++ b/src/com/vaadin/annotations/StyleSheet.java
@@ -0,0 +1,32 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import com.vaadin.terminal.gwt.server.ClientConnector;
+
+/**
+ * If this annotation is present on a {@link ClientConnector} class, the
+ * framework ensures the referenced style sheets are loaded before the init
+ * method for the corresponding client-side connector is invoked.
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface StyleSheet {
+ /**
+ * Style sheets to load before initializing the client-side connector.
+ *
+ * @return an array of style sheet urls
+ */
+ public String[] value();
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java b/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java
index 960b0a8b0e..540841a6ae 100644
--- a/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java
+++ b/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java
@@ -218,7 +218,7 @@ public class ApplicationConfiguration implements EntryPoint {
static// TODO consider to make this hashmap per application
LinkedList<Command> callbacks = new LinkedList<Command>();
- private static int widgetsLoading;
+ private static int dependenciesLoading;
private static ArrayList<ApplicationConnection> runningApplications = new ArrayList<ApplicationConnection>();
@@ -454,26 +454,26 @@ public class ApplicationConfiguration implements EntryPoint {
*
* @param c
*/
- static void runWhenWidgetsLoaded(Command c) {
- if (widgetsLoading == 0) {
+ static void runWhenDependenciesLoaded(Command c) {
+ if (dependenciesLoading == 0) {
c.execute();
} else {
callbacks.add(c);
}
}
- static void startWidgetLoading() {
- widgetsLoading++;
+ static void startDependencyLoading() {
+ dependenciesLoading++;
}
- static void endWidgetLoading() {
- widgetsLoading--;
- if (widgetsLoading == 0 && !callbacks.isEmpty()) {
+ static void endDependencyLoading() {
+ dependenciesLoading--;
+ if (dependenciesLoading == 0 && !callbacks.isEmpty()) {
for (Command cmd : callbacks) {
cmd.execute();
}
callbacks.clear();
- } else if (widgetsLoading == 0 && deferredWidgetLoader != null) {
+ } else if (dependenciesLoading == 0 && deferredWidgetLoader != null) {
deferredWidgetLoader.trigger();
}
@@ -534,7 +534,7 @@ public class ApplicationConfiguration implements EntryPoint {
}
private boolean isBusy() {
- if (widgetsLoading > 0) {
+ if (dependenciesLoading > 0) {
communicationFree = 0;
return true;
}
diff --git a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
index f0470c8ee8..da4dfa08dc 100644
--- a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
+++ b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
@@ -35,11 +35,12 @@ import com.google.gwt.regexp.shared.RegExp;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.terminal.gwt.client.ApplicationConfiguration.ErrorMessage;
+import com.vaadin.terminal.gwt.client.ResourceLoader.ResourceLoadEvent;
+import com.vaadin.terminal.gwt.client.ResourceLoader.ResourceLoadListener;
import com.vaadin.terminal.gwt.client.communication.HasJavaScriptConnectorHelper;
import com.vaadin.terminal.gwt.client.communication.JsonDecoder;
import com.vaadin.terminal.gwt.client.communication.JsonEncoder;
@@ -1067,6 +1068,14 @@ public class ApplicationConnection {
json.getValueMap("typeMappings"), widgetSet);
}
+ VConsole.log("Handling resource dependencies");
+ if (json.containsKey("scriptDependencies")) {
+ loadScriptDependencies(json.getJSStringArray("scriptDependencies"));
+ }
+ if (json.containsKey("styleDependencies")) {
+ loadStyleDependencies(json.getJSStringArray("styleDependencies"));
+ }
+
handleUIDLDuration.logDuration(
" * Handling type mappings from server completed", 10);
/*
@@ -1608,7 +1617,67 @@ public class ApplicationConnection {
}
};
- ApplicationConfiguration.runWhenWidgetsLoaded(c);
+ ApplicationConfiguration.runWhenDependenciesLoaded(c);
+ }
+
+ private void loadStyleDependencies(JsArrayString dependencies) {
+ // Assuming no reason to interpret in a defined order
+ ResourceLoadListener resourceLoadListener = new ResourceLoadListener() {
+ public void onLoad(ResourceLoadEvent event) {
+ ApplicationConfiguration.endDependencyLoading();
+ }
+
+ public void onError(ResourceLoadEvent event) {
+ VConsole.error(event.getResourceUrl()
+ + " could not be loaded, or the load detection failed because the stylesheet is empty.");
+ // The show must go on
+ onLoad(event);
+ }
+ };
+ ResourceLoader loader = ResourceLoader.get();
+ for (int i = 0; i < dependencies.length(); i++) {
+ String url = translateVaadinUri(dependencies.get(i));
+ ApplicationConfiguration.startDependencyLoading();
+ loader.loadStylesheet(url, resourceLoadListener);
+ }
+ }
+
+ private void loadScriptDependencies(final JsArrayString dependencies) {
+ if (dependencies.length() == 0) {
+ return;
+ }
+
+ // Listener that loads the next when one is completed
+ ResourceLoadListener resourceLoadListener = new ResourceLoadListener() {
+ public void onLoad(ResourceLoadEvent event) {
+ if (dependencies.length() != 0) {
+ String url = translateVaadinUri(dependencies.shift());
+ ApplicationConfiguration.startDependencyLoading();
+ // Load next in chain (hopefully already preloaded)
+ event.getResourceLoader().loadScript(url, this);
+ }
+ // Call start for next before calling end for current
+ ApplicationConfiguration.endDependencyLoading();
+ }
+
+ public void onError(ResourceLoadEvent event) {
+ VConsole.error(event.getResourceUrl() + " could not be loaded.");
+ // The show must go on
+ onLoad(event);
+ }
+ };
+
+ ResourceLoader loader = ResourceLoader.get();
+
+ // Start chain by loading first
+ String url = translateVaadinUri(dependencies.shift());
+ ApplicationConfiguration.startDependencyLoading();
+ loader.loadScript(url, resourceLoadListener);
+
+ // Preload all remaining
+ for (int i = 0; i < dependencies.length(); i++) {
+ loader.loadScript(dependencies.get(i), null);
+ }
}
// Redirect browser, null reloads current page
@@ -2216,6 +2285,9 @@ public class ApplicationConnection {
}
if (uidlUri.startsWith("app://")) {
uidlUri = getAppUri() + uidlUri.substring(6);
+ } else if (uidlUri.startsWith("connector://")) {
+ uidlUri = getAppUri() + "APP/CONNECTOR/"
+ + uidlUri.substring("connector://".length());
}
return uidlUri;
}
@@ -2250,57 +2322,8 @@ public class ApplicationConnection {
/* Extended title handling */
- /**
- * Data showed in tooltips are stored centrilized as it may be needed in
- * varios place: caption, layouts, and in owner components themselves.
- *
- * Updating TooltipInfo is done in updateComponent method.
- *
- */
- public TooltipInfo getTooltipTitleInfo(ComponentConnector titleOwner,
- Object key) {
- if (null == titleOwner) {
- return null;
- }
- return connectorMap.getTooltipInfo(titleOwner, key);
- }
-
private final VTooltip tooltip = new VTooltip(this);
- /**
- * Component may want to delegate Tooltip handling to client. Layouts add
- * Tooltip (description, errors) to caption, but some components may want
- * them to appear one other elements too.
- *
- * Events wanted by this handler are same as in Tooltip.TOOLTIP_EVENTS
- *
- * @param event
- * @param owner
- */
- public void handleTooltipEvent(Event event, ComponentConnector owner) {
- tooltip.handleTooltipEvent(event, owner, null);
-
- }
-
- /**
- * Component may want to delegate Tooltip handling to client. Layouts add
- * Tooltip (description, errors) to caption, but some components may want
- * them to appear one other elements too.
- *
- * Events wanted by this handler are same as in Tooltip.TOOLTIP_EVENTS
- *
- * @param event
- * @param owner
- * @param key
- * the key for tooltip if this is "additional" tooltip, null for
- * components "main tooltip"
- */
- public void handleTooltipEvent(Event event, ComponentConnector owner,
- Object key) {
- tooltip.handleTooltipEvent(event, owner, key);
-
- }
-
private ConnectorMap connectorMap = GWT.create(ConnectorMap.class);
protected String getUidlSecurityKey() {
@@ -2328,34 +2351,6 @@ public class ApplicationConnection {
}
/**
- * If component has several tooltips in addition to the one provided by
- * {@link com.vaadin.ui.AbstractComponent}, component can register them with
- * this method.
- * <p>
- * Component must also pipe events to
- * {@link #handleTooltipEvent(Event, ComponentConnector, Object)} method.
- * <p>
- * This method can also be used to deregister tooltips by using null as
- * tooltip
- *
- * @param paintable
- * Paintable "owning" this tooltip
- * @param key
- * key assosiated with given tooltip. Can be any object. For
- * example a related dom element. Same key must be given for
- * {@link #handleTooltipEvent(Event, ComponentConnector, Object)}
- * method.
- *
- * @param tooltip
- * the TooltipInfo object containing details shown in tooltip,
- * null if deregistering tooltip
- */
- public void registerTooltip(ComponentConnector paintable, Object key,
- TooltipInfo tooltip) {
- connectorMap.registerTooltip(paintable, key, tooltip);
- }
-
- /**
* Gets the {@link ApplicationConfiguration} for the current application.
*
* @see ApplicationConfiguration
@@ -2437,15 +2432,15 @@ public class ApplicationConnection {
// connectorMap.unregisterConnector(p);
}
+ /**
+ * Get VTooltip instance related to application connection
+ *
+ * @return VTooltip instance
+ */
public VTooltip getVTooltip() {
return tooltip;
}
- @Deprecated
- public void handleTooltipEvent(Event event, Widget owner, Object key) {
- handleTooltipEvent(event, getConnectorMap().getConnector(owner), key);
- }
-
/**
* Method provided for backwards compatibility. Duties previously done by
* this method is now handled by the state change event handler in
@@ -2474,17 +2469,6 @@ public class ApplicationConnection {
}
@Deprecated
- public void handleTooltipEvent(Event event, Widget owner) {
- handleTooltipEvent(event, getConnectorMap().getConnector(owner));
-
- }
-
- @Deprecated
- public void registerTooltip(Widget owner, Object key, TooltipInfo info) {
- registerTooltip(getConnectorMap().getConnector(owner), key, info);
- }
-
- @Deprecated
public boolean hasEventListeners(Widget widget, String eventIdentifier) {
return hasEventListeners(getConnectorMap().getConnector(widget),
eventIdentifier);
diff --git a/src/com/vaadin/terminal/gwt/client/ComponentConnector.java b/src/com/vaadin/terminal/gwt/client/ComponentConnector.java
index 4e6a690a3c..95e9a4cf78 100644
--- a/src/com/vaadin/terminal/gwt/client/ComponentConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ComponentConnector.java
@@ -4,6 +4,7 @@
package com.vaadin.terminal.gwt.client;
+import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.ui.Widget;
/**
@@ -104,4 +105,14 @@ public interface ComponentConnector extends ServerConnector {
*/
public void setWidgetEnabled(boolean widgetEnabled);
+ /**
+ * Gets the tooltip info for the given element.
+ *
+ * @param element
+ * The element to lookup a tooltip for
+ * @return The tooltip for the element or null if no tooltip is defined for
+ * this element.
+ */
+ public TooltipInfo getTooltipInfo(Element element);
+
}
diff --git a/src/com/vaadin/terminal/gwt/client/ConnectorMap.java b/src/com/vaadin/terminal/gwt/client/ConnectorMap.java
index efb50b5e00..8bc4a4aacf 100644
--- a/src/com/vaadin/terminal/gwt/client/ConnectorMap.java
+++ b/src/com/vaadin/terminal/gwt/client/ConnectorMap.java
@@ -200,49 +200,11 @@ public class ConnectorMap {
return idToConnector.size();
}
- /**
- * FIXME: Should be moved to VAbstractPaintableWidget
- *
- * @param paintable
- * @return
- */
- @Deprecated
- public TooltipInfo getTooltipInfo(ComponentConnector paintable, Object key) {
- ComponentDetail componentDetail = getComponentDetail(paintable);
- if (componentDetail == null) {
- return null;
- }
- return componentDetail.getTooltipInfo(key);
- }
-
- @Deprecated
- public TooltipInfo getWidgetTooltipInfo(Widget widget, Object key) {
- ComponentConnector connector = getConnector(widget);
- if (connector == null) {
- return null;
- }
- return getTooltipInfo(connector, key);
- }
-
public Collection<? extends ServerConnector> getConnectors() {
return Collections.unmodifiableCollection(idToConnector.values());
}
/**
- * FIXME: Should not be here
- *
- * @param componentConnector
- * @return
- */
- @Deprecated
- public void registerTooltip(ComponentConnector componentConnector,
- Object key, TooltipInfo tooltip) {
- getComponentDetail(componentConnector).putAdditionalTooltip(key,
- tooltip);
-
- }
-
- /**
* Tests if the widget is the root widget of a {@link ComponentConnector}.
*
* @param widget
diff --git a/src/com/vaadin/terminal/gwt/client/JavaScriptConnectorHelper.java b/src/com/vaadin/terminal/gwt/client/JavaScriptConnectorHelper.java
index bd62a759cb..f3a3aa3e83 100644
--- a/src/com/vaadin/terminal/gwt/client/JavaScriptConnectorHelper.java
+++ b/src/com/vaadin/terminal/gwt/client/JavaScriptConnectorHelper.java
@@ -238,8 +238,8 @@ public class JavaScriptConnectorHelper {
return connector;
}
- return ConnectorMap.get(connector.getConnection())
- .getConnector(connectorId);
+ return ConnectorMap.get(connector.getConnection()).getConnector(
+ connectorId);
}
private void fireRpc(String iface, String method,
diff --git a/src/com/vaadin/terminal/gwt/client/ResourceLoader.java b/src/com/vaadin/terminal/gwt/client/ResourceLoader.java
new file mode 100644
index 0000000000..8c481e0356
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/ResourceLoader.java
@@ -0,0 +1,529 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import com.google.gwt.core.client.Duration;
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.core.client.Scheduler.RepeatingCommand;
+import com.google.gwt.dom.client.AnchorElement;
+import com.google.gwt.dom.client.Document;
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.LinkElement;
+import com.google.gwt.dom.client.NodeList;
+import com.google.gwt.dom.client.ObjectElement;
+import com.google.gwt.dom.client.ScriptElement;
+import com.google.gwt.user.client.Timer;
+
+/**
+ * ResourceLoader lets you dynamically include external scripts and styles on
+ * the page and lets you know when the resource has been loaded.
+ *
+ * You can also preload resources, allowing them to get cached by the browser
+ * without being evaluated. This enables downloading multiple resources at once
+ * while still controlling in which order e.g. scripts are executed.
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public class ResourceLoader {
+ /**
+ * Event fired when a resource has been loaded.
+ */
+ public static class ResourceLoadEvent {
+ private ResourceLoader loader;
+ private String resourceUrl;
+ private final boolean preload;
+
+ /**
+ * Creates a new event.
+ *
+ * @param loader
+ * the resource loader that has loaded the resource
+ * @param resourceUrl
+ * the url of the loaded resource
+ * @param preload
+ * true if the resource has only been preloaded, false if
+ * it's fully loaded
+ */
+ public ResourceLoadEvent(ResourceLoader loader, String resourceUrl,
+ boolean preload) {
+ this.loader = loader;
+ this.resourceUrl = resourceUrl;
+ this.preload = preload;
+ }
+
+ /**
+ * Gets the resource loader that has fired this event
+ *
+ * @return the resource loader
+ */
+ public ResourceLoader getResourceLoader() {
+ return loader;
+ }
+
+ /**
+ * Gets the absolute url of the loaded resource.
+ *
+ * @return the absolute url of the loaded resource
+ */
+ public String getResourceUrl() {
+ return resourceUrl;
+ }
+
+ /**
+ * Returns true if the resource has been preloaded, false if it's fully
+ * loaded
+ *
+ * @see ResourceLoader#preloadResource(String, ResourceLoadListener)
+ *
+ * @return true if the resource has been preloaded, false if it's fully
+ * loaded
+ */
+ public boolean isPreload() {
+ return preload;
+ }
+ }
+
+ /**
+ * Event listener that gets notified when a resource has been loaded
+ */
+ public interface ResourceLoadListener {
+ /**
+ * Notifies this ResourceLoadListener that a resource has been loaded.
+ * Some browsers do not support any way of detecting load errors. In
+ * these cases, onLoad will be called regardless of the status.
+ *
+ * @see ResourceLoadEvent
+ *
+ * @param event
+ * a resource load event with information about the loaded
+ * resource
+ */
+ public void onLoad(ResourceLoadEvent event);
+
+ /**
+ * Notifies this ResourceLoadListener that a resource could not be
+ * loaded, e.g. because the file could not be found or because the
+ * server did not respond. Some browsers do not support any way of
+ * detecting load errors. In these cases, onLoad will be called
+ * regardless of the status.
+ *
+ * @see ResourceLoadEvent
+ *
+ * @param event
+ * a resource load event with information about the resource
+ * that could not be loaded.
+ */
+ public void onError(ResourceLoadEvent event);
+ }
+
+ private static final ResourceLoader INSTANCE = GWT
+ .create(ResourceLoader.class);
+
+ private ApplicationConnection connection;
+
+ private final Set<String> loadedResources = new HashSet<String>();
+ private final Set<String> preloadedResources = new HashSet<String>();
+
+ private final Map<String, Collection<ResourceLoadListener>> loadListeners = new HashMap<String, Collection<ResourceLoadListener>>();
+ private final Map<String, Collection<ResourceLoadListener>> preloadListeners = new HashMap<String, Collection<ResourceLoadListener>>();
+
+ private final Element head;
+
+ /**
+ * Creates a new resource loader. You should generally not create you own
+ * resource loader, but instead use {@link ResourceLoader#get()} to get an
+ * instance.
+ */
+ protected ResourceLoader() {
+ Document document = Document.get();
+ head = document.getElementsByTagName("head").getItem(0);
+
+ // detect already loaded scripts and stylesheets
+ NodeList<Element> scripts = document.getElementsByTagName("script");
+ for (int i = 0; i < scripts.getLength(); i++) {
+ ScriptElement element = ScriptElement.as(scripts.getItem(i));
+ String src = element.getSrc();
+ if (src != null && src.length() != 0) {
+ loadedResources.add(src);
+ }
+ }
+
+ NodeList<Element> links = document.getElementsByTagName("link");
+ for (int i = 0; i < links.getLength(); i++) {
+ LinkElement linkElement = LinkElement.as(links.getItem(i));
+ String rel = linkElement.getRel();
+ String href = linkElement.getHref();
+ if ("stylesheet".equalsIgnoreCase(rel) && href != null
+ && href.length() != 0) {
+ loadedResources.add(href);
+ }
+ }
+ }
+
+ /**
+ * Returns the default ResourceLoader
+ *
+ * @return the default ResourceLoader
+ */
+ public static ResourceLoader get() {
+ return INSTANCE;
+ }
+
+ /**
+ * Load a script and notify a listener when the script is loaded. Calling
+ * this method when the script is currently loading or already loaded
+ * doesn't cause the script to be loaded again, but the listener will still
+ * be notified when appropriate.
+ *
+ *
+ * @param scriptUrl
+ * the url of the script to load
+ * @param resourceLoadListener
+ * the listener that will get notified when the script is loaded
+ */
+ public void loadScript(final String scriptUrl,
+ final ResourceLoadListener resourceLoadListener) {
+ final String url = getAbsoluteUrl(scriptUrl);
+ ResourceLoadEvent event = new ResourceLoadEvent(this, url, false);
+ if (loadedResources.contains(url)) {
+ if (resourceLoadListener != null) {
+ resourceLoadListener.onLoad(event);
+ }
+ return;
+ }
+
+ if (preloadListeners.containsKey(url)) {
+ // Preload going on, continue when preloaded
+ preloadResource(url, new ResourceLoadListener() {
+ public void onLoad(ResourceLoadEvent event) {
+ loadScript(url, resourceLoadListener);
+ }
+
+ public void onError(ResourceLoadEvent event) {
+ // Preload failed -> signal error to own listener
+ if (resourceLoadListener != null) {
+ resourceLoadListener.onError(event);
+ }
+ }
+ });
+ return;
+ }
+
+ if (addListener(url, resourceLoadListener, loadListeners)) {
+ ScriptElement scriptTag = Document.get().createScriptElement();
+ scriptTag.setSrc(url);
+ scriptTag.setType("text/javascript");
+ addOnloadHandler(scriptTag, new ResourceLoadListener() {
+ public void onLoad(ResourceLoadEvent event) {
+ fireLoad(event);
+ }
+
+ public void onError(ResourceLoadEvent event) {
+ fireError(event);
+ }
+ }, event);
+ head.appendChild(scriptTag);
+ }
+ }
+
+ private static String getAbsoluteUrl(String url) {
+ AnchorElement a = Document.get().createAnchorElement();
+ a.setHref(url);
+ return a.getHref();
+ }
+
+ /**
+ * Download a resource and notify a listener when the resource is loaded
+ * without attempting to interpret the resource. When a resource has been
+ * preloaded, it will be present in the browser's cache (provided the HTTP
+ * headers allow caching), making a subsequent load operation complete
+ * without having to wait for the resource to be downloaded again.
+ *
+ * Calling this method when the resource is currently loading, currently
+ * preloading, already preloaded or already loaded doesn't cause the
+ * resource to be preloaded again, but the listener will still be notified
+ * when appropriate.
+ *
+ * @param url
+ * the url of the resource to preload
+ * @param resourceLoadListener
+ * the listener that will get notified when the resource is
+ * preloaded
+ */
+ public void preloadResource(String url,
+ ResourceLoadListener resourceLoadListener) {
+ url = getAbsoluteUrl(url);
+ ResourceLoadEvent event = new ResourceLoadEvent(this, url, true);
+ if (loadedResources.contains(url) || preloadedResources.contains(url)) {
+ // Already loaded or preloaded -> just fire listener
+ if (resourceLoadListener != null) {
+ resourceLoadListener.onLoad(event);
+ }
+ return;
+ }
+
+ if (addListener(url, resourceLoadListener, preloadListeners)
+ && !loadListeners.containsKey(url)) {
+ // Inject loader element if this is the first time this is preloaded
+ // AND the resources isn't already being loaded in the normal way
+
+ Element element = getPreloadElement(url);
+ addOnloadHandler(element, new ResourceLoadListener() {
+ public void onLoad(ResourceLoadEvent event) {
+ fireLoad(event);
+ }
+
+ public void onError(ResourceLoadEvent event) {
+ fireError(event);
+ }
+ }, event);
+
+ // TODO Remove object when loaded (without causing spinner in FF)
+ Document.get().getBody().appendChild(element);
+ }
+ }
+
+ private static Element getPreloadElement(String url) {
+ if (BrowserInfo.get().isIE()) {
+ ScriptElement element = Document.get().createScriptElement();
+ element.setSrc(url);
+ element.setType("text/cache");
+ return element;
+ } else {
+ ObjectElement element = Document.get().createObjectElement();
+ element.setData(url);
+ element.setType("text/plain");
+ element.setHeight("0px");
+ element.setWidth("0px");
+ return element;
+ }
+ }
+
+ private native void addOnloadHandler(Element element,
+ ResourceLoadListener listener, ResourceLoadEvent event)
+ /*-{
+ element.onload = $entry(function() {
+ element.onload = null;
+ element.onerror = null;
+ element.onreadystatechange = null;
+ listener.@com.vaadin.terminal.gwt.client.ResourceLoader.ResourceLoadListener::onLoad(Lcom/vaadin/terminal/gwt/client/ResourceLoader$ResourceLoadEvent;)(event);
+ });
+ element.onerror = $entry(function() {
+ element.onload = null;
+ element.onerror = null;
+ element.onreadystatechange = null;
+ listener.@com.vaadin.terminal.gwt.client.ResourceLoader.ResourceLoadListener::onError(Lcom/vaadin/terminal/gwt/client/ResourceLoader$ResourceLoadEvent;)(event);
+ });
+ element.onreadystatechange = function() {
+ if ("loaded" === element.readyState || "complete" === element.readyState ) {
+ element.onload(arguments[0]);
+ }
+ };
+ }-*/;
+
+ /**
+ * Load a stylesheet and notify a listener when the stylesheet is loaded.
+ * Calling this method when the stylesheet is currently loading or already
+ * loaded doesn't cause the stylesheet to be loaded again, but the listener
+ * will still be notified when appropriate.
+ *
+ * @param stylesheetUrl
+ * the url of the stylesheet to load
+ * @param resourceLoadListener
+ * the listener that will get notified when the stylesheet is
+ * loaded
+ */
+ public void loadStylesheet(final String stylesheetUrl,
+ final ResourceLoadListener resourceLoadListener) {
+ final String url = getAbsoluteUrl(stylesheetUrl);
+ final ResourceLoadEvent event = new ResourceLoadEvent(this, url, false);
+ if (loadedResources.contains(url)) {
+ if (resourceLoadListener != null) {
+ resourceLoadListener.onLoad(event);
+ }
+ return;
+ }
+
+ if (preloadListeners.containsKey(url)) {
+ // Preload going on, continue when preloaded
+ preloadResource(url, new ResourceLoadListener() {
+ public void onLoad(ResourceLoadEvent event) {
+ loadStylesheet(url, resourceLoadListener);
+ }
+
+ public void onError(ResourceLoadEvent event) {
+ // Preload failed -> signal error to own listener
+ if (resourceLoadListener != null) {
+ resourceLoadListener.onError(event);
+ }
+ }
+ });
+ return;
+ }
+
+ if (addListener(url, resourceLoadListener, loadListeners)) {
+ LinkElement linkElement = Document.get().createLinkElement();
+ linkElement.setRel("stylesheet");
+ linkElement.setType("text/css");
+ linkElement.setHref(url);
+
+ if (BrowserInfo.get().isSafari()) {
+ // Safari doesn't fire any events for link elements
+ // See http://www.phpied.com/when-is-a-stylesheet-really-loaded/
+ Scheduler.get().scheduleFixedPeriod(new RepeatingCommand() {
+ private final Duration duration = new Duration();
+
+ public boolean execute() {
+ int styleSheetLength = getStyleSheetLength(url);
+ if (getStyleSheetLength(url) > 0) {
+ fireLoad(event);
+ return false; // Stop repeating
+ } else if (styleSheetLength == 0) {
+ // "Loaded" empty sheet -> most likely 404 error
+ fireError(event);
+ return true;
+ } else if (duration.elapsedMillis() > 60 * 1000) {
+ fireError(event);
+ return false;
+ } else {
+ return true; // Continue repeating
+ }
+ }
+ }, 10);
+ } else {
+ addOnloadHandler(linkElement, new ResourceLoadListener() {
+ public void onLoad(ResourceLoadEvent event) {
+ // Chrome && IE fires load for errors, must check
+ // stylesheet data
+ if (BrowserInfo.get().isChrome()
+ || BrowserInfo.get().isIE()) {
+ int styleSheetLength = getStyleSheetLength(url);
+ // Error if there's an empty stylesheet
+ if (styleSheetLength == 0) {
+ fireError(event);
+ return;
+ }
+ }
+ fireLoad(event);
+ }
+
+ public void onError(ResourceLoadEvent event) {
+ fireError(event);
+ }
+ }, event);
+ if (BrowserInfo.get().isOpera()) {
+ // Opera onerror never fired, assume error if no onload in x
+ // seconds
+ new Timer() {
+ @Override
+ public void run() {
+ if (!loadedResources.contains(url)) {
+ fireError(event);
+ }
+ }
+ }.schedule(5 * 1000);
+ }
+ }
+
+ head.appendChild(linkElement);
+ }
+ }
+
+ private static native int getStyleSheetLength(String url)
+ /*-{
+ for(var i = 0; i < $doc.styleSheets.length; i++) {
+ if ($doc.styleSheets[i].href === url) {
+ var sheet = $doc.styleSheets[i];
+ try {
+ var rules = sheet.cssRules
+ if (rules === undefined) {
+ rules = sheet.rules;
+ }
+
+ if (rules === null) {
+ // Style sheet loaded, but can't access length because of XSS -> assume there's something there
+ return 1;
+ }
+
+ // Return length so we can distinguish 0 (probably 404 error) from normal case.
+ return rules.length;
+ } catch (err) {
+ return 1;
+ }
+ }
+ }
+ // No matching stylesheet found -> not yet loaded
+ return -1;
+ }-*/;
+
+ private static boolean addListener(String url,
+ ResourceLoadListener listener,
+ Map<String, Collection<ResourceLoadListener>> listenerMap) {
+ Collection<ResourceLoadListener> listeners = listenerMap.get(url);
+ if (listeners == null) {
+ listeners = new HashSet<ResourceLoader.ResourceLoadListener>();
+ listeners.add(listener);
+ listenerMap.put(url, listeners);
+ return true;
+ } else {
+ listeners.add(listener);
+ return false;
+ }
+ }
+
+ private void fireError(ResourceLoadEvent event) {
+ String resource = event.getResourceUrl();
+
+ Collection<ResourceLoadListener> listeners;
+ if (event.isPreload()) {
+ // Also fire error for load listeners
+ fireError(new ResourceLoadEvent(this, resource, false));
+ listeners = preloadListeners.remove(resource);
+ } else {
+ listeners = loadListeners.remove(resource);
+ }
+ if (listeners != null && !listeners.isEmpty()) {
+ for (ResourceLoadListener listener : listeners) {
+ if (listener != null) {
+ listener.onError(event);
+ }
+ }
+ }
+ }
+
+ private void fireLoad(ResourceLoadEvent event) {
+ String resource = event.getResourceUrl();
+ Collection<ResourceLoadListener> listeners;
+ if (event.isPreload()) {
+ preloadedResources.add(resource);
+ listeners = preloadListeners.remove(resource);
+ } else {
+ if (preloadListeners.containsKey(resource)) {
+ // Also fire preload events for potential listeners
+ fireLoad(new ResourceLoadEvent(this, resource, true));
+ }
+ preloadedResources.remove(resource);
+ loadedResources.add(resource);
+ listeners = loadListeners.remove(resource);
+ }
+ if (listeners != null && !listeners.isEmpty()) {
+ for (ResourceLoadListener listener : listeners) {
+ if (listener != null) {
+ listener.onLoad(event);
+ }
+ }
+ }
+ }
+
+}
diff --git a/src/com/vaadin/terminal/gwt/client/TooltipInfo.java b/src/com/vaadin/terminal/gwt/client/TooltipInfo.java
index fb33a56c56..1ad1ea43cd 100644
--- a/src/com/vaadin/terminal/gwt/client/TooltipInfo.java
+++ b/src/com/vaadin/terminal/gwt/client/TooltipInfo.java
@@ -16,6 +16,11 @@ public class TooltipInfo {
setTitle(tooltip);
}
+ public TooltipInfo(String tooltip, String errorMessage) {
+ setTitle(tooltip);
+ setErrorMessage(errorMessage);
+ }
+
public String getTitle() {
return title;
}
@@ -32,4 +37,18 @@ public class TooltipInfo {
errorMessageHtml = errorMessage;
}
+ /**
+ * Checks is a message has been defined for the tooltip.
+ *
+ * @return true if title or error message is present, false if both are
+ * empty
+ */
+ public boolean hasMessage() {
+ return (title != null && !title.isEmpty())
+ || (errorMessageHtml != null && errorMessageHtml.isEmpty());
+ }
+
+ public boolean equals(TooltipInfo other) {
+ return (other != null && other.title == title && other.errorMessageHtml == errorMessageHtml);
+ }
}
diff --git a/src/com/vaadin/terminal/gwt/client/VCaption.java b/src/com/vaadin/terminal/gwt/client/VCaption.java
index 6f3fcf2c3a..2f7ba87870 100644
--- a/src/com/vaadin/terminal/gwt/client/VCaption.java
+++ b/src/com/vaadin/terminal/gwt/client/VCaption.java
@@ -35,6 +35,8 @@ public class VCaption extends HTML {
ICON, CAPTION, REQUIRED, ERROR
}
+ private TooltipInfo tooltipInfo = null;
+
/**
* Creates a caption that is not linked to a {@link ComponentConnector}.
*
@@ -74,8 +76,6 @@ public class VCaption extends HTML {
}
setStyleName(CLASSNAME);
- sinkEvents(VTooltip.TOOLTIP_EVENTS);
-
}
/**
@@ -345,9 +345,6 @@ public class VCaption extends HTML {
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
final Element target = DOM.eventGetTarget(event);
- if (client != null && owner != null && target != getElement()) {
- client.handleTooltipEvent(event, owner);
- }
if (DOM.eventGetType(event) == Event.ONLOAD
&& icon.getElement() == target) {
@@ -555,6 +552,26 @@ public class VCaption extends HTML {
}
}
+ /**
+ * Sets the tooltip that should be shown for the caption
+ *
+ * @param tooltipInfo
+ * The tooltip that should be shown or null if no tooltip should
+ * be shown
+ */
+ public void setTooltipInfo(TooltipInfo tooltipInfo) {
+ this.tooltipInfo = tooltipInfo;
+ }
+
+ /**
+ * Returns the tooltip that should be shown for the caption
+ *
+ * @return The tooltip to show or null if no tooltip should be shown
+ */
+ public TooltipInfo getTooltipInfo() {
+ return tooltipInfo;
+ }
+
protected Element getTextElement() {
return captionText;
}
diff --git a/src/com/vaadin/terminal/gwt/client/VTooltip.java b/src/com/vaadin/terminal/gwt/client/VTooltip.java
index 70f4a0de0a..7fd3a3238b 100644
--- a/src/com/vaadin/terminal/gwt/client/VTooltip.java
+++ b/src/com/vaadin/terminal/gwt/client/VTooltip.java
@@ -3,12 +3,19 @@
*/
package com.vaadin.terminal.gwt.client;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.KeyDownEvent;
+import com.google.gwt.event.dom.client.KeyDownHandler;
+import com.google.gwt.event.dom.client.MouseMoveEvent;
+import com.google.gwt.event.dom.client.MouseMoveHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.Widget;
import com.vaadin.terminal.gwt.client.ui.VOverlay;
/**
@@ -27,15 +34,12 @@ public class VTooltip extends VOverlay {
private static final int QUICK_OPEN_DELAY = 100;
VErrorMessage em = new VErrorMessage();
Element description = DOM.createDiv();
- private ComponentConnector tooltipOwner;
private boolean closing = false;
private boolean opening = false;
private ApplicationConnection ac;
// Open next tooltip faster. Disabled after 2 sec of showTooltip-silence.
private boolean justClosed = false;
- // If this is "additional" tooltip, this field contains the key for it
- private Object tooltipKey;
public VTooltip(ApplicationConnection client) {
super(false, false, true);
@@ -115,51 +119,30 @@ public class VTooltip extends VOverlay {
}
}
- public void showTooltip(ComponentConnector owner, Event event, Object key) {
- if (closing && tooltipOwner == owner && tooltipKey == key) {
- // return to same tooltip, cancel closing
- closeTimer.cancel();
- closing = false;
- justClosedTimer.cancel();
- justClosed = false;
- return;
- }
+ private void showTooltip() {
- if (closing) {
+ // Close current tooltip
+ if (isShowing()) {
closeNow();
}
- updatePosition(event);
-
- if (opening) {
- showTimer.cancel();
- }
- tooltipOwner = owner;
- tooltipKey = key;
-
// Schedule timer for showing the tooltip according to if it was
// recently closed or not.
- if (justClosed) {
- showTimer.schedule(QUICK_OPEN_DELAY);
- } else {
- showTimer.schedule(OPEN_DELAY);
- }
+ int timeout = justClosed ? QUICK_OPEN_DELAY : OPEN_DELAY;
+ showTimer.schedule(timeout);
opening = true;
}
private void closeNow() {
- if (closing) {
- hide();
- tooltipOwner = null;
- setWidth("");
- closing = false;
- }
+ hide();
+ setWidth("");
+ closing = false;
}
private Timer showTimer = new Timer() {
@Override
public void run() {
- TooltipInfo info = ac.getTooltipTitleInfo(tooltipOwner, tooltipKey);
+ TooltipInfo info = tooltipEventHandler.getTooltipInfo();
if (null != info) {
show(info);
}
@@ -187,7 +170,6 @@ public class VTooltip extends VOverlay {
if (opening) {
showTimer.cancel();
opening = false;
- tooltipOwner = null;
}
if (!isAttached()) {
return;
@@ -209,24 +191,6 @@ public class VTooltip extends VOverlay {
public void updatePosition(Event event) {
tooltipEventMouseX = DOM.eventGetClientX(event);
tooltipEventMouseY = DOM.eventGetClientY(event);
-
- }
-
- public void handleTooltipEvent(Event event, ComponentConnector owner,
- Object key) {
- final int type = DOM.eventGetType(event);
- if ((VTooltip.TOOLTIP_EVENTS & type) == type) {
- if (type == Event.ONMOUSEOVER) {
- showTooltip(owner, event, key);
- } else if (type == Event.ONMOUSEMOVE) {
- updatePosition(event);
- } else {
- hideTooltip();
- }
- } else {
- // non-tooltip event, hide tooltip
- hideTooltip();
- }
}
@Override
@@ -235,17 +199,149 @@ public class VTooltip extends VOverlay {
// cancel closing event if tooltip is mouseovered; the user might want
// to scroll of cut&paste
- switch (type) {
- case Event.ONMOUSEOVER:
+ if (type == Event.ONMOUSEOVER) {
+ // Cancel closing so tooltip stays open and user can copy paste the
+ // tooltip
closeTimer.cancel();
closing = false;
- break;
- case Event.ONMOUSEOUT:
+ }
+ }
+
+ /**
+ * Replace current open tooltip with new content
+ */
+ public void replaceCurrentTooltip() {
+ if (closing) {
+ closeTimer.cancel();
+ closeNow();
+ }
+
+ TooltipInfo info = tooltipEventHandler.getTooltipInfo();
+ if (null != info) {
+ show(info);
+ }
+ opening = false;
+ }
+
+ private class TooltipEventHandler implements MouseMoveHandler,
+ ClickHandler, KeyDownHandler {
+
+ /**
+ * Current element hovered
+ */
+ private com.google.gwt.dom.client.Element currentElement = null;
+
+ /**
+ * Current tooltip active
+ */
+ private TooltipInfo currentTooltipInfo = null;
+
+ /**
+ * Get current active tooltip information
+ *
+ * @return Current active tooltip information or null
+ */
+ public TooltipInfo getTooltipInfo() {
+ return currentTooltipInfo;
+ }
+
+ /**
+ * Locate connector and it's tooltip for given element
+ *
+ * @param element
+ * Element used in search
+ * @return true if connector and tooltip found
+ */
+ private boolean resolveConnector(Element element) {
+
+ ComponentConnector connector = Util.getConnectorForElement(ac, ac
+ .getRootConnector().getWidget(), element);
+
+ // Try to find first connector with proper tooltip info
+ TooltipInfo info = null;
+ while (connector != null) {
+
+ info = connector.getTooltipInfo(element);
+
+ if (info != null && info.hasMessage()) {
+ break;
+ }
+
+ if (!(connector.getParent() instanceof ComponentConnector)) {
+ connector = null;
+ info = null;
+ break;
+ }
+ connector = (ComponentConnector) connector.getParent();
+ }
+
+ if (connector != null && info != null) {
+ currentTooltipInfo = info;
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Handle hide event
+ *
+ * @param event
+ * Event causing hide
+ */
+ private void handleHideEvent() {
hideTooltip();
- break;
- default:
- // NOP
+ currentTooltipInfo = null;
+ }
+
+ public void onMouseMove(MouseMoveEvent mme) {
+ Event event = Event.as(mme.getNativeEvent());
+ com.google.gwt.dom.client.Element element = Element.as(event
+ .getEventTarget());
+
+ // We can ignore move event if it's handled by move or over already
+ if (currentElement == element) {
+ return;
+ }
+ currentElement = element;
+
+ boolean connectorAndTooltipFound = resolveConnector((com.google.gwt.user.client.Element) element);
+ if (!connectorAndTooltipFound) {
+ if (isShowing()) {
+ handleHideEvent();
+ } else {
+ currentTooltipInfo = null;
+ }
+ } else {
+ updatePosition(event);
+ if (isShowing()) {
+ replaceCurrentTooltip();
+ } else {
+ showTooltip();
+ }
+ }
+ }
+
+ public void onClick(ClickEvent event) {
+ handleHideEvent();
+ }
+
+ public void onKeyDown(KeyDownEvent event) {
+ handleHideEvent();
}
}
+ private final TooltipEventHandler tooltipEventHandler = new TooltipEventHandler();
+
+ /**
+ * Connects DOM handlers to widget that are needed for tooltip presentation.
+ *
+ * @param widget
+ * Widget which DOM handlers are connected
+ */
+ public void connectHandlersToWidget(Widget widget) {
+ widget.addDomHandler(tooltipEventHandler, MouseMoveEvent.getType());
+ widget.addDomHandler(tooltipEventHandler, ClickEvent.getType());
+ widget.addDomHandler(tooltipEventHandler, KeyDownEvent.getType());
+ }
}
diff --git a/src/com/vaadin/terminal/gwt/client/WidgetLoader.java b/src/com/vaadin/terminal/gwt/client/WidgetLoader.java
index 16e99716a0..491e569411 100644
--- a/src/com/vaadin/terminal/gwt/client/WidgetLoader.java
+++ b/src/com/vaadin/terminal/gwt/client/WidgetLoader.java
@@ -9,12 +9,12 @@ import com.google.gwt.core.client.RunAsyncCallback;
abstract class WidgetLoader implements RunAsyncCallback {
public void onFailure(Throwable reason) {
- ApplicationConfiguration.endWidgetLoading();
+ ApplicationConfiguration.endDependencyLoading();
}
public void onSuccess() {
addInstantiator();
- ApplicationConfiguration.endWidgetLoading();
+ ApplicationConfiguration.endDependencyLoading();
}
abstract void addInstantiator();
diff --git a/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java b/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java
index f0b9d518ca..6105c545f6 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java
@@ -3,8 +3,11 @@
*/
package com.vaadin.terminal.gwt.client.ui;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Set;
+import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.ui.Focusable;
import com.google.gwt.user.client.ui.HasEnabled;
import com.google.gwt.user.client.ui.Widget;
@@ -21,6 +24,7 @@ import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.Util;
import com.vaadin.terminal.gwt.client.VConsole;
import com.vaadin.terminal.gwt.client.communication.StateChangeEvent;
+import com.vaadin.terminal.gwt.client.ui.datefield.PopupDateFieldConnector;
import com.vaadin.terminal.gwt.client.ui.root.RootConnector;
public abstract class AbstractComponentConnector extends AbstractConnector
@@ -32,11 +36,27 @@ public abstract class AbstractComponentConnector extends AbstractConnector
private String lastKnownHeight = "";
/**
+ * The style names from getState().getStyles() which are currently applied
+ * to the widget.
+ */
+ protected List<String> styleNames = new ArrayList<String>();
+
+ /**
* Default constructor
*/
public AbstractComponentConnector() {
}
+ @Override
+ protected void init() {
+ super.init();
+
+ getConnection().getVTooltip().connectHandlersToWidget(getWidget());
+
+ // Set v-connector style names for the widget
+ getWidget().setStyleName("v-connector", true);
+ }
+
/**
* Creates and returns the widget for this VPaintableWidget. This method
* should only be called once when initializing the paintable.
@@ -96,18 +116,7 @@ public abstract class AbstractComponentConnector extends AbstractConnector
super.onStateChanged(stateChangeEvent);
// Style names
- String styleName = getStyleNames(getWidget().getStylePrimaryName());
- getWidget().setStyleName(styleName);
-
- // Update tooltip
- TooltipInfo tooltipInfo = paintableMap.getTooltipInfo(this, null);
- if (getState().hasDescription()) {
- tooltipInfo.setTitle(getState().getDescription());
- } else {
- tooltipInfo.setTitle(null);
- }
- // add error info to tooltip if present
- tooltipInfo.setErrorMessage(getState().getErrorMessage());
+ updateWidgetStyleNames();
// Set captions
if (delegateCaptionHandling()) {
@@ -130,12 +139,14 @@ public abstract class AbstractComponentConnector extends AbstractConnector
}
public void setWidgetEnabled(boolean widgetEnabled) {
+ // add or remove v-disabled style name from the widget
+ setWidgetStyleName(ApplicationConnection.DISABLED_CLASSNAME,
+ !widgetEnabled);
+
if (getWidget() instanceof HasEnabled) {
// set widget specific enabled state
((HasEnabled) getWidget()).setEnabled(widgetEnabled);
- // add or remove v-disabled style name from the widget
- getWidget().setStyleName(ApplicationConnection.DISABLED_CLASSNAME,
- !widgetEnabled);
+
// make sure the caption has or has not v-disabled style
if (delegateCaptionHandling()) {
ServerConnector parent = getParent();
@@ -213,58 +224,112 @@ public abstract class AbstractComponentConnector extends AbstractConnector
}
/**
- * Generates the style name for the widget based on the given primary style
- * name and the shared state.
+ * Updates the user defined, read-only and error style names for the widget
+ * based the shared state. User defined style names are prefixed with the
+ * primary style name of the widget returned by {@link #getWidget()}
* <p>
* This method can be overridden to provide additional style names for the
- * component
+ * component, for example see
+ * {@link AbstractFieldConnector#updateWidgetStyleNames()}
* </p>
- *
- * @param primaryStyleName
- * The primary style name to use when generating the final style
- * names
- * @return The style names, settable using
- * {@link Widget#setStyleName(String)}
*/
- protected String getStyleNames(String primaryStyleName) {
+ protected void updateWidgetStyleNames() {
ComponentState state = getState();
- StringBuilder styleBuf = new StringBuilder();
- styleBuf.append(primaryStyleName);
- styleBuf.append(" v-connector");
+ String primaryStyleName = getWidget().getStylePrimaryName();
- // Uses connector methods to enable connectors to take hierarchy or
- // multiple state variables into account
- if (!isEnabled()) {
- styleBuf.append(" ");
- styleBuf.append(ApplicationConnection.DISABLED_CLASSNAME);
- }
- if (isReadOnly()) {
- styleBuf.append(" ");
- styleBuf.append("v-readonly");
- }
+ // should be in AbstractFieldConnector ?
+ // add / remove read-only style name
+ setWidgetStyleName("v-readonly", isReadOnly());
+
+ // add / remove error style name
+ setWidgetStyleNameWithPrefix(primaryStyleName,
+ ApplicationConnection.ERROR_CLASSNAME_EXT,
+ null != state.getErrorMessage());
- // add additional styles as css classes, prefixed with component default
- // stylename
+ // add additional user defined style names as class names, prefixed with
+ // component default class name. remove nonexistent style names.
if (state.hasStyles()) {
- for (String style : state.getStyles()) {
- styleBuf.append(" ");
- styleBuf.append(primaryStyleName);
- styleBuf.append("-");
- styleBuf.append(style);
- styleBuf.append(" ");
- styleBuf.append(style);
+ // add new style names
+ List<String> newStyles = new ArrayList<String>();
+ newStyles.addAll(state.getStyles());
+ newStyles.removeAll(styleNames);
+ for (String newStyle : newStyles) {
+ setWidgetStyleName(newStyle, true);
+ setWidgetStyleNameWithPrefix(primaryStyleName + "-", newStyle,
+ true);
+ }
+ // remove nonexistent style names
+ styleNames.removeAll(state.getStyles());
+ for (String oldStyle : styleNames) {
+ setWidgetStyleName(oldStyle, false);
+ setWidgetStyleNameWithPrefix(primaryStyleName + "-", oldStyle,
+ false);
}
+ styleNames.clear();
+ styleNames.addAll(state.getStyles());
+ } else {
+ // remove all old style names
+ for (String oldStyle : styleNames) {
+ setWidgetStyleName(oldStyle, false);
+ setWidgetStyleNameWithPrefix(primaryStyleName + "-", oldStyle,
+ false);
+ }
+ styleNames.clear();
}
- // add error classname to components w/ error
- if (null != state.getErrorMessage()) {
- styleBuf.append(" ");
- styleBuf.append(primaryStyleName);
- styleBuf.append(ApplicationConnection.ERROR_CLASSNAME_EXT);
- }
+ }
+
+ /**
+ * This is used to add / remove state related style names from the widget.
+ * <p>
+ * Override this method for example if the style name given here should be
+ * updated in another widget in addition to the one returned by the
+ * {@link #getWidget()}.
+ * </p>
+ *
+ * @param styleName
+ * the style name to be added or removed
+ * @param add
+ * <code>true</code> to add the given style, <code>false</code>
+ * to remove it
+ */
+ protected void setWidgetStyleName(String styleName, boolean add) {
+ getWidget().setStyleName(styleName, add);
+ }
- return styleBuf.toString();
+ /**
+ * This is used to add / remove state related prefixed style names from the
+ * widget.
+ * <p>
+ * Override this method if the prefixed style name given here should be
+ * updated in another widget in addition to the one returned by the
+ * <code>Connector</code>'s {@link #getWidget()}, or if the prefix should be
+ * different. For example see
+ * {@link PopupDateFieldConnector#setWidgetStyleNameWithPrefix(String, String, boolean)}
+ * </p>
+ *
+ * @param styleName
+ * the style name to be added or removed
+ * @param add
+ * <code>true</code> to add the given style, <code>false</code>
+ * to remove it
+ * @deprecated This will be removed once styles are no longer added with
+ * prefixes.
+ */
+ @Deprecated
+ protected void setWidgetStyleNameWithPrefix(String prefix,
+ String styleName, boolean add) {
+ if (!styleName.startsWith("-")) {
+ if (!prefix.endsWith("-")) {
+ prefix += "-";
+ }
+ } else {
+ if (prefix.endsWith("-")) {
+ styleName.replaceFirst("-", "");
+ }
+ }
+ getWidget().setStyleName(prefix + styleName, add);
}
/*
@@ -315,4 +380,16 @@ public abstract class AbstractComponentConnector extends AbstractConnector
+ ") has been unregistered. Widget was removed.");
}
}
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.vaadin.terminal.gwt.client.ComponentConnector#getTooltipInfo(com.
+ * google.gwt.dom.client.Element)
+ */
+ public TooltipInfo getTooltipInfo(Element element) {
+ return new TooltipInfo(getState().getDescription(), getState()
+ .getErrorMessage());
+ }
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/AbstractFieldConnector.java b/src/com/vaadin/terminal/gwt/client/ui/AbstractFieldConnector.java
index 4be0f02c2a..5bff88c774 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/AbstractFieldConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/AbstractFieldConnector.java
@@ -35,20 +35,15 @@ public abstract class AbstractFieldConnector extends AbstractComponentConnector
}
@Override
- protected String getStyleNames(String primaryStyleName) {
- String styleNames = super.getStyleNames(primaryStyleName);
+ protected void updateWidgetStyleNames() {
+ super.updateWidgetStyleNames();
- if (isModified()) {
- // add modified classname to Fields
- styleNames += " " + ApplicationConnection.MODIFIED_CLASSNAME;
- }
+ // add / remove modified style name to Fields
+ setWidgetStyleName(ApplicationConnection.MODIFIED_CLASSNAME,
+ isModified());
- if (isRequired()) {
- // add required classname to Fields
- styleNames += " " + primaryStyleName
- + ApplicationConnection.REQUIRED_CLASSNAME_EXT;
- }
-
- return styleNames;
+ // add / remove error style name to Fields
+ setWidgetStyleNameWithPrefix(getWidget().getStylePrimaryName(),
+ ApplicationConnection.REQUIRED_CLASSNAME_EXT, isRequired());
}
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/UnknownComponentConnector.java b/src/com/vaadin/terminal/gwt/client/ui/UnknownComponentConnector.java
index 0cccec6481..83ac97458e 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/UnknownComponentConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/UnknownComponentConnector.java
@@ -4,7 +4,6 @@
package com.vaadin.terminal.gwt.client.ui;
-
public class UnknownComponentConnector extends AbstractComponentConnector {
@Override
diff --git a/src/com/vaadin/terminal/gwt/client/ui/button/VButton.java b/src/com/vaadin/terminal/gwt/client/ui/button/VButton.java
index 0cd8bc54f4..bb3d8e2985 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/button/VButton.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/button/VButton.java
@@ -18,7 +18,6 @@ import com.google.gwt.user.client.ui.FocusWidget;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.BrowserInfo;
import com.vaadin.terminal.gwt.client.Util;
-import com.vaadin.terminal.gwt.client.VTooltip;
import com.vaadin.terminal.gwt.client.ui.Icon;
public class VButton extends FocusWidget implements ClickHandler {
@@ -90,7 +89,6 @@ public class VButton extends FocusWidget implements ClickHandler {
setTabIndex(0);
sinkEvents(Event.ONCLICK | Event.MOUSEEVENTS | Event.FOCUSEVENTS
| Event.KEYEVENTS);
- sinkEvents(VTooltip.TOOLTIP_EVENTS);
setStyleName(CLASSNAME);
@@ -128,9 +126,6 @@ public class VButton extends FocusWidget implements ClickHandler {
* -onload event handler added (for icon handling)
*/
public void onBrowserEvent(Event event) {
- if (client != null) {
- client.handleTooltipEvent(event, this);
- }
if (DOM.eventGetType(event) == Event.ONLOAD) {
Util.notifyParentOfSizeChange(this, true);
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/checkbox/VCheckBox.java b/src/com/vaadin/terminal/gwt/client/ui/checkbox/VCheckBox.java
index fd90796ea5..a6eec2de8a 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/checkbox/VCheckBox.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/checkbox/VCheckBox.java
@@ -31,7 +31,6 @@ public class VCheckBox extends com.google.gwt.user.client.ui.CheckBox implements
public VCheckBox() {
setStyleName(CLASSNAME);
- sinkEvents(VTooltip.TOOLTIP_EVENTS);
Element el = DOM.getFirstChild(getElement());
while (el != null) {
DOM.sinkEvents(el,
@@ -53,9 +52,6 @@ public class VCheckBox extends com.google.gwt.user.client.ui.CheckBox implements
if (event.getTypeInt() == Event.ONLOAD) {
Util.notifyParentOfSizeChange(this, true);
}
- if (client != null) {
- client.handleTooltipEvent(event, this);
- }
}
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/combobox/VFilterSelect.java b/src/com/vaadin/terminal/gwt/client/ui/combobox/VFilterSelect.java
index 8c5d521445..9831001024 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/combobox/VFilterSelect.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/combobox/VFilterSelect.java
@@ -54,7 +54,6 @@ import com.vaadin.terminal.gwt.client.Focusable;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.Util;
import com.vaadin.terminal.gwt.client.VConsole;
-import com.vaadin.terminal.gwt.client.VTooltip;
import com.vaadin.terminal.gwt.client.ui.Field;
import com.vaadin.terminal.gwt.client.ui.SubPartAware;
import com.vaadin.terminal.gwt.client.ui.VLazyExecutor;
@@ -824,21 +823,6 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* The text box where the filter is written
*/
protected final TextBox tb = new TextBox() {
- /*
- * (non-Javadoc)
- *
- * @see
- * com.google.gwt.user.client.ui.TextBoxBase#onBrowserEvent(com.google
- * .gwt.user.client.Event)
- */
-
- @Override
- public void onBrowserEvent(Event event) {
- super.onBrowserEvent(event);
- if (client != null) {
- client.handleTooltipEvent(event, VFilterSelect.this);
- }
- }
// Overridden to avoid selecting text when text input is disabled
@Override
@@ -869,9 +853,6 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
@Override
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
- if (client != null) {
- client.handleTooltipEvent(event, VFilterSelect.this);
- }
/*
* Prevent the keyboard focus from leaving the textfield by
@@ -972,8 +953,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
}
});
- tb.sinkEvents(VTooltip.TOOLTIP_EVENTS);
- popupOpener.sinkEvents(VTooltip.TOOLTIP_EVENTS | Event.ONMOUSEDOWN);
+ popupOpener.sinkEvents(Event.ONMOUSEDOWN);
panel.add(tb);
panel.add(popupOpener);
initWidget(panel);
diff --git a/src/com/vaadin/terminal/gwt/client/ui/datefield/AbstractDateFieldConnector.java b/src/com/vaadin/terminal/gwt/client/ui/datefield/AbstractDateFieldConnector.java
index b55f480bac..72555214fa 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/datefield/AbstractDateFieldConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/datefield/AbstractDateFieldConnector.java
@@ -63,15 +63,17 @@ public class AbstractDateFieldConnector extends AbstractFieldConnector
newResolution = VDateField.RESOLUTION_YEAR;
}
+ // Remove old stylename that indicates current resolution
+ setWidgetStyleNameWithPrefix(VDateField.CLASSNAME,
+ VDateField.resolutionToString(getWidget().currentResolution),
+ false);
+
getWidget().currentResolution = newResolution;
// Add stylename that indicates current resolution
- getWidget()
- .addStyleName(
- VDateField.CLASSNAME
- + "-"
- + VDateField
- .resolutionToString(getWidget().currentResolution));
+ setWidgetStyleNameWithPrefix(VDateField.CLASSNAME,
+ VDateField.resolutionToString(getWidget().currentResolution),
+ true);
final int year = uidl.getIntVariable("year");
final int month = (getWidget().currentResolution >= VDateField.RESOLUTION_MONTH) ? uidl
diff --git a/src/com/vaadin/terminal/gwt/client/ui/datefield/PopupDateFieldConnector.java b/src/com/vaadin/terminal/gwt/client/ui/datefield/PopupDateFieldConnector.java
index e169d83b48..dfe0b327ac 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/datefield/PopupDateFieldConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/datefield/PopupDateFieldConnector.java
@@ -35,14 +35,6 @@ public class PopupDateFieldConnector extends TextualDateConnector {
super.updateFromUIDL(uidl, client);
- String popupStyleNames = getStyleNames(VPopupCalendar.POPUP_PRIMARY_STYLE_NAME);
- popupStyleNames += " "
- + VDateField.CLASSNAME
- + "-"
- + VPopupCalendar
- .resolutionToString(getWidget().currentResolution);
- getWidget().popup.setStyleName(popupStyleNames);
-
getWidget().calendar.setDateTimeService(getWidget()
.getDateTimeService());
getWidget().calendar.setShowISOWeekNumbers(getWidget()
@@ -114,4 +106,30 @@ public class PopupDateFieldConnector extends TextualDateConnector {
public VPopupCalendar getWidget() {
return (VPopupCalendar) super.getWidget();
}
+
+ @Override
+ protected void setWidgetStyleName(String styleName, boolean add) {
+ super.setWidgetStyleName(styleName, add);
+
+ // update the style change to popup calendar widget
+ getWidget().popup.setStyleName(styleName, add);
+ }
+
+ @Override
+ protected void setWidgetStyleNameWithPrefix(String prefix,
+ String styleName, boolean add) {
+ super.setWidgetStyleNameWithPrefix(prefix, styleName, add);
+
+ // update the style change to popup calendar widget with the correct
+ // prefix
+ if (!styleName.startsWith("-")) {
+ getWidget().popup.setStyleName(
+ VPopupCalendar.POPUP_PRIMARY_STYLE_NAME + "-" + styleName,
+ add);
+ } else {
+ getWidget().popup.setStyleName(
+ VPopupCalendar.POPUP_PRIMARY_STYLE_NAME + styleName, add);
+ }
+ }
+
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/datefield/VDateField.java b/src/com/vaadin/terminal/gwt/client/ui/datefield/VDateField.java
index d169b1b47e..614c4febdd 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/datefield/VDateField.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/datefield/VDateField.java
@@ -6,11 +6,9 @@ package com.vaadin.terminal.gwt.client.ui.datefield;
import java.util.Date;
-import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.FlowPanel;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.DateTimeService;
-import com.vaadin.terminal.gwt.client.VTooltip;
import com.vaadin.terminal.gwt.client.ui.Field;
public class VDateField extends FlowPanel implements Field {
@@ -66,15 +64,6 @@ public class VDateField extends FlowPanel implements Field {
public VDateField() {
setStyleName(CLASSNAME);
dts = new DateTimeService();
- sinkEvents(VTooltip.TOOLTIP_EVENTS);
- }
-
- @Override
- public void onBrowserEvent(Event event) {
- super.onBrowserEvent(event);
- if (client != null) {
- client.handleTooltipEvent(event, this);
- }
}
/*
diff --git a/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/VDragAndDropWrapper.java b/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/VDragAndDropWrapper.java
index 4c36e92bbb..b1fffc8355 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/VDragAndDropWrapper.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/VDragAndDropWrapper.java
@@ -29,7 +29,6 @@ import com.vaadin.terminal.gwt.client.LayoutManager;
import com.vaadin.terminal.gwt.client.MouseEventDetailsBuilder;
import com.vaadin.terminal.gwt.client.Util;
import com.vaadin.terminal.gwt.client.VConsole;
-import com.vaadin.terminal.gwt.client.VTooltip;
import com.vaadin.terminal.gwt.client.ValueMap;
import com.vaadin.terminal.gwt.client.ui.customcomponent.VCustomComponent;
import com.vaadin.terminal.gwt.client.ui.dd.DDUtil;
@@ -64,7 +63,6 @@ public class VDragAndDropWrapper extends VCustomComponent implements
public VDragAndDropWrapper() {
super();
- sinkEvents(VTooltip.TOOLTIP_EVENTS);
hookHtml5Events(getElement());
setStyleName(CLASSNAME);
@@ -92,16 +90,6 @@ public class VDragAndDropWrapper extends VCustomComponent implements
sinkEvents(Event.TOUCHEVENTS);
}
- @Override
- public void onBrowserEvent(Event event) {
- super.onBrowserEvent(event);
-
- if (hasTooltip && client != null) {
- // Override child tooltips if the wrapper has a tooltip defined
- client.handleTooltipEvent(event, this);
- }
- }
-
/**
* Starts a drag and drop operation from mousedown or touchstart event if
* required conditions are met.
diff --git a/src/com/vaadin/terminal/gwt/client/ui/embedded/EmbeddedConnector.java b/src/com/vaadin/terminal/gwt/client/ui/embedded/EmbeddedConnector.java
index af3ad67db4..fe3549e7f2 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/embedded/EmbeddedConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/embedded/EmbeddedConnector.java
@@ -54,6 +54,16 @@ public class EmbeddedConnector extends AbstractComponentConnector implements
clickEventHandler.handleEventHandlerRegistration();
if (uidl.hasAttribute("type")) {
+ // remove old style name related to type
+ if (getWidget().type != null) {
+ getWidget().removeStyleName(
+ VEmbedded.CLASSNAME + "-" + getWidget().type);
+ }
+ // remove old style name related to mime type
+ if (getWidget().mimetype != null) {
+ getWidget().removeStyleName(
+ VEmbedded.CLASSNAME + "-" + getWidget().mimetype);
+ }
getWidget().type = uidl.getStringAttribute("type");
if (getWidget().type.equals("image")) {
getWidget().addStyleName(VEmbedded.CLASSNAME + "-image");
@@ -118,13 +128,25 @@ public class EmbeddedConnector extends AbstractComponentConnector implements
VConsole.log("Unknown Embedded type '" + getWidget().type + "'");
}
} else if (uidl.hasAttribute("mimetype")) {
+ // remove old style name related to type
+ if (getWidget().type != null) {
+ getWidget().removeStyleName(
+ VEmbedded.CLASSNAME + "-" + getWidget().type);
+ }
+ // remove old style name related to mime type
+ if (getWidget().mimetype != null) {
+ getWidget().removeStyleName(
+ VEmbedded.CLASSNAME + "-" + getWidget().mimetype);
+ }
final String mime = uidl.getStringAttribute("mimetype");
if (mime.equals("application/x-shockwave-flash")) {
+ getWidget().mimetype = "flash";
// Handle embedding of Flash
getWidget().addStyleName(VEmbedded.CLASSNAME + "-flash");
getWidget().setHTML(getWidget().createFlashEmbed(uidl));
} else if (mime.equals("image/svg+xml")) {
+ getWidget().mimetype = "svg";
getWidget().addStyleName(VEmbedded.CLASSNAME + "-svg");
String data;
Map<String, String> parameters = VEmbedded.getParameters(uidl);
diff --git a/src/com/vaadin/terminal/gwt/client/ui/embedded/VEmbedded.java b/src/com/vaadin/terminal/gwt/client/ui/embedded/VEmbedded.java
index 203e7362f3..1d2a5a156a 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/embedded/VEmbedded.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/embedded/VEmbedded.java
@@ -26,6 +26,7 @@ public class VEmbedded extends HTML {
protected Element browserElement;
protected String type;
+ protected String mimetype;
protected ApplicationConnection client;
@@ -232,8 +233,6 @@ public class VEmbedded extends HTML {
VConsole.log("Embeddable onload");
Util.notifyParentOfSizeChange(this, true);
}
-
- client.handleTooltipEvent(event, this);
}
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/formlayout/FormLayoutConnector.java b/src/com/vaadin/terminal/gwt/client/ui/formlayout/FormLayoutConnector.java
index ca21947a6c..c08651ded1 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/formlayout/FormLayoutConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/formlayout/FormLayoutConnector.java
@@ -3,9 +3,12 @@
*/
package com.vaadin.terminal.gwt.client.ui.formlayout;
+import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.terminal.gwt.client.ComponentConnector;
import com.vaadin.terminal.gwt.client.ConnectorHierarchyChangeEvent;
+import com.vaadin.terminal.gwt.client.TooltipInfo;
+import com.vaadin.terminal.gwt.client.Util;
import com.vaadin.terminal.gwt.client.communication.StateChangeEvent;
import com.vaadin.terminal.gwt.client.ui.AbstractFieldConnector;
import com.vaadin.terminal.gwt.client.ui.AbstractLayoutConnector;
@@ -96,4 +99,36 @@ public class FormLayoutConnector extends AbstractLayoutConnector {
return (VFormLayout) super.getWidget();
}
+ @Override
+ public TooltipInfo getTooltipInfo(Element element) {
+ TooltipInfo info = null;
+
+ if (element != getWidget().getElement()) {
+ Object node = Util.findWidget(
+ (com.google.gwt.user.client.Element) element,
+ VFormLayout.Caption.class);
+
+ if (node != null) {
+ VFormLayout.Caption caption = (VFormLayout.Caption) node;
+ info = caption.getOwner().getTooltipInfo(element);
+ } else {
+
+ node = Util.findWidget(
+ (com.google.gwt.user.client.Element) element,
+ VFormLayout.ErrorFlag.class);
+
+ if (node != null) {
+ VFormLayout.ErrorFlag flag = (VFormLayout.ErrorFlag) node;
+ info = flag.getOwner().getTooltipInfo(element);
+ }
+ }
+ }
+
+ if (info == null) {
+ info = super.getTooltipInfo(element);
+ }
+
+ return info;
+ }
+
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/formlayout/VFormLayout.java b/src/com/vaadin/terminal/gwt/client/ui/formlayout/VFormLayout.java
index 8a859c409c..1a161c529d 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/formlayout/VFormLayout.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/formlayout/VFormLayout.java
@@ -12,7 +12,6 @@ import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.SimplePanel;
@@ -215,8 +214,6 @@ public class VFormLayout extends SimplePanel {
public Caption(ComponentConnector component) {
super();
owner = component;
-
- sinkEvents(VTooltip.TOOLTIP_EVENTS);
}
private void setStyles(String[] styles) {
@@ -324,12 +321,6 @@ public class VFormLayout extends SimplePanel {
public ComponentConnector getOwner() {
return owner;
}
-
- @Override
- public void onBrowserEvent(Event event) {
- super.onBrowserEvent(event);
- owner.getConnection().handleTooltipEvent(event, owner);
- }
}
class ErrorFlag extends HTML {
@@ -345,6 +336,10 @@ public class VFormLayout extends SimplePanel {
this.owner = owner;
}
+ public ComponentConnector getOwner() {
+ return owner;
+ }
+
public void updateError(String errorMessage, boolean hideErrors) {
boolean showError = null != errorMessage;
if (hideErrors) {
@@ -366,13 +361,5 @@ public class VFormLayout extends SimplePanel {
}
}
- @Override
- public void onBrowserEvent(Event event) {
- super.onBrowserEvent(event);
- if (owner != null) {
- owner.getConnection().handleTooltipEvent(event, owner);
- }
- }
-
}
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/label/ContentMode.java b/src/com/vaadin/terminal/gwt/client/ui/label/ContentMode.java
index 4892c7e6bd..5e621681c3 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/label/ContentMode.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/label/ContentMode.java
@@ -10,38 +10,36 @@ package com.vaadin.terminal.gwt.client.ui.label;
*/
public enum ContentMode {
/**
- * Content mode, where the label contains only plain text. The getValue()
- * result is coded to XML when painting.
+ * Content mode, where the label contains only plain text.
*/
TEXT,
/**
- * Content mode, where the label contains preformatted text.
+ * Content mode, where the label contains pre formatted text. In this mode
+ * newlines are preserved when rendered on the screen.
*/
PREFORMATTED,
/**
- * Content mode, where the label contains XHTML.
+ * Content mode, where the label contains XHTML. Care should be taken to
+ * ensure
*/
XHTML,
/**
* Content mode, where the label contains well-formed or well-balanced XML.
- * Each of the root elements must have their default namespace specified.
+ * This is handled in the same way as {@link #XHTML}.
*
- * @deprecated Use {@link #XHTML}
+ * @deprecated Use {@link #XHTML} instead
*/
@Deprecated
XML,
/**
- * Content mode, where the label contains RAW output. Output is not required
- * to comply to with XML. In Web Adapter output is inserted inside the
- * resulting HTML document as-is. This is useful for some specific purposes
- * where possibly broken HTML content needs to be shown, but in most cases
- * XHTML mode should be preferred.
+ * Legacy content mode, where the label contains RAW output. This is handled
+ * in exactly the same way as {@link #XHTML}.
*
- * @deprecated Use {@link #XHTML}, {@link #TEXT} or {@link #PREFORMATTED}.
+ * @deprecated Use {@link #XHTML} instead
*/
@Deprecated
RAW;
diff --git a/src/com/vaadin/terminal/gwt/client/ui/label/VLabel.java b/src/com/vaadin/terminal/gwt/client/ui/label/VLabel.java
index f47b8437b7..f0c170c6b0 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/label/VLabel.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/label/VLabel.java
@@ -28,7 +28,6 @@ public class VLabel extends HTML {
public VLabel(String text) {
super(text);
setStyleName(CLASSNAME);
- sinkEvents(VTooltip.TOOLTIP_EVENTS);
}
@Override
@@ -39,9 +38,6 @@ public class VLabel extends HTML {
event.stopPropagation();
return;
}
- if (connection != null) {
- connection.handleTooltipEvent(event, this);
- }
}
@Override
diff --git a/src/com/vaadin/terminal/gwt/client/ui/link/VLink.java b/src/com/vaadin/terminal/gwt/client/ui/link/VLink.java
index 68fe5d9292..bef7943e3f 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/link/VLink.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/link/VLink.java
@@ -13,7 +13,6 @@ import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HTML;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.Util;
-import com.vaadin.terminal.gwt.client.VTooltip;
import com.vaadin.terminal.gwt.client.ui.Icon;
public class VLink extends HTML implements ClickHandler {
@@ -51,7 +50,6 @@ public class VLink extends HTML implements ClickHandler {
getElement().appendChild(anchor);
anchor.appendChild(captionElement);
addClickHandler(this);
- sinkEvents(VTooltip.TOOLTIP_EVENTS);
setStyleName(CLASSNAME);
}
@@ -101,9 +99,6 @@ public class VLink extends HTML implements ClickHandler {
if (event.getTypeInt() == Event.ONLOAD) {
Util.notifyParentOfSizeChange(this, true);
}
- if (client != null) {
- client.handleTooltipEvent(event, this);
- }
if (target == captionElement || target == anchor
|| (icon != null && target == icon.getElement())) {
super.onBrowserEvent(event);
diff --git a/src/com/vaadin/terminal/gwt/client/ui/listselect/TooltipListBox.java b/src/com/vaadin/terminal/gwt/client/ui/listselect/TooltipListBox.java
deleted file mode 100644
index abecd844da..0000000000
--- a/src/com/vaadin/terminal/gwt/client/ui/listselect/TooltipListBox.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.client.ui.listselect;
-
-import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.ui.ListBox;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.VTooltip;
-
-/**
- * Extended ListBox to listen tooltip events and forward them to generic
- * handler.
- */
-public class TooltipListBox extends ListBox {
- private ApplicationConnection client;
- private Widget widget;
-
- public TooltipListBox(boolean isMultiselect) {
- super(isMultiselect);
- sinkEvents(VTooltip.TOOLTIP_EVENTS);
- }
-
- public void setClient(ApplicationConnection client) {
- this.client = client;
- }
-
- public void setSelect(Widget widget) {
- this.widget = widget;
- }
-
- @Override
- public void onBrowserEvent(Event event) {
- super.onBrowserEvent(event);
- if (client != null) {
- client.handleTooltipEvent(event, widget);
- }
- }
-
-} \ No newline at end of file
diff --git a/src/com/vaadin/terminal/gwt/client/ui/listselect/VListSelect.java b/src/com/vaadin/terminal/gwt/client/ui/listselect/VListSelect.java
index e338897841..1b1c2c44e3 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/listselect/VListSelect.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/listselect/VListSelect.java
@@ -8,6 +8,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.user.client.ui.ListBox;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.ui.optiongroup.VOptionGroupBase;
@@ -17,23 +18,25 @@ public class VListSelect extends VOptionGroupBase {
private static final int VISIBLE_COUNT = 10;
- protected TooltipListBox select;
+ protected ListBox select;
private int lastSelectedIndex = -1;
public VListSelect() {
- super(new TooltipListBox(true), CLASSNAME);
- select = (TooltipListBox) optionsContainer;
- select.setSelect(this);
+ super(new ListBox(true), CLASSNAME);
+ select = getOptionsContainer();
select.addChangeHandler(this);
select.addClickHandler(this);
select.setStyleName(CLASSNAME + "-select");
select.setVisibleItemCount(VISIBLE_COUNT);
}
+ protected ListBox getOptionsContainer() {
+ return (ListBox) optionsContainer;
+ }
+
@Override
protected void buildOptions(UIDL uidl) {
- select.setClient(client);
select.setMultipleSelect(isMultiselect());
select.setEnabled(!isDisabled() && !isReadonly());
select.clear();
@@ -99,7 +102,7 @@ public class VListSelect extends VOptionGroupBase {
@Override
protected void setTabIndex(int tabIndex) {
- ((TooltipListBox) optionsContainer).setTabIndex(tabIndex);
+ getOptionsContainer().setTabIndex(tabIndex);
}
public void focus() {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/menubar/VMenuBar.java b/src/com/vaadin/terminal/gwt/client/ui/menubar/VMenuBar.java
index e48483cb02..821fa5032c 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/menubar/VMenuBar.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/menubar/VMenuBar.java
@@ -33,10 +33,8 @@ import com.google.gwt.user.client.ui.Widget;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.BrowserInfo;
import com.vaadin.terminal.gwt.client.LayoutManager;
-import com.vaadin.terminal.gwt.client.TooltipInfo;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.Util;
-import com.vaadin.terminal.gwt.client.VTooltip;
import com.vaadin.terminal.gwt.client.ui.Icon;
import com.vaadin.terminal.gwt.client.ui.SimpleFocusablePanel;
import com.vaadin.terminal.gwt.client.ui.SubPartAware;
@@ -140,8 +138,6 @@ public class VMenuBar extends SimpleFocusablePanel implements
sinkEvents(Event.ONCLICK | Event.ONMOUSEOVER | Event.ONMOUSEOUT
| Event.ONLOAD);
-
- sinkEvents(VTooltip.TOOLTIP_EVENTS);
}
@Override
@@ -340,15 +336,6 @@ public class VMenuBar extends SimpleFocusablePanel implements
}
}
- // Handle tooltips
- if (targetItem == null && client != null) {
- // Handle root menubar tooltips
- client.handleTooltipEvent(e, this);
- } else if (targetItem != null) {
- // Handle item tooltips
- targetItem.onBrowserEvent(e);
- }
-
if (targetItem != null) {
switch (DOM.eventGetType(e)) {
@@ -761,7 +748,6 @@ public class VMenuBar extends SimpleFocusablePanel implements
setSelected(false);
setStyleName(CLASSNAME + "-menuitem");
- sinkEvents(VTooltip.TOOLTIP_EVENTS);
}
public void setSelected(boolean selected) {
@@ -917,22 +903,6 @@ public class VMenuBar extends SimpleFocusablePanel implements
addStyleDependentName(itemStyle);
}
- if (uidl.hasAttribute(ATTRIBUTE_ITEM_DESCRIPTION)) {
- String description = uidl
- .getStringAttribute(ATTRIBUTE_ITEM_DESCRIPTION);
- TooltipInfo info = new TooltipInfo(description);
-
- VMenuBar root = findRootMenu();
- client.registerTooltip(root, this, info);
- }
- }
-
- @Override
- public void onBrowserEvent(Event event) {
- super.onBrowserEvent(event);
- if (client != null) {
- client.handleTooltipEvent(event, findRootMenu(), this);
- }
}
private VMenuBar findRootMenu() {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/nativebutton/VNativeButton.java b/src/com/vaadin/terminal/gwt/client/ui/nativebutton/VNativeButton.java
index dd6e741126..e5a2e1253c 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/nativebutton/VNativeButton.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/nativebutton/VNativeButton.java
@@ -15,7 +15,6 @@ import com.vaadin.terminal.gwt.client.BrowserInfo;
import com.vaadin.terminal.gwt.client.MouseEventDetails;
import com.vaadin.terminal.gwt.client.MouseEventDetailsBuilder;
import com.vaadin.terminal.gwt.client.Util;
-import com.vaadin.terminal.gwt.client.VTooltip;
import com.vaadin.terminal.gwt.client.ui.Icon;
import com.vaadin.terminal.gwt.client.ui.button.ButtonServerRpc;
@@ -54,7 +53,6 @@ public class VNativeButton extends Button implements ClickHandler {
addClickHandler(this);
- sinkEvents(VTooltip.TOOLTIP_EVENTS);
sinkEvents(Event.ONMOUSEDOWN);
sinkEvents(Event.ONMOUSEUP);
}
@@ -87,10 +85,6 @@ public class VNativeButton extends Button implements ClickHandler {
}
clickPending = false;
}
-
- if (client != null) {
- client.handleTooltipEvent(event, this);
- }
}
@Override
diff --git a/src/com/vaadin/terminal/gwt/client/ui/nativeselect/VNativeSelect.java b/src/com/vaadin/terminal/gwt/client/ui/nativeselect/VNativeSelect.java
index 54f5e9aff5..cab23b1bc2 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/nativeselect/VNativeSelect.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/nativeselect/VNativeSelect.java
@@ -8,32 +8,34 @@ import java.util.ArrayList;
import java.util.Iterator;
import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.user.client.ui.ListBox;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.ui.Field;
-import com.vaadin.terminal.gwt.client.ui.listselect.TooltipListBox;
import com.vaadin.terminal.gwt.client.ui.optiongroup.VOptionGroupBase;
public class VNativeSelect extends VOptionGroupBase implements Field {
public static final String CLASSNAME = "v-select";
- protected TooltipListBox select;
+ protected ListBox select;
private boolean firstValueIsTemporaryNullItem = false;
public VNativeSelect() {
- super(new TooltipListBox(false), CLASSNAME);
- select = (TooltipListBox) optionsContainer;
- select.setSelect(this);
+ super(new ListBox(false), CLASSNAME);
+ select = getOptionsContainer();
select.setVisibleItemCount(1);
select.addChangeHandler(this);
select.setStyleName(CLASSNAME + "-select");
}
+ protected ListBox getOptionsContainer() {
+ return (ListBox) optionsContainer;
+ }
+
@Override
protected void buildOptions(UIDL uidl) {
- select.setClient(client);
select.setEnabled(!isDisabled() && !isReadonly());
select.clear();
firstValueIsTemporaryNullItem = false;
@@ -103,7 +105,7 @@ public class VNativeSelect extends VOptionGroupBase implements Field {
@Override
protected void setTabIndex(int tabIndex) {
- ((TooltipListBox) optionsContainer).setTabIndex(tabIndex);
+ getOptionsContainer().setTabIndex(tabIndex);
}
public void focus() {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java b/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java
index 9a89553fd2..7c748df29d 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java
@@ -48,6 +48,7 @@ public abstract class AbstractOrderedLayoutConnector extends
@Override
public void init() {
+ super.init();
rpc = RpcProxy.create(AbstractOrderedLayoutServerRpc.class, this);
getLayoutManager().registerDependency(this,
getWidget().spacingMeasureElement);
diff --git a/src/com/vaadin/terminal/gwt/client/ui/panel/PanelConnector.java b/src/com/vaadin/terminal/gwt/client/ui/panel/PanelConnector.java
index d9096526f3..ea7ffda9db 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/panel/PanelConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/panel/PanelConnector.java
@@ -46,6 +46,7 @@ public class PanelConnector extends AbstractComponentContainerConnector
@Override
public void init() {
+ super.init();
rpc = RpcProxy.create(PanelServerRpc.class, this);
VPanel panel = getWidget();
LayoutManager layoutManager = getLayoutManager();
diff --git a/src/com/vaadin/terminal/gwt/client/ui/panel/VPanel.java b/src/com/vaadin/terminal/gwt/client/ui/panel/VPanel.java
index 6a06367acd..d56a82c46b 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/panel/VPanel.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/panel/VPanel.java
@@ -167,10 +167,6 @@ public class VPanel extends SimplePanel implements ShortcutActionHandlerOwner,
client.updateVariable(id, "scrollTop", scrollTop, false);
client.updateVariable(id, "scrollLeft", scrollLeft, false);
}
- } else if (captionNode.isOrHasChild(target)) {
- if (client != null) {
- client.handleTooltipEvent(event, this);
- }
}
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/popupview/VPopupView.java b/src/com/vaadin/terminal/gwt/client/ui/popupview/VPopupView.java
index da48975726..c8a0222ee2 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/popupview/VPopupView.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/popupview/VPopupView.java
@@ -26,7 +26,6 @@ import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.ComponentConnector;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.VCaptionWrapper;
-import com.vaadin.terminal.gwt.client.VTooltip;
import com.vaadin.terminal.gwt.client.ui.VOverlay;
import com.vaadin.terminal.gwt.client.ui.richtextarea.VRichTextArea;
@@ -73,7 +72,6 @@ public class VPopupView extends HTML {
});
popup.setAnimationEnabled(true);
- sinkEvents(VTooltip.TOOLTIP_EVENTS);
}
/**
@@ -337,12 +335,4 @@ public class VPopupView extends HTML {
}// class CustomPopup
- @Override
- public void onBrowserEvent(Event event) {
- super.onBrowserEvent(event);
- if (client != null) {
- client.handleTooltipEvent(event, this);
- }
- }
-
}// class VPopupView
diff --git a/src/com/vaadin/terminal/gwt/client/ui/slider/VSlider.java b/src/com/vaadin/terminal/gwt/client/ui/slider/VSlider.java
index 5c7ee7a784..e5282dc45e 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/slider/VSlider.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/slider/VSlider.java
@@ -18,7 +18,6 @@ import com.vaadin.terminal.gwt.client.BrowserInfo;
import com.vaadin.terminal.gwt.client.ContainerResizedListener;
import com.vaadin.terminal.gwt.client.Util;
import com.vaadin.terminal.gwt.client.VConsole;
-import com.vaadin.terminal.gwt.client.VTooltip;
import com.vaadin.terminal.gwt.client.ui.Field;
import com.vaadin.terminal.gwt.client.ui.SimpleFocusablePanel;
import com.vaadin.terminal.gwt.client.ui.VLazyExecutor;
@@ -114,8 +113,6 @@ public class VSlider extends SimpleFocusablePanel implements Field,
feedbackPopup.addStyleName(CLASSNAME + "-feedback");
feedbackPopup.setWidget(feedback);
-
- sinkEvents(VTooltip.TOOLTIP_EVENTS);
}
void setFeedbackValue(double value) {
@@ -291,9 +288,6 @@ public class VSlider extends SimpleFocusablePanel implements Field,
event.preventDefault(); // avoid simulated events
event.stopPropagation();
}
- if (client != null) {
- client.handleTooltipEvent(event, this);
- }
}
private void processMouseWheelEvent(final Event event) {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/table/TableConnector.java b/src/com/vaadin/terminal/gwt/client/ui/table/TableConnector.java
index ada0f2424f..ab867ea045 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/table/TableConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/table/TableConnector.java
@@ -7,6 +7,7 @@ import java.util.Iterator;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
+import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style.Position;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.ui.Widget;
@@ -17,6 +18,7 @@ import com.vaadin.terminal.gwt.client.ComponentConnector;
import com.vaadin.terminal.gwt.client.DirectionalManagedLayout;
import com.vaadin.terminal.gwt.client.Paintable;
import com.vaadin.terminal.gwt.client.ServerConnector;
+import com.vaadin.terminal.gwt.client.TooltipInfo;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.Util;
import com.vaadin.terminal.gwt.client.ui.AbstractComponentContainerConnector;
@@ -328,4 +330,27 @@ public class TableConnector extends AbstractComponentContainerConnector
}
}
+ @Override
+ public TooltipInfo getTooltipInfo(Element element) {
+
+ TooltipInfo info = null;
+
+ if (element != getWidget().getElement()) {
+ Object node = Util.findWidget(
+ (com.google.gwt.user.client.Element) element,
+ VScrollTableRow.class);
+
+ if (node != null) {
+ VScrollTableRow row = (VScrollTableRow) node;
+ info = row.getTooltip(element);
+ }
+ }
+
+ if (info == null) {
+ info = super.getTooltipInfo(element);
+ }
+
+ return info;
+ }
+
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/table/VScrollTable.java b/src/com/vaadin/terminal/gwt/client/ui/table/VScrollTable.java
index c4a57f5c8b..b5f10e68ec 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/table/VScrollTable.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/table/VScrollTable.java
@@ -11,6 +11,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import com.google.gwt.core.client.JavaScriptObject;
@@ -4194,14 +4195,6 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
private void unlinkRowAtActualIndex(int index) {
final VScrollTableRow toBeRemoved = (VScrollTableRow) renderedRows
.get(index);
- // Unregister row tooltip
- client.registerTooltip(VScrollTable.this, toBeRemoved.getElement(),
- null);
- for (int i = 0; i < toBeRemoved.getElement().getChildCount(); i++) {
- // Unregister cell tooltips
- Element td = toBeRemoved.getElement().getChild(i).cast();
- client.registerTooltip(VScrollTable.this, td, null);
- }
tBodyElement.removeChild(toBeRemoved.getElement());
orphan(toBeRemoved);
renderedRows.remove(index);
@@ -4423,6 +4416,8 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
private Timer dragTouchTimeout;
private int touchStartY;
private int touchStartX;
+ private TooltipInfo tooltipInfo = null;
+ private Map<TableCellElement, TooltipInfo> cellToolTips = new HashMap<TableCellElement, TooltipInfo>();
private boolean isDragging = false;
private VScrollTableRow(int rowKey) {
@@ -4450,11 +4445,9 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
String rowDescription = uidl.getStringAttribute("rowdescr");
if (rowDescription != null && !rowDescription.equals("")) {
- TooltipInfo info = new TooltipInfo(rowDescription);
- client.registerTooltip(VScrollTable.this, rowElement, info);
+ tooltipInfo = new TooltipInfo(rowDescription);
} else {
- // Remove possibly previously set tooltip
- client.registerTooltip(VScrollTable.this, rowElement, null);
+ tooltipInfo = null;
}
tHead.getColumnAlignments();
@@ -4480,6 +4473,10 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
}
}
+ public TooltipInfo getTooltipInfo() {
+ return tooltipInfo;
+ }
+
/**
* Add a dummy row, used for measurements if Table is empty.
*/
@@ -4665,10 +4662,9 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
if (description != null && !description.equals("")) {
TooltipInfo info = new TooltipInfo(description);
- client.registerTooltip(VScrollTable.this, td, info);
+ cellToolTips.put(td, info);
} else {
- // Remove possibly previously set tooltip
- client.registerTooltip(VScrollTable.this, td, null);
+ cellToolTips.remove(td);
}
td.appendChild(container);
@@ -4776,39 +4772,22 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
return true;
}
- private void handleTooltips(final Event event, Element target) {
+ public TooltipInfo getTooltip(
+ com.google.gwt.dom.client.Element target) {
+
+ TooltipInfo info = null;
+
if (target.hasTagName("TD")) {
- // Table cell (td)
- Element container = target.getFirstChildElement().cast();
- Element widget = container.getFirstChildElement().cast();
-
- boolean containsWidget = false;
- for (Widget w : childWidgets) {
- if (widget == w.getElement()) {
- containsWidget = true;
- break;
- }
- }
- if (!containsWidget) {
- // Only text nodes has tooltips
- if (ConnectorMap.get(client).getWidgetTooltipInfo(
- VScrollTable.this, target) != null) {
- // Cell has description, use it
- client.handleTooltipEvent(event, VScrollTable.this,
- target);
- } else {
- // Cell might have row description, use row
- // description
- client.handleTooltipEvent(event, VScrollTable.this,
- target.getParentElement());
- }
- }
+ TableCellElement td = (TableCellElement) target.cast();
+ info = cellToolTips.get(td);
+ }
- } else {
- // Table row (tr)
- client.handleTooltipEvent(event, VScrollTable.this, target);
+ if (info == null) {
+ info = tooltipInfo;
}
+
+ return info;
}
/**
@@ -4953,9 +4932,6 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
}
boolean targetCellOrRowFound = targetTdOrTr != null;
- if (targetCellOrRowFound) {
- handleTooltips(event, targetTdOrTr);
- }
switch (type) {
case Event.ONDBLCLICK:
diff --git a/src/com/vaadin/terminal/gwt/client/ui/tabsheet/TabsheetConnector.java b/src/com/vaadin/terminal/gwt/client/ui/tabsheet/TabsheetConnector.java
index 08d4679dc5..51a7801f91 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/tabsheet/TabsheetConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/tabsheet/TabsheetConnector.java
@@ -3,12 +3,13 @@
*/
package com.vaadin.terminal.gwt.client.ui.tabsheet;
-import com.google.gwt.core.client.GWT;
+import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.ui.Widget;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.ComponentConnector;
+import com.vaadin.terminal.gwt.client.TooltipInfo;
import com.vaadin.terminal.gwt.client.UIDL;
+import com.vaadin.terminal.gwt.client.Util;
import com.vaadin.terminal.gwt.client.ui.Connect;
import com.vaadin.terminal.gwt.client.ui.SimpleManagedLayout;
import com.vaadin.terminal.gwt.client.ui.layout.MayScrollChildren;
@@ -97,4 +98,29 @@ public class TabsheetConnector extends TabsheetBaseConnector implements
}
+ @Override
+ public TooltipInfo getTooltipInfo(Element element) {
+
+ TooltipInfo info = null;
+
+ // Find a tooltip for the tab, if the element is a tab
+ if (element != getWidget().getElement()) {
+ Object node = Util.findWidget(
+ (com.google.gwt.user.client.Element) element,
+ VTabsheet.TabCaption.class);
+
+ if (node != null) {
+ VTabsheet.TabCaption caption = (VTabsheet.TabCaption) node;
+ info = caption.getTooltipInfo();
+ }
+ }
+
+ // If not tab tooltip was found, use the default
+ if (info == null) {
+ info = super.getTooltipInfo(element);
+ }
+
+ return info;
+ }
+
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheet.java b/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheet.java
index aba5a41f9a..24ea3b2d38 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheet.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheet.java
@@ -233,7 +233,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
}
}
- private static class TabCaption extends VCaption {
+ public static class TabCaption extends VCaption {
private boolean closable = false;
private Element closeButton;
@@ -248,16 +248,11 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
public boolean updateCaption(UIDL uidl) {
if (uidl.hasAttribute(TabsheetBaseConnector.ATTRIBUTE_TAB_DESCRIPTION)) {
- TooltipInfo tooltipInfo = new TooltipInfo();
- tooltipInfo
- .setTitle(uidl
- .getStringAttribute(TabsheetBaseConnector.ATTRIBUTE_TAB_DESCRIPTION));
- tooltipInfo
- .setErrorMessage(uidl
- .getStringAttribute(TabsheetBaseConnector.ATTRIBUTE_TAB_ERROR_MESSAGE));
- client.registerTooltip(getTabsheet(), getElement(), tooltipInfo);
+ setTooltipInfo(new TooltipInfo(
+ uidl.getStringAttribute(TabsheetBaseConnector.ATTRIBUTE_TAB_DESCRIPTION),
+ uidl.getStringAttribute(TabsheetBaseConnector.ATTRIBUTE_TAB_ERROR_MESSAGE)));
} else {
- client.registerTooltip(getTabsheet(), getElement(), null);
+ setTooltipInfo(null);
}
// TODO need to call this instead of super because the caption does
@@ -292,7 +287,6 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
if (event.getTypeInt() == Event.ONLOAD) {
getTabsheet().tabSizeMightHaveChanged(getTab());
}
- client.handleTooltipEvent(event, getTabsheet(), getElement());
}
public Tab getTab() {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/textfield/VTextField.java b/src/com/vaadin/terminal/gwt/client/ui/textfield/VTextField.java
index aeae165f60..bd55c26a24 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/textfield/VTextField.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/textfield/VTextField.java
@@ -22,7 +22,6 @@ import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.BrowserInfo;
import com.vaadin.terminal.gwt.client.EventId;
import com.vaadin.terminal.gwt.client.Util;
-import com.vaadin.terminal.gwt.client.VTooltip;
import com.vaadin.terminal.gwt.client.ui.Field;
/**
@@ -88,7 +87,6 @@ public class VTextField extends TextBoxBase implements Field, ChangeHandler,
}
addFocusHandler(this);
addBlurHandler(this);
- sinkEvents(VTooltip.TOOLTIP_EVENTS);
}
/*
@@ -107,9 +105,6 @@ public class VTextField extends TextBoxBase implements Field, ChangeHandler,
@Override
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
- if (client != null) {
- client.handleTooltipEvent(event, this);
- }
if (listenTextChangeEvents
&& (event.getTypeInt() & TEXTCHANGE_EVENTS) == event
diff --git a/src/com/vaadin/terminal/gwt/client/ui/tree/TreeConnector.java b/src/com/vaadin/terminal/gwt/client/ui/tree/TreeConnector.java
index e4afa32143..3f96a61bf3 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/tree/TreeConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/tree/TreeConnector.java
@@ -3,14 +3,18 @@
*/
package com.vaadin.terminal.gwt.client.ui.tree;
+import java.util.HashMap;
import java.util.Iterator;
+import java.util.Map;
+import com.google.gwt.dom.client.Element;
import com.vaadin.terminal.gwt.client.AbstractFieldState;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.BrowserInfo;
import com.vaadin.terminal.gwt.client.Paintable;
import com.vaadin.terminal.gwt.client.TooltipInfo;
import com.vaadin.terminal.gwt.client.UIDL;
+import com.vaadin.terminal.gwt.client.Util;
import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector;
import com.vaadin.terminal.gwt.client.ui.Connect;
import com.vaadin.terminal.gwt.client.ui.tree.VTree.TreeNode;
@@ -27,6 +31,8 @@ public class TreeConnector extends AbstractComponentConnector implements
public static final String ATTRIBUTE_ACTION_CAPTION = "caption";
public static final String ATTRIBUTE_ACTION_ICON = ATTRIBUTE_NODE_ICON;
+ protected final Map<TreeNode, TooltipInfo> tooltipMap = new HashMap<TreeNode, TooltipInfo>();
+
public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
if (!isRealUpdate(uidl)) {
return;
@@ -62,6 +68,8 @@ public class TreeConnector extends AbstractComponentConnector implements
getWidget().body.clear();
// clear out any references to nodes that no longer are attached
getWidget().clearNodeToKeyMap();
+ tooltipMap.clear();
+
TreeNode childTree = null;
UIDL childUidl = null;
for (final Iterator<?> i = uidl.getChildIterator(); i.hasNext();) {
@@ -74,6 +82,7 @@ public class TreeConnector extends AbstractComponentConnector implements
continue;
}
childTree = getWidget().new TreeNode();
+ getConnection().getVTooltip().connectHandlersToWidget(childTree);
updateNodeFromUIDL(childTree, childUidl);
getWidget().body.add(childTree);
childTree.addStyleDependentName("root");
@@ -193,13 +202,8 @@ public class TreeConnector extends AbstractComponentConnector implements
}
String description = uidl.getStringAttribute("descr");
- if (description != null && getConnection() != null) {
- // Set tooltip
- TooltipInfo info = new TooltipInfo(description);
- getConnection().registerTooltip(this, nodeKey, info);
- } else {
- // Remove possible previous tooltip
- getConnection().registerTooltip(this, nodeKey, null);
+ if (description != null) {
+ tooltipMap.put(treeNode, new TooltipInfo(description));
}
if (uidl.getBooleanAttribute("expanded") && !treeNode.getState()) {
@@ -228,6 +232,7 @@ public class TreeConnector extends AbstractComponentConnector implements
continue;
}
final TreeNode childTree = getWidget().new TreeNode();
+ getConnection().getVTooltip().connectHandlersToWidget(childTree);
updateNodeFromUIDL(childTree, childUidl);
containerNode.childNodeContainer.add(childTree);
if (!i.hasNext()) {
@@ -250,4 +255,32 @@ public class TreeConnector extends AbstractComponentConnector implements
return (AbstractFieldState) super.getState();
}
+ @Override
+ public TooltipInfo getTooltipInfo(Element element) {
+
+ TooltipInfo info = null;
+
+ // Try to find a tooltip for a node
+ if (element != getWidget().getElement()) {
+ Object node = Util.findWidget(
+ (com.google.gwt.user.client.Element) element,
+ TreeNode.class);
+
+ if (node != null) {
+ TreeNode tnode = (TreeNode) node;
+ if (tnode.isCaptionElement(element)) {
+ info = tooltipMap.get(tnode);
+ }
+ }
+ }
+
+ // If no tooltip found for the node or if the target was not a node, use
+ // the default tooltip
+ if (info == null) {
+ info = super.getTooltipInfo(element);
+ }
+
+ return info;
+ }
+
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/tree/VTree.java b/src/com/vaadin/terminal/gwt/client/ui/tree/VTree.java
index 6f19cba957..7462160bad 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/tree/VTree.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/tree/VTree.java
@@ -45,7 +45,6 @@ import com.vaadin.terminal.gwt.client.MouseEventDetails;
import com.vaadin.terminal.gwt.client.MouseEventDetailsBuilder;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.Util;
-import com.vaadin.terminal.gwt.client.VTooltip;
import com.vaadin.terminal.gwt.client.ui.Action;
import com.vaadin.terminal.gwt.client.ui.ActionOwner;
import com.vaadin.terminal.gwt.client.ui.FocusElementPanel;
@@ -656,12 +655,7 @@ public class VTree extends FocusElementPanel implements VHasDropHandler,
return;
}
- if (target == nodeCaptionSpan) {
- client.handleTooltipEvent(event, VTree.this, key);
- }
-
- final boolean inCaption = target == nodeCaptionSpan
- || (icon != null && target == icon.getElement());
+ final boolean inCaption = isCaptionElement(target);
if (inCaption
&& client
.hasEventListeners(VTree.this, ITEM_CLICK_EVENT_ID)
@@ -751,6 +745,18 @@ public class VTree extends FocusElementPanel implements VHasDropHandler,
}
}
+ /**
+ * Checks if the given element is the caption or the icon.
+ *
+ * @param target
+ * The element to check
+ * @return true if the element is the caption or the icon
+ */
+ public boolean isCaptionElement(com.google.gwt.dom.client.Element target) {
+ return (target == nodeCaptionSpan || (icon != null && target == icon
+ .getElement()));
+ }
+
private void fireClick(final Event evt) {
/*
* Ensure we have focus in tree before sending variables. Otherwise
@@ -825,7 +831,6 @@ public class VTree extends FocusElementPanel implements VHasDropHandler,
+ "-caption");
Element wrapper = DOM.createDiv();
nodeCaptionSpan = DOM.createSpan();
- DOM.sinkEvents(nodeCaptionSpan, VTooltip.TOOLTIP_EVENTS);
DOM.appendChild(getElement(), nodeCaptionDiv);
DOM.appendChild(nodeCaptionDiv, wrapper);
DOM.appendChild(wrapper, nodeCaptionSpan);
diff --git a/src/com/vaadin/terminal/gwt/client/ui/upload/VUpload.java b/src/com/vaadin/terminal/gwt/client/ui/upload/VUpload.java
index 4fe53fb89c..ac475ce5a5 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/upload/VUpload.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/upload/VUpload.java
@@ -24,7 +24,6 @@ import com.google.gwt.user.client.ui.SimplePanel;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.BrowserInfo;
import com.vaadin.terminal.gwt.client.VConsole;
-import com.vaadin.terminal.gwt.client.VTooltip;
import com.vaadin.terminal.gwt.client.ui.button.VButton;
/**
@@ -128,16 +127,6 @@ public class VUpload extends SimplePanel {
panel.add(submitButton);
setStyleName(CLASSNAME);
-
- sinkEvents(VTooltip.TOOLTIP_EVENTS);
- }
-
- @Override
- public void onBrowserEvent(Event event) {
- if ((event.getTypeInt() & VTooltip.TOOLTIP_EVENTS) > 0) {
- client.handleTooltipEvent(event, this);
- }
- super.onBrowserEvent(event);
}
private static native void setEncoding(Element form, String encoding)
diff --git a/src/com/vaadin/terminal/gwt/client/ui/window/VWindow.java b/src/com/vaadin/terminal/gwt/client/ui/window/VWindow.java
index 8fd84a9ea6..3946a026c6 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/window/VWindow.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/window/VWindow.java
@@ -552,11 +552,6 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
final Element target = DOM.eventGetTarget(event);
- if (client != null && header.isOrHasChild(target)) {
- // Handle window caption tooltips
- client.handleTooltipEvent(event, this);
- }
-
if (resizing || resizeBox == target) {
onResizeEvent(event);
bubble = false;
diff --git a/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java b/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java
index f7e46a7ca9..6930961497 100644
--- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java
+++ b/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java
@@ -136,6 +136,8 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
static final String UPLOAD_URL_PREFIX = "APP/UPLOAD/";
+ static final String CONNECTOR_RESOURCE_PREFIX = "/APP/CONNECTOR/";
+
/**
* Called by the servlet container to indicate to a servlet that the servlet
* is being placed into service.
@@ -396,6 +398,19 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
CommunicationManager applicationManager = webApplicationContext
.getApplicationManager(application, this);
+ if (requestType == RequestType.CONNECTOR_RESOURCE) {
+ String pathInfo = getRequestPathInfo(request);
+ String resourceName = pathInfo
+ .substring(CONNECTOR_RESOURCE_PREFIX.length());
+
+ final String mimetype = getServletContext().getMimeType(
+ resourceName);
+
+ applicationManager.serveConnectorResource(resourceName,
+ request, response, mimetype);
+ return;
+ }
+
/* Update browser information from the request */
webApplicationContext.getBrowser().updateRequestDetails(request);
@@ -1250,12 +1265,14 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
}
protected enum RequestType {
- FILE_UPLOAD, BROWSER_DETAILS, UIDL, OTHER, STATIC_FILE, APPLICATION_RESOURCE;
+ FILE_UPLOAD, BROWSER_DETAILS, UIDL, OTHER, STATIC_FILE, APPLICATION_RESOURCE, CONNECTOR_RESOURCE;
}
protected RequestType getRequestType(HttpServletRequest request) {
if (isFileUploadRequest(request)) {
return RequestType.FILE_UPLOAD;
+ } else if (isConnectorResourceRequest(request)) {
+ return RequestType.CONNECTOR_RESOURCE;
} else if (isBrowserDetailsRequest(request)) {
return RequestType.BROWSER_DETAILS;
} else if (isUIDLRequest(request)) {
@@ -1276,6 +1293,14 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
&& request.getParameter("browserDetails") != null;
}
+ private boolean isConnectorResourceRequest(HttpServletRequest request) {
+ String path = getRequestPathInfo(request);
+ if (path != null && path.startsWith(CONNECTOR_RESOURCE_PREFIX)) {
+ return true;
+ }
+ return false;
+ }
+
private boolean isApplicationRequest(HttpServletRequest request) {
String path = getRequestPathInfo(request);
if (path != null && path.startsWith("/APP/")) {
diff --git a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java
index 7cad8e3a33..4ee300edac 100644
--- a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java
+++ b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java
@@ -18,6 +18,8 @@ import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.security.GeneralSecurityException;
import java.text.CharacterIterator;
import java.text.DateFormat;
@@ -42,10 +44,14 @@ import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
+import javax.servlet.http.HttpServletResponse;
+
import com.vaadin.Application;
import com.vaadin.Application.SystemMessages;
import com.vaadin.RootRequiresMoreInformationException;
import com.vaadin.Version;
+import com.vaadin.annotations.JavaScript;
+import com.vaadin.annotations.StyleSheet;
import com.vaadin.external.json.JSONArray;
import com.vaadin.external.json.JSONException;
import com.vaadin.external.json.JSONObject;
@@ -154,6 +160,8 @@ public abstract class AbstractCommunicationManager implements Serializable {
private Connector highlightedConnector;
+ private Map<String, Class<?>> connectoResourceContexts = new HashMap<String, Class<?>>();
+
/**
* TODO New constructor - document me!
*
@@ -497,10 +505,11 @@ public abstract class AbstractCommunicationManager implements Serializable {
* found
* @throws IOException
* @throws InvalidUIDLSecurityKeyException
+ * @throws JSONException
*/
public void handleUidlRequest(WrappedRequest request,
WrappedResponse response, Callback callback, Root root)
- throws IOException, InvalidUIDLSecurityKeyException {
+ throws IOException, InvalidUIDLSecurityKeyException, JSONException {
checkWidgetsetVersion(request);
requestThemeName = request.getParameter("theme");
@@ -696,11 +705,12 @@ public abstract class AbstractCommunicationManager implements Serializable {
* @param analyzeLayouts
* @throws PaintException
* @throws IOException
+ * @throws JSONException
*/
private void paintAfterVariableChanges(WrappedRequest request,
WrappedResponse response, Callback callback, boolean repaintAll,
final PrintWriter outWriter, Root root, boolean analyzeLayouts)
- throws PaintException, IOException {
+ throws PaintException, IOException, JSONException {
// Removes application if it has stopped during variable changes
if (!application.isRunning()) {
@@ -764,7 +774,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
@SuppressWarnings("unchecked")
public void writeUidlResponse(WrappedRequest request, boolean repaintAll,
final PrintWriter outWriter, Root root, boolean analyzeLayouts)
- throws PaintException {
+ throws PaintException, JSONException {
ArrayList<ClientConnector> dirtyVisibleConnectors = new ArrayList<ClientConnector>();
Application application = root.getApplication();
// Paints components
@@ -1095,10 +1105,14 @@ public abstract class AbstractCommunicationManager implements Serializable {
boolean typeMappingsOpen = false;
ClientCache clientCache = getClientCache(root);
+ List<Class<? extends ClientConnector>> newConnectorTypes = new ArrayList<Class<? extends ClientConnector>>();
+
for (Class<? extends ClientConnector> class1 : usedClientConnectors) {
if (clientCache.cache(class1)) {
// client does not know the mapping key for this type, send
// mapping to client
+ newConnectorTypes.add(class1);
+
if (!typeMappingsOpen) {
typeMappingsOpen = true;
outWriter.print(", \"typeMappings\" : { ");
@@ -1142,6 +1156,57 @@ public abstract class AbstractCommunicationManager implements Serializable {
}
}
+ /*
+ * Ensure super classes come before sub classes to get script dependency
+ * order right. Sub class @JavaScript might assume that @JavaScript
+ * defined by super class is already loaded.
+ */
+ Collections.sort(newConnectorTypes, new Comparator<Class<?>>() {
+ public int compare(Class<?> o1, Class<?> o2) {
+ // TODO optimize using Class.isAssignableFrom?
+ return hierarchyDepth(o1) - hierarchyDepth(o2);
+ }
+
+ private int hierarchyDepth(Class<?> type) {
+ if (type == Object.class) {
+ return 0;
+ } else {
+ return hierarchyDepth(type.getSuperclass()) + 1;
+ }
+ }
+ });
+
+ List<String> scriptDependencies = new ArrayList<String>();
+ List<String> styleDependencies = new ArrayList<String>();
+
+ for (Class<? extends ClientConnector> class1 : newConnectorTypes) {
+ JavaScript jsAnnotation = class1.getAnnotation(JavaScript.class);
+ if (jsAnnotation != null) {
+ for (String resource : jsAnnotation.value()) {
+ scriptDependencies.add(registerResource(resource, class1));
+ }
+ }
+
+ StyleSheet styleAnnotation = class1.getAnnotation(StyleSheet.class);
+ if (styleAnnotation != null) {
+ for (String resource : styleAnnotation.value()) {
+ styleDependencies.add(registerResource(resource, class1));
+ }
+ }
+ }
+
+ // Include script dependencies in output if there are any
+ if (!scriptDependencies.isEmpty()) {
+ outWriter.print(", \"scriptDependencies\": "
+ + new JSONArray(scriptDependencies).toString());
+ }
+
+ // Include style dependencies in output if there are any
+ if (!styleDependencies.isEmpty()) {
+ outWriter.print(", \"styleDependencies\": "
+ + new JSONArray(styleDependencies).toString());
+ }
+
// add any pending locale definitions requested by the client
printLocaleDeclarations(outWriter);
@@ -1152,6 +1217,51 @@ public abstract class AbstractCommunicationManager implements Serializable {
writePerformanceData(outWriter);
}
+ private String registerResource(String resource, Class<?> context) {
+ try {
+ URI uri = new URI(resource);
+ String protocol = uri.getScheme();
+
+ if ("connector".equals(protocol)) {
+ return registerContextResource(uri, context);
+ }
+
+ if (protocol != null || uri.getHost() != null) {
+ return resource;
+ }
+
+ String path = uri.getPath();
+ if (path.startsWith("/")) {
+ return resource;
+ }
+
+ // Default if just simple relative url
+ return registerContextResource(uri, context);
+ } catch (URISyntaxException e) {
+ getLogger().log(Level.WARNING,
+ "Could not parse resource url " + resource, e);
+ return resource;
+ }
+ }
+
+ private String registerContextResource(URI uri, Class<?> context) {
+ String path = uri.getPath();
+ synchronized (connectoResourceContexts) {
+ // Connector resource
+ if (connectoResourceContexts.containsKey(path)) {
+ Class<?> oldContext = connectoResourceContexts.get(path);
+ getLogger().warning(
+ "Resource " + path + " defined by both " + context
+ + " and " + oldContext + ". Resource from "
+ + oldContext + " will be used.");
+ } else {
+ connectoResourceContexts.put(path, context);
+ }
+ }
+
+ return "connector://" + path;
+ }
+
/**
* Adds the performance timing data (used by TestBench 3) to the UIDL
* response.
@@ -1380,7 +1490,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
private boolean handleVariables(WrappedRequest request,
WrappedResponse response, Callback callback,
Application application2, Root root) throws IOException,
- InvalidUIDLSecurityKeyException {
+ InvalidUIDLSecurityKeyException, JSONException {
boolean success = true;
String changes = getRequestPayload(request);
@@ -2256,9 +2366,11 @@ public abstract class AbstractCommunicationManager implements Serializable {
* @return a string with the initial UIDL message
* @throws PaintException
* if an exception occurs while painting
+ * @throws JSONException
+ * if an exception occurs while encoding output
*/
protected String getInitialUIDL(WrappedRequest request, Root root)
- throws PaintException {
+ throws PaintException, JSONException {
// TODO maybe unify writeUidlResponse()?
StringWriter sWriter = new StringWriter();
PrintWriter pWriter = new PrintWriter(sWriter);
@@ -2273,6 +2385,60 @@ public abstract class AbstractCommunicationManager implements Serializable {
return initialUIDL;
}
+ public void serveConnectorResource(String resourceName,
+ WrappedRequest request, WrappedResponse response, String mimetype)
+ throws IOException {
+ if (resourceName.startsWith("/")) {
+ response.sendError(HttpServletResponse.SC_NOT_FOUND, resourceName);
+ return;
+ }
+
+ Class<?> context;
+ synchronized (connectoResourceContexts) {
+ context = connectoResourceContexts.get(resourceName);
+ }
+
+ if (context == null) {
+ response.sendError(HttpServletResponse.SC_NOT_FOUND, resourceName);
+ return;
+ }
+
+ InputStream in = context.getResourceAsStream(resourceName);
+ if (in == null) {
+ response.sendError(HttpServletResponse.SC_NOT_FOUND, resourceName);
+ return;
+ }
+ OutputStream out = null;
+ try {
+ if (mimetype != null) {
+ response.setContentType(mimetype);
+ }
+
+ out = response.getOutputStream();
+
+ final byte[] buffer = new byte[Constants.DEFAULT_BUFFER_SIZE];
+
+ int bytesRead = 0;
+ while ((bytesRead = in.read(buffer)) > 0) {
+ out.write(buffer, 0, bytesRead);
+ }
+ out.flush();
+ } finally {
+ try {
+ in.close();
+ } catch (Exception e) {
+ // Do nothing
+ }
+ if (out != null) {
+ try {
+ out.close();
+ } catch (Exception e) {
+ // Do nothing
+ }
+ }
+ }
+ }
+
/**
* Stream that extracts content from another stream until the boundary
* string is encountered.
diff --git a/src/com/vaadin/terminal/gwt/server/BootstrapHandler.java b/src/com/vaadin/terminal/gwt/server/BootstrapHandler.java
index 69f033c8cd..d32fa325f4 100644
--- a/src/com/vaadin/terminal/gwt/server/BootstrapHandler.java
+++ b/src/com/vaadin/terminal/gwt/server/BootstrapHandler.java
@@ -9,10 +9,6 @@ import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Serializable;
import java.io.Writer;
-import java.lang.annotation.Annotation;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
@@ -20,7 +16,6 @@ import javax.servlet.http.HttpServletResponse;
import com.vaadin.Application;
import com.vaadin.RootRequiresMoreInformationException;
import com.vaadin.Version;
-import com.vaadin.annotations.LoadScripts;
import com.vaadin.external.json.JSONException;
import com.vaadin.external.json.JSONObject;
import com.vaadin.terminal.DeploymentConfiguration;
@@ -490,50 +485,6 @@ public abstract class BootstrapHandler implements RequestHandler {
page.write("<title>"
+ AbstractApplicationServlet.safeEscapeForHtml(title)
+ "</title>\n");
-
- if (root != null) {
- List<LoadScripts> loadScriptsAnnotations = getAnnotationsFor(
- root.getClass(), LoadScripts.class);
- Collections.reverse(loadScriptsAnnotations);
- // Begin from the end as a class might requests scripts that depend
- // on script loaded by a super class
- for (int i = loadScriptsAnnotations.size() - 1; i >= 0; i--) {
- LoadScripts loadScripts = loadScriptsAnnotations.get(i);
- String[] value = loadScripts.value();
- if (value != null) {
- for (String script : value) {
- page.write("<script type='text/javascript' src='");
- page.write(script);
- page.write("'></script>\n");
- }
- }
- }
-
- }
- }
-
- private static <T extends Annotation> List<T> getAnnotationsFor(
- Class<?> type, Class<T> annotationType) {
- List<T> list = new ArrayList<T>();
- // Find from the class hierarchy
- Class<?> currentType = type;
- while (currentType != Object.class) {
- T annotation = currentType.getAnnotation(annotationType);
- if (annotation != null) {
- list.add(annotation);
- }
- currentType = currentType.getSuperclass();
- }
-
- // Find from an implemented interface
- for (Class<?> iface : type.getInterfaces()) {
- T annotation = iface.getAnnotation(annotationType);
- if (annotation != null) {
- list.add(annotation);
- }
- }
-
- return list;
}
/**
@@ -645,8 +596,10 @@ public abstract class BootstrapHandler implements RequestHandler {
* @return a string with the initial UIDL message
* @throws PaintException
* if an exception occurs while painting the components
+ * @throws JSONException
+ * if an exception occurs while formatting the output
*/
protected abstract String getInitialUIDL(WrappedRequest request, Root root)
- throws PaintException;
+ throws PaintException, JSONException;
}
diff --git a/src/com/vaadin/terminal/gwt/server/CommunicationManager.java b/src/com/vaadin/terminal/gwt/server/CommunicationManager.java
index cc2981dc45..2d2888e034 100644
--- a/src/com/vaadin/terminal/gwt/server/CommunicationManager.java
+++ b/src/com/vaadin/terminal/gwt/server/CommunicationManager.java
@@ -15,6 +15,7 @@ import java.util.UUID;
import javax.servlet.ServletContext;
import com.vaadin.Application;
+import com.vaadin.external.json.JSONException;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.StreamVariable;
import com.vaadin.terminal.WrappedRequest;
@@ -245,7 +246,7 @@ public class CommunicationManager extends AbstractCommunicationManager {
@Override
protected String getInitialUIDL(WrappedRequest request, Root root)
- throws PaintException {
+ throws PaintException, JSONException {
return CommunicationManager.this.getInitialUIDL(request, root);
}
};
diff --git a/src/com/vaadin/terminal/gwt/server/PortletCommunicationManager.java b/src/com/vaadin/terminal/gwt/server/PortletCommunicationManager.java
index d3fbf4d988..7398315ee2 100644
--- a/src/com/vaadin/terminal/gwt/server/PortletCommunicationManager.java
+++ b/src/com/vaadin/terminal/gwt/server/PortletCommunicationManager.java
@@ -104,7 +104,7 @@ public class PortletCommunicationManager extends AbstractCommunicationManager {
@Override
public void handleUidlRequest(WrappedRequest request,
WrappedResponse response, Callback callback, Root root)
- throws IOException, InvalidUIDLSecurityKeyException {
+ throws IOException, InvalidUIDLSecurityKeyException, JSONException {
setCurrentMimeReponse(response);
super.handleUidlRequest(request, response, callback, root);
currentMimeResponse = null;
@@ -253,7 +253,7 @@ public class PortletCommunicationManager extends AbstractCommunicationManager {
@Override
protected String getInitialUIDL(WrappedRequest request, Root root)
- throws PaintException {
+ throws PaintException, JSONException {
return PortletCommunicationManager.this.getInitialUIDL(request,
root);
}
diff --git a/src/com/vaadin/tools/WidgetsetCompiler.java b/src/com/vaadin/tools/WidgetsetCompiler.java
index 407f0e2387..987fd8f734 100644
--- a/src/com/vaadin/tools/WidgetsetCompiler.java
+++ b/src/com/vaadin/tools/WidgetsetCompiler.java
@@ -31,7 +31,8 @@ import com.vaadin.terminal.gwt.widgetsetutils.WidgetSetBuilder;
* included in the classpath, as well as the gwt-dev-[platform].jar and other
* relevant JARs.
*
- * @deprecated with Java 6, can use com.google.gwt.dev.Compiler directly (also in Eclipse plug-in etc.)
+ * @deprecated with Java 6, can use com.google.gwt.dev.Compiler directly (also
+ * in Eclipse plug-in etc.)
*/
@Deprecated
public class WidgetsetCompiler {
diff --git a/src/com/vaadin/ui/AbstractJavaScriptComponent.java b/src/com/vaadin/ui/AbstractJavaScriptComponent.java
index 95c45f55f9..0d7f60186a 100644
--- a/src/com/vaadin/ui/AbstractJavaScriptComponent.java
+++ b/src/com/vaadin/ui/AbstractJavaScriptComponent.java
@@ -110,7 +110,7 @@ import com.vaadin.terminal.gwt.client.ui.JavaScriptWidget;
* @version @VERSION@
* @since 7.0.0
*/
-public class AbstractJavaScriptComponent extends AbstractComponent {
+public abstract class AbstractJavaScriptComponent extends AbstractComponent {
private JavaScriptCallbackHelper callbackHelper = new JavaScriptCallbackHelper(
this);
diff --git a/src/com/vaadin/ui/AbstractMedia.java b/src/com/vaadin/ui/AbstractMedia.java
index 760d9878ca..eafc6c4ed9 100644
--- a/src/com/vaadin/ui/AbstractMedia.java
+++ b/src/com/vaadin/ui/AbstractMedia.java
@@ -18,7 +18,7 @@ import com.vaadin.terminal.gwt.server.ResourceReference;
*
* @author Vaadin Ltd
*/
-public class AbstractMedia extends AbstractComponent {
+public abstract class AbstractMedia extends AbstractComponent {
@Override
public AbstractMediaState getState() {
diff --git a/src/com/vaadin/ui/Component.java b/src/com/vaadin/ui/Component.java
index 81e0319880..5d05f9d0f2 100644
--- a/src/com/vaadin/ui/Component.java
+++ b/src/com/vaadin/ui/Component.java
@@ -520,8 +520,8 @@ public interface Component extends ClientConnector, Sizeable, Serializable {
* <p>
* Getting a null value is often a problem in constructors of regular
* components and in the initializers of custom composite components. A
- * standard workaround is to use {@link Application#getCurrent()}
- * to retrieve the application instance that the current request relates to.
+ * standard workaround is to use {@link Application#getCurrent()} to
+ * retrieve the application instance that the current request relates to.
* Another way is to move the problematic initialization to
* {@link #attach()}, as described in the documentation of the method.
* </p>
diff --git a/src/com/vaadin/ui/ConnectorTracker.java b/src/com/vaadin/ui/ConnectorTracker.java
index 75a75ad22a..e3d1bf86db 100644
--- a/src/com/vaadin/ui/ConnectorTracker.java
+++ b/src/com/vaadin/ui/ConnectorTracker.java
@@ -17,7 +17,7 @@ import com.vaadin.terminal.gwt.client.ServerConnector;
import com.vaadin.terminal.gwt.server.ClientConnector;
/**
- * A class which takes care of book keeping of {@link ClientConnector}s for one
+ * A class which takes care of book keeping of {@link ClientConnector}s for a
* Root.
* <p>
* Provides {@link #getConnector(String)} which can be used to lookup a
@@ -53,6 +53,14 @@ public class ConnectorTracker implements Serializable {
return Logger.getLogger(ConnectorTracker.class.getName());
}
+ /**
+ * Creates a new ConnectorTracker for the given root. A tracker is always
+ * attached to a root and the root cannot be changed during the lifetime of
+ * a {@link ConnectorTracker}.
+ *
+ * @param root
+ * The root to attach to. Cannot be null.
+ */
public ConnectorTracker(Root root) {
this.root = root;
}
@@ -144,61 +152,134 @@ public class ConnectorTracker implements Serializable {
while (iterator.hasNext()) {
String connectorId = iterator.next();
ClientConnector connector = connectorIdToConnector.get(connectorId);
- if (connector instanceof Component) {
- Component component = (Component) connector;
- if (component.getRoot() != root) {
- // If component is no longer part of this application,
- // remove it from the map. If it is re-attached to the
- // application at some point it will be re-added through
- // registerConnector(connector)
- iterator.remove();
- }
+ if (getRootForConnector(connector) != root) {
+ // If connector is no longer part of this root,
+ // remove it from the map. If it is re-attached to the
+ // application at some point it will be re-added through
+ // registerConnector(connector)
+
+ // This code should never be called as cleanup should take place
+ // in detach()
+ getLogger()
+ .warning(
+ "cleanConnectorMap unregistered connector "
+ + getConnectorAndParentInfo(connector)
+ + "). This should have been done when the connector was detached.");
+ iterator.remove();
}
}
}
+ /**
+ * Finds the root that the connector is attached to.
+ *
+ * @param connector
+ * The connector to lookup
+ * @return The root the connector is attached to or null if it is not
+ * attached to any root.
+ */
+ private Root getRootForConnector(ClientConnector connector) {
+ if (connector == null) {
+ return null;
+ }
+ if (connector instanceof Component) {
+ return ((Component) connector).getRoot();
+ }
+
+ return getRootForConnector(connector.getParent());
+ }
+
+ /**
+ * Mark the connector as dirty.
+ *
+ * @see #getDirtyConnectors()
+ *
+ * @param connector
+ * The connector that should be marked clean.
+ */
public void markDirty(ClientConnector connector) {
if (getLogger().isLoggable(Level.FINE)) {
if (!dirtyConnectors.contains(connector)) {
- getLogger()
- .fine(getDebugInfo(connector) + " " + "is now dirty");
+ getLogger().fine(
+ getConnectorAndParentInfo(connector) + " "
+ + "is now dirty");
}
}
dirtyConnectors.add(connector);
}
+ /**
+ * Mark the connector as clean.
+ *
+ * @param connector
+ * The connector that should be marked clean.
+ */
public void markClean(ClientConnector connector) {
if (getLogger().isLoggable(Level.FINE)) {
if (dirtyConnectors.contains(connector)) {
getLogger().fine(
- getDebugInfo(connector) + " " + "is no longer dirty");
+ getConnectorAndParentInfo(connector) + " "
+ + "is no longer dirty");
}
}
dirtyConnectors.remove(connector);
}
- private String getDebugInfo(ClientConnector connector) {
- String message = getObjectString(connector);
+ /**
+ * Returns {@link #getConnectorString(ClientConnector)} for the connector
+ * and its parent (if it has a parent).
+ *
+ * @param connector
+ * The connector
+ * @return A string describing the connector and its parent
+ */
+ private String getConnectorAndParentInfo(ClientConnector connector) {
+ String message = getConnectorString(connector);
if (connector.getParent() != null) {
- message += " (parent: " + getObjectString(connector.getParent())
+ message += " (parent: " + getConnectorString(connector.getParent())
+ ")";
}
return message;
}
- private String getObjectString(Object connector) {
- return connector.getClass().getName() + "@"
- + Integer.toHexString(connector.hashCode());
+ /**
+ * Returns a string with the connector name and id. Useful mostly for
+ * debugging and logging.
+ *
+ * @param connector
+ * The connector
+ * @return A string that describes the connector
+ */
+ private String getConnectorString(ClientConnector connector) {
+ if (connector == null) {
+ return "(null)";
+ }
+
+ String connectorId;
+ try {
+ connectorId = connector.getConnectorId();
+ } catch (RuntimeException e) {
+ // This happens if the connector is not attached to the application.
+ // SHOULD not happen in this case but theoretically can.
+ connectorId = "@" + Integer.toHexString(connector.hashCode());
+ }
+ return connector.getClass().getName() + "(" + connectorId + ")";
}
+ /**
+ * Mark all connectors in this root as dirty.
+ */
public void markAllConnectorsDirty() {
markConnectorsDirtyRecursively(root);
getLogger().fine("All connectors are now dirty");
}
+ /**
+ * Mark all connectors in this root as clean.
+ */
public void markAllConnectorsClean() {
dirtyConnectors.clear();
getLogger().fine("All connectors are now clean");
@@ -222,6 +303,16 @@ public class ConnectorTracker implements Serializable {
}
}
+ /**
+ * Returns a collection of all connectors which have been marked as dirty.
+ * <p>
+ * The state and pending RPC calls for dirty connectors are sent to the
+ * client in the following request.
+ * </p>
+ *
+ * @return A collection of all dirty connectors for this root. This list may
+ * contain invisible connectors.
+ */
public Collection<ClientConnector> getDirtyConnectors() {
return dirtyConnectors;
}
diff --git a/src/com/vaadin/ui/Label.java b/src/com/vaadin/ui/Label.java
index e1c64605d7..e98da384cf 100644
--- a/src/com/vaadin/ui/Label.java
+++ b/src/com/vaadin/ui/Label.java
@@ -142,10 +142,13 @@ public class Label extends AbstractComponent implements Property<String>,
}
/**
- * Gets the value of the label. Value of the label is the XML contents of
- * the label.
+ * Gets the value of the label.
+ * <p>
+ * The value of the label is the text that is shown to the end user.
+ * Depending on the {@link ContentMode} it is plain text or markup.
+ * </p>
*
- * @return the Value of the label.
+ * @return the value of the label.
*/
public String getValue() {
if (getPropertyDataSource() == null) {
@@ -180,8 +183,7 @@ public class Label extends AbstractComponent implements Property<String>,
/**
* @see java.lang.Object#toString()
- * @deprecated use the data source value or {@link #getStringValue()}
- * instead
+ * @deprecated Use {@link #getValue()} instead
*/
@Deprecated
@Override