forked from phoedos/pmd
Merge branch 'master' into designer-exception-noise
This commit is contained in:
@@ -112,7 +112,7 @@
|
||||
<dependency>
|
||||
<groupId>org.fxmisc.richtext</groupId>
|
||||
<artifactId>richtextfx</artifactId>
|
||||
<version>0.9.0</version>
|
||||
<version>0.9.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.controlsfx</groupId>
|
||||
@@ -133,7 +133,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.kordamp.ikonli</groupId>
|
||||
<artifactId>ikonli-fontawesome-pack</artifactId>
|
||||
<artifactId>ikonli-fontawesome5-pack</artifactId>
|
||||
<version>2.3.0</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ import static net.sourceforge.pmd.util.fxdesigner.model.LogEntry.Category.PARSE_
|
||||
import static net.sourceforge.pmd.util.fxdesigner.model.LogEntry.Category.XPATH_EVALUATION_EXCEPTION;
|
||||
import static net.sourceforge.pmd.util.fxdesigner.model.LogEntry.Category.XPATH_OK;
|
||||
|
||||
import java.net.URL;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.Duration;
|
||||
@@ -18,7 +17,6 @@ import java.util.Date;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import org.reactfx.EventStream;
|
||||
import org.reactfx.EventStreams;
|
||||
@@ -27,11 +25,11 @@ import org.reactfx.value.Var;
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.util.fxdesigner.model.LogEntry;
|
||||
import net.sourceforge.pmd.util.fxdesigner.model.LogEntry.Category;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.AbstractController;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.DesignerUtil;
|
||||
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.TableCell;
|
||||
import javafx.scene.control.TableColumn;
|
||||
import javafx.scene.control.TableColumn.SortType;
|
||||
@@ -44,7 +42,7 @@ import javafx.scene.control.cell.PropertyValueFactory;
|
||||
* @author Clément Fournier
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class EventLogController implements Initializable {
|
||||
public class EventLogController extends AbstractController {
|
||||
|
||||
/**
|
||||
* Exceptions from XPath evaluation or parsing are never emitted
|
||||
@@ -76,7 +74,8 @@ public class EventLogController implements Initializable {
|
||||
|
||||
|
||||
@Override
|
||||
public void initialize(URL location, ResourceBundle resources) {
|
||||
protected void beforeParentInit() {
|
||||
|
||||
logCategoryColumn.setCellValueFactory(new PropertyValueFactory<>("category"));
|
||||
logMessageColumn.setCellValueFactory(new PropertyValueFactory<>("message"));
|
||||
final DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
|
||||
|
||||
@@ -6,7 +6,6 @@ package net.sourceforge.pmd.util.fxdesigner;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
@@ -14,7 +13,6 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Stack;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -26,10 +24,10 @@ import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.symboltable.NameDeclaration;
|
||||
import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
|
||||
import net.sourceforge.pmd.util.fxdesigner.model.XPathEvaluationException;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.AbstractController;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.DesignerUtil;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.LimitedSizeStack;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.TextAwareNodeWrapper;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.beans.SettingsOwner;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.beans.SettingsPersistenceUtil;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.beans.SettingsPersistenceUtil.PersistentProperty;
|
||||
|
||||
@@ -39,10 +37,8 @@ import javafx.animation.Timeline;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.DoubleProperty;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.Alert;
|
||||
import javafx.scene.control.Alert.AlertType;
|
||||
import javafx.scene.control.ChoiceBox;
|
||||
import javafx.scene.control.CustomMenuItem;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.Menu;
|
||||
@@ -70,7 +66,7 @@ import javafx.util.Duration;
|
||||
* @since 6.0.0
|
||||
*/
|
||||
@SuppressWarnings("PMD.UnusedPrivateField")
|
||||
public class MainDesignerController implements Initializable, SettingsOwner {
|
||||
public class MainDesignerController extends AbstractController {
|
||||
|
||||
/**
|
||||
* Callback to the owner.
|
||||
@@ -88,17 +84,9 @@ public class MainDesignerController implements Initializable, SettingsOwner {
|
||||
@FXML
|
||||
private Menu openRecentMenu;
|
||||
@FXML
|
||||
private MenuItem exportToTestCodeMenuItem;
|
||||
@FXML
|
||||
private MenuItem exportXPathMenuItem;
|
||||
@FXML
|
||||
private Menu fileMenu;
|
||||
/* Center toolbar */
|
||||
@FXML
|
||||
private ChoiceBox<LanguageVersion> languageChoiceBox;
|
||||
@FXML
|
||||
private ChoiceBox<String> xpathVersionChoiceBox;
|
||||
@FXML
|
||||
private ToggleButton bottomTabsToggle;
|
||||
/* Bottom panel */
|
||||
@FXML
|
||||
@@ -121,18 +109,14 @@ public class MainDesignerController implements Initializable, SettingsOwner {
|
||||
|
||||
// Other fields
|
||||
private Stack<File> recentFiles = new LimitedSizeStack<>(5);
|
||||
// Properties
|
||||
private Val<LanguageVersion> languageVersion = Val.constant(DesignerUtil.defaultLanguageVersion());
|
||||
private Val<String> xpathVersion = Val.constant(DesignerUtil.defaultXPathVersion());
|
||||
|
||||
|
||||
public MainDesignerController(DesignerRoot owner) {
|
||||
this.designerRoot = owner;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void initialize(URL location, ResourceBundle resources) {
|
||||
protected void beforeParentInit() {
|
||||
try {
|
||||
SettingsPersistenceUtil.restoreProperties(this, DesignerUtil.getSettingsFile());
|
||||
} catch (Exception e) {
|
||||
@@ -141,55 +125,23 @@ public class MainDesignerController implements Initializable, SettingsOwner {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
initializeLanguageVersionMenu();
|
||||
initializeViewAnimation();
|
||||
|
||||
xpathPanelController.initialiseVersionChoiceBox(xpathVersionChoiceBox);
|
||||
|
||||
languageVersion = Val.wrap(languageChoiceBox.getSelectionModel().selectedItemProperty());
|
||||
DesignerUtil.rewire(sourceEditorController.languageVersionProperty(),
|
||||
languageVersion, this::setLanguageVersion);
|
||||
|
||||
xpathVersion = Val.wrap(xpathVersionChoiceBox.getSelectionModel().selectedItemProperty());
|
||||
DesignerUtil.rewire(xpathPanelController.xpathVersionProperty(),
|
||||
xpathVersion, this::setXpathVersion);
|
||||
|
||||
|
||||
licenseMenuItem.setOnAction(e -> showLicensePopup());
|
||||
openFileMenuItem.setOnAction(e -> onOpenFileClicked());
|
||||
openRecentMenu.setOnAction(e -> updateRecentFilesMenu());
|
||||
openRecentMenu.setOnShowing(e -> updateRecentFilesMenu());
|
||||
fileMenu.setOnShowing(e -> onFileMenuShowing());
|
||||
exportXPathMenuItem.setOnAction(e -> {
|
||||
try {
|
||||
xpathPanelController.showExportXPathToRuleWizard();
|
||||
} catch (IOException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
});
|
||||
|
||||
setupAuxclasspathMenuItem.setOnAction(e -> sourceEditorController.showAuxclasspathSetupPopup(designerRoot));
|
||||
|
||||
Platform.runLater(this::updateRecentFilesMenu);
|
||||
Platform.runLater(this::refreshAST); // initial refreshing
|
||||
|
||||
Platform.runLater(() -> sourceEditorController.moveCaret(0, 0));
|
||||
Platform.runLater(() -> { // fixes choicebox bad rendering on first opening
|
||||
languageChoiceBox.show();
|
||||
languageChoiceBox.hide();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void initializeLanguageVersionMenu() {
|
||||
List<LanguageVersion> supported = DesignerUtil.getSupportedLanguageVersions();
|
||||
supported.sort(LanguageVersion::compareTo);
|
||||
languageChoiceBox.getItems().addAll(supported);
|
||||
|
||||
languageChoiceBox.setConverter(DesignerUtil.languageVersionStringConverter());
|
||||
|
||||
languageChoiceBox.getSelectionModel().select(DesignerUtil.defaultLanguageVersion());
|
||||
languageChoiceBox.show();
|
||||
@Override
|
||||
protected void afterChildrenInit() {
|
||||
updateRecentFilesMenu();
|
||||
refreshAST(); // initial refreshing
|
||||
sourceEditorController.moveCaret(0, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -360,7 +312,7 @@ public class MainDesignerController implements Initializable, SettingsOwner {
|
||||
sourceEditorController.setText(source);
|
||||
LanguageVersion guess = DesignerUtil.getLanguageVersionFromExtension(file.getName());
|
||||
if (guess != null) { // guess the language from the extension
|
||||
languageChoiceBox.getSelectionModel().select(guess);
|
||||
sourceEditorController.setLanguageVersion(guess);
|
||||
refreshAST();
|
||||
}
|
||||
|
||||
@@ -417,36 +369,17 @@ public class MainDesignerController implements Initializable, SettingsOwner {
|
||||
|
||||
|
||||
public LanguageVersion getLanguageVersion() {
|
||||
return languageVersion.getValue();
|
||||
return sourceEditorController.getLanguageVersion();
|
||||
}
|
||||
|
||||
|
||||
public void setLanguageVersion(LanguageVersion version) {
|
||||
if (languageChoiceBox.getItems().contains(version)) {
|
||||
languageChoiceBox.getSelectionModel().select(version);
|
||||
}
|
||||
sourceEditorController.setLanguageVersion(version);
|
||||
}
|
||||
|
||||
|
||||
public Val<LanguageVersion> languageVersionProperty() {
|
||||
return languageVersion;
|
||||
}
|
||||
|
||||
|
||||
public String getXpathVersion() {
|
||||
return xpathVersion.getValue();
|
||||
}
|
||||
|
||||
|
||||
public void setXpathVersion(String version) {
|
||||
if (xpathVersionChoiceBox.getItems().contains(version)) {
|
||||
xpathVersionChoiceBox.getSelectionModel().select(version);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Val<String> xpathVersionProperty() {
|
||||
return xpathVersion;
|
||||
return sourceEditorController.languageVersionProperty();
|
||||
}
|
||||
|
||||
|
||||
@@ -496,7 +429,7 @@ public class MainDesignerController implements Initializable, SettingsOwner {
|
||||
|
||||
|
||||
@Override
|
||||
public List<SettingsOwner> getChildrenSettingsNodes() {
|
||||
return Arrays.asList(xpathPanelController, sourceEditorController);
|
||||
public List<AbstractController> getChildren() {
|
||||
return Arrays.asList(xpathPanelController, sourceEditorController, nodeInfoPanelController, eventLogPanelController);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,11 +4,9 @@
|
||||
|
||||
package net.sourceforge.pmd.util.fxdesigner;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.Objects;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import org.reactfx.EventStreams;
|
||||
|
||||
@@ -18,13 +16,13 @@ import net.sourceforge.pmd.lang.java.ast.TypeNode;
|
||||
import net.sourceforge.pmd.lang.symboltable.NameDeclaration;
|
||||
import net.sourceforge.pmd.util.fxdesigner.model.MetricEvaluator;
|
||||
import net.sourceforge.pmd.util.fxdesigner.model.MetricResult;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.AbstractController;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.controls.ScopeHierarchyTreeCell;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.controls.ScopeHierarchyTreeItem;
|
||||
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.ListView;
|
||||
import javafx.scene.control.Tab;
|
||||
@@ -40,7 +38,7 @@ import javafx.scene.control.TreeView;
|
||||
* @since 6.0.0
|
||||
*/
|
||||
@SuppressWarnings("PMD.UnusedPrivateField")
|
||||
public class NodeInfoPanelController implements Initializable {
|
||||
public class NodeInfoPanelController extends AbstractController {
|
||||
|
||||
private final MainDesignerController parent;
|
||||
|
||||
@@ -65,9 +63,8 @@ public class NodeInfoPanelController implements Initializable {
|
||||
parent = mainController;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void initialize(URL location, ResourceBundle resources) {
|
||||
protected void beforeParentInit() {
|
||||
EventStreams.valuesOf(scopeHierarchyTreeView.getSelectionModel().selectedItemProperty())
|
||||
.filter(Objects::nonNull)
|
||||
.map(TreeItem::getValue)
|
||||
|
||||
@@ -11,7 +11,6 @@ import static net.sourceforge.pmd.util.fxdesigner.util.IteratorUtil.toIterable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@@ -19,7 +18,6 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.IntFunction;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -38,22 +36,26 @@ 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.popups.AuxclasspathSetupController;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.AbstractController;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.DesignerUtil;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.TextAwareNodeWrapper;
|
||||
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;
|
||||
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.ASTTreeCell;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.controls.ASTTreeItem;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.controls.ToolbarTitledPane;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.controls.TreeViewWrapper;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.css.PseudoClass;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.MenuButton;
|
||||
import javafx.scene.control.RadioMenuItem;
|
||||
import javafx.scene.control.SelectionModel;
|
||||
import javafx.scene.control.ToggleGroup;
|
||||
import javafx.scene.control.TreeItem;
|
||||
import javafx.scene.control.TreeView;
|
||||
|
||||
@@ -64,10 +66,16 @@ import javafx.scene.control.TreeView;
|
||||
* @author Clément Fournier
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class SourceEditorController implements Initializable, SettingsOwner {
|
||||
public class SourceEditorController extends AbstractController {
|
||||
|
||||
private static final Duration AST_REFRESH_DELAY = Duration.ofMillis(100);
|
||||
|
||||
@FXML
|
||||
private ToolbarTitledPane editorTitledPane;
|
||||
@FXML
|
||||
private MenuButton languageSelectionMenuButton;
|
||||
@FXML
|
||||
private Label sourceCodeTitleLabel;
|
||||
@FXML
|
||||
private Label astTitleLabel;
|
||||
@FXML
|
||||
@@ -93,6 +101,9 @@ public class SourceEditorController implements Initializable, SettingsOwner {
|
||||
}
|
||||
});
|
||||
|
||||
private Var<LanguageVersion> languageVersionUIProperty;
|
||||
|
||||
|
||||
public SourceEditorController(DesignerRoot owner, MainDesignerController mainController) {
|
||||
parent = mainController;
|
||||
astManager = new ASTManager(owner);
|
||||
@@ -100,16 +111,23 @@ public class SourceEditorController implements Initializable, SettingsOwner {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(URL location, ResourceBundle resources) {
|
||||
|
||||
protected void beforeParentInit() {
|
||||
treeViewWrapper = new TreeViewWrapper<>(astTreeView);
|
||||
astTreeView.setCellFactory(treeView -> new ASTTreeCell(parent));
|
||||
|
||||
initializeLanguageSelector(); // languageVersionProperty() must be initialized
|
||||
|
||||
languageVersionProperty().values()
|
||||
.filterMap(Objects::nonNull, LanguageVersion::getLanguage)
|
||||
.distinct()
|
||||
.subscribe(this::updateSyntaxHighlighter);
|
||||
|
||||
languageVersionProperty().values()
|
||||
.filter(Objects::nonNull)
|
||||
.map(LanguageVersion::getShortName)
|
||||
.map(lang -> "Source Code (" + lang + ")")
|
||||
.subscribe(editorTitledPane::setTitle);
|
||||
|
||||
EventStreams.valuesOf(astTreeView.getSelectionModel().selectedItemProperty())
|
||||
.filterMap(Objects::nonNull, TreeItem::getValue)
|
||||
.subscribe(parent::onNodeItemSelected);
|
||||
@@ -130,6 +148,33 @@ public class SourceEditorController implements Initializable, SettingsOwner {
|
||||
}
|
||||
|
||||
|
||||
private void initializeLanguageSelector() {
|
||||
|
||||
ToggleGroup languageToggleGroup = new ToggleGroup();
|
||||
|
||||
DesignerUtil.getSupportedLanguageVersions()
|
||||
.stream()
|
||||
.sorted(LanguageVersion::compareTo)
|
||||
.map(lv -> {
|
||||
RadioMenuItem item = new RadioMenuItem(lv.getShortName());
|
||||
item.setUserData(lv);
|
||||
return item;
|
||||
})
|
||||
.forEach(item -> {
|
||||
languageToggleGroup.getToggles().add(item);
|
||||
languageSelectionMenuButton.getItems().add(item);
|
||||
});
|
||||
|
||||
languageVersionUIProperty = DesignerUtil.mapToggleGroupToUserData(languageToggleGroup);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void afterParentInit() {
|
||||
DesignerUtil.rewire(astManager.languageVersionProperty(), languageVersionUIProperty);
|
||||
}
|
||||
|
||||
|
||||
private IntFunction<javafx.scene.Node> lineNumberFactory() {
|
||||
IntFunction<javafx.scene.Node> base = LineNumberFactory.get(codeEditorArea);
|
||||
Val<Integer> activePar = Val.wrap(codeEditorArea.currentParagraphProperty());
|
||||
@@ -341,20 +386,19 @@ public class SourceEditorController implements Initializable, SettingsOwner {
|
||||
|
||||
@PersistentProperty
|
||||
public LanguageVersion getLanguageVersion() {
|
||||
return astManager.getLanguageVersion();
|
||||
return languageVersionUIProperty.getValue();
|
||||
}
|
||||
|
||||
|
||||
public void setLanguageVersion(LanguageVersion version) {
|
||||
astManager.setLanguageVersion(version);
|
||||
languageVersionUIProperty.setValue(version);
|
||||
}
|
||||
|
||||
|
||||
public Var<LanguageVersion> languageVersionProperty() {
|
||||
return astManager.languageVersionProperty();
|
||||
return languageVersionUIProperty;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the most up-to-date compilation unit, or empty if it can't be parsed.
|
||||
*/
|
||||
@@ -418,5 +462,4 @@ public class SourceEditorController implements Initializable, SettingsOwner {
|
||||
return styleClass;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,12 +6,11 @@ package net.sourceforge.pmd.util.fxdesigner;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -33,33 +32,34 @@ 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.AbstractController;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.DesignerUtil;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.TextAwareNodeWrapper;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.autocomplete.CompletionResultSource;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.autocomplete.XPathAutocompleteProvider;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.autocomplete.XPathCompletionSource;
|
||||
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.SyntaxHighlightingCodeArea;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting.XPathSyntaxHighlighter;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.controls.PropertyTableView;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.controls.ToolbarTitledPane;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.controls.XpathViolationListCell;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.ChoiceBox;
|
||||
import javafx.scene.control.ContextMenu;
|
||||
import javafx.scene.control.ListView;
|
||||
import javafx.scene.control.MenuButton;
|
||||
import javafx.scene.control.MenuItem;
|
||||
import javafx.scene.control.RadioMenuItem;
|
||||
import javafx.scene.control.TextArea;
|
||||
import javafx.scene.control.TitledPane;
|
||||
import javafx.scene.control.ToggleGroup;
|
||||
import javafx.scene.input.MouseButton;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.stage.Modality;
|
||||
@@ -68,13 +68,14 @@ import javafx.stage.StageStyle;
|
||||
|
||||
|
||||
/**
|
||||
* XPath panel controller.
|
||||
* XPath panel controller. One such controller is a presenter for an {@link ObservableXPathRuleBuilder},
|
||||
* which stores all data about one currently edited rule.
|
||||
*
|
||||
* @author Clément Fournier
|
||||
* @see ExportXPathWizardController
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class XPathPanelController implements Initializable, SettingsOwner {
|
||||
public class XPathPanelController extends AbstractController {
|
||||
|
||||
private static final Duration XPATH_REFRESH_DELAY = Duration.ofMillis(100);
|
||||
private final DesignerRoot designerRoot;
|
||||
@@ -82,6 +83,13 @@ public class XPathPanelController implements Initializable, SettingsOwner {
|
||||
private final XPathEvaluator xpathEvaluator = new XPathEvaluator();
|
||||
private final ObservableXPathRuleBuilder ruleBuilder = new ObservableXPathRuleBuilder();
|
||||
|
||||
|
||||
@FXML
|
||||
public ToolbarTitledPane expressionTitledPane;
|
||||
@FXML
|
||||
public Button exportXpathToRuleButton;
|
||||
@FXML
|
||||
private MenuButton xpathVersionMenuButton;
|
||||
@FXML
|
||||
private PropertyTableView propertyTableView;
|
||||
@FXML
|
||||
@@ -91,9 +99,8 @@ public class XPathPanelController implements Initializable, SettingsOwner {
|
||||
@FXML
|
||||
private ListView<TextAwareNodeWrapper> xpathResultListView;
|
||||
|
||||
// Actually a child of the main view toolbar, but this controller is responsible for it
|
||||
@SuppressWarnings("PMD.SingularField")
|
||||
private ChoiceBox<String> xpathVersionChoiceBox;
|
||||
// ui property
|
||||
private Var<String> xpathVersionUIProperty = Var.newSimpleVar(XPathRuleQuery.XPATH_2_0);
|
||||
|
||||
|
||||
public XPathPanelController(DesignerRoot owner, MainDesignerController mainController) {
|
||||
@@ -105,21 +112,24 @@ public class XPathPanelController implements Initializable, SettingsOwner {
|
||||
|
||||
|
||||
@Override
|
||||
public void initialize(URL location, ResourceBundle resources) {
|
||||
protected void beforeParentInit() {
|
||||
xpathExpressionArea.setSyntaxHighlighter(new XPathSyntaxHighlighter());
|
||||
|
||||
initGenerateXPathFromStackTrace();
|
||||
initialiseVersionSelection();
|
||||
|
||||
expressionTitledPane.titleProperty().bind(xpathVersionUIProperty.map(v -> "XPath Expression (" + v + ")"));
|
||||
|
||||
xpathResultListView.setCellFactory(v -> new XpathViolationListCell());
|
||||
|
||||
exportXpathToRuleButton.setOnAction(e -> showExportXPathToRuleWizard());
|
||||
|
||||
EventStreams.valuesOf(xpathResultListView.getSelectionModel().selectedItemProperty())
|
||||
.conditionOn(xpathResultListView.focusedProperty())
|
||||
.filter(Objects::nonNull)
|
||||
.map(TextAwareNodeWrapper::getNode)
|
||||
.subscribe(parent::onNodeItemSelected);
|
||||
|
||||
Platform.runLater(this::bindToParent);
|
||||
|
||||
xpathExpressionArea.richChanges()
|
||||
.filter(t -> !t.isIdentity())
|
||||
.successionEnds(XPATH_REFRESH_DELAY)
|
||||
@@ -127,12 +137,51 @@ public class XPathPanelController implements Initializable, SettingsOwner {
|
||||
.or(xpathVersionProperty().changes())
|
||||
.subscribe(tick -> parent.refreshXPathResults());
|
||||
|
||||
Supplier<CompletionResultSource> suggestionMaker = () -> XPathCompletionSource.forLanguage(parent.getLanguageVersion().getLanguage());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void afterParentInit() {
|
||||
bindToParent();
|
||||
|
||||
// init autocompletion only after binding to parent and settings restore
|
||||
// otherwise the popup is shown on startup
|
||||
Supplier<CompletionResultSource> suggestionMaker = () -> XPathCompletionSource.forLanguage(parent.getLanguageVersion().getLanguage());
|
||||
new XPathAutocompleteProvider(xpathExpressionArea, suggestionMaker).initialiseAutoCompletion();
|
||||
}
|
||||
|
||||
|
||||
// Binds the underlying rule parameters to the parent UI, disconnecting it from the wizard if need be
|
||||
private void bindToParent() {
|
||||
DesignerUtil.rewire(getRuleBuilder().languageProperty(), Val.map(parent.languageVersionProperty(), LanguageVersion::getLanguage));
|
||||
|
||||
DesignerUtil.rewireInit(getRuleBuilder().xpathVersionProperty(), xpathVersionProperty());
|
||||
DesignerUtil.rewireInit(getRuleBuilder().xpathExpressionProperty(), xpathExpressionProperty());
|
||||
|
||||
DesignerUtil.rewireInit(getRuleBuilder().rulePropertiesProperty(),
|
||||
propertyTableView.rulePropertiesProperty(), propertyTableView::setRuleProperties);
|
||||
}
|
||||
|
||||
private void initialiseVersionSelection() {
|
||||
ToggleGroup xpathVersionToggleGroup = new ToggleGroup();
|
||||
|
||||
List<String> versionItems = new ArrayList<>();
|
||||
versionItems.add(XPathRuleQuery.XPATH_1_0);
|
||||
versionItems.add(XPathRuleQuery.XPATH_1_0_COMPATIBILITY);
|
||||
versionItems.add(XPathRuleQuery.XPATH_2_0);
|
||||
|
||||
versionItems.forEach(v -> {
|
||||
RadioMenuItem item = new RadioMenuItem("XPath " + v);
|
||||
item.setUserData(v);
|
||||
item.setToggleGroup(xpathVersionToggleGroup);
|
||||
xpathVersionMenuButton.getItems().add(item);
|
||||
});
|
||||
|
||||
xpathVersionUIProperty = DesignerUtil.mapToggleGroupToUserData(xpathVersionToggleGroup);
|
||||
|
||||
setXpathVersion(XPathRuleQuery.XPATH_2_0);
|
||||
}
|
||||
|
||||
|
||||
private void initGenerateXPathFromStackTrace() {
|
||||
@@ -178,30 +227,6 @@ public class XPathPanelController implements Initializable, SettingsOwner {
|
||||
}
|
||||
|
||||
|
||||
// Binds the underlying rule parameters to the parent UI, disconnecting it from the wizard if need be
|
||||
private void bindToParent() {
|
||||
DesignerUtil.rewire(getRuleBuilder().languageProperty(),
|
||||
Val.map(parent.languageVersionProperty(), LanguageVersion::getLanguage));
|
||||
|
||||
DesignerUtil.rewire(getRuleBuilder().xpathVersionProperty(), parent.xpathVersionProperty());
|
||||
DesignerUtil.rewire(getRuleBuilder().xpathExpressionProperty(), xpathExpressionProperty());
|
||||
|
||||
DesignerUtil.rewire(getRuleBuilder().rulePropertiesProperty(),
|
||||
propertyTableView.rulePropertiesProperty(), propertyTableView::setRuleProperties);
|
||||
}
|
||||
|
||||
|
||||
public void initialiseVersionChoiceBox(ChoiceBox<String> choiceBox) {
|
||||
this.xpathVersionChoiceBox = choiceBox;
|
||||
|
||||
ObservableList<String> versionItems = choiceBox.getItems();
|
||||
versionItems.add(XPathRuleQuery.XPATH_1_0);
|
||||
versionItems.add(XPathRuleQuery.XPATH_1_0_COMPATIBILITY);
|
||||
versionItems.add(XPathRuleQuery.XPATH_2_0);
|
||||
|
||||
xpathVersionChoiceBox.getSelectionModel().select(XPathRuleQuery.XPATH_2_0);
|
||||
choiceBox.setConverter(DesignerUtil.stringConverter(s -> "XPath " + s, s -> s.substring(6)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@@ -223,11 +248,11 @@ public class XPathPanelController implements Initializable, SettingsOwner {
|
||||
}
|
||||
|
||||
ObservableList<Node> results
|
||||
= FXCollections.observableArrayList(xpathEvaluator.evaluateQuery(compilationUnit,
|
||||
version,
|
||||
getXpathVersion(),
|
||||
xpath,
|
||||
ruleBuilder.getRuleProperties()));
|
||||
= FXCollections.observableArrayList(xpathEvaluator.evaluateQuery(compilationUnit,
|
||||
version,
|
||||
getXpathVersion(),
|
||||
xpath,
|
||||
ruleBuilder.getRuleProperties()));
|
||||
xpathResultListView.setItems(results.stream().map(parent::wrapNode).collect(Collectors.toCollection(LiveArrayList::new)));
|
||||
parent.highlightXPathResults(results);
|
||||
violationsTitledPane.setText("Matched nodes\t(" + results.size() + ")");
|
||||
@@ -256,9 +281,9 @@ public class XPathPanelController implements Initializable, SettingsOwner {
|
||||
}
|
||||
|
||||
|
||||
public void showExportXPathToRuleWizard() throws IOException {
|
||||
public void showExportXPathToRuleWizard() {
|
||||
ExportXPathWizardController wizard
|
||||
= new ExportXPathWizardController(xpathExpressionProperty());
|
||||
= new ExportXPathWizardController(xpathExpressionProperty());
|
||||
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("fxml/xpath-export-wizard.fxml"));
|
||||
loader.setController(wizard);
|
||||
@@ -268,7 +293,12 @@ public class XPathPanelController implements Initializable, SettingsOwner {
|
||||
dialog.setOnCloseRequest(e -> wizard.shutdown());
|
||||
dialog.initModality(Modality.WINDOW_MODAL);
|
||||
|
||||
Parent root = loader.load();
|
||||
Parent root;
|
||||
try {
|
||||
root = loader.load();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
Scene scene = new Scene(root);
|
||||
//stage.setTitle("PMD Rule Designer (v " + PMD.VERSION + ')');
|
||||
dialog.setScene(scene);
|
||||
@@ -276,7 +306,6 @@ public class XPathPanelController implements Initializable, SettingsOwner {
|
||||
}
|
||||
|
||||
|
||||
@PersistentProperty
|
||||
public String getXpathExpression() {
|
||||
return xpathExpressionArea.getText();
|
||||
}
|
||||
@@ -287,24 +316,23 @@ public class XPathPanelController implements Initializable, SettingsOwner {
|
||||
}
|
||||
|
||||
|
||||
public Val<String> xpathExpressionProperty() {
|
||||
return Val.wrap(xpathExpressionArea.textProperty());
|
||||
public Var<String> xpathExpressionProperty() {
|
||||
return Var.fromVal(xpathExpressionArea.textProperty(), this::setXpathExpression);
|
||||
}
|
||||
|
||||
|
||||
@PersistentProperty
|
||||
public String getXpathVersion() {
|
||||
return getRuleBuilder().getXpathVersion();
|
||||
return xpathVersionProperty().getValue();
|
||||
}
|
||||
|
||||
|
||||
public void setXpathVersion(String xpathVersion) {
|
||||
getRuleBuilder().setXpathVersion(xpathVersion);
|
||||
xpathVersionProperty().setValue(xpathVersion);
|
||||
}
|
||||
|
||||
|
||||
public Var<String> xpathVersionProperty() {
|
||||
return getRuleBuilder().xpathVersionProperty();
|
||||
return xpathVersionUIProperty;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ package net.sourceforge.pmd.util.fxdesigner.model;
|
||||
import org.reactfx.value.Var;
|
||||
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.DesignerUtil;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.beans.SettingsPersistenceUtil.PersistentProperty;
|
||||
|
||||
|
||||
/**
|
||||
@@ -22,6 +23,7 @@ public class ObservableXPathRuleBuilder extends ObservableRuleBuilder {
|
||||
private final Var<String> xpathExpression = Var.newSimpleVar("");
|
||||
|
||||
|
||||
@PersistentProperty
|
||||
public String getXpathVersion() {
|
||||
return xpathVersion.getValue();
|
||||
}
|
||||
@@ -37,11 +39,17 @@ public class ObservableXPathRuleBuilder extends ObservableRuleBuilder {
|
||||
}
|
||||
|
||||
|
||||
@PersistentProperty
|
||||
public String getXpathExpression() {
|
||||
return xpathExpression.getValue();
|
||||
}
|
||||
|
||||
|
||||
public void setXpathExpression(String value) {
|
||||
xpathExpression.setValue(value);
|
||||
}
|
||||
|
||||
|
||||
public Var<String> xpathExpressionProperty() {
|
||||
return xpathExpression;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ 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;
|
||||
import static net.sourceforge.pmd.util.fxdesigner.util.DesignerUtil.rewire;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Objects;
|
||||
@@ -127,10 +126,10 @@ public class EditPropertyDialogController implements Initializable {
|
||||
public void bindToDescriptor(PropertyDescriptorSpec spec, ObservableList<PropertyDescriptorSpec> allDescriptors) {
|
||||
backingDescriptor.setValue(spec);
|
||||
backingDescriptorList.setValue(allDescriptors);
|
||||
rewire(spec.nameProperty(), this.nameProperty(), this::setName);
|
||||
rewire(spec.typeIdProperty(), this.typeIdProperty(), this::setTypeId);
|
||||
rewire(spec.valueProperty(), this.valueProperty(), this::setValue);
|
||||
rewire(spec.descriptionProperty(), this.descriptionProperty(), this::setDescription);
|
||||
DesignerUtil.rewireInit(spec.nameProperty(), this.nameProperty(), this::setName);
|
||||
DesignerUtil.rewireInit(spec.typeIdProperty(), this.typeIdProperty(), this::setTypeId);
|
||||
DesignerUtil.rewireInit(spec.valueProperty(), this.valueProperty(), this::setValue);
|
||||
DesignerUtil.rewireInit(spec.descriptionProperty(), this.descriptionProperty(), this::setDescription);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.util.fxdesigner.util;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.beans.SettingsOwner;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.fxml.Initializable;
|
||||
|
||||
|
||||
/**
|
||||
* Make the initialization cycle of JavaFX clearer. Children controller
|
||||
* are initialized before their parent, but sometimes it should only
|
||||
* perform some actions after its parent has been initialized, e.g. binding
|
||||
* properties that depend on a restored setting or stuff. This is part
|
||||
* of the reason why {@link Platform#runLater(Runnable)} can sometimes
|
||||
* be enough to solve initialization problems.
|
||||
*
|
||||
* This only works if all controllers in the tree extend this class.
|
||||
*
|
||||
* @author Clément Fournier
|
||||
* @since 7.0.0
|
||||
*/
|
||||
public class AbstractController implements Initializable, SettingsOwner {
|
||||
|
||||
@Override
|
||||
public final void initialize(URL url, ResourceBundle resourceBundle) {
|
||||
beforeParentInit();
|
||||
for (AbstractController child : getChildren()) {
|
||||
child.afterParentInit();
|
||||
}
|
||||
afterChildrenInit();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Executed before the parent's initialization.
|
||||
* Always executed once at the start of the initialization
|
||||
* of this controller.
|
||||
*/
|
||||
protected void beforeParentInit() {
|
||||
// by default do nothing
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Executed after the parent's initialization (so after {@link #afterChildrenInit()}).
|
||||
* This also means, after persistent settings restoration. If this node has no
|
||||
* parent, then this is never executed.
|
||||
*/
|
||||
protected void afterParentInit() {
|
||||
// by default do nothing
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Runs once after every child has finished their initialization.
|
||||
* This will be run in all cases. It's only useful if the children
|
||||
* do something useful in their {@link #afterParentInit()}.
|
||||
*/
|
||||
protected void afterChildrenInit() {
|
||||
// by default do nothing
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<? extends SettingsOwner> getChildrenSettingsNodes() {
|
||||
return getChildren();
|
||||
}
|
||||
|
||||
|
||||
protected List<? extends AbstractController> getChildren() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
import org.reactfx.value.Var;
|
||||
|
||||
import net.sourceforge.pmd.lang.Language;
|
||||
import net.sourceforge.pmd.lang.LanguageRegistry;
|
||||
@@ -30,10 +31,12 @@ import net.sourceforge.pmd.lang.LanguageVersion;
|
||||
import net.sourceforge.pmd.lang.Parser;
|
||||
import net.sourceforge.pmd.lang.rule.xpath.XPathRuleQuery;
|
||||
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.Property;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.scene.control.ListCell;
|
||||
import javafx.scene.control.ListView;
|
||||
import javafx.scene.control.ToggleGroup;
|
||||
import javafx.scene.control.Tooltip;
|
||||
import javafx.util.Callback;
|
||||
import javafx.util.StringConverter;
|
||||
@@ -126,6 +129,24 @@ public final class DesignerUtil {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given a toggle group whose toggles all have user data of type T,
|
||||
* maps the selected toggle property to a Var<T>
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> Var<T> mapToggleGroupToUserData(ToggleGroup toggleGroup) {
|
||||
return Var.fromVal(toggleGroup.selectedToggleProperty(), toggleGroup::selectToggle)
|
||||
.mapBidirectional(
|
||||
item -> (T) item.getUserData(),
|
||||
t -> toggleGroup.getToggles()
|
||||
.stream()
|
||||
.filter(toggle -> toggle.getUserData().equals(t))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new IllegalStateException("Unknown toggle " + t))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public static StringConverter<LanguageVersion> languageVersionStringConverter() {
|
||||
return DesignerUtil.stringConverter(LanguageVersion::getShortName,
|
||||
s -> LanguageRegistry.findLanguageVersionByTerseName(s.toLowerCase(Locale.ROOT)));
|
||||
@@ -172,20 +193,27 @@ public final class DesignerUtil {
|
||||
}
|
||||
|
||||
|
||||
/** Like the other overload, using the setter of the ui property. */
|
||||
public static <T> void rewireInit(Property<T> underlying, Property<T> ui) {
|
||||
rewireInit(underlying, ui, ui::setValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds the underlying property to a source of values. The source property is also initialised using the setter.
|
||||
* Binds the underlying property to a source of values (UI property). The UI
|
||||
* property is also initialised using a setter.
|
||||
*
|
||||
* @param underlying The underlying property
|
||||
* @param ui The property exposed to the user (the one in this wizard)
|
||||
* @param setter Setter to initialise the UI value
|
||||
* @param <T> Type of values
|
||||
*/
|
||||
public static <T> void rewire(Property<T> underlying, ObservableValue<? extends T> ui, Consumer<? super T> setter) {
|
||||
public static <T> void rewireInit(Property<T> underlying, ObservableValue<? extends T> ui, Consumer<? super T> setter) {
|
||||
setter.accept(underlying.getValue());
|
||||
rewire(underlying, ui);
|
||||
}
|
||||
|
||||
/** Like rewire, with no initialisation. */
|
||||
|
||||
|
||||
/** Like rewireInit, with no initialisation. */
|
||||
public static <T> void rewire(Property<T> underlying, ObservableValue<? extends T> source) {
|
||||
underlying.unbind();
|
||||
underlying.bind(source); // Bindings are garbage collected after the popup dies
|
||||
@@ -230,4 +258,9 @@ public final class DesignerUtil {
|
||||
public static Optional<String> stackTraceToXPath(Throwable e) {
|
||||
return stackTraceToXPath(ExceptionUtils.getStackTrace(e));
|
||||
}
|
||||
|
||||
|
||||
public static Var<Boolean> booleanVar(BooleanProperty p) {
|
||||
return Var.mapBidirectional(p, Boolean::booleanValue, Function.identity());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,10 @@ public class RestorePropertyVisitor extends BeanNodeVisitor<SettingsOwner> {
|
||||
}
|
||||
|
||||
for (SettingsOwner child : target.getChildrenSettingsNodes()) {
|
||||
model.getChildrenByType().get(child.getClass()).accept(this, child);
|
||||
BeanModelNode childModel = model.getChildrenByType().get(child.getClass());
|
||||
if (childModel != null) {
|
||||
childModel.accept(this, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ public interface SettingsOwner {
|
||||
|
||||
|
||||
/** Gets the children of this node in order. */
|
||||
default List<SettingsOwner> getChildrenSettingsNodes() {
|
||||
default List<? extends SettingsOwner> getChildrenSettingsNodes() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.util.fxdesigner.util.controls;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.reactfx.value.Val;
|
||||
import org.reactfx.value.Var;
|
||||
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TitledPane;
|
||||
import javafx.scene.control.ToolBar;
|
||||
import javafx.scene.layout.StackPane;
|
||||
|
||||
|
||||
/**
|
||||
* A Titled pane that has a toolbar in its header region.
|
||||
* Supported by some CSS in designer.less.
|
||||
*
|
||||
* @author Clément Fournier
|
||||
* @since 7.0.0
|
||||
*/
|
||||
public final class ToolbarTitledPane extends TitledPane {
|
||||
|
||||
|
||||
private ToolBar toolBar = new ToolBar();
|
||||
private Var<String> title = Var.newSimpleVar("Title");
|
||||
|
||||
|
||||
public ToolbarTitledPane() {
|
||||
|
||||
getStyleClass().add("tool-bar-title");
|
||||
|
||||
toolBar.setPadding(Insets.EMPTY);
|
||||
|
||||
Label titleLabel = new Label("Title");
|
||||
titleLabel.textProperty().bind(title);
|
||||
|
||||
toolBar.getItems().add(titleLabel);
|
||||
|
||||
setGraphic(toolBar);
|
||||
|
||||
// should be an empty string, binding prevents to set it
|
||||
textProperty().bind(Val.constant(""));
|
||||
|
||||
// The toolbar is too large for the title region and is not
|
||||
// centered unless we bind the height, like follows
|
||||
|
||||
Val.wrap(toolBar.parentProperty())
|
||||
.values()
|
||||
.filter(Objects::nonNull)
|
||||
.subscribe(parent -> {
|
||||
// The title region is provided by the skin,
|
||||
// this is the only way to access it outside of css
|
||||
StackPane titleRegion = (StackPane) parent;
|
||||
toolBar.maxHeightProperty().unbind();
|
||||
toolBar.maxHeightProperty().bind(titleRegion.heightProperty());
|
||||
toolBar.minHeightProperty().unbind();
|
||||
toolBar.minHeightProperty().bind(titleRegion.heightProperty());
|
||||
toolBar.prefHeightProperty().unbind();
|
||||
toolBar.prefHeightProperty().bind(titleRegion.heightProperty());
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
public ObservableList<Node> getToolbarItems() {
|
||||
return toolBar.getItems();
|
||||
}
|
||||
|
||||
|
||||
public void setToolbarItems(Collection<? extends Node> nodes) {
|
||||
toolBar.getItems().setAll(nodes);
|
||||
}
|
||||
|
||||
|
||||
public String getTitle() {
|
||||
return title.getValue();
|
||||
}
|
||||
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title.setValue(title);
|
||||
}
|
||||
|
||||
|
||||
/** Title of the pane, not equivalent to {@link #textProperty()}. */
|
||||
public Var<String> titleProperty() {
|
||||
return title;
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@
|
||||
styleClass="icon-button"
|
||||
textAlignment="CENTER">
|
||||
<graphic>
|
||||
<FontIcon iconLiteral="fa-plus"/>
|
||||
<FontIcon iconLiteral="fas-plus"/>
|
||||
</graphic>
|
||||
<tooltip>
|
||||
<Tooltip text="Add new jars"/>
|
||||
@@ -44,7 +44,7 @@
|
||||
styleClass="icon-button"
|
||||
textAlignment="CENTER">
|
||||
<graphic>
|
||||
<FontIcon iconLiteral="fa-minus"/>
|
||||
<FontIcon iconLiteral="fas-minus"/>
|
||||
</graphic>
|
||||
<tooltip>
|
||||
<Tooltip text="Remove item"/>
|
||||
@@ -52,12 +52,12 @@
|
||||
</Button>
|
||||
<Button fx:id="moveItemUpButton" minWidth="-Infinity" mnemonicParsing="false" styleClass="icon-button">
|
||||
<graphic>
|
||||
<FontIcon iconLiteral="fa-arrow-up"/>
|
||||
<FontIcon iconLiteral="fas-arrow-up"/>
|
||||
</graphic>
|
||||
</Button>
|
||||
<Button fx:id="moveItemDownButton" minWidth="-Infinity" mnemonicParsing="false" styleClass="icon-button">
|
||||
<graphic>
|
||||
<FontIcon iconLiteral="fa-arrow-down"/>
|
||||
<FontIcon iconLiteral="fas-arrow-down"/>
|
||||
</graphic>
|
||||
<tooltip>
|
||||
<Tooltip text="Move item down"/>
|
||||
|
||||
@@ -18,39 +18,34 @@
|
||||
<?import javafx.scene.layout.BorderPane?>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
<?import javafx.scene.layout.Pane?>
|
||||
<AnchorPane prefHeight="750.0" prefWidth="1200.0" stylesheets="@../css/designer.css"
|
||||
xmlns="http://javafx.com/javafx/8.0.121" xmlns:fx="http://javafx.com/fxml/1"
|
||||
fx:controller="net.sourceforge.pmd.util.fxdesigner.MainDesignerController">
|
||||
|
||||
<AnchorPane prefHeight="750.0" prefWidth="1200.0" stylesheets="@../css/designer.css" xmlns="http://javafx.com/javafx/8.0.172-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="net.sourceforge.pmd.util.fxdesigner.MainDesignerController">
|
||||
<children>
|
||||
<BorderPane prefHeight="600.0" prefWidth="900.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||
<top>
|
||||
<AnchorPane>
|
||||
<children>
|
||||
<MenuBar layoutX="-11.0" maxHeight="20.0" prefHeight="20.0" AnchorPane.bottomAnchor="0.0"
|
||||
AnchorPane.leftAnchor="-11.0" AnchorPane.rightAnchor="11.0" AnchorPane.topAnchor="0.0">
|
||||
<MenuBar layoutX="-11.0" maxHeight="20.0" prefHeight="20.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="-11.0" AnchorPane.rightAnchor="11.0" AnchorPane.topAnchor="0.0">
|
||||
<menus>
|
||||
<Menu fx:id="fileMenu" mnemonicParsing="false" text="File">
|
||||
<items>
|
||||
<MenuItem fx:id="openFileMenuItem" mnemonicParsing="false" text="Open..." />
|
||||
<Menu fx:id="openRecentMenu" mnemonicParsing="false" text="Open recent..." />
|
||||
<SeparatorMenuItem mnemonicParsing="false" />
|
||||
<MenuItem fx:id="exportToTestCodeMenuItem" mnemonicParsing="false" text="Export code to test code" />
|
||||
<MenuItem fx:id="exportXPathMenuItem" mnemonicParsing="false" text="Export XPath to rule" />
|
||||
<Menu fx:id="openRecentMenu" mnemonicParsing="false" text="Open recent" />
|
||||
</items>
|
||||
</Menu>
|
||||
|
||||
<Menu mnemonicParsing="false" text="Configuration">
|
||||
<items>
|
||||
<MenuItem fx:id="setupAuxclasspathMenuItem" mnemonicParsing="false"
|
||||
text="Set up the auxclasspath" >
|
||||
<MenuItem fx:id="setupAuxclasspathMenuItem" mnemonicParsing="false" text="Set up the auxclasspath...">
|
||||
</MenuItem>
|
||||
</items>
|
||||
</Menu>
|
||||
|
||||
<Menu mnemonicParsing="false" text="About">
|
||||
<items>
|
||||
<MenuItem mnemonicParsing="false" text="About"/>
|
||||
<MenuItem fx:id="licenseMenuItem" mnemonicParsing="false" text="License"/>
|
||||
<!-- TODO add link to doc pages -->
|
||||
<!--<MenuItem mnemonicParsing="false" text="About" />-->
|
||||
<MenuItem fx:id="licenseMenuItem" mnemonicParsing="false" text="License..." />
|
||||
</items>
|
||||
</Menu>
|
||||
|
||||
@@ -74,23 +69,6 @@
|
||||
<bottom>
|
||||
<ToolBar id="main-toolbar" prefHeight="40.0" prefWidth="200.0" BorderPane.alignment="CENTER">
|
||||
<items>
|
||||
<HBox alignment="CENTER" spacing="10.0">
|
||||
<children>
|
||||
<Label text="Language Version:" />
|
||||
<ChoiceBox fx:id="languageChoiceBox" maxWidth="115.0" prefWidth="115.0" HBox.hgrow="NEVER">
|
||||
<padding>
|
||||
<Insets bottom="-3.0" left="-3.0" right="-3.0" top="-3.0" />
|
||||
</padding>
|
||||
</ChoiceBox>
|
||||
<Pane prefWidth="10.0" HBox.hgrow="NEVER" />
|
||||
<Label text="XPath Version:" />
|
||||
<ChoiceBox maxWidth="115.0" prefWidth="115.0" fx:id="xpathVersionChoiceBox">
|
||||
<padding>
|
||||
<Insets bottom="-3.0" left="-3.0" right="-3.0" top="-3.0" />
|
||||
</padding>
|
||||
</ChoiceBox>
|
||||
</children>
|
||||
</HBox>
|
||||
<Pane HBox.hgrow="ALWAYS" />
|
||||
<ToggleButton fx:id="bottomTabsToggle" mnemonicParsing="false" selected="true" styleClass="expand-toggle" />
|
||||
</items>
|
||||
|
||||
@@ -2,42 +2,68 @@
|
||||
|
||||
<!-- One editor, ie source + ast view -->
|
||||
|
||||
<?import org.kordamp.ikonli.javafx.FontIcon?>
|
||||
<?import net.sourceforge.pmd.util.fxdesigner.util.codearea.HighlightLayerCodeArea?>
|
||||
<?import net.sourceforge.pmd.util.fxdesigner.util.controls.ToolbarTitledPane?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.MenuButton?>
|
||||
<?import javafx.scene.control.SplitPane?>
|
||||
<?import javafx.scene.control.ToolBar?>
|
||||
<?import javafx.scene.control.TreeView?>
|
||||
<?import javafx.scene.layout.AnchorPane?>
|
||||
<?import javafx.scene.layout.BorderPane?>
|
||||
<SplitPane dividerPositions="0.5" prefHeight="400.0" prefWidth="500.0" styleClass="accent-header" stylesheets="@../css/designer.css" BorderPane.alignment="CENTER" xmlns="http://javafx.com/javafx/9" xmlns:fx="http://javafx.com/fxml/1" fx:controller="net.sourceforge.pmd.util.fxdesigner.SourceEditorController">
|
||||
<SplitPane dividerPositions="0.5, 0.5"
|
||||
prefHeight="400.0"
|
||||
prefWidth="500.0"
|
||||
styleClass="accent-header"
|
||||
stylesheets="@../css/designer.css"
|
||||
BorderPane.alignment="CENTER"
|
||||
xmlns="http://javafx.com/javafx/8.0.172-ea"
|
||||
xmlns:fx="http://javafx.com/fxml/1"
|
||||
fx:controller="net.sourceforge.pmd.util.fxdesigner.SourceEditorController">
|
||||
<items>
|
||||
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
|
||||
<AnchorPane>
|
||||
<children>
|
||||
<BorderPane prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||
<center>
|
||||
<HighlightLayerCodeArea fx:id="codeEditorArea" idEnum="net.sourceforge.pmd.util.fxdesigner.SourceEditorController$StyleLayerIds"
|
||||
prefHeight="346.0" prefWidth="445.0" stylesheets="@../css/editor-theme.css" BorderPane.alignment="CENTER">
|
||||
<ToolbarTitledPane
|
||||
collapsible="false"
|
||||
fx:id="editorTitledPane"
|
||||
styleClass="accent-header,full-size-title"
|
||||
title="Source Code"
|
||||
AnchorPane.bottomAnchor="0.0"
|
||||
AnchorPane.leftAnchor="0.0"
|
||||
AnchorPane.rightAnchor="0.0"
|
||||
AnchorPane.topAnchor="0.0">
|
||||
<toolbarItems>
|
||||
<MenuButton mnemonicParsing="false" styleClass="menu-button-no-arrow,icon-button"
|
||||
fx:id="languageSelectionMenuButton">
|
||||
<graphic>
|
||||
<FontIcon iconLiteral="fas-cog" />
|
||||
</graphic>
|
||||
<items>
|
||||
|
||||
</items>
|
||||
</MenuButton>
|
||||
</toolbarItems>
|
||||
<content>
|
||||
<HighlightLayerCodeArea fx:id="codeEditorArea"
|
||||
idEnum="net.sourceforge.pmd.util.fxdesigner.SourceEditorController$StyleLayerIds"
|
||||
stylesheets="@../css/editor-theme.css"
|
||||
BorderPane.alignment="CENTER">
|
||||
<BorderPane.margin>
|
||||
<Insets />
|
||||
</BorderPane.margin>
|
||||
</HighlightLayerCodeArea>
|
||||
</center>
|
||||
<top>
|
||||
<ToolBar prefHeight="40.0" prefWidth="200.0" styleClass="accent-header" BorderPane.alignment="CENTER">
|
||||
<items>
|
||||
<Label text="Source code" />
|
||||
</items>
|
||||
</ToolBar>
|
||||
</top>
|
||||
</BorderPane>
|
||||
<!--<TextArea />-->
|
||||
</content>
|
||||
</ToolbarTitledPane>
|
||||
</children>
|
||||
</AnchorPane>
|
||||
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
|
||||
<children>
|
||||
<BorderPane prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||
<center>
|
||||
<TreeView fx:id="astTreeView" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER"/>
|
||||
<TreeView fx:id="astTreeView" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER" />
|
||||
</center>
|
||||
<top>
|
||||
<ToolBar prefHeight="40.0" prefWidth="200.0" styleClass="accent-header" BorderPane.alignment="CENTER">
|
||||
|
||||
@@ -1,23 +1,51 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import java.lang.String?>
|
||||
<?import org.kordamp.ikonli.javafx.FontIcon?>
|
||||
<?import net.sourceforge.pmd.util.fxdesigner.util.codearea.SyntaxHighlightingCodeArea?>
|
||||
<?import net.sourceforge.pmd.util.fxdesigner.util.controls.PropertyTableView?>
|
||||
<?import net.sourceforge.pmd.util.fxdesigner.util.controls.ToolbarTitledPane?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.ListView?>
|
||||
<?import javafx.scene.control.MenuButton?>
|
||||
<?import javafx.scene.control.SplitPane?>
|
||||
<?import javafx.scene.control.TitledPane?>
|
||||
<?import javafx.scene.control.Tooltip?>
|
||||
<?import javafx.scene.layout.AnchorPane?>
|
||||
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="1200.0" stylesheets="@../css/designer.css" xmlns="http://javafx.com/javafx/9" xmlns:fx="http://javafx.com/fxml/1" fx:controller="net.sourceforge.pmd.util.fxdesigner.XPathPanelController">
|
||||
<?import javafx.scene.shape.SVGPath?>
|
||||
<AnchorPane minHeight="0.0"
|
||||
minWidth="0.0"
|
||||
prefHeight="180.0"
|
||||
prefWidth="1200.0"
|
||||
stylesheets="@../css/designer.css"
|
||||
xmlns="http://javafx.com/javafx/8.0.172-ea"
|
||||
xmlns:fx="http://javafx.com/fxml/1"
|
||||
fx:controller="net.sourceforge.pmd.util.fxdesigner.XPathPanelController">
|
||||
<children>
|
||||
<SplitPane dividerPositions="0.2, 0.8" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||
<SplitPane dividerPositions="0.2, 0.8"
|
||||
AnchorPane.bottomAnchor="0.0"
|
||||
AnchorPane.leftAnchor="0.0"
|
||||
AnchorPane.rightAnchor="0.0"
|
||||
AnchorPane.topAnchor="0.0">
|
||||
<items>
|
||||
<AnchorPane>
|
||||
<children>
|
||||
<TitledPane animated="false" collapsible="false" styleClass="accent-header" text="Properties" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||
<TitledPane animated="false"
|
||||
collapsible="false"
|
||||
styleClass="accent-header"
|
||||
text="Properties"
|
||||
AnchorPane.bottomAnchor="0.0"
|
||||
AnchorPane.leftAnchor="0.0"
|
||||
AnchorPane.rightAnchor="0.0"
|
||||
AnchorPane.topAnchor="0.0">
|
||||
<content>
|
||||
<AnchorPane>
|
||||
<PropertyTableView fx:id="propertyTableView" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
|
||||
<PropertyTableView fx:id="propertyTableView"
|
||||
AnchorPane.bottomAnchor="0.0"
|
||||
AnchorPane.leftAnchor="0.0"
|
||||
AnchorPane.rightAnchor="0.0"
|
||||
AnchorPane.topAnchor="0.0" />
|
||||
<padding>
|
||||
<Insets bottom="-0.5" left="-0.5" right="-0.5" top="-0.5" />
|
||||
</padding>
|
||||
@@ -28,24 +56,68 @@
|
||||
</AnchorPane>
|
||||
<AnchorPane>
|
||||
<children>
|
||||
<TitledPane collapsible="false" styleClass="accent-header" text="XPath Expression" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||
<ToolbarTitledPane fx:id="expressionTitledPane"
|
||||
styleClass="accent-header"
|
||||
collapsible="false"
|
||||
title="XPath Expression"
|
||||
AnchorPane.bottomAnchor="0.0"
|
||||
AnchorPane.leftAnchor="0.0"
|
||||
AnchorPane.rightAnchor="0.0"
|
||||
AnchorPane.topAnchor="0.0">
|
||||
<toolbarItems>
|
||||
<MenuButton mnemonicParsing="false"
|
||||
styleClass="menu-button-no-arrow,icon-button"
|
||||
fx:id="xpathVersionMenuButton">
|
||||
<graphic>
|
||||
<FontIcon iconLiteral="fas-cog" />
|
||||
</graphic>
|
||||
<tooltip>
|
||||
<Tooltip>
|
||||
<text>
|
||||
<String fx:value="Configure XPath version" />
|
||||
</text>
|
||||
</Tooltip>
|
||||
</tooltip>
|
||||
<items>
|
||||
<!-- Populated in the controller -->
|
||||
</items>
|
||||
</MenuButton>
|
||||
<Button fx:id="exportXpathToRuleButton" mnemonicParsing="false" styleClass="icon-button">
|
||||
<graphic>
|
||||
<!--Needs FA 5.1.0 -->
|
||||
<!--<FontIcon iconLiteral="fas-file-export" />-->
|
||||
<SVGPath styleClass="svg-icon"
|
||||
scaleX="0.024" scaleY="0.024"
|
||||
content="M384 121.9c0-6.3-2.5-12.4-7-16.9L279.1 7c-4.5-4.5-10.6-7-17-7H256v128h128v-6.1zM192 336v-32c0-8.84 7.16-16 16-16h176V160H248c-13.2 0-24-10.8-24-24V0H24C10.7 0 0 10.7 0 24v464c0 13.3 10.7 24 24 24h336c13.3 0 24-10.7 24-24V352H208c-8.84 0-16-7.16-16-16zm379.05-28.02l-95.7-96.43c-10.06-10.14-27.36-3.01-27.36 11.27V288H384v64h63.99v65.18c0 14.28 17.29 21.41 27.36 11.27l95.7-96.42c6.6-6.66 6.6-17.4 0-24.05z" />
|
||||
</graphic>
|
||||
<tooltip>
|
||||
<Tooltip>
|
||||
<text>
|
||||
<String fx:value="Export XPath to XML rule" />
|
||||
</text>
|
||||
</Tooltip>
|
||||
</tooltip>
|
||||
</Button>
|
||||
</toolbarItems>
|
||||
<content>
|
||||
<SyntaxHighlightingCodeArea stylesheets="@../css/editor-theme.css"
|
||||
fx:id="xpathExpressionArea">
|
||||
</SyntaxHighlightingCodeArea>
|
||||
<SyntaxHighlightingCodeArea stylesheets="@../css/editor-theme.css" fx:id="xpathExpressionArea" />
|
||||
</content>
|
||||
</TitledPane>
|
||||
</ToolbarTitledPane>
|
||||
</children>
|
||||
</AnchorPane>
|
||||
<AnchorPane>
|
||||
<children>
|
||||
<TitledPane fx:id="violationsTitledPane" animated="false"
|
||||
collapsible="false" styleClass="accent-header"
|
||||
text="Matched Nodes" AnchorPane.bottomAnchor="0.0"
|
||||
AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0"
|
||||
<TitledPane fx:id="violationsTitledPane"
|
||||
animated="false"
|
||||
collapsible="false"
|
||||
styleClass="accent-header"
|
||||
text="Matched Nodes"
|
||||
AnchorPane.bottomAnchor="0.0"
|
||||
AnchorPane.leftAnchor="0.0"
|
||||
AnchorPane.rightAnchor="0.0"
|
||||
AnchorPane.topAnchor="0.0">
|
||||
<content>
|
||||
<ListView fx:id="xpathResultListView" stylesheets="@../css/syntax-highlighting.css" />
|
||||
<ListView stylesheets="@../css/syntax-highlighting.css" fx:id="xpathResultListView" />
|
||||
</content>
|
||||
</TitledPane>
|
||||
</children>
|
||||
|
||||
@@ -43,6 +43,9 @@
|
||||
|
||||
@selection-focus-color: lighten(royalblue, 20%);
|
||||
|
||||
@normal-font-size: 10pt;
|
||||
@smaller-font-size: 9pt;
|
||||
|
||||
// mixin to fix the width of a component
|
||||
.fix-width(@width) {
|
||||
-fx-pref-width: @width;
|
||||
@@ -57,6 +60,11 @@
|
||||
-fx-max-height: @height;
|
||||
}
|
||||
|
||||
.force-square(@side) {
|
||||
.fix-width(@side);
|
||||
.fix-height(@side);
|
||||
}
|
||||
|
||||
// Mixin to iterate over the range [0, @i]
|
||||
// * The selector in which the mixin is called is appended with a class depth-x,
|
||||
// where x is the index of the color in the stack
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
#d62c49,
|
||||
#ff6a7a;
|
||||
|
||||
.ikonli-font-icon {
|
||||
-fx-icon-size: 14;
|
||||
}
|
||||
|
||||
.list-view, .tree-view, .table-view {
|
||||
-fx-selection-bar: @selection-focus-color;
|
||||
@@ -131,7 +134,7 @@
|
||||
|
||||
.titled-pane .title,
|
||||
.info-title-bar {
|
||||
-fx-font-size: 9pt;
|
||||
-fx-font-size: @smaller-font-size;
|
||||
-fx-pref-height: 24.0;
|
||||
-fx-border-radius: 0.0;
|
||||
-fx-background-radius: 0.0;
|
||||
@@ -140,42 +143,118 @@
|
||||
&.info-title-bar .label {
|
||||
-fx-padding: 0 0 0 6;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO convert every header to ToolbarTitledPane and get rid of info-title-bar
|
||||
.info-title-bar {
|
||||
.fix-height(30);
|
||||
}
|
||||
|
||||
.titled-pane.full-size-title {
|
||||
|
||||
& > .title {
|
||||
.fix-height(30);
|
||||
}
|
||||
|
||||
&.tool-bar-title > .title > .tool-bar > .container > .label {
|
||||
// TODO we can make that bigger when all titled panes rely on ToolbarTitledPane
|
||||
-fx-font-size: @smaller-font-size;
|
||||
}
|
||||
}
|
||||
|
||||
// Supports the ToolbarTitledPane
|
||||
.titled-pane.tool-bar-title > .title {
|
||||
|
||||
-fx-padding: 0 6 0 6;
|
||||
|
||||
& > .tool-bar {
|
||||
-fx-background-color: transparent;
|
||||
|
||||
& > .container {
|
||||
|
||||
-fx-background-insets: 0;
|
||||
-fx-border-insets: 0;
|
||||
-fx-border-image-insets: 0;
|
||||
|
||||
& > .label {
|
||||
-fx-background-color: transparent;
|
||||
-fx-font-size: @smaller-font-size;
|
||||
}
|
||||
|
||||
.separator {
|
||||
//-fx-background-color: transparent;
|
||||
|
||||
-fx-padding: 4 2 4 2;
|
||||
|
||||
.line {
|
||||
-fx-border-style: none solid none none;
|
||||
-fx-border-width: 0.5px;
|
||||
-fx-border-color: @fx-text-fill;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.menu-bar {
|
||||
-fx-background-color: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.menu-button.menu-button-no-arrow .arrow-button {
|
||||
|
||||
&, * {
|
||||
-fx-padding: 0;
|
||||
.fix-height(0);
|
||||
.fix-width(0);
|
||||
}
|
||||
}
|
||||
|
||||
// This is used for buttons that have just an icon and no text
|
||||
.icon-button {
|
||||
|
||||
-fx-background-color: transparent;
|
||||
-fx-border-width: 0;
|
||||
-fx-border-insets: 0;
|
||||
.force-square(24);
|
||||
|
||||
&, * {
|
||||
-fx-graphic-text-gap: 0;
|
||||
}
|
||||
|
||||
&.menu-button .ikonli-font-icon {
|
||||
// Fixes a bug where the cog icon is misplaced to the right
|
||||
// Probably needs to be synced with icon size
|
||||
-fx-translate-x: -4;
|
||||
}
|
||||
.ikonli-font-icon, .svg-icon {
|
||||
-fx-fill: @fx-text-fill;
|
||||
}
|
||||
|
||||
&:showing, &:hover {
|
||||
-fx-background-color: @selection-focus-color;
|
||||
}
|
||||
|
||||
.label {
|
||||
-fx-background-color: transparent;
|
||||
//-fx-padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#main-horizontal-split-pane > .split-pane-divider {
|
||||
-fx-background-color: @darker-accent-focus;
|
||||
}
|
||||
|
||||
// TODO use ToolbarTitledPane everywhere and simplify stylesheets
|
||||
|
||||
#main-toolbar,
|
||||
.tool-bar.accent-header,
|
||||
.split-pane.accent-header > .split-pane-divider {
|
||||
.fix-height(30);
|
||||
-fx-background-color: @app-darker-slate-color;
|
||||
}
|
||||
|
||||
|
||||
.tool-bar {
|
||||
.fix-height(30);
|
||||
-fx-border-color: transparent;
|
||||
-fx-border-width: .6;
|
||||
|
||||
.button, .choice-box {
|
||||
-fx-background-color: @app-base-color;
|
||||
-fx-border-color: @darker-accent-border;
|
||||
-fx-border-radius: 3;
|
||||
}
|
||||
|
||||
.button {
|
||||
-fx-padding: -3 5 -3 5;
|
||||
}
|
||||
}
|
||||
|
||||
// This is used for buttons that have just an icon and no text
|
||||
.button.icon-button {
|
||||
-fx-pref-width: 20;
|
||||
-fx-pref-height: 20;
|
||||
}
|
||||
|
||||
/* This is the special button to reduce the lower split pane. */
|
||||
.toggle-button.expand-toggle {
|
||||
-fx-background-color: -fx-mark-highlight-color, -fx-mark-color;
|
||||
@@ -192,7 +271,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.tab {
|
||||
-fx-background-insets: 0.0;
|
||||
-fx-background-radius: 0.0;
|
||||
|
||||
Reference in New Issue
Block a user