From f759408c0fa75cc1610b6a598737bf4eec039104 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Leif=20=C3=85strand?= Date: Fri, 15 Feb 2013 16:28:07 +0200 Subject: [PATCH] Only add tooltip listeners when needed (#11051) Change-Id: I2b097ed67d59260390cd939b2f2d844548b5fced --- .../ConnectorBundleLoaderFactory.java | 16 +++++ .../metadata/ConnectorBundle.java | 35 ++++++++++ .../metadata/WidgetInitVisitor.java | 19 ++++++ .../vaadin/client/metadata/TypeDataStore.java | 19 ++++++ .../client/ui/AbstractComponentConnector.java | 67 ++++++++++++++----- 5 files changed, 141 insertions(+), 15 deletions(-) diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/ConnectorBundleLoaderFactory.java b/client-compiler/src/com/vaadin/server/widgetsetutils/ConnectorBundleLoaderFactory.java index f8aa586064..2be3bf5a16 100644 --- a/client-compiler/src/com/vaadin/server/widgetsetutils/ConnectorBundleLoaderFactory.java +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/ConnectorBundleLoaderFactory.java @@ -334,6 +334,22 @@ public class ConnectorBundleLoaderFactory extends Generator { writeGetters(logger, w, bundle); writeSerializers(logger, w, bundle); writeDelegateToWidget(logger, w, bundle); + writeHasGetTooltip(logger, w, bundle); + } + + /** + * @deprecated As of 7.0.1. This is just a hack to avoid breaking backwards + * compatibility and will be removed in Vaadin 7.1 + */ + @Deprecated + private void writeHasGetTooltip(TreeLogger logger, SplittingSourceWriter w, + ConnectorBundle bundle) { + Set types = bundle.getHasGetTooltip(); + for (JClassType type : types) { + w.println("store.setHasGetTooltipInfo(%s);", + getClassLiteralString(type)); + w.splitIfNeeded(); + } } private void writeDelegateToWidget(TreeLogger logger, diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ConnectorBundle.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ConnectorBundle.java index ff91e249b7..f6dc982f15 100644 --- a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ConnectorBundle.java +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ConnectorBundle.java @@ -63,6 +63,7 @@ public class ConnectorBundle { private final Set needsGwtConstructor = new HashSet(); private final Set visitedTypes = new HashSet(); private final Set needsProxySupport = new HashSet(); + private final Set hasGetTooltip = new HashSet(); private final Map> identifiers = new HashMap>(); private final Map> needsReturnType = new HashMap>(); @@ -618,4 +619,38 @@ public class ConnectorBundle { public Set getNeedsDelegateToWidget() { return Collections.unmodifiableSet(needsDelegateToWidget); } + + /** + * @deprecated As of 7.0.1. This is just a hack to avoid breaking backwards + * compatibility and will be removed in Vaadin 7.1 + */ + @Deprecated + public Set getHasGetTooltip() { + return Collections.unmodifiableSet(hasGetTooltip); + } + + /** + * @deprecated As of 7.0.1. This is just a hack to avoid breaking backwards + * compatibility and will be removed in Vaadin 7.1 + */ + @Deprecated + public void setHasGetTooltip(JClassType type) { + if (!isHasGetTooltip(type)) { + hasGetTooltip.add(type); + } + } + + /** + * @deprecated As of 7.0.1. This is just a hack to avoid breaking backwards + * compatibility and will be removed in Vaadin 7.1 + */ + @Deprecated + private boolean isHasGetTooltip(JClassType type) { + if (hasGetTooltip.contains(type)) { + return true; + } else { + return previousBundle != null + && previousBundle.isHasGetTooltip(type); + } + } } \ No newline at end of file diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/WidgetInitVisitor.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/WidgetInitVisitor.java index 4de9d2ae99..662ecf872b 100644 --- a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/WidgetInitVisitor.java +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/WidgetInitVisitor.java @@ -47,6 +47,25 @@ public class WidgetInitVisitor extends TypeVisitor { bundle.setNeedsReturnType(type, getWidget); } + // Hack to detect when getTooltipInfo has a custom implementation + // #11051 + JClassType getTooltipParamType = type.getOracle().findType( + "com.google.gwt.dom.client.Element"); + JMethod getTooltipInfoMethod = findInheritedMethod(type, + "getTooltipInfo", getTooltipParamType); + if (getTooltipInfoMethod == null) { + logger.log(Type.ERROR, "Could not find getTooltipInfo in " + + type.getQualifiedSourceName()); + throw new UnableToCompleteException(); + } + JClassType enclosingType = getTooltipInfoMethod.getEnclosingType(); + if (!enclosingType.getQualifiedSourceName().equals( + AbstractComponentConnector.class.getCanonicalName())) { + logger.log(Type.WARN, type.getQualifiedSourceName() + + " has overridden getTooltipInfo"); + bundle.setHasGetTooltip(type); + } + // Check state properties for @DelegateToWidget JMethod getState = findInheritedMethod(type, "getState"); JClassType stateType = getState.getReturnType().isClass(); diff --git a/client/src/com/vaadin/client/metadata/TypeDataStore.java b/client/src/com/vaadin/client/metadata/TypeDataStore.java index 5b466146a3..c1eca0a168 100644 --- a/client/src/com/vaadin/client/metadata/TypeDataStore.java +++ b/client/src/com/vaadin/client/metadata/TypeDataStore.java @@ -38,6 +38,7 @@ public class TypeDataStore { private final FastStringSet delayedMethods = FastStringSet.create(); private final FastStringSet lastOnlyMethods = FastStringSet.create(); + private final FastStringSet hasGetTooltipInfo = FastStringSet.create(); private final FastStringMap returnTypes = FastStringMap.create(); private final FastStringMap invokers = FastStringMap.create(); @@ -276,4 +277,22 @@ public class TypeDataStore { public static boolean hasProperties(Type type) { return get().properties.containsKey(type.getSignature()); } + + /** + * @deprecated As of 7.0.1. This is just a hack to avoid breaking backwards + * compatibility and will be removed in Vaadin 7.1 + */ + @Deprecated + public void setHasGetTooltipInfo(Class clazz) { + hasGetTooltipInfo.add(getType(clazz).getSignature()); + } + + /** + * @deprecated As of 7.0.1. This is just a hack to avoid breaking backwards + * compatibility and will be removed in Vaadin 7.1 + */ + @Deprecated + public static boolean getHasGetTooltipInfo(Class clazz) { + return get().hasGetTooltipInfo.contains(getType(clazz).getSignature()); + } } diff --git a/client/src/com/vaadin/client/ui/AbstractComponentConnector.java b/client/src/com/vaadin/client/ui/AbstractComponentConnector.java index e3bdc5a93f..51051644c0 100644 --- a/client/src/com/vaadin/client/ui/AbstractComponentConnector.java +++ b/client/src/com/vaadin/client/ui/AbstractComponentConnector.java @@ -15,9 +15,6 @@ */ package com.vaadin.client.ui; -import java.util.ArrayList; -import java.util.List; - import com.google.gwt.core.client.JsArrayString; import com.google.gwt.dom.client.Element; import com.google.gwt.user.client.ui.Focusable; @@ -38,6 +35,7 @@ import com.vaadin.client.communication.StateChangeEvent; import com.vaadin.client.metadata.NoDataException; import com.vaadin.client.metadata.Type; import com.vaadin.client.metadata.TypeData; +import com.vaadin.client.metadata.TypeDataStore; import com.vaadin.client.ui.datefield.PopupDateFieldConnector; import com.vaadin.client.ui.ui.UIConnector; import com.vaadin.shared.AbstractComponentState; @@ -56,6 +54,8 @@ public abstract class AbstractComponentConnector extends AbstractConnector private boolean initialStateEvent = true; + private boolean tooltipListenersAttached = false; + /** * The style names from getState().getStyles() which are currently applied * to the widget. @@ -68,14 +68,6 @@ public abstract class AbstractComponentConnector extends AbstractConnector public AbstractComponentConnector() { } - @Override - protected void init() { - super.init(); - - getConnection().getVTooltip().connectHandlersToWidget(getWidget()); - - } - /** * Creates and returns the widget for this VPaintableWidget. This method * should only be called once when initializing the paintable. @@ -164,6 +156,17 @@ public abstract class AbstractComponentConnector extends AbstractConnector updateComponentSize(); + Profiler.enter("AbstractComponentContainer.onStateChanged check tooltip"); + if (!tooltipListenersAttached && hasTooltip()) { + /* + * Add event handlers for tooltips if they are needed but have not + * yet been added. + */ + tooltipListenersAttached = true; + getConnection().getVTooltip().connectHandlersToWidget(getWidget()); + } + Profiler.leave("AbstractComponentContainer.onStateChanged check tooltip"); + initialStateEvent = false; Profiler.leave("AbstractComponentConnector.onStateChanged"); @@ -415,17 +418,51 @@ public abstract class AbstractComponentConnector extends AbstractConnector } } - /* - * (non-Javadoc) + /** + * {@inheritDoc} * - * @see com.vaadin.client.ComponentConnector#getTooltipInfo(com. - * google.gwt.dom.client.Element) + *

+ * When overriding this method, {@link #hasTooltip()} should also be + * overridden to return true in all situations where this method might + * return a non-empty result. + *

+ * + * @see ComponentConnector#getTooltipInfo(Element) */ @Override public TooltipInfo getTooltipInfo(Element element) { return new TooltipInfo(getState().description, getState().errorMessage); } + /** + * Check whether there might be a tooltip for this component. The framework + * will only add event listeners for automatically handling tooltips (using + * {@link #getTooltipInfo(Element)}) if this method returns true. + * + * @return true if some part of the component might have a + * tooltip, otherwise false + */ + private boolean hasTooltip() { + /* + * Hack to avoid breaking backwards compatibility - use a generator to + * know whether there's a custom implementation of getTooltipInfo, and + * in that case always assume that there might be tooltip. + */ + if (TypeDataStore.getHasGetTooltipInfo(getClass())) { + return true; + } + + // Normally, there is a tooltip if description or errorMessage is set + AbstractComponentState state = getState(); + if (state.description != null && !state.description.equals("")) { + return true; + } else if (state.errorMessage != null && !state.errorMessage.equals("")) { + return true; + } else { + return false; + } + } + /** * Gets the icon set for this component. * -- 2.39.5