Skip to content

Commit

Permalink
Fix Grid initial render performance (#10579)
Browse files Browse the repository at this point in the history
Fixes #10232
  • Loading branch information
tsuoanttila authored and Teemu Suo-Anttila committed Feb 13, 2018
1 parent 1277ebb commit 8f06444
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 78 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ public void onUnregister() {
// If the grid itself was unregistered there is no point in spending
// time to remove columns (and have problems with frozen columns)
// before throwing everything away
parent.removeColumn(column);
parent.removeColumnMapping(column);
parent = null;
}
column = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import com.vaadin.client.TooltipInfo;
import com.vaadin.client.WidgetUtil;
import com.vaadin.client.annotations.OnStateChange;
import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.connectors.AbstractListingConnector;
import com.vaadin.client.connectors.grid.ColumnConnector.CustomColumn;
import com.vaadin.client.data.DataSource;
Expand All @@ -56,6 +57,7 @@
import com.vaadin.client.widgets.Grid.Column;
import com.vaadin.client.widgets.Grid.FooterRow;
import com.vaadin.client.widgets.Grid.HeaderRow;
import com.vaadin.client.widgets.Grid.SelectionColumn;
import com.vaadin.shared.MouseEventDetails;
import com.vaadin.shared.data.sort.SortDirection;
import com.vaadin.shared.ui.Connect;
Expand Down Expand Up @@ -227,14 +229,12 @@ public void scrollToRow(int row, ScrollDestination destination) {

@Override
public void scrollToStart() {
Scheduler.get()
.scheduleFinally(() -> getWidget().scrollToStart());
Scheduler.get().scheduleFinally(() -> grid.scrollToStart());
}

@Override
public void scrollToEnd() {
Scheduler.get()
.scheduleFinally(() -> getWidget().scrollToEnd());
Scheduler.get().scheduleFinally(() -> grid.scrollToEnd());
addDetailsRefreshCallback(() -> {
if (rowHasDetails(getWidget().getDataSource().size() - 1)) {
getWidget().scrollToEnd();
Expand All @@ -252,7 +252,8 @@ public void recalculateColumnWidths() {
getWidget().setRowStyleGenerator(rowRef -> {
JsonObject json = rowRef.getRow();
return json.hasKey(GridState.JSONKEY_ROWSTYLE)
? json.getString(GridState.JSONKEY_ROWSTYLE) : null;
? json.getString(GridState.JSONKEY_ROWSTYLE)
: null;
});
getWidget().setCellStyleGenerator(cellRef -> {
JsonObject row = cellRef.getRow();
Expand Down Expand Up @@ -308,13 +309,27 @@ public void recalculateColumnWidths() {
layout();
}

@SuppressWarnings("unchecked")
@OnStateChange("columnOrder")
@Override
public void onStateChanged(StateChangeEvent stateChangeEvent) {
super.onStateChanged(stateChangeEvent);

if (!getState().columnOrder.containsAll(idToColumn.keySet())) {
updateColumns();
} else if (stateChangeEvent.hasPropertyChanged("columnOrder")) {
updateColumnOrder();
}

if (stateChangeEvent.hasPropertyChanged("header")) {
updateHeader();
}
if (stateChangeEvent.hasPropertyChanged("footer")) {
updateFooter();
}
}

void updateColumnOrder() {
Scheduler.get()
.scheduleFinally(() -> getWidget().setColumnOrder(
getState().columnOrder.stream().map(this::getColumn)
.toArray(size -> new Column[size])));
getWidget().setColumnOrder(getState().columnOrder.stream()
.map(this::getColumn).toArray(size -> new CustomColumn[size]));
}

@OnStateChange("columnResizeMode")
Expand All @@ -325,7 +340,6 @@ void updateColumnResizeMode() {
/**
* Updates the grid header section on state change.
*/
@OnStateChange("header")
void updateHeader() {
final Grid<JsonObject> grid = getWidget();
final SectionState state = getState().header;
Expand Down Expand Up @@ -411,7 +425,6 @@ private void updateStaticCellFromState(Grid.StaticSection.StaticCell cell,
/**
* Updates the grid footer section on state change.
*/
@OnStateChange("footer")
void updateFooter() {
final Grid<JsonObject> grid = getWidget();
final SectionState state = getState().footer;
Expand Down Expand Up @@ -462,22 +475,68 @@ public void setDataSource(DataSource<JsonObject> dataSource) {
public void addColumn(CustomColumn column, String id) {
assert !columnToIdMap.containsKey(column) && !columnToIdMap
.containsValue(id) : "Column with given id already exists.";
getWidget().addColumn(column);
columnToIdMap.put(column, id);
idToColumn.put(id, column);

if (idToColumn.keySet().containsAll(getState().columnOrder)) {
// All columns are available.
updateColumns();
}
}

/**
* Updates the widgets columns to match the map in this connector.
*/
protected void updateColumns() {
List<Column<?, JsonObject>> currentColumns = getWidget().getColumns();

List<CustomColumn> columnOrder = getState().columnOrder.stream()
.map(this::getColumn).collect(Collectors.toList());

if (isColumnOrderCorrect(currentColumns, columnOrder)) {
// All up to date
return;
}

Grid<JsonObject> grid = getWidget();

// Remove old column
currentColumns.stream()
.filter(col -> !(columnOrder.contains(col)
|| col instanceof SelectionColumn))
.forEach(grid::removeColumn);

// Add new columns
grid.addColumns(columnOrder.stream()
.filter(col -> !currentColumns.contains(col))
.toArray(CustomColumn[]::new));

// Make sure order is correct.
grid.setColumnOrder(
columnOrder.toArray(new CustomColumn[columnOrder.size()]));
}

private boolean isColumnOrderCorrect(List<Column<?, JsonObject>> current,
List<CustomColumn> order) {
List<Column<?, JsonObject>> columnsToCompare = current;
if (current.size() > 0 && current.get(0) instanceof SelectionColumn) {
// Remove selection column.
columnsToCompare = current.subList(1, current.size());
}
return columnsToCompare.equals(order);
}

/**
* Removes a column from Grid widget. This method also removes communication
* id mapping for the column.
* Removes the given column from mappings in this Connector.
*
* @param column
* column to remove
* column to remove from the mapping
*/
public void removeColumn(CustomColumn column) {
public void removeColumnMapping(CustomColumn column) {
assert columnToIdMap
.containsKey(column) : "Given Column does not exist.";
getWidget().removeColumn(column);

// Remove mapping. Columns are removed from Grid when state changes.
String id = columnToIdMap.remove(column);
idToColumn.remove(id);
}
Expand Down Expand Up @@ -555,7 +614,6 @@ public List<ComponentConnector> getChildComponents() {
@Override
public void setChildComponents(List<ComponentConnector> children) {
childComponents = children;

}

@Override
Expand Down
Loading

0 comments on commit 8f06444

Please sign in to comment.