diff --git a/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/MainDesignerController.java b/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/MainDesignerController.java index c8fb430e41..645b6ccfff 100644 --- a/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/MainDesignerController.java +++ b/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/MainDesignerController.java @@ -165,7 +165,7 @@ public class MainDesignerController extends AbstractController implements NodeSelectionSource { + private static final Pattern EXCEPTION_PREFIX_PATTERN = Pattern.compile("(?:(?:\\w+\\.)*\\w+:\\s*)*\\s*(.*)$", Pattern.DOTALL); + private static final String NO_MATCH_MESSAGE = "No match in text"; private static final Duration XPATH_REFRESH_DELAY = Duration.ofMillis(100); private final XPathEvaluator xpathEvaluator = new XPathEvaluator(); private final ObservableXPathRuleBuilder ruleBuilder = new ObservableXPathRuleBuilder(); @@ -135,9 +141,12 @@ public class XPathPanelController extends AbstractController "Matched nodes (" + n + ")")); } + @Override protected void afterParentInit() { bindToParent(); @@ -252,7 +261,7 @@ public class XPathPanelController extends AbstractController results, + String emptyResultsPlaceholder) { + + Label emptyLabel = xpathError || otherError + ? new Label(emptyResultsPlaceholder, new FontIcon("fas-exclamation")) + : new Label(emptyResultsPlaceholder); + + xpathResultListView.setPlaceholder(emptyLabel); + + xpathResultListView.setItems(results.stream().map(parent::wrapNode).collect(Collectors.toCollection(LiveArrayList::new))); + this.currentResults.setValue(results); + // only show the error label here when it's an xpath error + expressionTitledPane.errorMessageProperty().setValue(xpathError ? emptyResultsPlaceholder : ""); + } + + + private static String sanitizeExceptionMessage(Throwable exception) { + Matcher matcher = EXCEPTION_PREFIX_PATTERN.matcher(exception.getMessage()); + return matcher.matches() ? matcher.group(1) : exception.getMessage(); + } + } diff --git a/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/util/controls/ToolbarTitledPane.java b/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/util/controls/ToolbarTitledPane.java index 7ec3b541ac..369ccb8d9e 100644 --- a/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/util/controls/ToolbarTitledPane.java +++ b/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/util/controls/ToolbarTitledPane.java @@ -4,9 +4,10 @@ package net.sourceforge.pmd.util.fxdesigner.util.controls; -import java.util.Collection; import java.util.Objects; +import org.apache.commons.lang3.StringUtils; +import org.kordamp.ikonli.javafx.FontIcon; import org.reactfx.value.Val; import org.reactfx.value.Var; @@ -18,6 +19,7 @@ import javafx.scene.Node; import javafx.scene.control.Label; import javafx.scene.control.TitledPane; import javafx.scene.control.ToolBar; +import javafx.scene.control.Tooltip; import javafx.scene.layout.StackPane; @@ -33,10 +35,22 @@ public final class ToolbarTitledPane extends TitledPane { private final ToolBar toolBar = new ToolBar(); private final Var title = Var.newSimpleVar("Title"); + private final Var errorMessage = Var.newSimpleVar(""); public ToolbarTitledPane() { + Label errorLabel = new Label(); + + FontIcon errorIcon = new FontIcon("fas-exclamation-triangle"); + errorLabel.setGraphic(errorIcon); + errorLabel.tooltipProperty().bind(errorMessage.map(message -> StringUtils.isBlank(message) ? null : new Tooltip(message))); + errorLabel.visibleProperty().bind(errorMessage.map(StringUtils::isNotBlank)); + // makes the label zero-width when it's not visible + errorLabel.managedProperty().bind(errorLabel.visibleProperty()); + + toolBar.getItems().add(errorLabel); + getStyleClass().add("tool-bar-title"); // change the default @@ -79,11 +93,6 @@ public final class ToolbarTitledPane extends TitledPane { } - public void setToolbarItems(Collection nodes) { - toolBar.getItems().setAll(nodes); - } - - public String getTitle() { return title.getValue(); } @@ -94,6 +103,10 @@ public final class ToolbarTitledPane extends TitledPane { } + public Var errorMessageProperty() { + return errorMessage; + } + /** Title of the pane, not equivalent to {@link #textProperty()}. */ public Var titleProperty() { return title;