From 3895a2eed9cc4eee55e839891c38372d392428a1 Mon Sep 17 00:00:00 2001 From: Alexander Diewald <diewald@fortiss.org> Date: Fri, 25 May 2018 11:46:07 +0200 Subject: [PATCH] JavaFX: Use generics for basic controls. * DynamicTreeViewers and alike are often used for a specific set of base types. Thus, generics can be used to reduce the code by subclassing these controls for specific meta-model types like IHierarchicElements. * Second, a bit more type-safety is achieved without sacrificing ease-of-use since the controls can still be constructed for Objects for complex object relations. Issue-Ref: 3209 Issue-Url: https://af3-developer.fortiss.org/issues/3209 Signed-off-by: Alexander Diewald <diewald@fortiss.org> --- .../ui/javafx/control/treetableview/.ratings | 16 +++--- .../DynamicTreeContentProviderBase.java | 10 ++-- .../treetableview/DynamicTreeItem.java | 20 +++---- .../treetableview/DynamicTreeTableViewer.java | 35 +++++++------ .../DynamicTreeUIProviderBase.java | 8 +-- .../treetableview/DynamicTreeViewer.java | 52 +++++++++++-------- .../treetableview/DynamicTreeViewerBase.java | 10 ++-- .../treetableview/IDoubleClickHandler.java | 2 + 8 files changed, 86 insertions(+), 67 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 9628a0d72..dbd2e7da4 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,8 +1,8 @@ -DynamicTreeContentProviderBase.java d1786cd9aa0080db117d2efd5ed5f05f7b83e2aa RED -DynamicTreeItem.java fbaa05fd834fa23b586b31124987cf1b7dc7393e RED -DynamicTreeTableUIProviderBase.java fd9fce19a65eb1006ceacb0d869bbe90a8c578b3 RED -DynamicTreeTableViewer.java 748a6dcf5e61da5de65161fa7fd4e4fbcfbd0c10 RED -DynamicTreeUIProviderBase.java 796ebafa244c158c2b4b30b322228a0de74ddaed RED -DynamicTreeViewer.java c643043b746666830b2f6bbae24f1cf374a68bfe RED -DynamicTreeViewerBase.java fddff67e874074f48335f772d3ce3ccd8671aa6d RED -IDoubleClickHandler.java ba16696ee9f7074d5dbab126717e622a0ad5b3d5 RED +DynamicTreeContentProviderBase.java dff437afeaf7486af05460fa54eca4fa61d7eae6 YELLOW +DynamicTreeItem.java afc105cf5acf3d2506d89e0892555100c234ce5b YELLOW +DynamicTreeTableUIProviderBase.java fd9fce19a65eb1006ceacb0d869bbe90a8c578b3 YELLOW +DynamicTreeTableViewer.java 22bd5e5b13b959807596fff5b4024b3383737103 YELLOW +DynamicTreeUIProviderBase.java 56fe4df4577b35f1e5e6e4c4be189b706c852d52 YELLOW +DynamicTreeViewer.java 72945b28f34d9d268df4ce763fdabb7a8561fbc6 YELLOW +DynamicTreeViewerBase.java 47124c847de322a0ae26eb7a114f85ce4bd02d7e YELLOW +IDoubleClickHandler.java 447f7769dead9a106b3ea3139ef0da51eb0b9a89 YELLOW 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 d1786cd9a..dff437afe 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 @@ -9,6 +9,8 @@ * * Contributors: * Florian Hoelzl (fortiss GmbH) - initial implementation + * Alexander Diewald (fortiss GmbH) - backport to AF3 & Integration + * improvements * *******************************************************************************/ package org.fortiss.tooling.common.ui.javafx.control.treetableview; @@ -24,9 +26,9 @@ import java.util.function.Predicate; * Base class for implementing tree content providers used in {@link DynamicTreeViewer} and * {@link DynamicTreeTableViewer}. */ -public abstract class DynamicTreeContentProviderBase { +public abstract class DynamicTreeContentProviderBase<T> { /** Returns the children of the given parent in the tree. */ - protected abstract Collection<? extends Object> getChildren(Object parent); + protected abstract Collection<? extends T> getChildren(T parent); /** Returns the filer predicate. */ protected Predicate<Object> getFilterPredicate() { @@ -39,8 +41,8 @@ public abstract class DynamicTreeContentProviderBase { } /** Returns the filtered children of the given element. */ - public final Collection<? extends Object> getFilteredSortedChildren(Object parent) { - Collection<? extends Object> l = getChildren(parent); + public final Collection<? extends T> getFilteredSortedChildren(T parent) { + Collection<? extends T> l = getChildren(parent); if(l == null) { return emptyList(); } 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 fbaa05fd8..afc105cf5 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 @@ -9,6 +9,8 @@ * * Contributors: * Florian Hoelzl (fortiss GmbH) - initial implementation + * Alexander Diewald (fortiss GmbH) - backport to AF3 & Integration + * improvements * *******************************************************************************/ package org.fortiss.tooling.common.ui.javafx.control.treetableview; @@ -22,12 +24,12 @@ import javafx.scene.control.TreeItem; * {@link TreeItem} with support for dynamic children using the {@link DynamicTreeItem#update()} * method. */ -public class DynamicTreeItem extends TreeItem<Object> { +public class DynamicTreeItem<T> extends TreeItem<T> { /** The viewer. */ - private DynamicTreeViewerBase viewer; + private DynamicTreeViewerBase<T> viewer; /** Constructor. */ - public DynamicTreeItem(Object data, DynamicTreeViewerBase viewer) { + public DynamicTreeItem(T data, DynamicTreeViewerBase<T> viewer) { super(data); this.viewer = viewer; } @@ -35,20 +37,20 @@ public class DynamicTreeItem extends TreeItem<Object> { /** Updates the children of this item from the underlying content model. */ public void update() { // remember expanded state of children - HashMap<Object, TreeItem<Object>> expanded = new HashMap<>(); - for(TreeItem<Object> c : getChildren()) { + HashMap<T, TreeItem<T>> expanded = new HashMap<>(); + for(TreeItem<T> c : getChildren()) { if(c.isExpanded()) { expanded.put(c.getValue(), c); } } // get list of children and create tree items getChildren().clear(); - for(Object element : viewer.getContentProvider().getFilteredSortedChildren(getValue())) { - DynamicTreeItem dti; + for(T element : viewer.getContentProvider().getFilteredSortedChildren(getValue())) { + DynamicTreeItem<T> dti; if(expanded.containsKey(element)) { - dti = (DynamicTreeItem)expanded.get(element); + dti = (DynamicTreeItem<T>)expanded.get(element); } else { - dti = new DynamicTreeItem(element, viewer); + dti = new DynamicTreeItem<T>(element, viewer); } getChildren().add(dti); dti.update(); 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 748a6dcf5..22bd5e5b1 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 @@ -9,6 +9,8 @@ * * Contributors: * Florian Hoelzl (fortiss GmbH) - initial implementation + * Alexander Diewald (fortiss GmbH) - backport to AF3 & Integration + * improvements * *******************************************************************************/ package org.fortiss.tooling.common.ui.javafx.control.treetableview; @@ -26,28 +28,27 @@ import javafx.scene.control.TreeTableView; * {@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 a column is removed the index provided to the label provider might not be correct - * anymore. + * 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 + * a column is removed the index provided to the label provider might not be correct anymore. * <P> * Furthermore, the selection model is currently fixed to be row selection. */ -public final class DynamicTreeTableViewer extends DynamicTreeViewerBase { +public final class DynamicTreeTableViewer<T> extends DynamicTreeViewerBase<T> { /** The {@link TreeTableView} control to be managed. */ - private final TreeTableView<Object> view; + private final TreeTableView<T> view; /** The UI provider of this tree-table. */ private final DynamicTreeTableUIProviderBase uiProvider; /** Constructor. */ - public DynamicTreeTableViewer(Object root, boolean showRoot, int revealLevel, - DynamicTreeContentProviderBase contentProvider, + public DynamicTreeTableViewer(T root, boolean showRoot, int revealLevel, + DynamicTreeContentProviderBase<T> contentProvider, DynamicTreeTableUIProviderBase uiProvider) { super(contentProvider); this.uiProvider = uiProvider; // construct view - this.view = new TreeTableView<Object>(); - DynamicTreeItem rootItem = new DynamicTreeItem(root, this); + this.view = new TreeTableView<T>(); + DynamicTreeItem<T> rootItem = new DynamicTreeItem<T>(root, this); view.setRoot(rootItem); view.setShowRoot(showRoot); rootItem.update(); @@ -58,18 +59,18 @@ public final class DynamicTreeTableViewer extends DynamicTreeViewerBase { /** Updates the viewer content. */ public void update() { // wild cast works: see constructor - DynamicTreeItem rootItem = (DynamicTreeItem)view.getRoot(); + DynamicTreeItem<T> rootItem = (DynamicTreeItem<T>)view.getRoot(); rootItem.update(); } /** Expands items up to the given level. */ - private void expandItem(TreeItem<Object> parentItem, int revealLevel) { + private void expandItem(TreeItem<T> parentItem, int revealLevel) { if(revealLevel <= 0) { return; } parentItem.setExpanded(true); revealLevel--; - for(TreeItem<Object> child : parentItem.getChildren()) { + for(TreeItem<T> child : parentItem.getChildren()) { expandItem(child, revealLevel); } } @@ -77,21 +78,21 @@ public final class DynamicTreeTableViewer extends DynamicTreeViewerBase { /** Adds a column to the table part of the view. */ public void addColumn(String headerLabel, int prefWidth) { final int num = view.getColumns().size(); - TreeTableColumn<Object, String> col = new TreeTableColumn<>(headerLabel); + TreeTableColumn<T, String> col = new TreeTableColumn<>(headerLabel); col.setPrefWidth(prefWidth); col.setCellValueFactory(param -> { Object data = param.getValue().getValue(); return new ReadOnlyStringWrapper(uiProvider.getLabel(data, num)); }); col.setCellFactory(param -> { - TreeTableCell<Object, String> cell = new TreeTableCell<Object, String>() { + TreeTableCell<T, String> cell = new TreeTableCell<T, String>() { @Override protected void updateItem(String item, boolean empty) { super.updateItem(item, empty); ContextMenu menu = null; Node icon = null; if(!empty && item != null) { - Object data = this.getTreeTableRow().getItem(); + T data = this.getTreeTableRow().getItem(); menu = uiProvider.createContextMenu(data, num); icon = uiProvider.getIconNode(data, num); } @@ -106,7 +107,7 @@ public final class DynamicTreeTableViewer extends DynamicTreeViewerBase { } /** Returns the underlying {@link TreeTableView}. */ - public TreeTableView<Object> getControl() { + public TreeTableView<T> getControl() { return view; } } diff --git a/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/DynamicTreeUIProviderBase.java b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/DynamicTreeUIProviderBase.java index 796ebafa2..56fe4df45 100644 --- a/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/DynamicTreeUIProviderBase.java +++ b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/DynamicTreeUIProviderBase.java @@ -20,13 +20,13 @@ import javafx.scene.control.ContextMenu; * This UI provider is responsible to return the label, the icon, and the context menu for each cell * in the {@link DynamicTreeViewer} based on the data object. */ -public abstract class DynamicTreeUIProviderBase { +public abstract class DynamicTreeUIProviderBase<T> { /** * @param element * the displayed element * @return the label to be displayed */ - public String getLabel(Object element) { + public String getLabel(T element) { return ""; } @@ -35,7 +35,7 @@ public abstract class DynamicTreeUIProviderBase { * the displayed element * @return the node to be displayed as the icon */ - public Node getIconNode(Object element) { + public Node getIconNode(T element) { return null; } @@ -44,7 +44,7 @@ public abstract class DynamicTreeUIProviderBase { * the displayed element * @return the context menu */ - public ContextMenu createContextMenu(Object element) { + public ContextMenu createContextMenu(T element) { return null; } } diff --git a/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/DynamicTreeViewer.java b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/DynamicTreeViewer.java index c643043b7..72945b28f 100644 --- a/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/DynamicTreeViewer.java +++ b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/DynamicTreeViewer.java @@ -9,6 +9,8 @@ * * Contributors: * Florian Hoelzl (fortiss GmbH) - initial implementation + * Alexander Diewald (fortiss GmbH) - backport to AF3 & Integration + * improvements * *******************************************************************************/ package org.fortiss.tooling.common.ui.javafx.control.treetableview; @@ -29,24 +31,25 @@ import javafx.scene.input.MouseEvent; * {@link DynamicTreeUIProviderBase}. This class is intended to be used as a wrapper for * {@link TreeView} and its rather complex expert API. */ -public final class DynamicTreeViewer extends DynamicTreeViewerBase { +public final class DynamicTreeViewer<T> extends DynamicTreeViewerBase<T> { /** The {@link TreeView} control to be managed. */ - private final TreeView<Object> view; + private final TreeView<T> view; /** The UI provider implementation. */ - private final DynamicTreeUIProviderBase uiProvider; + private final DynamicTreeUIProviderBase<T> uiProvider; /** The selection change listener. */ private ChangeListener<Object> selectionChangeListener = null; /** The double click handler. */ private IDoubleClickHandler doubleClickHandler; /** Constructor. */ - public DynamicTreeViewer(Object root, boolean showRoot, int revealLevel, - DynamicTreeContentProviderBase contentProvider, DynamicTreeUIProviderBase uiProvider) { + public DynamicTreeViewer(TreeView<T> view, T root, boolean showRoot, int revealLevel, + DynamicTreeContentProviderBase<T> contentProvider, + DynamicTreeUIProviderBase<T> uiProvider) { super(contentProvider); this.uiProvider = uiProvider; // construct view - this.view = new TreeView<Object>(); - DynamicTreeItem rootItem = new DynamicTreeItem(root, this); + this.view = view; + DynamicTreeItem<T> rootItem = new DynamicTreeItem<T>(root, this); view.setRoot(rootItem); view.setShowRoot(showRoot); configureCellFactory(); @@ -62,33 +65,40 @@ public final class DynamicTreeViewer extends DynamicTreeViewerBase { expandItem(rootItem, showRoot ? revealLevel : revealLevel + 1); } + /** Constructor. */ + public DynamicTreeViewer(T root, boolean showRoot, int revealLevel, + DynamicTreeContentProviderBase<T> contentProvider, + DynamicTreeUIProviderBase<T> uiProvider) { + this(new TreeView<T>(), root, showRoot, revealLevel, contentProvider, uiProvider); + } + /** Updates the tree view. */ public void update() { // wild cast works: see constructor - DynamicTreeItem rootItem = (DynamicTreeItem)view.getRoot(); + DynamicTreeItem<T> rootItem = (DynamicTreeItem<T>)view.getRoot(); rootItem.update(); } /** Sets the selection of this tree view. */ public void setSelection(Object value) { // wild cast works: see constructor - DynamicTreeItem rootItem = (DynamicTreeItem)view.getRoot(); - DynamicTreeItem item = findItem(rootItem, value); + DynamicTreeItem<T> rootItem = (DynamicTreeItem<T>)view.getRoot(); + DynamicTreeItem<T> item = findItem(rootItem, value); int row = view.getRow(item); view.getSelectionModel().select(row); } /** Searches the {@link DynamicTreeItem} for the given value. */ - public DynamicTreeItem findItem(DynamicTreeItem item, Object value) { + public DynamicTreeItem<T> findItem(DynamicTreeItem<T> item, Object value) { if(item == null || value == null) { return null; } if(item.getValue().equals(value)) { return item; } - for(TreeItem<Object> subItem : item.getChildren()) { + for(TreeItem<T> subItem : item.getChildren()) { if(subItem instanceof DynamicTreeItem) { - DynamicTreeItem i = findItem((DynamicTreeItem)subItem, value); + DynamicTreeItem<T> i = findItem((DynamicTreeItem<T>)subItem, value); if(i != null) { return i; } @@ -110,9 +120,9 @@ public final class DynamicTreeViewer extends DynamicTreeViewerBase { /** Configures the cell factory for the viewer. */ private void configureCellFactory() { view.setCellFactory(param -> { - TreeCell<Object> cell = new TreeCell<Object>() { + TreeCell<T> cell = new TreeCell<T>() { @Override - public void updateItem(Object item, boolean empty) { + public void updateItem(T item, boolean empty) { super.updateItem(item, empty); ContextMenu menu = null; if(!empty && item != null) { @@ -130,24 +140,24 @@ public final class DynamicTreeViewer extends DynamicTreeViewerBase { } /** Expands items up to the given level. */ - private void expandItem(TreeItem<Object> parentItem, int revealLevel) { + private void expandItem(TreeItem<T> parentItem, int revealLevel) { if(revealLevel <= 0) { return; } parentItem.setExpanded(true); revealLevel--; - for(TreeItem<Object> child : parentItem.getChildren()) { + for(TreeItem<T> child : parentItem.getChildren()) { expandItem(child, revealLevel); } } /** Returns the underlying {@link TreeView}. */ - public TreeView<Object> getControl() { + public TreeView<T> getControl() { return view; } /** Returns the UI provider. */ - public DynamicTreeUIProviderBase getUIProvider() { + public DynamicTreeUIProviderBase<T> getUIProvider() { return uiProvider; } @@ -172,8 +182,8 @@ public final class DynamicTreeViewer extends DynamicTreeViewerBase { if(mevt.getButton() == MouseButton.PRIMARY && mevt.getClickCount() >= 2) { if(mevt.getEventType().equals(MouseEvent.MOUSE_CLICKED) && doubleClickHandler != null) { - DynamicTreeItem item = - (DynamicTreeItem)view.getSelectionModel().getSelectedItem(); + DynamicTreeItem<T> item = + (DynamicTreeItem<T>)view.getSelectionModel().getSelectedItem(); if(item != null) { doubleClickHandler.doubleClicked(item.getValue()); } diff --git a/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/DynamicTreeViewerBase.java b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/DynamicTreeViewerBase.java index fddff67e8..47124c847 100644 --- a/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/DynamicTreeViewerBase.java +++ b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/DynamicTreeViewerBase.java @@ -9,6 +9,8 @@ * * Contributors: * Florian Hoelzl (fortiss GmbH) - initial implementation + * Alexander Diewald (fortiss GmbH) - backport to AF3 & Integration + * improvements * *******************************************************************************/ package org.fortiss.tooling.common.ui.javafx.control.treetableview; @@ -16,17 +18,17 @@ package org.fortiss.tooling.common.ui.javafx.control.treetableview; /** * Base class for {@link DynamicTreeViewer} and {@link DynamicTreeTableViewer}. */ -abstract class DynamicTreeViewerBase { +abstract class DynamicTreeViewerBase<T> { /** The content provider implementation. */ - private final DynamicTreeContentProviderBase contentProvider; + private final DynamicTreeContentProviderBase<T> contentProvider; /** Constructor. */ - public DynamicTreeViewerBase(DynamicTreeContentProviderBase contentProvider) { + public DynamicTreeViewerBase(DynamicTreeContentProviderBase<T> contentProvider) { this.contentProvider = contentProvider; } /** Returns the content provider. */ - public final DynamicTreeContentProviderBase getContentProvider() { + public final DynamicTreeContentProviderBase<T> getContentProvider() { return contentProvider; } } diff --git a/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/IDoubleClickHandler.java b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/IDoubleClickHandler.java index ba16696ee..447f7769d 100644 --- a/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/IDoubleClickHandler.java +++ b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/IDoubleClickHandler.java @@ -9,6 +9,8 @@ * * Contributors: * Florian Hoelzl (fortiss GmbH) - initial implementation + * Alexander Diewald (fortiss GmbH) - backport to AF3 & Integration + * improvements * *******************************************************************************/ package org.fortiss.tooling.common.ui.javafx.control.treetableview; -- GitLab