From 5cf5f5c6a88e870e768200cfb4629c058f51c67c Mon Sep 17 00:00:00 2001
From: Florian Hoelzl <hoelzl@fortiss.org>
Date: Tue, 28 Jan 2020 14:20:31 +0100
Subject: [PATCH] Kernel: DynamicTreeTableUIProvider filter base
 implementation.

Issue-Ref: 3907
Issue-Url: https://af3-developer.fortiss.org/issues/3907
Signed-off-by: Florian Hoelzl <hoelzl@fortiss.org>
---
 .../ui/javafx/control/treetableview/.ratings  |  6 +--
 .../DynamicTreeContentProviderBase.java       | 29 ++++++++++---
 .../treetableview/DynamicTreeItem.java        | 17 ++++++--
 .../treetableview/DynamicTreeTableViewer.java | 41 ++++++++++++++++---
 4 files changed, 75 insertions(+), 18 deletions(-)

diff --git a/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/.ratings b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/.ratings
index d804a3a10..15f383373 100644
--- a/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/.ratings
+++ b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/.ratings
@@ -1,7 +1,7 @@
-DynamicTreeContentProviderBase.java dff437afeaf7486af05460fa54eca4fa61d7eae6 GREEN
-DynamicTreeItem.java afc105cf5acf3d2506d89e0892555100c234ce5b GREEN
+DynamicTreeContentProviderBase.java 767a518dc8f4ea755aeff0858d06db41c8721c0d YELLOW
+DynamicTreeItem.java f68e85125aecdb2e588450b7652ffa57c4dc9088 YELLOW
 DynamicTreeTableUIProviderBase.java 7bfc1395283d3dc10026aff5e2e65df88d25f3a7 YELLOW
-DynamicTreeTableViewer.java 41bfddb704b5fd7ba546d574103ad01192072d2a YELLOW
+DynamicTreeTableViewer.java 3b8850f097093230401aee834fe61a16250c215c YELLOW
 DynamicTreeUIProviderBase.java 56fe4df4577b35f1e5e6e4c4be189b706c852d52 GREEN
 DynamicTreeViewer.java da5e24ae57777a482d8e12c8262513d8143bfa93 GREEN
 DynamicTreeViewerBase.java 47124c847de322a0ae26eb7a114f85ce4bd02d7e GREEN
