diff --git a/pmd-ui/pom.xml b/pmd-ui/pom.xml
index 5bbdebbbe2..a9d8f00365 100644
--- a/pmd-ui/pom.xml
+++ b/pmd-ui/pom.xml
@@ -16,9 +16,6 @@
1.${java.version}
1.${java.version}
- ${project.build.outputDirectory}/META-INF/versions/9
-
-
11
@@ -64,57 +61,6 @@
-
-
-
-
-
- org.apache.maven.plugins
- maven-dependency-plugin
-
-
- layout-java-8-specific-code
- generate-sources
-
- unpack
-
-
- org.controlsfx:controlsfx:8.40.13
- ${project.build.outputDirectory}
- **/*
- MANIFEST.MF
-
-
-
-
- layout-java-9-specific-code
- generate-resources
-
- unpack
-
-
- org.controlsfx:controlsfx:9.0.0
- ${build.mr.java9.output}
- **/*
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-jar-plugin
-
-
-
-
- true
- net.sourceforge.pmd.util.fxdesigner.DesignerStarter
-
-
- pmd-ui-${project.version}
-
-
@@ -169,12 +115,9 @@
0.9.2
-
-
org.controlsfx
controlsfx
8.40.13
- provided
commons-beanutils
diff --git a/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/SourceEditorController.java b/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/SourceEditorController.java
index c4c8891d2d..9c11c4e47f 100644
--- a/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/SourceEditorController.java
+++ b/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/SourceEditorController.java
@@ -29,13 +29,13 @@ import net.sourceforge.pmd.lang.LanguageVersion;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
import net.sourceforge.pmd.util.ClasspathClassLoader;
+import net.sourceforge.pmd.util.fxdesigner.app.AbstractController;
+import net.sourceforge.pmd.util.fxdesigner.app.CompositeSelectionSource;
+import net.sourceforge.pmd.util.fxdesigner.app.NodeSelectionSource;
import net.sourceforge.pmd.util.fxdesigner.model.ASTManager;
import net.sourceforge.pmd.util.fxdesigner.model.ParseAbortedException;
import net.sourceforge.pmd.util.fxdesigner.popups.AuxclasspathSetupController;
-import net.sourceforge.pmd.util.fxdesigner.app.AbstractController;
-import net.sourceforge.pmd.util.fxdesigner.app.CompositeSelectionSource;
import net.sourceforge.pmd.util.fxdesigner.util.DesignerUtil;
-import net.sourceforge.pmd.util.fxdesigner.app.NodeSelectionSource;
import net.sourceforge.pmd.util.fxdesigner.util.TextAwareNodeWrapper;
import net.sourceforge.pmd.util.fxdesigner.util.beans.SettingsPersistenceUtil.PersistentProperty;
import net.sourceforge.pmd.util.fxdesigner.util.codearea.AvailableSyntaxHighlighters;
@@ -43,7 +43,6 @@ import net.sourceforge.pmd.util.fxdesigner.util.codearea.HighlightLayerCodeArea;
import net.sourceforge.pmd.util.fxdesigner.util.codearea.HighlightLayerCodeArea.LayerId;
import net.sourceforge.pmd.util.fxdesigner.util.controls.ASTTreeItem;
import net.sourceforge.pmd.util.fxdesigner.util.controls.AstTreeView;
-import net.sourceforge.pmd.util.fxdesigner.util.controls.NodeParentageCrumbBar;
import net.sourceforge.pmd.util.fxdesigner.util.controls.ToolbarTitledPane;
import javafx.application.Platform;
@@ -76,8 +75,6 @@ public class SourceEditorController extends AbstractController codeEditorArea;
- @FXML
- private NodeParentageCrumbBar focusNodeParentageCrumbBar;
private final ASTManager astManager;
@@ -107,7 +104,6 @@ public class SourceEditorController extends AbstractController getSubSelectionSources() {
- return FXCollections.observableSet(astTreeView, focusNodeParentageCrumbBar);
+ return FXCollections.observableSet(astTreeView);
}
diff --git a/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/app/NodeSelectionSource.java b/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/app/NodeSelectionSource.java
index 76db3bf0ac..7df2533640 100644
--- a/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/app/NodeSelectionSource.java
+++ b/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/app/NodeSelectionSource.java
@@ -10,14 +10,14 @@ import org.reactfx.EventStream;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.util.fxdesigner.MainDesignerController;
+import net.sourceforge.pmd.util.fxdesigner.XPathPanelController;
import net.sourceforge.pmd.util.fxdesigner.util.beans.SettingsOwner;
import net.sourceforge.pmd.util.fxdesigner.util.controls.AstTreeView;
-import net.sourceforge.pmd.util.fxdesigner.util.controls.NodeParentageCrumbBar;
/**
* A control or controller that somehow displays nodes in a form that the user can select.
- * When a node is selected by the user (e.g. {@link AstTreeView}, {@link NodeParentageCrumbBar}, etc),
+ * When a node is selected by the user (e.g. {@link AstTreeView}, {@link XPathPanelController}, etc),
* the whole UI is synchronized to reflect information about the node. This includes scrolling
* the TreeView, the editor, etc. To achieve that uniformly, node selection events are merged
* into a global stream for the whole app. Events from that stream are handled by {@link MainDesignerController}.
diff --git a/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/util/controls/NodeParentageCrumbBar.java b/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/util/controls/NodeParentageCrumbBar.java
deleted file mode 100644
index 10f26dd89c..0000000000
--- a/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/util/controls/NodeParentageCrumbBar.java
+++ /dev/null
@@ -1,237 +0,0 @@
-/**
- * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
- */
-
-package net.sourceforge.pmd.util.fxdesigner.util.controls;
-
-
-import static net.sourceforge.pmd.internal.util.IteratorUtil.asReversed;
-import static net.sourceforge.pmd.internal.util.IteratorUtil.count;
-import static net.sourceforge.pmd.util.fxdesigner.util.DesignerIteratorUtil.parentIterator;
-
-import java.util.function.Function;
-
-import org.controlsfx.control.BreadCrumbBar;
-import org.reactfx.EventSource;
-import org.reactfx.EventStream;
-import org.reactfx.value.Val;
-
-import net.sourceforge.pmd.lang.ast.Node;
-import net.sourceforge.pmd.util.fxdesigner.app.DesignerRoot;
-import net.sourceforge.pmd.util.fxdesigner.app.NodeSelectionSource;
-
-import javafx.application.Platform;
-import javafx.css.PseudoClass;
-import javafx.scene.control.Button;
-import javafx.scene.control.Labeled;
-import javafx.scene.control.Tooltip;
-import javafx.scene.control.TreeItem;
-import javafx.scene.layout.Region;
-import javafx.util.Callback;
-
-
-/**
- * Bread crumb bar to display the parents of a node. Avoids overflow
- * by estimating the number of crumbs we can layout based on the actual
- * size of the control.
- *
- * @author Clément Fournier
- * @since 7.0.0
- */
-public class NodeParentageCrumbBar extends BreadCrumbBar implements NodeSelectionSource {
-
- private static final int DEFAULT_PX_BY_CHAR = 5;
- private static final int DEFAULT_CONSTANT_PADDING = 19;
-
- /** Special item used to truncate paths when they're too long. */
- private final TreeItem ellipsisCrumb = new TreeItem<>(null);
- /** number of nodes currently behind the ellipsis */
- private int numElidedNodes = 0;
- private final EventSource selectionEvents = new EventSource<>();
-
- private DesignerRoot designerRoot;
-
-
- public NodeParentageCrumbBar() {
- // This allows to click on a parent crumb and keep the children crumb
- setAutoNavigationEnabled(false);
-
- // captured in the closure
- final Callback, Button> originalCrumbFactory = getCrumbFactory();
-
- setOnCrumbAction(ev -> {
- if (ev.getSelectedCrumb() != ellipsisCrumb) {
- selectionEvents.push(ev.getSelectedCrumb().getValue());
- }
- });
-
- setCrumbFactory(item -> {
- Button button = originalCrumbFactory.call(item);
- if (item == ellipsisCrumb) {
- button.setText("... (" + numElidedNodes + ")");
- button.setTooltip(new Tooltip(numElidedNodes + " ancestors are not shown"));
- }
- // we use that to communicate the node later on
- button.setUserData(item);
- Val.wrap(button.focusedProperty())
- .values()
- .distinct()
- .filter(Boolean::booleanValue)
- // will change the node in the treeview on <- -> key presses
- .subscribe(b -> getOnCrumbAction().handle(new BreadCrumbActionEvent<>(item)));
- return button;
- });
-
-
- }
-
-
- @Override
- public boolean alwaysHandleSelection() {
- // We need to reset the pseudo class we artificially added.
- // if the event originated from here, then we know the crumb is displayed
- // and we won't reset the displayed nodes
- return true;
- }
-
-
- @Override
- public EventStream getSelectionEvents() {
- return selectionEvents.map(n -> new NodeSelectionEvent(n, this));
- }
-
- // getSelectedCrumb gets the deepest displayed node
-
-
- /**
- * If the node is already displayed on the crumbbar, only
- * sets the focus on it. Otherwise, sets the node to be
- * the deepest one of the crumb bar. Noop if node is null.
- */
- @Override
- public void setFocusNode(Node node) {
- if (node == null) {
- return;
- }
-
- boolean found = false;
-
- // We're trying to estimate the ratio of px/crumb,
- // to make an educated guess about how many crumbs we can fit
- // in case we need to call setDeepestNode
- int totalNumChar = 0;
- int totalNumCrumbs = 0;
- // the sum of children width is the actual width with overflow
- // the width of this control is the max acceptable width *without* overflow
- double totalChildrenWidth = 0;
- // constant padding around the graphic of a BreadCrumbButton
- // (difference between width of a BreadCrumbButton and that of its graphic)
- double constantPadding = Double.NaN;
-
- for (javafx.scene.Node button : asReversed(getChildren())) {
- Node n = (Node) ((TreeItem>) button.getUserData()).getValue();
-
- // set the focus on the one being selected, remove on the others
- // calling requestFocus would switch the focus from eg the treeview to the crumb bar (unusable)
- button.pseudoClassStateChanged(PseudoClass.getPseudoClass("focused"), node.equals(n));
-
- // update counters
- totalNumChar += ((Labeled) button).getText().length();
- double childWidth = ((Region) button).getWidth();
- totalChildrenWidth += childWidth;
- totalNumCrumbs++;
- if (Double.isNaN(constantPadding)) {
- Region graphic = (Region) ((Labeled) button).getGraphic();
- if (graphic != null) {
- constantPadding = childWidth - graphic.getWidth();
- }
- }
-
- if (node.equals(n)) {
- found = true;
- }
- }
-
- if (!found) {
- // Then we reset the deepest node.
-
- setDeepestNode(node, getWidthEstimator(totalNumChar, totalChildrenWidth, totalNumCrumbs, constantPadding));
- // set the deepest as focused
- Platform.runLater(() ->
- getChildren()
- .get(getChildren().size() - 1)
- .pseudoClassStateChanged(PseudoClass.getPseudoClass("focused"), true)
- );
- }
- }
-
-
- /**
- * Sets the given node to the selected (deepest) crumb. Parent crumbs are
- * added until they are estimated to overflow the visual space, after
- * which they are hidden into the ellipsis crumb.
- *
- * @param node Node to set
- * @param widthEstimator Estimates the visual width of the crumb for one node
- */
- private void setDeepestNode(Node node, Function widthEstimator) {
- TreeItem deepest = new TreeItem<>(node);
- TreeItem current = deepest;
- Node parent = node.jjtGetParent();
- double pathLength = widthEstimator.apply(node);
-
- final double maxPathLength = getWidth() * 0.9;
-
- while (parent != null && pathLength < maxPathLength) {
- TreeItem newItem = new TreeItem<>(parent);
- newItem.getChildren().add(current);
- current = newItem;
- pathLength += widthEstimator.apply(parent);
- parent = current.getValue().jjtGetParent();
- }
-
- if (pathLength >= maxPathLength
- // if parent == null then it's the root, no need for ellipsis
- && parent != null) {
-
- numElidedNodes = count(parentIterator(parent, true));
-
- // the rest are children of the ellipsis
- ellipsisCrumb.getChildren().clear();
- ellipsisCrumb.getChildren().add(current);
- }
-
- setSelectedCrumb(deepest);
- }
-
-
- private Function getWidthEstimator(int totalNumDisplayedChars, double totalChildrenWidth, int totalNumCrumbs, double constantPadding) {
-
- double safeConstantPadding = Double.isNaN(constantPadding)
- ? DEFAULT_CONSTANT_PADDING // that's the value on my machine
- : constantPadding;
-
- double thisPxByChar = totalNumDisplayedChars == 0
- ? DEFAULT_PX_BY_CHAR // we have no data, too bad
- : (totalChildrenWidth - safeConstantPadding * totalNumCrumbs) / totalNumDisplayedChars;
-
- return node -> node.getXPathNodeName().length() * (thisPxByChar + 1 /*scale it up a bit*/) + safeConstantPadding;
- }
-
-
- @Override
- public DesignerRoot getDesignerRoot() {
- return designerRoot;
- }
-
-
- public void setDesignerRoot(DesignerRoot designerRoot) {
- this.designerRoot = designerRoot;
- }
-
-
- @Override
- public String getDebugName() {
- return "crumb-bar";
- }
-}
diff --git a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/fxml/editor.fxml b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/fxml/editor.fxml
index 2e559f1d4b..328d29cc00 100644
--- a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/fxml/editor.fxml
+++ b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/fxml/editor.fxml
@@ -6,7 +6,6 @@
-
@@ -80,8 +79,8 @@
-
+
+
+
diff --git a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/crumbbar.less b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/crumbbar.less
deleted file mode 100644
index c2ce88f268..0000000000
--- a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/less/crumbbar.less
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
- */
-/*
- * Sheet for the AST crumb bar.
- */
-@import "constants";
-
-.bread-crumb-bar {
-
- -fx-border-color: transparent;
- .button {
- -fx-background-color: @fx-base;
- -fx-border-color: @darker-accent;
- -fx-border-style: none solid none solid;
- -fx-border-width: 1;
- }
-
- .button:focused {
- -fx-background-color: @selection-focus-color;
- }
-
-}