From 29421b1981a016bd63653ffc889350ca00287055 Mon Sep 17 00:00:00 2001 From: Simon Barner <barner@fortiss.org> Date: Thu, 28 Sep 2023 11:32:41 +0200 Subject: [PATCH] Make TreeContextMenuItem reusable for other ContextMenus * Move to separate file * Move construction of TreeContextMenuItem-based ContextMenus from DynamicTreeUIProviderBase to static factory method TreeContextMenuItem.createTreeContextMenu() Issue-Ref: 4322 Issue-URL: https://git.fortiss.org/af3/af3/-/issues/4322 Signed-off-by: Simon Barner <barner@fortiss.org> --- .../ui/javafx/control/treetableview/.ratings | 3 +- .../DynamicTreeUIProviderBase.java | 79 +------------ .../treetableview/TreeContextMenuItem.java | 109 ++++++++++++++++++ 3 files changed, 114 insertions(+), 77 deletions(-) create mode 100644 org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/TreeContextMenuItem.java 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 3aa6ebc49..bb4bdf30c 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 @@ -7,9 +7,10 @@ DynamicTreeItem.java 7e81ea98038b5eca90df583e0268d4e8f37aaf25 GREEN DynamicTreeItemBase.java d883066ecc181120302ca32f328538de7a45b093 GREEN DynamicTreeTableUIProviderBase.java c52a1f9598de25874f83c133a8cbbcddc86442e9 GREEN DynamicTreeTableViewer.java 77e9995a3bee37d57578dad9434a53c702128efa YELLOW -DynamicTreeUIProviderBase.java 3688498020e322174d222d433220ee56c4549fbb YELLOW +DynamicTreeUIProviderBase.java 6c186ade3aba51037303ed7a4ad812399bd70c56 YELLOW DynamicTreeViewer.java b0d8cc4b3e11aa970446af12d1e54c750713b297 YELLOW DynamicTreeViewerBase.java a2013538b62d86f6a09efdf2cd78babac2072484 GREEN EmptyChildrenContentProvider.java 51b4468f9df8423abeea5ac6aa2f6cf99c2eb512 GREEN IDoubleClickHandler.java 447f7769dead9a106b3ea3139ef0da51eb0b9a89 GREEN IDynamicItem.java 083d02459e7ec33542d9910c04abe2581e0b5422 GREEN +TreeContextMenuItem.java c7f72dc795c7960f9088126361ead456fa7c02db YELLOW 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 368849802..6c186ade3 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 @@ -13,15 +13,11 @@ *******************************************************************************/ package org.fortiss.tooling.common.ui.javafx.control.treetableview; -import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.List; -import javafx.event.ActionEvent; -import javafx.event.EventHandler; import javafx.scene.Node; import javafx.scene.control.ContextMenu; -import javafx.scene.control.MenuItem; import javafx.scene.control.TreeItem; import javafx.scene.input.ClipboardContent; import javafx.scene.input.Dragboard; @@ -61,51 +57,6 @@ public abstract class DynamicTreeUIProviderBase<T> { return null; } - /** - * Base class for {@link MenuItem}s used by {@link DynamicTreeViewer}s. Subclasses must provide - * exactly one public constructor that takes the underlying tree element as single argument. - */ - public static abstract class TreeContextMenuItem<T> extends MenuItem { - - /** The model element on which the context menu operates. */ - private T element; - - /** Constructor. */ - public TreeContextMenuItem(T element, String label) { - super(label); - init(element); - } - - /** Constructor. */ - public TreeContextMenuItem(T element, String label, Node graphic) { - super(label, graphic); - init(element); - } - - /** Helper for constructors. */ - private void init(T element) { - this.element = element; - setOnAction(createOnActionHandler()); - } - - /** Getter for {@link #element}. */ - protected T getElement() { - return element; - } - - /** Predicate iff this {@link TreeContextMenuItem} is hidden. */ - public abstract boolean isHidden(); - - /** Predicate when this {@link TreeContextMenuItem} is disabled. */ - public abstract boolean isDisabled(); - - /** - * Factory method for {@link EventHandler} that implements the action triggered by the - * context menu. - */ - protected abstract EventHandler<ActionEvent> createOnActionHandler(); - } - /** * List of context menu entries types that supplied by clients * (see{@link #addContextMenuEntry(Class)}). @@ -124,33 +75,9 @@ public abstract class DynamicTreeUIProviderBase<T> { * Creates a context menu based on the the {@link TreeContextMenuItem} types registered via * {@link #addContextMenuEntry(Class)}. */ - public final ContextMenu createContextMenu(T element) { - ContextMenu menu = new ContextMenu(); - for(Class<? extends TreeContextMenuItem<T>> entryType : contextMenuEntryTypes) { - - try { - Constructor<?>[] ctrs = entryType.getConstructors(); - if(ctrs.length != 1) { - throw new RuntimeException( - "Subclasses of TreeContextMenuItem must provide exactly one public constructor"); - } - @SuppressWarnings("unchecked") Constructor<? extends TreeContextMenuItem<T>> ctr = - (Constructor<? extends TreeContextMenuItem<T>>)ctrs[0]; - if(ctr.getParameterCount() != 1) { - throw new RuntimeException( - "The constructor of subclasses of TreeContextMenuItem must take the tree element for which the context menu is created as single argument."); - } - - TreeContextMenuItem<T> entry = ctr.newInstance(element); - if(!entry.isHidden()) { - menu.getItems().add(entry); - entry.setDisable(entry.isDisabled()); - } - } catch(Exception e) { - e.printStackTrace(); - } - } - return menu; + /** package */ + final ContextMenu createContextMenu(T element) { + return TreeContextMenuItem.createTreeContextMenu(contextMenuEntryTypes, element); } /** diff --git a/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/TreeContextMenuItem.java b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/TreeContextMenuItem.java new file mode 100644 index 000000000..c7f72dc79 --- /dev/null +++ b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/control/treetableview/TreeContextMenuItem.java @@ -0,0 +1,109 @@ +/*-------------------------------------------------------------------------+ +| Copyright 2023 fortiss GmbH | +| | +| Licensed under the Apache License, Version 2.0 (the "License"); | +| you may not use this file except in compliance with the License. | +| You may obtain a copy of the License at | +| | +| http://www.apache.org/licenses/LICENSE-2.0 | +| | +| Unless required by applicable law or agreed to in writing, software | +| distributed under the License is distributed on an "AS IS" BASIS, | +| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | +| See the License for the specific language governing permissions and | +| limitations under the License. | ++--------------------------------------------------------------------------*/ +package org.fortiss.tooling.common.ui.javafx.control.treetableview; + +import java.lang.reflect.Constructor; +import java.util.Collection; + +import javafx.event.ActionEvent; +import javafx.event.EventHandler; +import javafx.scene.Node; +import javafx.scene.control.ContextMenu; +import javafx.scene.control.MenuItem; + +/** + * Base class for {@link MenuItem}s used by {@link DynamicTreeViewer}s (but in principle generally + * applicable for JavaFX {@link ContextMenu}s). + * <ul> + * <li>Subclasses must provide exactly one public constructor that takes the underlying tree element + * as single argument.</li> + * <li>Instances must be created using factory method + * {@link #createTreeContextMenu(Collection, Object)}.</li> + * </ul> + */ +public abstract class TreeContextMenuItem<T> extends MenuItem { + + /** The model element on which the context menu operates. */ + private T element; + + /** Constructor. */ + protected TreeContextMenuItem(T element, String label) { + super(label); + init(element); + } + + /** Constructor. */ + protected TreeContextMenuItem(T element, String label, Node graphic) { + super(label, graphic); + init(element); + } + + /** Helper for constructors. */ + private void init(T element) { + this.element = element; + setOnAction(createOnActionHandler()); + } + + /** Getter for {@link #element}. */ + protected T getElement() { + return element; + } + + /** Predicate iff this {@link TreeContextMenuItem} is hidden. */ + public abstract boolean isHidden(); + + /** Predicate when this {@link TreeContextMenuItem} is disabled. */ + public abstract boolean isDisabled(); + + /** + * Factory method for {@link EventHandler} that implements the action triggered by the + * context menu. + */ + protected abstract EventHandler<ActionEvent> createOnActionHandler(); + + /** Factory method for a {@link ContextMenu} defined based on {@link TreeContextMenuItem}s. */ + public static <T> ContextMenu createTreeContextMenu( + Collection<Class<? extends TreeContextMenuItem<T>>> contextMenuEntryTypes, T element) { + + ContextMenu menu = new ContextMenu(); + for(Class<? extends TreeContextMenuItem<T>> entryType : contextMenuEntryTypes) { + + try { + Constructor<?>[] ctrs = entryType.getConstructors(); + if(ctrs.length != 1) { + throw new RuntimeException( + "Subclasses of TreeContextMenuItem must provide exactly one public constructor"); + } + @SuppressWarnings("unchecked") Constructor<? extends TreeContextMenuItem<T>> ctr = + (Constructor<? extends TreeContextMenuItem<T>>)ctrs[0]; + if(ctr.getParameterCount() != 1) { + throw new RuntimeException( + "The constructor of subclasses of TreeContextMenuItem must take the tree element for which the context menu is created as single argument."); + } + + TreeContextMenuItem<?> entry = ctr.newInstance(element); + if(!entry.isHidden()) { + menu.getItems().add(entry); + entry.setDisable(entry.isDisabled()); + } + } catch(Exception e) { + e.printStackTrace(); + } + } + + return menu; + } +} -- GitLab