diff --git a/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/DynamicTreeContentProviderBase.java b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/DynamicTreeContentProviderBase.java
index dff437afe..767a518dc 100644
--- a/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/DynamicTreeContentProviderBase.java
+++ b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/DynamicTreeContentProviderBase.java
@@ -30,23 +30,42 @@ public abstract class DynamicTreeContentProviderBase<T> {
 	/** Returns the children of the given parent in the tree. */
 	protected abstract Collection<? extends T> getChildren(T parent);
 
-	/** Returns the filer predicate. */
-	protected Predicate<Object> getFilterPredicate() {
+	/** Returns whether the filter input should be enabled. */
+	protected boolean enableFiltering() {
+		return false;
+	}
+
+	/**
+	 * Returns the filter predicate for the given filter value. The default checks if the object's
+	 * toString() contains the filter value. Sub-classes may override or implement
+	 * {@link #filter(Object, String)}.
+	 */
+	protected Predicate<T> getFilterPredicate(String filterValue) {
+		if(filterValue != null && !"".equals(filterValue.trim())) {
+			return (o) -> {
+				return filter(o, filterValue);
+			};
+		}
 		return (o) -> true;
 	}
 
+	/** Sub-classes may override to implement simple filter behavior. */
+	protected boolean filter(T element, String filterValue) {
+		return element != null && element.toString().contains(filterValue);
+	}
+
 	/** Returns the sorter comparator. */
-	protected Comparator<Object> getSortingComparator() {
+	protected Comparator<T> getSortingComparator() {
 		return (o1, o2) -> 0;
 	}
 
 	/** Returns the filtered children of the given element. */
-	public final Collection<? extends T> getFilteredSortedChildren(T parent) {
+	public final Collection<? extends T> getFilteredSortedChildren(T parent, String filterValue) {
 		Collection<? extends T> l = getChildren(parent);
 		if(l == null) {
 			return emptyList();
 		}
-		return l.stream().filter(getFilterPredicate()).sorted(getSortingComparator())
+		return l.stream().filter(getFilterPredicate(filterValue)).sorted(getSortingComparator())
 				.collect(toList());
 	}
 }
diff --git a/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/DynamicTreeItem.java b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/DynamicTreeItem.java
index afc105cf5..f68e85125 100644
--- a/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/DynamicTreeItem.java
+++ b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/DynamicTreeItem.java
@@ -21,8 +21,8 @@ import java.util.HashMap;
 import javafx.scene.control.TreeItem;
 
 /**
- * {@link TreeItem} with support for dynamic children using the {@link DynamicTreeItem#update()}
- * method.
+ * {@link TreeItem} with support for dynamic children using the
+ * {@link DynamicTreeItem#update(String)} method.
  */
 public class DynamicTreeItem<T> extends TreeItem<T> {
 	/** The viewer. */
@@ -36,6 +36,14 @@ public class DynamicTreeItem<T> extends TreeItem<T> {
 
 	/** Updates the children of this item from the underlying content model. */
 	public void update() {
+		update(null);
+	}
+
+	/**
+	 * Updates the children of this item from the underlying content model using the given filter
+	 * value.
+	 */
+	public void update(String filterValue) {
 		// remember expanded state of children
 		HashMap<T, TreeItem<T>> expanded = new HashMap<>();
 		for(TreeItem<T> c : getChildren()) {
@@ -45,7 +53,8 @@ public class DynamicTreeItem<T> extends TreeItem<T> {
 		}
 		// get list of children and create tree items
 		getChildren().clear();
-		for(T element : viewer.getContentProvider().getFilteredSortedChildren(getValue())) {
+		DynamicTreeContentProviderBase<T> cp = viewer.getContentProvider();
+		for(T element : cp.getFilteredSortedChildren(getValue(), filterValue)) {
 			DynamicTreeItem<T> dti;
 			if(expanded.containsKey(element)) {
 				dti = (DynamicTreeItem<T>)expanded.get(element);
@@ -53,7 +62,7 @@ public class DynamicTreeItem<T> extends TreeItem<T> {
 				dti = new DynamicTreeItem<T>(element, viewer);
 			}
 			getChildren().add(dti);
-			dti.update();
+			dti.update(filterValue);
 		}
 	}
 
diff --git a/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/DynamicTreeTableViewer.java b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/DynamicTreeTableViewer.java
index 41bfddb70..3b8850f09 100644
--- a/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/DynamicTreeTableViewer.java
+++ b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/DynamicTreeTableViewer.java
@@ -16,17 +16,19 @@
 package org.fortiss.tooling.common.ui.javafx.control.treetableview;
 
 import javafx.beans.property.SimpleObjectProperty;
+import javafx.scene.Parent;
 import javafx.scene.control.SelectionMode;
+import javafx.scene.control.TextField;
 import javafx.scene.control.TreeItem;
 import javafx.scene.control.TreeTableColumn;
 import javafx.scene.control.TreeTableView;
 import javafx.scene.control.TreeTableView.TreeTableViewSelectionModel;
+import javafx.scene.layout.BorderPane;
 
 /**
- * A JavaFX {@link TreeTableView} based on an {@link DynamicTreeContentProviderBase},
- * {@link DynamicTreeTableUIProviderBase}, and {@link DynamicTreeTableEditingSupportBase}. This
- * class is intended to be used as a wrapper for {@link TreeTableView} and its rather complex expert
- * API.
+ * A JavaFX {@link TreeTableView} based on an {@link DynamicTreeContentProviderBase} and
+ * {@link DynamicTreeTableUIProviderBase}. This class is intended to be used as a wrapper for
+ * {@link TreeTableView} and its rather complex expert API.
  * <P>
  * This class currently supports only a static tree-table layout, i.e., there is no way to alter the
  * columns unless the developer changes the underlying {@link TreeTableView} directly. Note that if
@@ -37,6 +39,12 @@ import javafx.scene.control.TreeTableView.TreeTableViewSelectionModel;
 public final class DynamicTreeTableViewer<T> extends DynamicTreeViewerBase<T> {
 	/** The {@link TreeTableView} control to be managed. */
 	private final TreeTableView<T> view;
+	/** The filter text field if filtering is enabled in content provider. */
+	private final TextField filter;
+	/** The pane for filter and tree widgets. */
+	private final BorderPane pane;
+	/** The content provider of this tree-table. */
+	private final DynamicTreeContentProviderBase<T> contentProvider;
 	/** The UI provider of this tree-table. */
 	private final DynamicTreeTableUIProviderBase<T> uiProvider;
 
@@ -45,9 +53,22 @@ public final class DynamicTreeTableViewer<T> extends DynamicTreeViewerBase<T> {
 			DynamicTreeContentProviderBase<T> contentProvider,
 			DynamicTreeTableUIProviderBase<T> uiProvider) {
 		super(contentProvider);
+		this.contentProvider = contentProvider;
 		this.uiProvider = uiProvider;
 		// construct view
 		this.view = view;
+		if(contentProvider.enableFiltering()) {
+			filter = new TextField();
+			filter.textProperty().addListener((obs, oVal, nVal) -> {
+				update();
+			});
+			pane = new BorderPane();
+			pane.setTop(filter);
+			pane.setCenter(view);
+		} else {
+			filter = null;
+			pane = null;
+		}
 		DynamicTreeItem<T> rootItem = new DynamicTreeItem<T>(root, this);
 		view.setRoot(rootItem);
 		view.setShowRoot(showRoot);
@@ -76,7 +97,7 @@ public final class DynamicTreeTableViewer<T> extends DynamicTreeViewerBase<T> {
 	public void update() {
 		// wild cast works: see constructor
 		DynamicTreeItem<T> rootItem = (DynamicTreeItem<T>)view.getRoot();
-		rootItem.update();
+		rootItem.update(filter != null ? filter.getText() : null);
 	}
 
 	/** Expands items up to the given level. */
@@ -118,7 +139,7 @@ public final class DynamicTreeTableViewer<T> extends DynamicTreeViewerBase<T> {
 	 */
 	@Deprecated
 	public TreeTableColumn<T, String> addColumn(String headerLabel, int prefWidth,
-			boolean readOnly) {
+			@SuppressWarnings("unused") boolean readOnly) {
 		return addColumn(headerLabel, prefWidth);
 	}
 
@@ -126,4 +147,12 @@ public final class DynamicTreeTableViewer<T> extends DynamicTreeViewerBase<T> {
 	public TreeTableView<T> getControl() {
 		return view;
 	}
+
+	/** Returns the filter pane or the tree view if filtering is disabled. */
+	public Parent getFilterControl() {
+		if(contentProvider.enableFiltering()) {
+			return pane;
+		}
+		return getControl();
+	}
 }
-- 
GitLab