diff --git a/pmd-ui/pom.xml b/pmd-ui/pom.xml
index 047796f660..8dea8dd2cc 100644
--- a/pmd-ui/pom.xml
+++ b/pmd-ui/pom.xml
@@ -66,6 +66,20 @@
commons-beanutils-core
1.8.3
+
+
+
+ org.kordamp.ikonli
+ ikonli-javafx
+ 2.3.0
+
+
+ org.kordamp.ikonli
+ ikonli-fontawesome-pack
+ 2.3.0
+
+
+
net.sourceforge.pmd
pmd-apex
diff --git a/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/AuxClassPathController.java b/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/AuxClassPathController.java
deleted file mode 100644
index 059dc3b21a..0000000000
--- a/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/AuxClassPathController.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/**
- * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
- */
-
-
-package net.sourceforge.pmd.util.fxdesigner;
-
-import java.io.File;
-import java.net.URL;
-import java.util.List;
-import java.util.ResourceBundle;
-import java.util.function.Consumer;
-
-import org.reactfx.value.Var;
-
-import net.sourceforge.pmd.util.fxdesigner.util.beans.SettingsOwner;
-
-import javafx.collections.FXCollections;
-import javafx.fxml.FXML;
-import javafx.fxml.Initializable;
-import javafx.scene.control.Button;
-import javafx.scene.control.ListView;
-import javafx.stage.FileChooser;
-
-public class AuxClassPathController implements Initializable, SettingsOwner {
-
- private final DesignerRoot designerRoot;
-
- private final Var onCancel = Var.newSimpleVar(() -> {});
- private final Var>> onApply = Var.newSimpleVar(l -> {});
-
-
- @FXML
- private Button removeFileButton;
- @FXML
- private Button selectFilesButton;
- @FXML
- private ListView fileListView = new ListView<>();
- @FXML
- private Button moveItemUpButton;
- @FXML
- private Button moveItemDownButton;
- @FXML
- private Button setClassPathButton;
- @FXML
- private Button cancelButton;
-
-
- public AuxClassPathController(DesignerRoot designerRoot) {
- this.designerRoot = designerRoot;
- }
-
- @Override
- public void initialize(URL location, ResourceBundle resources) {
-
-
- removeFileButton.disableProperty().bind(fileListView.getSelectionModel().selectedItemProperty().isNull());
- moveItemUpButton.disableProperty().bind(fileListView.getSelectionModel().selectedItemProperty().isNull());
- moveItemDownButton.disableProperty().bind(fileListView.getSelectionModel().selectedItemProperty().isNull());
-
-
-
- selectFilesButton.setOnAction(e -> onSelectFileClicked());
- removeFileButton.setOnAction(e -> onRemoveFileClicked());
- setClassPathButton.setOnAction(e -> onApply.ifPresent(f -> f.accept(fileListView.getItems())));
- moveItemUpButton.setOnAction(e -> moveUp());
- moveItemDownButton.setOnAction(e -> moveDown());
- cancelButton.setOnAction(e -> onCancel.ifPresent(Runnable::run));
-
- }
-
-
- private void onSelectFileClicked() {
- FileChooser chooser = new FileChooser();
- chooser.setTitle("Select Files");
- chooser.getExtensionFilters().addAll(
- new FileChooser.ExtensionFilter("Java JARs", "*.jar"),
- new FileChooser.ExtensionFilter("Java WARs", "*.war"),
- new FileChooser.ExtensionFilter("Java EARs", "*.ear"),
- new FileChooser.ExtensionFilter("Java class files", "*.class")
- );
- List files = chooser.showOpenMultipleDialog(designerRoot.getMainStage());
- fileListView.getItems().addAll(files);
- }
-
-
- private void onRemoveFileClicked() {
- File f = fileListView.getSelectionModel().getSelectedItem();
- fileListView.getItems().remove(f);
- }
-
-
- public void setAuxclasspathFiles(List lst) {
- fileListView.setItems(FXCollections.observableArrayList(lst));
- }
-
-
- public void setOnCancel(Runnable run) {
- onCancel.setValue(run);
- }
-
-
- public void setOnApply(Consumer> onApply) {
- this.onApply.setValue(onApply);
- }
-
-
- private void moveUp() {
- moveItem(-1);
- }
-
-
- private void moveDown() {
- moveItem(1);
- }
-
-
- public void moveItem(int direction) {
- // Checking selected item
- if (fileListView.getSelectionModel().getSelectedItem() == null) {
- return;
- }
-
- // Calculate new index using move direction
- int newIndex = fileListView.getSelectionModel().getSelectedIndex() + direction;
-
- if (newIndex < 0 || newIndex >= fileListView.getItems().size()) {
- return;
- }
-
- File selected = fileListView.getSelectionModel().getSelectedItem();
-
- // Removing removable element
- fileListView.getItems().remove(selected);
- // Insert it in new position
- fileListView.getItems().add(newIndex, selected);
- //Restore Selection
- fileListView.scrollTo(newIndex);
- fileListView.getSelectionModel().select(newIndex);
-
- }
-
-}
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 8d5e4a14cf..2d5a631ec5 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
@@ -164,13 +164,7 @@ public class MainDesignerController implements Initializable, SettingsOwner {
}
});
- setupAuxclasspathMenuItem.setOnAction(e -> {
- try {
- sourceEditorController.showAuxClassPathController(designerRoot);
- } catch (Exception e1) {
- e1.printStackTrace();
- }
- });
+ setupAuxclasspathMenuItem.setOnAction(e -> sourceEditorController.showAuxclasspathSetupPopup(designerRoot));
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 86c434c448..8b69853754 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
@@ -30,7 +30,7 @@ import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.util.ClasspathClassLoader;
import net.sourceforge.pmd.util.fxdesigner.model.ASTManager;
import net.sourceforge.pmd.util.fxdesigner.model.ParseAbortedException;
-import net.sourceforge.pmd.util.fxdesigner.util.DesignerUtil;
+import net.sourceforge.pmd.util.fxdesigner.popups.AuxclasspathSetupController;
import net.sourceforge.pmd.util.fxdesigner.util.beans.SettingsOwner;
import net.sourceforge.pmd.util.fxdesigner.util.beans.SettingsPersistenceUtil.PersistentProperty;
import net.sourceforge.pmd.util.fxdesigner.util.codearea.AvailableSyntaxHighlighters;
@@ -41,16 +41,11 @@ import net.sourceforge.pmd.util.fxdesigner.util.controls.ASTTreeItem;
import net.sourceforge.pmd.util.fxdesigner.util.controls.TreeViewWrapper;
import javafx.fxml.FXML;
-import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
-import javafx.scene.Parent;
-import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.SelectionModel;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
-import javafx.stage.Modality;
-import javafx.stage.Stage;
/**
@@ -148,42 +143,10 @@ public class SourceEditorController implements Initializable, SettingsOwner {
}
- public void showAuxClassPathController(DesignerRoot root) {
- AuxClassPathController auxClassPathController = new AuxClassPathController(root);
-
- FXMLLoader fxmlLoader = new FXMLLoader(DesignerUtil.getFxml("auxclasspath-setup-popup.fxml"));
-
- fxmlLoader.setControllerFactory(type -> {
- if (type == AuxClassPathController.class) {
- return auxClassPathController;
- } else {
- throw new IllegalStateException("Wrong controller!");
- }
- });
- try {
- Parent root1 = fxmlLoader.load();
-
- auxClassPathController.setAuxclasspathFiles(auxclasspathFiles.getValue());
-
- Stage stage = new Stage();
- stage.initOwner(root.getMainStage());
- stage.initModality(Modality.WINDOW_MODAL);
- stage.setScene(new Scene(root1));
- stage.show();
-
- auxClassPathController.setOnApply(files -> {
- stage.close();
- auxclasspathFiles.setValue(files);
- });
-
- auxClassPathController.setOnCancel(stage::close);
-
-
- } catch (IOException e) {
- e.printStackTrace();
- }
-
-
+ public void showAuxclasspathSetupPopup(DesignerRoot root) {
+ new AuxclasspathSetupController(root).show(root.getMainStage(),
+ auxclasspathFiles.getValue(),
+ auxclasspathFiles::setValue);
}
diff --git a/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/XPathPanelController.java b/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/XPathPanelController.java
index f9959b4062..8fbc7eb324 100644
--- a/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/XPathPanelController.java
+++ b/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/XPathPanelController.java
@@ -28,6 +28,7 @@ import net.sourceforge.pmd.util.fxdesigner.model.LogEntry.Category;
import net.sourceforge.pmd.util.fxdesigner.model.ObservableXPathRuleBuilder;
import net.sourceforge.pmd.util.fxdesigner.model.XPathEvaluationException;
import net.sourceforge.pmd.util.fxdesigner.model.XPathEvaluator;
+import net.sourceforge.pmd.util.fxdesigner.popups.ExportXPathWizardController;
import net.sourceforge.pmd.util.fxdesigner.util.DesignerUtil;
import net.sourceforge.pmd.util.fxdesigner.util.beans.SettingsOwner;
import net.sourceforge.pmd.util.fxdesigner.util.beans.SettingsPersistenceUtil.PersistentProperty;
diff --git a/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/popups/AuxclasspathSetupController.java b/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/popups/AuxclasspathSetupController.java
new file mode 100644
index 0000000000..91ddba00e9
--- /dev/null
+++ b/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/popups/AuxclasspathSetupController.java
@@ -0,0 +1,176 @@
+/**
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+
+
+package net.sourceforge.pmd.util.fxdesigner.popups;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.List;
+import java.util.ResourceBundle;
+import java.util.function.Consumer;
+
+import org.reactfx.collection.LiveList;
+import org.reactfx.value.Val;
+
+import net.sourceforge.pmd.util.fxdesigner.DesignerRoot;
+import net.sourceforge.pmd.util.fxdesigner.util.DesignerUtil;
+
+import javafx.beans.binding.Bindings;
+import javafx.beans.binding.BooleanBinding;
+import javafx.beans.binding.IntegerBinding;
+import javafx.collections.FXCollections;
+import javafx.fxml.FXML;
+import javafx.fxml.FXMLLoader;
+import javafx.fxml.Initializable;
+import javafx.scene.Scene;
+import javafx.scene.control.Button;
+import javafx.scene.control.ListView;
+import javafx.stage.FileChooser;
+import javafx.stage.Modality;
+import javafx.stage.Stage;
+
+
+public class AuxclasspathSetupController implements Initializable {
+
+ private final DesignerRoot designerRoot;
+
+ @FXML
+ private Button removeFileButton;
+ @FXML
+ private Button selectFilesButton;
+ @FXML
+ private ListView fileListView = new ListView<>();
+ @FXML
+ private Button moveItemUpButton;
+ @FXML
+ private Button moveItemDownButton;
+ @FXML
+ private Button setClassPathButton;
+ @FXML
+ private Button cancelButton;
+
+
+ public AuxclasspathSetupController(DesignerRoot designerRoot) {
+ this.designerRoot = designerRoot;
+ }
+
+ @Override
+ public void initialize(URL location, ResourceBundle resources) {
+
+ BooleanBinding noSelection = fileListView.getSelectionModel().selectedItemProperty().isNull();
+
+ removeFileButton.disableProperty().bind(noSelection);
+
+ moveItemUpButton.disableProperty().bind(noSelection.or(fileListView.getSelectionModel().selectedIndexProperty().isEqualTo(0)));
+
+
+ // we can't just map the val because we need an ObservableNumberValue
+ IntegerBinding lastIndexBinding = Bindings.createIntegerBinding(() -> fileListView.getItems().size() - 1,
+ Val.wrap(fileListView.itemsProperty()).flatMap(LiveList::sizeOf));
+
+ moveItemDownButton.disableProperty().bind(noSelection.or(fileListView.getSelectionModel().selectedIndexProperty().isEqualTo(lastIndexBinding)));
+
+ fileListView.setCellFactory(DesignerUtil.simpleListCellFactory(File::getName, File::getAbsolutePath));
+
+ selectFilesButton.setOnAction(e -> onSelectFileClicked());
+ removeFileButton.setOnAction(e -> onRemoveFileClicked());
+ moveItemUpButton.setOnAction(e -> moveUp());
+ moveItemDownButton.setOnAction(e -> moveDown());
+
+ }
+
+
+ private void onSelectFileClicked() {
+ FileChooser chooser = new FileChooser();
+ chooser.setTitle("Add files to the auxilliary classpath");
+ chooser.getExtensionFilters().addAll(
+ new FileChooser.ExtensionFilter("Java archives", "*.jar", "*.war", "*.ear"),
+ new FileChooser.ExtensionFilter("Java class files", "*.class")
+ );
+ List files = chooser.showOpenMultipleDialog(designerRoot.getMainStage());
+ fileListView.getItems().addAll(files);
+ }
+
+
+ private void onRemoveFileClicked() {
+ File f = fileListView.getSelectionModel().getSelectedItem();
+ fileListView.getItems().remove(f);
+ }
+
+
+ private void moveUp() {
+ moveItem(-1);
+ }
+
+
+ private void moveDown() {
+ moveItem(1);
+ }
+
+
+ private void moveItem(int direction) {
+ // Checking selected item
+ if (fileListView.getSelectionModel().getSelectedItem() == null) {
+ return;
+ }
+
+ // Calculate new index using move direction
+ int newIndex = fileListView.getSelectionModel().getSelectedIndex() + direction;
+
+ if (newIndex < 0 || newIndex >= fileListView.getItems().size()) {
+ return;
+ }
+
+ File selected = fileListView.getSelectionModel().getSelectedItem();
+
+ // Removing removable element
+ fileListView.getItems().remove(selected);
+ // Insert it in new position
+ fileListView.getItems().add(newIndex, selected);
+ //Restore Selection
+ fileListView.scrollTo(newIndex);
+ fileListView.getSelectionModel().select(newIndex);
+
+ }
+
+
+ /** Displays the popup. */
+ public void show(Stage parentStage, List currentItems, Consumer> onApply) {
+
+ FXMLLoader fxmlLoader = new FXMLLoader(DesignerUtil.getFxml("auxclasspath-setup-popup.fxml"));
+
+ fxmlLoader.setControllerFactory(type -> {
+ if (type == AuxclasspathSetupController.class) {
+ return this;
+ } else {
+ throw new IllegalStateException("Wrong controller!");
+ }
+ });
+
+ Stage stage = new Stage();
+ try {
+ stage.setScene(new Scene(fxmlLoader.load()));
+ } catch (IOException e) {
+ e.printStackTrace();
+ return;
+ }
+
+ fileListView.setItems(FXCollections.observableArrayList(currentItems));
+
+ stage.setTitle("Auxilliary classpath setup");
+ stage.initOwner(parentStage);
+ stage.initModality(Modality.WINDOW_MODAL);
+
+ setClassPathButton.setOnAction(e -> {
+ stage.close();
+ onApply.accept(fileListView.getItems());
+ });
+
+ cancelButton.setOnAction(e -> stage.close());
+
+ stage.show();
+ }
+}
diff --git a/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/EditPropertyDialogController.java b/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/popups/EditPropertyDialogController.java
similarity index 99%
rename from pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/EditPropertyDialogController.java
rename to pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/popups/EditPropertyDialogController.java
index 05f37a9d1a..ae025478f4 100644
--- a/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/EditPropertyDialogController.java
+++ b/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/popups/EditPropertyDialogController.java
@@ -2,7 +2,7 @@
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
-package net.sourceforge.pmd.util.fxdesigner;
+package net.sourceforge.pmd.util.fxdesigner.popups;
import static net.sourceforge.pmd.properties.MultiValuePropertyDescriptor.DEFAULT_DELIMITER;
import static net.sourceforge.pmd.properties.MultiValuePropertyDescriptor.DEFAULT_NUMERIC_DELIMITER;
diff --git a/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/ExportXPathWizardController.java b/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/popups/ExportXPathWizardController.java
similarity index 99%
rename from pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/ExportXPathWizardController.java
rename to pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/popups/ExportXPathWizardController.java
index 51570ac3f6..b3327eca58 100644
--- a/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/ExportXPathWizardController.java
+++ b/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/popups/ExportXPathWizardController.java
@@ -2,7 +2,7 @@
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
-package net.sourceforge.pmd.util.fxdesigner;
+package net.sourceforge.pmd.util.fxdesigner.popups;
import java.net.URL;
import java.util.Map;
diff --git a/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/util/DesignerUtil.java b/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/util/DesignerUtil.java
index ee234a62ae..9d2395e107 100644
--- a/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/util/DesignerUtil.java
+++ b/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/util/DesignerUtil.java
@@ -30,6 +30,10 @@ import net.sourceforge.pmd.lang.rule.xpath.XPathRuleQuery;
import javafx.beans.property.Property;
import javafx.beans.value.ObservableValue;
+import javafx.scene.control.ListCell;
+import javafx.scene.control.ListView;
+import javafx.scene.control.Tooltip;
+import javafx.util.Callback;
import javafx.util.StringConverter;
@@ -85,6 +89,25 @@ public final class DesignerUtil {
}
+ public static Callback, ListCell> simpleListCellFactory(Function converter, Function toolTipMaker) {
+ return collection -> new ListCell() {
+ @Override
+ protected void updateItem(T item, boolean empty) {
+ super.updateItem(item, empty);
+
+ if (empty || item == null) {
+ setText(null);
+ setGraphic(null);
+ Tooltip.uninstall(this, getTooltip());
+ } else {
+ setText(converter.apply(item));
+ Tooltip.install(this, new Tooltip(toolTipMaker.apply(item)));
+ }
+ }
+ };
+ }
+
+
public static StringConverter stringConverter(Function toString, Function fromString) {
return new StringConverter() {
@Override
diff --git a/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/util/controls/PropertyTableView.java b/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/util/controls/PropertyTableView.java
index 79a2e4d608..3a03537398 100644
--- a/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/util/controls/PropertyTableView.java
+++ b/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/util/controls/PropertyTableView.java
@@ -12,7 +12,7 @@ import java.util.function.Consumer;
import org.reactfx.value.Var;
import net.sourceforge.pmd.properties.PropertyTypeId;
-import net.sourceforge.pmd.util.fxdesigner.EditPropertyDialogController;
+import net.sourceforge.pmd.util.fxdesigner.popups.EditPropertyDialogController;
import net.sourceforge.pmd.util.fxdesigner.util.DesignerUtil;
import net.sourceforge.pmd.util.fxdesigner.util.PropertyDescriptorSpec;
diff --git a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/css/designer.css b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/css/designer.css
index 0bff0a645e..602b8f7519 100644
--- a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/css/designer.css
+++ b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/css/designer.css
@@ -124,6 +124,11 @@
-fx-border-radius: 3;
}
+.button.icon-button {
+ -fx-pref-width: 20;
+ -fx-pref-height: 20;
+}
+
.tool-bar .choice-box {
-fx-background-color: derive(-fx-base, 10%);
-fx-border-color: derive(-fx-base, -20%);
diff --git a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/fxml/auxclasspath-setup-popup.fxml b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/fxml/auxclasspath-setup-popup.fxml
index f66299513c..c3a773f04e 100644
--- a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/fxml/auxclasspath-setup-popup.fxml
+++ b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/fxml/auxclasspath-setup-popup.fxml
@@ -3,71 +3,96 @@
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
-
+
+
+
+
diff --git a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/fxml/designer.fxml b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/fxml/designer.fxml
index 4afb18add8..35cf435c9e 100644
--- a/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/fxml/designer.fxml
+++ b/pmd-ui/src/main/resources/net/sourceforge/pmd/util/fxdesigner/fxml/designer.fxml
@@ -44,10 +44,11 @@
-