aboutsummaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
authorLeif Åstrand <leif@vaadin.com>2015-03-27 13:57:51 +0200
committerVaadin Code Review <review@vaadin.com>2015-03-30 12:08:19 +0000
commit103b329d328ab0dde95da9426462491be510a8be (patch)
tree2ef6172c21970a396138d59f470993f5de5349d9 /client
parent722072bb53f0699bc337446048db2beade0df421 (diff)
downloadvaadin-framework-103b329d328ab0dde95da9426462491be510a8be.tar.gz
vaadin-framework-103b329d328ab0dde95da9426462491be510a8be.zip
Reduce reflows when sizing columns (#17315)
This patch increases the reported fps from 10 to 17 in Chrome and from 5 to 10 in Firefox. No automatic test since performance testing on our shared testing infrastructure would be quite error-prone. Change-Id: I0bb6af250743058a8f32bb2df89da97660e94b52
Diffstat (limited to 'client')
-rw-r--r--client/src/com/vaadin/client/widgets/Escalator.java110
1 files changed, 72 insertions, 38 deletions
diff --git a/client/src/com/vaadin/client/widgets/Escalator.java b/client/src/com/vaadin/client/widgets/Escalator.java
index 3d4459a0cc..83c176d6fd 100644
--- a/client/src/com/vaadin/client/widgets/Escalator.java
+++ b/client/src/com/vaadin/client/widgets/Escalator.java
@@ -16,6 +16,7 @@
package com.vaadin.client.widgets;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
@@ -2010,9 +2011,8 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker
return new Cell(domRowIndex, domColumnIndex, cellElement);
}
- double getMaxCellWidth(int colIndex) throws IllegalArgumentException {
- double maxCellWidth = -1;
-
+ void createAutoSizeElements(int colIndex,
+ Collection<TableCellElement> elements) {
assert isAttached() : "Can't measure max width of cell, since Escalator is not attached to the DOM.";
NodeList<TableRowElement> rows = root.getRows();
@@ -2041,24 +2041,9 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker
cellClone.getStyle().clearWidth();
rowElement.insertBefore(cellClone, cellOriginal);
- double requiredWidth = WidgetUtil
- .getRequiredWidthBoundingClientRectDouble(cellClone);
-
- if (BrowserInfo.get().isIE()) {
- /*
- * IE browsers have some issues with subpixels. Occasionally
- * content is overflown even if not necessary. Increase the
- * counted required size by 0.01 just to be on the safe
- * side.
- */
- requiredWidth += 0.01;
- }
- maxCellWidth = Math.max(requiredWidth, maxCellWidth);
- cellClone.removeFromParent();
+ elements.add(cellClone);
}
-
- return maxCellWidth;
}
private boolean cellIsPartOfSpan(TableCellElement cell) {
@@ -3789,7 +3774,8 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker
if (px < 0) {
if (isAttached()) {
- calculateWidth();
+ autosizeColumns(Collections.singletonList(columns
+ .indexOf(this)));
} else {
/*
* the column's width is calculated at Escalator.onLoad
@@ -3843,10 +3829,6 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker
}
return false;
}
-
- private void calculateWidth() {
- calculatedWidth = getMaxCellWidth(columns.indexOf(this));
- }
}
private final List<Column> columns = new ArrayList<Column>();
@@ -4151,6 +4133,7 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker
return;
}
+ List<Integer> autosizeColumns = new ArrayList<Integer>();
for (Entry<Integer, Double> entry : indexWidthMap.entrySet()) {
int index = entry.getKey().intValue();
double width = entry.getValue().doubleValue();
@@ -4160,10 +4143,15 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker
}
checkValidColumnIndex(index);
- columns.get(index).setWidth(width);
-
+ if (width >= 0) {
+ columns.get(index).setWidth(width);
+ } else {
+ autosizeColumns.add(index);
+ }
}
+ autosizeColumns(autosizeColumns);
+
widthsArray = null;
header.reapplyColumnWidths();
body.reapplyColumnWidths();
@@ -4174,6 +4162,64 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker
recalculateElementSizes();
}
+ private void autosizeColumns(List<Integer> columns) {
+ if (columns.isEmpty()) {
+ return;
+ }
+
+ // Must process columns in index order
+ Collections.sort(columns);
+
+ Map<Integer, List<TableCellElement>> autoSizeElements = new HashMap<Integer, List<TableCellElement>>();
+ try {
+ // Set up the entire DOM at once
+ for (int i = columns.size() - 1; i >= 0; i--) {
+ // Iterate backwards to not mess with the indexing
+ Integer colIndex = columns.get(i);
+
+ ArrayList<TableCellElement> elements = new ArrayList<TableCellElement>();
+ autoSizeElements.put(colIndex, elements);
+
+ header.createAutoSizeElements(colIndex, elements);
+ body.createAutoSizeElements(colIndex, elements);
+ footer.createAutoSizeElements(colIndex, elements);
+ }
+
+ // Extract all measurements & update values
+ for (Integer colIndex : columns) {
+ double maxWidth = Double.NEGATIVE_INFINITY;
+ List<TableCellElement> elements = autoSizeElements
+ .get(colIndex);
+ for (TableCellElement element : elements) {
+
+ double cellWidth = WidgetUtil
+ .getRequiredWidthBoundingClientRectDouble(element);
+
+ maxWidth = Math.max(maxWidth, cellWidth);
+ }
+ assert maxWidth >= 0 : "Got a negative max width for a column, which should be impossible.";
+
+ if (BrowserInfo.get().isIE()) {
+ /*
+ * IE browsers have some issues with subpixels.
+ * Occasionally content is overflown even if not
+ * necessary. Increase the counted required size by 0.01
+ * just to be on the safe side.
+ */
+ maxWidth += 0.01;
+ }
+
+ this.columns.get(colIndex).calculatedWidth = maxWidth;
+ }
+ } finally {
+ for (List<TableCellElement> list : autoSizeElements.values()) {
+ for (TableCellElement element : list) {
+ element.removeFromParent();
+ }
+ }
+ }
+ }
+
private void checkValidColumnIndex(int index)
throws IllegalArgumentException {
if (!Range.withLength(0, getColumnCount()).contains(index)) {
@@ -4193,18 +4239,6 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker
return columns.get(index).getCalculatedWidth();
}
- private double getMaxCellWidth(int colIndex)
- throws IllegalArgumentException {
- double headerWidth = header.getMaxCellWidth(colIndex);
- double bodyWidth = body.getMaxCellWidth(colIndex);
- double footerWidth = footer.getMaxCellWidth(colIndex);
-
- double maxWidth = Math.max(headerWidth,
- Math.max(bodyWidth, footerWidth));
- assert maxWidth >= 0 : "Got a negative max width for a column, which should be impossible.";
- return maxWidth;
- }
-
/**
* Calculates the width of the columns in a given range.
*