]> source.dussan.org Git - vaadin-framework.git/commitdiff
Add columns at once in a batched way to increase performance (#11261)
authorericflock <40864945+ericflock@users.noreply.github.com>
Tue, 6 Nov 2018 10:47:31 +0000 (11:47 +0100)
committerOlli Tietäväinen <ollit@vaadin.com>
Tue, 6 Nov 2018 10:47:31 +0000 (12:47 +0200)
* provide possibility to add columns in a batched way

This is the basis to increase the performance for further changes.

* add the columns at once to the grid to increase performance

* combined performance fixes

* respect the column order

* Fixed formatting

client/src/main/java/com/vaadin/client/connectors/GridConnector.java
client/src/main/java/com/vaadin/client/widgets/Grid.java

index 6b9e9254974652f5bbc2f4fb431d16a1e6ceb781..cecfb726dc3235e4001c88235591515381b9faaf 100644 (file)
@@ -178,6 +178,28 @@ public class GridConnector extends AbstractHasComponentsConnector
             this.id = id;
         }
 
+        /**
+         * Creates and initializes a custom grid column with attributes of given state.
+         *
+         * @param state with attributes to initialize the column.
+         */
+        @SuppressWarnings("unchecked")
+        private CustomGridColumn(GridColumnState state) {
+            this(state.id, (AbstractRendererConnector<Object>) state.rendererConnector);
+            this.hidingToggleCaption = state.hidingToggleCaption;
+            this.hidden = state.hidden;
+            this.hidable = state.hidable;
+            this.resizable = state.resizable;
+            this.sortable = state.sortable;
+            this.headerCaption = state.headerCaption == null ? "" : state.headerCaption;
+            this.widthUser = state.width;
+            this.minimumWidthPx = state.minWidth;
+            this.maximumWidthPx = state.maxWidth;
+            this.expandRatio = state.expandRatio;
+            this.editable = state.editable;
+            setEditorConnector((AbstractComponentConnector) state.editorConnector);
+        }
+
         /**
          * Sets a new renderer for this column object
          *
@@ -909,7 +931,7 @@ public class GridConnector extends AbstractHasComponentsConnector
         super.onStateChanged(stateChangeEvent);
 
         initialChange = stateChangeEvent.isInitialStateChange();
-        
+
         if (initialChange) {
             Scheduler.get().scheduleFinally(new ScheduledCommand() {
                 @Override
@@ -931,15 +953,10 @@ public class GridConnector extends AbstractHasComponentsConnector
             // Remove old columns
             purgeRemovedColumns();
 
-            // Add new columns
-            for (GridColumnState state : getState().columns) {
-                if (!columnIdToColumn.containsKey(state.id)) {
-                    addColumnFromStateChangeEvent(state);
-                }
-                updateColumnFromStateChangeEvent(state);
-            }
+            // Update all columns
+            updateColumnsFromState();
         }
-        
+
         if (stateChangeEvent.hasPropertyChanged("columnOrder")) {
             if (orderNeedsUpdate(getState().columnOrder)) {
                 updateColumnOrderFromState(getState().columnOrder);
@@ -1138,37 +1155,33 @@ public class GridConnector extends AbstractHasComponentsConnector
         cell.setStyleName(cellState.styleName);
     }
 
-    /**
-     * Updates a column from a state change event.
-     *
-     * @param columnIndex
-     *            The index of the column to update
-     */
-    private void updateColumnFromStateChangeEvent(GridColumnState columnState) {
-        CustomGridColumn column = columnIdToColumn.get(columnState.id);
-
-        columnsUpdatedFromState = true;
-        updateColumnFromState(column, columnState);
-        columnsUpdatedFromState = false;
-    }
 
     /**
-     * Adds a new column to the grid widget from a state change event
+     * Update columns from the current state.
      *
-     * @param columnIndex
-     *            The index of the column, according to how it
      */
