From af995de3b110987114435281047c0c31a164eaa6 Mon Sep 17 00:00:00 2001 From: Henri Sara Date: Thu, 22 Aug 2013 11:55:38 +0300 Subject: [PATCH] Optimize large Vertical/HorizontalLayout client side (#12420, #10899) Spacing is now only handled at the beginning and end of hierarchy updates, not for every component separately. Some more profiling data on potential hotspots is also generated when Profiler is used. Change-Id: Ief1138dfd9161b683f69513e3458b8174de592bc --- .../AbstractOrderedLayoutConnector.java | 18 +++++- .../orderedlayout/VAbstractOrderedLayout.java | 57 +++++++++++++++---- 2 files changed, 62 insertions(+), 13 deletions(-) diff --git a/client/src/com/vaadin/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java b/client/src/com/vaadin/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java index cea993310f..45cc18f3dc 100644 --- a/client/src/com/vaadin/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java +++ b/client/src/com/vaadin/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java @@ -294,7 +294,11 @@ public abstract class AbstractOrderedLayoutConnector extends int currentIndex = 0; VAbstractOrderedLayout layout = getWidget(); - layout.setSpacing(getState().spacing); + // remove spacing as it is exists as separate elements that cannot be + // removed easily after reordering the contents + Profiler.enter("AOLC.onConnectorHierarchyChange addOrMoveSlot temporarily remove spacing"); + layout.setSpacing(false); + Profiler.leave("AOLC.onConnectorHierarchyChange addOrMoveSlot temporarily remove spacing"); for (ComponentConnector child : getChildComponents()) { Profiler.enter("AOLC.onConnectorHierarchyChange add children"); @@ -305,12 +309,20 @@ public abstract class AbstractOrderedLayoutConnector extends Profiler.leave("AOLC.onConnectorHierarchyChange add state change handler"); } Profiler.enter("AOLC.onConnectorHierarchyChange addOrMoveSlot"); - layout.addOrMoveSlot(slot, currentIndex++); + layout.addOrMoveSlot(slot, currentIndex++, false); Profiler.leave("AOLC.onConnectorHierarchyChange addOrMoveSlot"); Profiler.leave("AOLC.onConnectorHierarchyChange add children"); } + // re-add spacing for the elements that should have it + Profiler.enter("AOLC.onConnectorHierarchyChange addOrMoveSlot setSpacing"); + // spacings were removed above + if (getState().spacing) { + layout.setSpacing(true); + } + Profiler.leave("AOLC.onConnectorHierarchyChange addOrMoveSlot setSpacing"); + for (ComponentConnector child : previousChildren) { Profiler.enter("AOLC.onConnectorHierarchyChange remove children"); if (child.getParent() != this) { @@ -325,7 +337,7 @@ public abstract class AbstractOrderedLayoutConnector extends child.removeStateChangeHandler(childStateChangeHandler); layout.removeWidget(child.getWidget()); } - Profiler.leave("AOL.onConnectorHierarchyChange remove children"); + Profiler.leave("AOLC.onConnectorHierarchyChange remove children"); } Profiler.leave("AOLC.onConnectorHierarchyChange"); diff --git a/client/src/com/vaadin/client/ui/orderedlayout/VAbstractOrderedLayout.java b/client/src/com/vaadin/client/ui/orderedlayout/VAbstractOrderedLayout.java index b5a6262693..a2c03eaed1 100644 --- a/client/src/com/vaadin/client/ui/orderedlayout/VAbstractOrderedLayout.java +++ b/client/src/com/vaadin/client/ui/orderedlayout/VAbstractOrderedLayout.java @@ -31,6 +31,7 @@ import com.google.gwt.user.client.ui.RequiresResize; import com.google.gwt.user.client.ui.Widget; import com.vaadin.client.BrowserInfo; import com.vaadin.client.LayoutManager; +import com.vaadin.client.Profiler; import com.vaadin.client.Util; import com.vaadin.shared.ui.MarginInfo; @@ -62,6 +63,23 @@ public class VAbstractOrderedLayout extends FlowPanel { this.vertical = vertical; } + /** + * See the method {@link #addOrMoveSlot(Slot, int, boolean)}. + * + *

+ * This method always adjusts spacings for the whole layout. + * + * @param slot + * The slot to move or add + * @param index + * The index where the slot should be placed. + * @deprecated since 7.1.4, use {@link #addOrMoveSlot(Slot, int, boolean)} + */ + @Deprecated + public void addOrMoveSlot(Slot slot, int index) { + addOrMoveSlot(slot, index, true); + } + /** * Add or move a slot to another index. *

@@ -83,27 +101,42 @@ public class VAbstractOrderedLayout extends FlowPanel { * * * When using this method never account for spacings. + *

+ * The caller should remove all spacings before calling this method and + * re-add them (if necessary) after this method. This can be done before and + * after all slots have been added/moved. *

* + * @since 7.1.4 + * * @param slot * The slot to move or add * @param index * The index where the slot should be placed. + * @param adjustSpacing + * true to recalculate spacings for the whole layout after the + * operation */ - public void addOrMoveSlot(Slot slot, int index) { + public void addOrMoveSlot(Slot slot, int index, boolean adjustSpacing) { + Profiler.enter("VAOL.onConnectorHierarchyChange addOrMoveSlot find index"); if (slot.getParent() == this) { int currentIndex = getWidgetIndex(slot); if (index == currentIndex) { + Profiler.leave("VAOL.onConnectorHierarchyChange addOrMoveSlot find index"); return; } } + Profiler.leave("VAOL.onConnectorHierarchyChange addOrMoveSlot find index"); + Profiler.enter("VAOL.onConnectorHierarchyChange addOrMoveSlot insert"); insert(slot, index); + Profiler.leave("VAOL.onConnectorHierarchyChange addOrMoveSlot insert"); - /* - * We need to confirm spacings are correctly applied after each insert. - */ - setSpacing(spacing); + if (adjustSpacing) { + Profiler.enter("VAOL.onConnectorHierarchyChange addOrMoveSlot setSpacing"); + setSpacing(spacing); + Profiler.leave("VAOL.onConnectorHierarchyChange addOrMoveSlot setSpacing"); + } } /** @@ -329,14 +362,18 @@ public class VAbstractOrderedLayout extends FlowPanel { * True if spacing should be used, false if not */ public void setSpacing(boolean spacing) { + Profiler.enter("VAOL.onConnectorHierarchyChange setSpacing"); this.spacing = spacing; + // first widget does not have spacing on + // optimization to avoid looking up widget indices on every iteration + Slot firstSlot = null; + if (getWidgetCount() > 0) { + firstSlot = widgetToSlot.get(getWidget(0)); + } for (Slot slot : widgetToSlot.values()) { - if (getWidgetIndex(slot) > 0) { - slot.setSpacing(spacing); - } else { - slot.setSpacing(false); - } + slot.setSpacing(spacing && firstSlot != slot); } + Profiler.leave("VAOL.onConnectorHierarchyChange setSpacing"); } /** -- 2.39.5