diff options
author | Leif Åstrand <leif@vaadin.com> | 2015-03-27 13:57:51 +0200 |
---|---|---|
committer | Vaadin Code Review <review@vaadin.com> | 2015-03-30 12:08:19 +0000 |
commit | 103b329d328ab0dde95da9426462491be510a8be (patch) | |
tree | 2ef6172c21970a396138d59f470993f5de5349d9 /client | |
parent | 722072bb53f0699bc337446048db2beade0df421 (diff) | |
download | vaadin-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.java | 110 |
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. * |