Skip to content
Snippets Groups Projects
Commit 0240b86e authored by Simon Barner's avatar Simon Barner
Browse files

Merge branch '4182' into 'master'

Improve update performance of DynamicTreeTableViewer

See merge request !164
parents 31433bed f0e0b960
No related branches found
No related tags found
1 merge request!164Improve update performance of DynamicTreeTableViewer
......@@ -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 7e81ea98038b5eca90df583e0268d4e8f37aaf25 GREEN
DynamicTreeItemBase.java d883066ecc181120302ca32f328538de7a45b093 GREEN
DynamicTreeTableUIProviderBase.java d150a4c379cc41aab2a44a5f1643f4956332c8e3 GREEN
DynamicTreeTableViewer.java cb289413d15159abbcccfea87d731738905b4b28 GREEN
DynamicTreeTableViewer.java 62712ba0f72b57c55256648204566ac2448b8d56 GREEN
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,59 @@ 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());
}
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());
}
// 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);
// 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++;
}
}
......
......@@ -16,15 +16,18 @@
package org.fortiss.tooling.common.ui.javafx.control.treetableview;
import static java.lang.Integer.MAX_VALUE;
import static java.util.stream.Collectors.toList;
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.Stream;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.ObservableList;
import javafx.scene.control.Label;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TreeItem;
......@@ -139,11 +142,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() {
ObservableList<TreeItem<T>> selectedItems = view.getSelectionModel().getSelectedItems();
return selectedItems.stream().map(c -> c.getValue()).collect(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