diff options
author | Matti Tahvonen <matti.tahvonen@itmill.com> | 2009-01-29 14:11:49 +0000 |
---|---|---|
committer | Matti Tahvonen <matti.tahvonen@itmill.com> | 2009-01-29 14:11:49 +0000 |
commit | a65c7b1d2e592f1473e1889662c0dd70d67d33be (patch) | |
tree | 6c53c51d52b8dc4449ce564440397ac58c77637a | |
parent | fdd97dd3b3659ffc0e11d2656b39ce802fd319d6 (diff) | |
download | vaadin-framework-a65c7b1d2e592f1473e1889662c0dd70d67d33be.tar.gz vaadin-framework-a65c7b1d2e592f1473e1889662c0dd70d67d33be.zip |
#2519, #2520 optimized usage of hasmaps in ac + dom inserts in cellbasedlayout
svn changeset:6676/svn branch:trunk
4 files changed, 279 insertions, 62 deletions
diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java b/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java index 00d43c3efb..47e1f06d52 100755 --- a/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java @@ -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 index 0000000000..7a47651332 --- /dev/null +++ b/src/com/itmill/toolkit/terminal/gwt/client/ComponentDetail.java @@ -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 index 0000000000..cc7f474a06 --- /dev/null +++ b/src/com/itmill/toolkit/terminal/gwt/client/ComponentDetailMap.java @@ -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; + } + +} diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/layout/CellBasedLayout.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/layout/CellBasedLayout.java index 7e9258a436..f0a06c26dd 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/layout/CellBasedLayout.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/layout/CellBasedLayout.java @@ -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); + + } } |