Skip to content
Snippets Groups Projects
Commit 2065ce00 authored by Ulrich Schöpp's avatar Ulrich Schöpp Committed by Ulrich Schöpp
Browse files

Improve update performance of DynamicTreeTableViewer


For models with larger data dictionaries, the update of the data
dictionary can become slow enough that editing element names becomes
difficult. This commit changes the DynamicTreeTableViewer such that
not the whole tree is re-build on every update. This solves the
issue with the data dictionaries.

Signed-off-by: default avatarUlrich Schöpp <schoepp@fortiss.org>
Issue-Ref: 4192
parent 31433bed
No related branches found
No related tags found
1 merge request!164Improve update performance of DynamicTreeTableViewer
Pipeline #32211 failed
......@@ -3,10 +3,10 @@ DynamicListContentProvider.java 817cba44f246a361207a88ef9a4e1869215803f7 GREEN
DynamicStreamContentProvider.java f46e91400609cba54793dd240be0fe2aa0d5cced GREEN
DynamicTextFieldTreeTableCell.java de24117e6f785b328f1ff62383626a0b4b54e8ff GREEN
DynamicTreeContentProviderBase.java 91896b1fb5104d126544c44c1ff8c30f2a13a8d6 GREEN
DynamicTreeItem.java 7486071d20e896d6ca9a9101bf105caccf3656d0 GREEN
DynamicTreeItem.java 2c4364e68d00f4ebd15cfbbdda7f991440ecc728 YELLOW
DynamicTreeItemBase.java d883066ecc181120302ca32f328538de7a45b093 GREEN
DynamicTreeTableUIProviderBase.java d150a4c379cc41aab2a44a5f1643f4956332c8e3 GREEN
DynamicTreeTableViewer.java cb289413d15159abbcccfea87d731738905b4b28 GREEN
DynamicTreeTableViewer.java 7ee2471bd403e4be19a3c12460f3af622b526357 YELLOW
DynamicTreeUIProviderBase.java 82d3c051213f0147f4c67ad247a08696cee73110 GREEN
DynamicTreeViewer.java 545f1ca10b7b3cad171b294a4b447875da45c9ed GREEN
DynamicTreeViewerBase.java a2013538b62d86f6a09efdf2cd78babac2072484 GREEN
......
......@@ -15,8 +15,10 @@
*******************************************************************************/
package org.fortiss.tooling.common.ui.javafx.control.treetableview;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import javafx.scene.control.TreeItem;
......@@ -37,24 +39,61 @@ public class DynamicTreeItem<T> extends DynamicTreeItemBase<T> {
/** {@inheritDoc} */
@Override
public void update() {
// remember expanded state of children
HashMap<T, TreeItem<T>> expanded = new HashMap<>();
for(TreeItem<T> c : getChildren()) {
if(c.isExpanded()) {
expanded.put(c.getValue(), c);
}
/*
* This method is written so that in the common cases of deleting a child, inserting a child
* and swapping two children, it only updates the affected children. Especially in these
* common
* cases, this is much faster than clearing and re-populating the list of children.
*/
List<TreeItem<T>> children = getChildren();
HashMap<T, Boolean> expanded = new HashMap<>();
for(TreeItem<T> child : children) {
expanded.put(child.getValue(), child.isExpanded());
}
// get list of children and create tree items
getChildren().clear();
for(T element : contentProvider.getFilteredSortedChildren(getValue())) {
DynamicTreeItem<T> dti;
if(expanded.containsKey(element)) {
dti = (DynamicTreeItem<T>)expanded.get(element);
Collection<? extends T> updatedContent =
contentProvider.getFilteredSortedChildren(getValue());
// List of values that are new since the last update
List<T> newlyAddedValues = new ArrayList<>(updatedContent);
for(TreeItem<T> child : children) {
newlyAddedValues.remove(child.getValue());
}
// Remove:
children.removeIf(ti -> !updatedContent.contains(ti.getValue()));
// Insert and Update:
// In the common cases where only new values have been inserted or values have been
// permuted, this will insert/modify only the affected values. This is faster than deleting
// all children and adding them from scratch.
int i = 0;
for(T updatedValue : updatedContent) {
DynamicTreeItem<T> child = null;
if(i < children.size()) {
if(updatedValue.equals(children.get(i).getValue())) {
// Child at position i already has the right value
child = (DynamicTreeItem<T>)children.get(i);
} else {
// There is a child at position i, but its value is incorrect
child = new DynamicTreeItem<T>(updatedValue, contentProvider);
child.setExpanded(expanded.getOrDefault(updatedValue, false));
if(newlyAddedValues.contains(updatedValue)) {
children.add(i, child);
} else {
children.set(i, child);
}
}
} else {
dti = new DynamicTreeItem<T>(element, contentProvider);
// There is no child at position i
child = new DynamicTreeItem<T>(updatedValue, contentProvider);
child.setExpanded(expanded.getOrDefault(updatedValue, false));
children.add(child);
}
getChildren().add(dti);
dti.update();
child.update();
i++;
}
}
......
......@@ -19,9 +19,11 @@ import static java.lang.Integer.MAX_VALUE;
import static javafx.scene.control.cell.CheckBoxTreeTableCell.forTreeTableColumn;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javafx.beans.property.SimpleObjectProperty;
......@@ -139,11 +141,33 @@ public final class DynamicTreeTableViewer<T> extends DynamicTreeViewerBase<T> {
/** Updates the viewer content. */
public void update() {
// wild cast works: see constructor
IDynamicItem rootItem = (IDynamicItem)view.getRoot();
DynamicTreeItemBase<T> rootItem = (DynamicTreeItemBase<T>)view.getRoot();
List<T> selectedValues = getSelectedValues();
view.getSelectionModel().clearSelection();
rootItem.update();
selectValues(rootItem, selectedValues);
view.refresh();
}
/** Returns a list of all selected values */
private List<T> getSelectedValues() {
return view.getSelectionModel().getSelectedItems().stream().map(c -> c.getValue())
.collect(Collectors.toList());
}
/** Selects the given values in item's subtree */
private void selectValues(TreeItem<T> item, List<T> values) {
if(values.contains(item.getValue())) {
view.getSelectionModel().select(item);
}
if(item.isExpanded()) {
for(TreeItem<T> child : item.getChildren()) {
selectValues(child, values);
}
}
}
/** Expands items up to the given level. */
private void expandItem(TreeItem<T> parentItem, int revealLevel) {
if(revealLevel <= 0) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment