]> source.dussan.org Git - vaadin-framework.git/commitdiff
Only add tooltip listeners when needed (#11051)
authorLeif Åstrand <leif@vaadin.com>
Fri, 15 Feb 2013 14:28:07 +0000 (16:28 +0200)
committerVaadin Code Review <review@vaadin.com>
Mon, 18 Feb 2013 12:20:27 +0000 (12:20 +0000)
Change-Id: I2b097ed67d59260390cd939b2f2d844548b5fced

client-compiler/src/com/vaadin/server/widgetsetutils/ConnectorBundleLoaderFactory.java
client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ConnectorBundle.java
client-compiler/src/com/vaadin/server/widgetsetutils/metadata/WidgetInitVisitor.java
client/src/com/vaadin/client/metadata/TypeDataStore.java
client/src/com/vaadin/client/ui/AbstractComponentConnector.java

index f8aa58606407a322507677fa1b69283131874773..2be3bf5a16f271c8eef6ea9790221b538d26150c 100644 (file)
@@ -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<JClassType> types = bundle.getHasGetTooltip();
+        for (JClassType type : types) {
+            w.println("store.setHasGetTooltipInfo(%s);",
+                    getClassLiteralString(type));
+            w.splitIfNeeded();
+        }
     }
 
     private void writeDelegateToWidget(TreeLogger logger,
index ff91e249b7cf82f862259fe83fb4ff6b1b437d5a..f6dc982f15e1615cd472eaa2ba1e23cb79880ff3 100644 (file)
@@ -63,6 +63,7 @@ public class ConnectorBundle {
     private final Set<JClassType> needsGwtConstructor = new HashSet<JClassType>();
     private final Set<JClassType> visitedTypes = new HashSet<JClassType>();
     private final Set<JClassType> needsProxySupport = new HashSet<JClassType>();
+    private final Set<JClassType> hasGetTooltip = new HashSet<JClassType>();
 
     private final Map<JClassType, Set<String>> identifiers = new HashMap<JClassType, Set<String>>();
     private final Map<JClassType, Set<JMethod>> needsReturnType = new HashMap<JClassType, Set<JMethod>>();
@@ -618,4 +619,38 @@ public class ConnectorBundle {
     public Set<Property> 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<JClassType> 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
index 4de9d2ae9976c2d2fff4b512ce0bb80c0546ea34..662ecf872bf8419fc03e789d92c9345fdf270a2e 100644 (file)
@@ -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();
index 5b466146a3192d91fd7358f8c14e47c6f01070a6..c1eca0a168953c3a7f211b54261b0d97643d33e1 100644 (file)
@@ -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<Type> returnTypes = FastStringMap.create();
     private final FastStringMap<Invoker> 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());
+    }
 }
index e3bdc5a93ffcbf6937ea9fecce12b74baec44380..51051644c02bddcc7bdd4cdc1f2541a8b0d3e4cf 100644 (file)
@@ -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)
+     * <p>
+     * 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.
+     * </p>
+     * 
+     * @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 <code>true</code> if some part of the component might have a
+     *         tooltip, otherwise <code>false</code>
+     */
+    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.
      *