]> source.dussan.org Git - vaadin-framework.git/commitdiff
#2519, #2520 optimized usage of hasmaps in ac + dom inserts in cellbasedlayout
authorMatti Tahvonen <matti.tahvonen@itmill.com>
Thu, 29 Jan 2009 14:11:49 +0000 (14:11 +0000)
committerMatti Tahvonen <matti.tahvonen@itmill.com>
Thu, 29 Jan 2009 14:11:49 +0000 (14:11 +0000)
svn changeset:6676/svn branch:trunk

src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java
src/com/itmill/toolkit/terminal/gwt/client/ComponentDetail.java [new file with mode: 0644]
src/com/itmill/toolkit/terminal/gwt/client/ComponentDetailMap.java [new file with mode: 0644]
src/com/itmill/toolkit/terminal/gwt/client/ui/layout/CellBasedLayout.java

index 00d43c3efbae76c13b1cadf2ea19af860431eeae..47e1f06d52c1a2690f0edcdac1ca008b31ce1eea 100755 (executable)
@@ -72,15 +72,8 @@ public class ApplicationConnection {
 
     private final Vector<String> pendingVariables = new Vector<String>();
 
-    private final HashMap<String, Paintable> idToPaintable = new HashMap<String, Paintable>();
-
-    private final HashMap<Paintable, String> paintableToId = new HashMap<Paintable, String>();
-
-    /** Contains ExtendedTitleInfo by paintable id */
-    private final HashMap<Paintable, TooltipInfo> paintableToTitle = new HashMap<Paintable, TooltipInfo>();
-
-    private final HashMap<Widget, FloatSize> componentRelativeSizes = new HashMap<Widget, FloatSize>();
-    private final HashMap<Widget, Size> componentOffsetSizes = new HashMap<Widget, Size>();
+    private final ComponentDetailMap idToPaintableDetail = ComponentDetailMap
+            .create();
 
     private final WidgetSet widgetSet;
 
@@ -516,7 +509,7 @@ public class ApplicationConnection {
         for (int i = 1; i < variableBurst.size(); i += 2) {
             String id = variableBurst.get(i);
             id = id.substring(0, id.indexOf(VAR_FIELD_SEPARATOR));
-            if (!idToPaintable.containsKey(id)) {
+            if (!idToPaintableDetail.containsKey(id)) {
                 // variable owner does not exist anymore
                 variableBurst.remove(i - 1);
                 variableBurst.remove(i - 1);
@@ -622,8 +615,7 @@ public class ApplicationConnection {
             meta = ((JSONObject) json).get("meta").isObject();
             if (meta.containsKey("repaintAll")) {
                 view.clear();
-                idToPaintable.clear();
-                paintableToId.clear();
+                idToPaintableDetail.clear();
                 if (meta.containsKey("invalidLayouts")) {
                     validatingLayouts = true;
                     zeroWidthComponents = new HashSet<Paintable>();
@@ -667,12 +659,14 @@ public class ApplicationConnection {
                     // it partially did at some part but now broken.
                 }
                 final UIDL uidl = change.getChildUIDL(0);
+                // TODO optimize
                 final Paintable paintable = getPaintable(uidl.getId());
                 if (paintable != null) {
                     paintable.updateFromUIDL(uidl, this);
                     // paintable may have changed during render to another
                     // implementation, use the new one for updated widgets map
-                    updatedWidgets.add(idToPaintable.get(uidl.getId()));
+                    updatedWidgets.add(idToPaintableDetail.get(uidl.getId())
+                            .getComponent());
                 } else {
                     if (!uidl.getTag().equals("window")) {
                         ClientExceptionHandler
@@ -696,14 +690,15 @@ public class ApplicationConnection {
         sizeUpdatedWidgets.addAll(componentCaptionSizeChanges);
 
         for (Paintable paintable : updatedWidgets) {
+            ComponentDetail detail = idToPaintableDetail.get(getPid(paintable));
             Widget widget = (Widget) paintable;
-            Size oldSize = componentOffsetSizes.get(widget);
+            Size oldSize = detail.getOffsetSize();
             Size newSize = new Size(widget.getOffsetWidth(), widget
                     .getOffsetHeight());
 
             if (oldSize == null || !oldSize.equals(newSize)) {
                 sizeUpdatedWidgets.add(paintable);
-                componentOffsetSizes.put(widget, newSize);
+                detail.setOffsetSize(newSize);
             }
 
         }
@@ -753,7 +748,7 @@ public class ApplicationConnection {
         final long prosessingTime = (new Date().getTime()) - start.getTime();
         console.log(" Processing time was " + String.valueOf(prosessingTime)
                 + "ms for " + jsonText.length() + " characters of JSON");
-        console.log("Referenced paintables: " + idToPaintable.size());
+        console.log("Referenced paintables: " + idToPaintableDetail.size());
 
         endRequest();
     }
@@ -783,16 +778,29 @@ public class ApplicationConnection {
      }-*/;
 
     public void registerPaintable(String id, Paintable paintable) {
-        idToPaintable.put(id, paintable);
-        paintableToId.put(paintable, id);
+        ComponentDetail componentDetail = new ComponentDetail();
+        componentDetail.setComponent(paintable);
+        idToPaintableDetail.put(id, componentDetail);
+        setPid(((Widget) paintable).getElement(), id);
     }
 
-    public void unregisterPaintable(Paintable p) {
-        String id = paintableToId.get(p);
-        idToPaintable.remove(id);
-        paintableToTitle.remove(id);
-        paintableToId.remove(p);
+    private native void setPid(Element el, String pid)
+    /*-{
+        el.tkPid = pid;
+    }-*/;
+
+    private String getPid(Paintable paintable) {
+        return getPid(((Widget) paintable).getElement());
+    }
 
+    private native String getPid(Element el)
+    /*-{
+        return el.tkPid;
+    }-*/;
+
+    public void unregisterPaintable(Paintable p) {
+        String id = getPid(p);
+        idToPaintableDetail.remove(id);
         if (p instanceof HasWidgets) {
             unregisterChildPaintables((HasWidgets) p);
         }
@@ -817,7 +825,12 @@ public class ApplicationConnection {
      *            Paintable ID
      */
     public Paintable getPaintable(String id) {
-        return idToPaintable.get(id);
+        ComponentDetail componentDetail = idToPaintableDetail.get(id);
+        if (componentDetail == null) {
+            return null;
+        } else {
+            return componentDetail.getComponent();
+        }
     }
 
     private void addVariableToQueue(String paintableId, String variableName,
@@ -993,6 +1006,8 @@ public class ApplicationConnection {
      */
     public boolean updateComponent(Widget component, UIDL uidl,
             boolean manageCaption) {
+        ComponentDetail componentDetail = idToPaintableDetail
+                .get(getPid(component.getElement()));
 
         // If the server request that a cached instance should be used, do
         // nothing
@@ -1019,7 +1034,7 @@ public class ApplicationConnection {
         if (!visible) {
             // component is invisible, delete old size to notify parent, if
             // later make visible
-            componentOffsetSizes.remove(component);
+            componentDetail.setOffsetSize(null);
             return true;
         }
 
@@ -1079,7 +1094,7 @@ public class ApplicationConnection {
             styleBuf.append(MODIFIED_CLASSNAME);
         }
 
-        TooltipInfo tooltipInfo = getTitleInfo((Paintable) component);
+        TooltipInfo tooltipInfo = componentDetail.getTooltipInfo();
         if (uidl.hasAttribute("description")) {
             tooltipInfo.setTitle(uidl.getStringAttribute("description"));
         } else {
@@ -1124,12 +1139,12 @@ public class ApplicationConnection {
          * taken into account
          */
 
-        updateComponentSize(component, uidl);
+        updateComponentSize(componentDetail, uidl);
 
         return false;
     }
 
-    private void updateComponentSize(Widget component, UIDL uidl) {
+    private void updateComponentSize(ComponentDetail cd, UIDL uidl) {
         String w = uidl.hasAttribute("width") ? uidl
                 .getStringAttribute("width") : "";
 
@@ -1144,18 +1159,20 @@ public class ApplicationConnection {
             // One or both is relative
             FloatSize relativeSize = new FloatSize(relativeWidth,
                     relativeHeight);
-            if (componentRelativeSizes.put(component, relativeSize) == null
-                    && componentOffsetSizes.containsKey(component)) {
+            if (cd.getRelativeSize() == null && cd.getOffsetSize() != null) {
                 // The component has changed from absolute size to relative size
-                relativeSizeChanges.add((Paintable) component);
+                relativeSizeChanges.add(cd.getComponent());
             }
+            cd.setRelativeSize(relativeSize);
         } else if (relativeHeight < 0.0 && relativeWidth < 0.0) {
-            if (componentRelativeSizes.remove(component) != null) {
+            if (cd.getRelativeSize() != null) {
                 // The component has changed from relative size to absolute size
-                relativeSizeChanges.add((Paintable) component);
+                relativeSizeChanges.add(cd.getComponent());
             }
+            cd.setRelativeSize(null);
         }
 
+        Widget component = (Widget) cd.getComponent();
         // Set absolute sizes
         if (relativeHeight < 0.0) {
             component.setHeight(h);
@@ -1167,7 +1184,7 @@ public class ApplicationConnection {
         // Set relative sizes
         if (relativeHeight >= 0.0 || relativeWidth >= 0.0) {
             // One or both is relative
-            handleComponentRelativeSize(component);
+            handleComponentRelativeSize(cd);
         }
 
     }
@@ -1197,7 +1214,11 @@ public class ApplicationConnection {
      * development. Published to JavaScript.
      */
     public void forceLayout() {
-        Util.componentSizeUpdated(paintableToId.keySet());
+        Set<Paintable> set = new HashSet<Paintable>();
+        for (ComponentDetail cd : idToPaintableDetail.values()) {
+            set.add(cd.getComponent());
+        }
+        Util.componentSizeUpdated(set);
     }
 
     private void internalRunDescendentsLayout(HasWidgets container) {
@@ -1232,15 +1253,12 @@ public class ApplicationConnection {
         }
     }
 
-    /**
-     * Converts relative sizes into pixel sizes.
-     * 
-     * @param child
-     * @return true if the child has a relative size
-     */
-    public boolean handleComponentRelativeSize(Widget child) {
-        Widget widget = child;
-        FloatSize relativeSize = getRelativeSize(child);
+    private boolean handleComponentRelativeSize(ComponentDetail cd) {
+        if (cd == null) {
+            return false;
+        }
+        Widget widget = (Widget) cd.getComponent();
+        FloatSize relativeSize = cd.getRelativeSize();
         if (relativeSize == null) {
             return false;
         }
@@ -1281,7 +1299,7 @@ public class ApplicationConnection {
                     height -= renderSpace.getScrollbarSize();
                 }
                 if (validatingLayouts && height <= 0) {
-                    zeroHeightComponents.add((Paintable) child);
+                    zeroHeightComponents.add(cd.getComponent());
                 }
 
                 height = (int) (height * relativeSize.getHeight() / 100.0);
@@ -1321,7 +1339,7 @@ public class ApplicationConnection {
                     width -= renderSpace.getScrollbarSize();
                 }
                 if (validatingLayouts && width <= 0) {
-                    zeroWidthComponents.add((Paintable) child);
+                    zeroWidthComponents.add(cd.getComponent());
                 }
 
                 width = (int) (width * relativeSize.getWidth() / 100.0);
@@ -1341,11 +1359,23 @@ public class ApplicationConnection {
         }
 
         return true;
+    }
+
+    /**
+     * Converts relative sizes into pixel sizes.
+     * 
+     * @param child
+     * @return true if the child has a relative size
+     */
+    public boolean handleComponentRelativeSize(Widget child) {
+        return handleComponentRelativeSize(idToPaintableDetail.get(getPid(child
+                .getElement())));
 
     }
 
     public FloatSize getRelativeSize(Widget widget) {
-        return componentRelativeSizes.get(widget);
+        return idToPaintableDetail.get(getPid(widget.getElement()))
+                .getRelativeSize();
     }
 
     /**
@@ -1365,10 +1395,12 @@ public class ApplicationConnection {
         Paintable w = getPaintable(id);
         if (w != null) {
             return w;
+        } else {
+            w = widgetSet.createWidget(uidl);
+            registerPaintable(id, w);
+            return w;
+
         }
-        w = widgetSet.createWidget(uidl);
-        registerPaintable(id, w);
-        return w;
     }
 
     public String getResource(String name) {
@@ -1448,12 +1480,7 @@ public class ApplicationConnection {
      * 
      */
     public TooltipInfo getTitleInfo(Paintable titleOwner) {
-        TooltipInfo info = paintableToTitle.get(titleOwner);
-        if (info == null) {
-            info = new TooltipInfo();
-            paintableToTitle.put(titleOwner, info);
-        }
-        return info;
+        return idToPaintableDetail.get(getPid(titleOwner)).getTooltipInfo();
     }
 
     private final ITooltip tooltip = new ITooltip(this);
diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ComponentDetail.java b/src/com/itmill/toolkit/terminal/gwt/client/ComponentDetail.java
new file mode 100644 (file)
index 0000000..7a47651
--- /dev/null
@@ -0,0 +1,88 @@
+package com.itmill.toolkit.terminal.gwt.client;
+
+import com.itmill.toolkit.terminal.gwt.client.RenderInformation.FloatSize;
+import com.itmill.toolkit.terminal.gwt.client.RenderInformation.Size;
+
+class ComponentDetail {
+    private String pid;
+    private Paintable component;
+    private TooltipInfo tooltipInfo = new TooltipInfo();
+    private FloatSize relativeSize;
+    private Size offsetSize;
+
+    /**
+     * @return the pid
+     */
+    String getPid() {
+        return pid;
+    }
+
+    /**
+     * @param pid
+     *            the pid to set
+     */
+    void setPid(String pid) {
+        this.pid = pid;
+    }
+
+    /**
+     * @return the component
+     */
+    Paintable getComponent() {
+        return component;
+    }
+
+    /**
+     * @param component
+     *            the component to set
+     */
+    void setComponent(Paintable component) {
+        this.component = component;
+    }
+
+    /**
+     * @return the tooltipInfo
+     */
+    TooltipInfo getTooltipInfo() {
+        return tooltipInfo;
+    }
+
+    /**
+     * @param tooltipInfo
+     *            the tooltipInfo to set
+     */
+    void setTooltipInfo(TooltipInfo tooltipInfo) {
+        this.tooltipInfo = tooltipInfo;
+    }
+
+    /**
+     * @return the relativeSize
+     */
+    FloatSize getRelativeSize() {
+        return relativeSize;
+    }
+
+    /**
+     * @param relativeSize
+     *            the relativeSize to set
+     */
+    void setRelativeSize(FloatSize relativeSize) {
+        this.relativeSize = relativeSize;
+    }
+
+    /**
+     * @return the offsetSize
+     */
+    Size getOffsetSize() {
+        return offsetSize;
+    }
+
+    /**
+     * @param offsetSize
+     *            the offsetSize to set
+     */
+    void setOffsetSize(Size offsetSize) {
+        this.offsetSize = offsetSize;
+    }
+
+}
diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ComponentDetailMap.java b/src/com/itmill/toolkit/terminal/gwt/client/ComponentDetailMap.java
new file mode 100644 (file)
index 0000000..cc7f474
--- /dev/null
@@ -0,0 +1,72 @@
+package com.itmill.toolkit.terminal.gwt.client;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import com.google.gwt.core.client.JavaScriptObject;
+
+final class ComponentDetailMap extends JavaScriptObject {
+
+    protected ComponentDetailMap() {
+    }
+
+    static ComponentDetailMap create() {
+        return (ComponentDetailMap) JavaScriptObject.createObject();
+    }
+
+    boolean isEmpty() {
+        return size() == 0;
+    }
+
+    final native boolean containsKey(String key)
+    /*-{
+        return this.hasOwnProperty(key);
+    }-*/;
+
+    final native ComponentDetail get(String key)
+    /*-{
+        return this[key];
+    }-*/;
+
+    final native void put(String id, ComponentDetail value)
+    /*-{
+        this[id] = value;
+    }-*/;
+
+    final native void remove(String id)
+    /*-{
+        delete this[id];
+    }-*/;
+
+    final native int size()
+    /*-{
+        var count = 0;
+        for(var key in this) {
+            count++;
+        }
+        return count;
+    }-*/;
+
+    final native void clear()
+    /*-{
+        for(var key in this) {
+            if(this.hasOwnProperty(key)) {
+                delete this[key];
+            }
+        }
+    }-*/;
+
+    private final native void fillWithValues(Collection<ComponentDetail> list)
+    /*-{
+        for(var key in this) {
+            list.@java.util.Collection::add(Ljava/lang/Object;)(this[key]);
+        }
+    }-*/;
+
+    final Collection<ComponentDetail> values() {
+        ArrayList<ComponentDetail> list = new ArrayList<ComponentDetail>();
+        fillWithValues(list);
+        return list;
+    }
+
+}
index 7e9258a436a6f326382524cbf0101dd5e035935c..f0a06c26dd60149ea13ab5d811e4651a2c3f7682 100644 (file)
@@ -6,7 +6,6 @@ import java.util.Map;
 import com.google.gwt.dom.client.DivElement;
 import com.google.gwt.dom.client.Document;
 import com.google.gwt.dom.client.Style;
-import com.google.gwt.user.client.Element;
 import com.google.gwt.user.client.ui.ComplexPanel;
 import com.google.gwt.user.client.ui.Widget;
 import com.itmill.toolkit.terminal.gwt.client.ApplicationConnection;
@@ -38,7 +37,7 @@ public abstract class CellBasedLayout extends ComplexPanel implements Container
 
     private boolean dynamicHeight;
 
-    private DivElement clearElement;
+    private final DivElement clearElement = Document.get().createDivElement();
 
     private String lastStyleName = "";
 
@@ -86,7 +85,6 @@ public abstract class CellBasedLayout extends ComplexPanel implements Container
 
         getElement().appendChild(root);
 
-        clearElement = Document.get().createDivElement();
         Style style = clearElement.getStyle();
         style.setProperty("width", "0px");
         style.setProperty("height", "0px");
@@ -163,9 +161,41 @@ public abstract class CellBasedLayout extends ComplexPanel implements Container
 
     protected void addOrMoveChild(ChildComponentContainer childComponent,
             int position) {
-        widgetToComponentContainer.put(childComponent.getWidget(),
-                childComponent);
-        super.insert(childComponent, (Element) root.cast(), position, true);
+        if (childComponent.getParent() == this) {
+            if (getWidgetIndex(childComponent) != position) {
+                // Detach from old position child.
+                childComponent.removeFromParent();
+
+                // Logical attach.
+                getChildren().insert(childComponent, position);
+
+                root.insertBefore(childComponent.getElement(), root
+                        .getChildNodes().getItem(position));
+
+                adopt(childComponent);
+            }
+        } else {
+            widgetToComponentContainer.put(childComponent.getWidget(),
+                    childComponent);
+
+            // Logical attach.
+            getChildren().insert(childComponent, position);
+
+            // avoid inserts (they are slower than appends)
+            boolean insert = true;
+            if (widgetToComponentContainer.size() == position) {
+                insert = false;
+            }
+            if (insert) {
+                root.insertBefore(childComponent.getElement(), root
+                        .getChildNodes().getItem(position));
+            } else {
+                root.insertBefore(childComponent.getElement(), clearElement);
+            }
+            // Adopt.
+            adopt(childComponent);
+
+        }
 
     }