-    private void addColumnFromStateChangeEvent(GridColumnState state) {
+    private void updateColumnsFromState() {
+        this.columnsUpdatedFromState = true;
+        final List<Column<?, JsonObject>> columns = new ArrayList<Column<?, JsonObject>>(getState().columns.size());
+        for (String columnId : getState().columnOrder) {
+            for (GridColumnState state : getState().columns) {
+                if (state.id.equals(columnId)) {
+                    CustomGridColumn column = this.columnIdToColumn.get(state.id);
+                    if (column == null) {
+                        column = new CustomGridColumn(state);
+                        this.columnIdToColumn.put(state.id, column);
+                        this.columnOrder.add(state.id);
+                        columns.add(column);
+                    } else {
+                        updateColumnFromState(column, state);
+                    }
+                }
+            }
+        }
         @SuppressWarnings("unchecked")
-        CustomGridColumn column = new CustomGridColumn(state.id,
-                ((AbstractRendererConnector<Object>) state.rendererConnector));
-        columnIdToColumn.put(state.id, column);
-
-        /*
-         * Add column to grid. Reordering is handled as a separate problem.
-         */
-        getWidget().addColumn(column);
-        columnOrder.add(state.id);
+        final Column<?, JsonObject>[] columnArray = columns.toArray(new Column[0]);
+        getWidget().addColumns(columnArray);
+        this.columnsUpdatedFromState = false;
     }
 
     /**
index b0bb391050993bb70d71440b2736f91d158582c3..4f0b012a0033106209ac5d7a09d9cfd2c0a707b7 100755 (executable)
@@ -4772,33 +4772,65 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
         private Grid<T> grid;
 
         /**
-         * Width of column in pixels as {@link #setWidth(double)} has been
-         * called
+         * Width of column in pixels as {@link #setWidth(double)} has been called.
          */
-        private double widthUser = GridConstants.DEFAULT_COLUMN_WIDTH_PX;
+        protected double widthUser = GridConstants.DEFAULT_COLUMN_WIDTH_PX;
 
         /**
          * Renderer for rendering a value into the cell
          */
         private Renderer<? super C> bodyRenderer;
 
-        private boolean sortable = false;
+        /**
+         * The sortable state of this column.
+         */
+        protected boolean sortable = false;
 
-        private boolean editable = true;
+        /**
+         * The editable state of this column.
+         */
+        protected boolean editable = true;
+
+        /**
+         * The resizable state of this column.
+         */
+        protected boolean resizable = true;
+
+        /**
+         * The hidden state of this column.
+         */
+        protected boolean hidden = false;
+
+        /**
+         * The hidable state of this column.
+         */
+        protected boolean hidable = false;
 
-        private boolean resizable = true;
+        /**
+         * The header-caption of this column.
+         */
+        protected String headerCaption = "";
 
-        private boolean hidden = false;
+        /**
+         * The hiding-toggle-caption of this column.
+         */
+        protected String hidingToggleCaption = null;
 
-        private boolean hidable = false;
+        /**
+         * The minimum width in pixels of this column.
+         */
+        protected double minimumWidthPx = GridConstants.DEFAULT_MIN_WIDTH;
 
-        private String headerCaption = "";
+        /**
+         * The maximum width in pixels of this column.
+         */
+        protected double maximumWidthPx = GridConstants.DEFAULT_MAX_WIDTH;
 
-        private String hidingToggleCaption = null;
+        /**
+         * The expand ratio of this column.
+         */
+        protected int expandRatio = GridConstants.DEFAULT_EXPAND_RATIO;
 
-        private double minimumWidthPx = GridConstants.DEFAULT_MIN_WIDTH;
-        private double maximumWidthPx = GridConstants.DEFAULT_MAX_WIDTH;
-        private int expandRatio = GridConstants.DEFAULT_EXPAND_RATIO;
 
         /**
          * Constructs a new column with a simple TextRenderer.
@@ -6419,9 +6451,24 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      *            the columns to add
      */
     public void addColumns(Column<?, T>... columns) {
-        int count = getColumnCount();
+        final int count = getColumnCount();
         for (Column<?, T> column : columns) {
-            addColumn(column, count++);
+            checkColumnIsValidToAdd(column, count);
+        }
+        addColumnsSkipSelectionColumnCheck(Arrays.asList(columns), count);
+    }
+
+
+    /**
+     * Checks the given column is valid to add at the given index.
+     */
+    private void checkColumnIsValidToAdd(Column<?, T> column, int index) {
+        if (column == this.selectionColumn) {
+            throw new IllegalArgumentException(
+                    "The selection column many " + "not be added manually");
+        } else if (this.selectionColumn != null && index == 0) {
+            throw new IllegalStateException("A column cannot be inserted "
+                    + "before the selection column");
         }
     }
 
@@ -6451,53 +6498,56 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      *             and {@code index} is 0.
      */
     public <C extends Column<?, T>> C addColumn(C column, int index) {
-        if (column == selectionColumn) {
-            throw new IllegalArgumentException(
-                    "The selection column many " + "not be added manually");
-        } else if (selectionColumn != null && index == 0) {
-            throw new IllegalStateException("A column cannot be inserted "
-                    + "before the selection column");
-        }
-
-        addColumnSkipSelectionColumnCheck(column, index);
+        checkColumnIsValidToAdd(column, index);
+        addColumnsSkipSelectionColumnCheck(Collections.singleton(column), index);
         return column;
     }
 
-    private void addColumnSkipSelectionColumnCheck(Column<?, T> column,
-            int index) {
-        // Register column with grid
-        columns.add(index, column);
 
-        header.addColumn(column);
-        footer.addColumn(column);
+    private <C extends Column<?, T>> void addColumnsSkipSelectionColumnCheck(Collection<C> columnCollection, int index) {
+        int visibleNewColumns = 0;
+        int currentIndex = index;
 
-        // Register this grid instance with the column
-        ((Column<?, T>) column).setGrid(this);
+        //prevent updates of hiding toggles.
+        //it will be updated finally all at once.
+        this.columnHider.hidingColumn = true;
 
-        // Grid knows about hidden columns, Escalator only knows about what is
-        // visible so column indexes do not match
-        if (!column.isHidden()) {
-            int escalatorIndex = index;
-            for (int existingColumn = 0; existingColumn < index; existingColumn++) {
-                if (getColumn(existingColumn).isHidden()) {
-                    escalatorIndex--;
-                }
+        for (final Column<?, T> column : columnCollection) {
+            // Register column with grid
+            this.columns.add(currentIndex++, column);
+            this.footer.addColumn(column);
+            this.header.addColumn(column);
+
+            // Register this grid instance with the column
+            column.setGrid(this);
+
+            if (!column.isHidden()) {
+                visibleNewColumns++;
             }
-            escalator.getColumnConfiguration().insertColumns(escalatorIndex, 1);
+        }
+        if (visibleNewColumns > 0) {
+            final ColumnConfiguration columnConfiguration = this.escalator.getColumnConfiguration();
+            columnConfiguration.insertColumns(index, visibleNewColumns);
         }
 
-        // Reapply column width
-        column.reapplyWidth();
-
-        // Sink all renderer events
-        Set<String> events = new HashSet<String>();
-        events.addAll(getConsumedEventsForRenderer(column.getRenderer()));
+        for (final Column<?, T> column : columnCollection) {
+            // Reapply column width
+            column.reapplyWidth();
+            // Sink all renderer events
+            final Set<String> events = new HashSet<String>();
+            events.addAll(getConsumedEventsForRenderer(column.getRenderer()));
 
-        if (column.isHidable()) {
-            columnHider.updateColumnHidable(column);
+            if (column.isHidable()) {
+                this.columnHider.updateColumnHidable(column);
+            }
+            sinkEvents(events);
         }
-
-        sinkEvents(events);
+        //now we do the update of the hiding toggles.
+        this.columnHider.hidingColumn = false;
+        this.columnHider.updateTogglesOrder();
+        refreshHeader();
+        this.header.updateColSpans();
+        this.footer.updateColSpans();
     }
 
     private void sinkEvents(Collection<String> events) {
@@ -7891,7 +7941,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
             cellFocusHandler.offsetRangeBy(1);
             selectionColumn = new SelectionColumn(selectColumnRenderer);
 
-            addColumnSkipSelectionColumnCheck(selectionColumn, 0);
+            addColumnsSkipSelectionColumnCheck(Collections.singleton(selectionColumn), 0);
 
             selectionColumn.setEnabled(isEnabled());
             selectionColumn.initDone();