Improve styling

This commit is contained in:
Clément Fournier
2018-06-09 00:36:36 +02:00
parent e533c54ffb
commit 1d4eb00ba3
13 changed files with 320 additions and 261 deletions

View File

@ -66,6 +66,20 @@
<artifactId>commons-beanutils-core</artifactId>
<version>1.8.3</version>
</dependency>
<!-- Icon packs -->
<dependency>
<groupId>org.kordamp.ikonli</groupId>
<artifactId>ikonli-javafx</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.kordamp.ikonli</groupId>
<artifactId>ikonli-fontawesome-pack</artifactId>
<version>2.3.0</version>
</dependency>
<!-- PMD dependencies -->
<dependency>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd-apex</artifactId>

View File

@ -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<Runnable> onCancel = Var.newSimpleVar(() -> {});
private final Var<Consumer<List<File>>> onApply = Var.newSimpleVar(l -> {});
@FXML
private Button removeFileButton;
@FXML
private Button selectFilesButton;
@FXML
private ListView<File> 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<File> 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<File> lst) {
fileListView.setItems(FXCollections.observableArrayList(lst));
}
public void setOnCancel(Runnable run) {
onCancel.setValue(run);
}
public void setOnApply(Consumer<List<File>> 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);
}
}

View File

@ -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));

View File

@ -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);
}

View File

@ -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;

View File

@ -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<File> 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<File> 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<File> currentItems, Consumer<List<File>> 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();
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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 <T> Callback<ListView<T>, ListCell<T>> simpleListCellFactory(Function<T, String> converter, Function<T, String> toolTipMaker) {
return collection -> new ListCell<T>() {
@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 <T> StringConverter<T> stringConverter(Function<T, String> toString, Function<String, T> fromString) {
return new StringConverter<T>() {
@Override

View File

@ -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;

View File

@ -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%);

View File

@ -3,71 +3,96 @@
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.control.TitledPane?>
<?import javafx.scene.control.ToolBar?>
<?import javafx.scene.control.Tooltip?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.VBox?>
<VBox minWidth="-Infinity" snapToPixel="false" xmlns="http://javafx.com/javafx/8.0.121"
xmlns:fx="http://javafx.com/fxml/1" fx:controller="net.sourceforge.pmd.util.fxdesigner.AuxClassPathController">
<children>
<TitledPane collapsible="false" prefHeight="25.0" prefWidth="647.0" text="PMD Configuration"/>
<AnchorPane VBox.vgrow="ALWAYS">
<children>
<SplitPane dividerPositions="0.8407350689127105" minWidth="-Infinity" AnchorPane.bottomAnchor="-19.0"
AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<VBox>
<children>
<ListView fx:id="fileListView" VBox.vgrow="ALWAYS"/>
</children>
</VBox>
<VBox alignment="CENTER" SplitPane.resizableWithParent="false">
<children>
<Button fx:id="moveItemUpButton" minWidth="-Infinity" mnemonicParsing="false"
text="Move Up">
<VBox.margin>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
</VBox.margin>
</Button>
<Button fx:id="moveItemDownButton" minWidth="-Infinity" mnemonicParsing="false"
text="Move Down">
<VBox.margin>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
</VBox.margin>
</Button>
<Button fx:id="selectFilesButton" minWidth="-Infinity" mnemonicParsing="false"
text="Select File" textAlignment="CENTER">
<VBox.margin>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
</VBox.margin>
</Button>
<Button fx:id="removeFileButton" minWidth="-Infinity" mnemonicParsing="false"
text="Remove File" textAlignment="CENTER">
<VBox.margin>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
</VBox.margin>
</Button>
<Button fx:id="setClassPathButton" minWidth="-Infinity" mnemonicParsing="false"
text="Apply" textAlignment="CENTER">
<VBox.margin>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
</VBox.margin>
</Button>
<Button fx:id="cancelButton" minWidth="-Infinity" mnemonicParsing="false" text="Cancel"
textAlignment="CENTER">
<VBox.margin>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
</VBox.margin>
</Button>
<?import javafx.scene.layout.HBox?>
<?import org.kordamp.ikonli.javafx.FontIcon?>
</children>
</VBox>
</items>
</SplitPane>
<AnchorPane prefHeight="300.0"
prefWidth="400.0"
xmlns="http://javafx.com/javafx/10.0.1"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="net.sourceforge.pmd.util.fxdesigner.popups.AuxclasspathSetupController">
<children>
<ToolBar layoutX="320.3999938964844"
layoutY="10.399999618530273"
maxWidth="40.0"
minWidth="40.0"
orientation="VERTICAL"
prefWidth="40.0"
AnchorPane.bottomAnchor="30.0"
AnchorPane.rightAnchor="0.0"
AnchorPane.topAnchor="0.0">
<items>
<Button fx:id="selectFilesButton"
defaultButton="true"
minWidth="-Infinity"
mnemonicParsing="false"
styleClass="icon-button"
textAlignment="CENTER">
<graphic>
<FontIcon iconLiteral="fa-plus"/>
</graphic>
<tooltip>
<Tooltip text="Add new jars"/>
</tooltip>
</Button>
<Button fx:id="removeFileButton"
minWidth="-Infinity"
mnemonicParsing="false"
styleClass="icon-button"
textAlignment="CENTER">
<graphic>
<FontIcon iconLiteral="fa-minus"/>
</graphic>
<tooltip>
<Tooltip text="Remove item"/>
</tooltip>
</Button>
<Button fx:id="moveItemUpButton" minWidth="-Infinity" mnemonicParsing="false" styleClass="icon-button">
<graphic>
<FontIcon iconLiteral="fa-arrow-up"/>
</graphic>
</Button>
<Button fx:id="moveItemDownButton" minWidth="-Infinity" mnemonicParsing="false" styleClass="icon-button">
<graphic>
<FontIcon iconLiteral="fa-arrow-down"/>
</graphic>
<tooltip>
<Tooltip text="Move item down"/>
</tooltip>
</Button>
</items>
<tooltip>
<Tooltip text="Move item up"/>
</tooltip>
</ToolBar>
<ListView fx:id="fileListView"
layoutX="10.399999618530273"
layoutY="10.399999618530273"
AnchorPane.bottomAnchor="30.0"
AnchorPane.leftAnchor="0.0"
AnchorPane.rightAnchor="40.0"
AnchorPane.topAnchor="0.0"/>
<HBox layoutX="14.399999618530273"
layoutY="248.60000610351562"
spacing="10.0"
AnchorPane.bottomAnchor="0.0"
AnchorPane.rightAnchor="0.0">
<children>
<Button fx:id="cancelButton"
cancelButton="true"
minWidth="-Infinity"
mnemonicParsing="false"
text="Cancel"
textAlignment="CENTER"/>
<Button fx:id="setClassPathButton" minWidth="-Infinity" mnemonicParsing="false" text="OK" textAlignment="CENTER"/>
</children>
<VBox.margin>
<Insets/>
</VBox.margin>
</AnchorPane>
</HBox>
</children>
</VBox>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/>
</padding>
</AnchorPane>

View File

@ -44,10 +44,11 @@
<MenuItem fx:id="licenseMenuItem" mnemonicParsing="false" text="License" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="PMD Configuration">
<Menu mnemonicParsing="false" text="Configuration">
<items>
<MenuItem fx:id="setupAuxclasspathMenuItem" mnemonicParsing="false"
text="Set up the auxclasspath"/>
text="Set up the auxclasspath" >
</MenuItem>
</items>
</Menu>