mirror of
https://github.com/frosch95/SmartCSV.fx.git
synced 2026-04-11 21:48:22 +02:00
add and remove rows
This commit is contained in:
@@ -27,7 +27,9 @@
|
||||
package ninja.javafx.smartcsv.fx;
|
||||
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.fxml.FXML;
|
||||
@@ -68,6 +70,7 @@ import java.util.ResourceBundle;
|
||||
import static java.lang.Math.max;
|
||||
import static javafx.application.Platform.exit;
|
||||
import static javafx.application.Platform.runLater;
|
||||
import static javafx.beans.binding.Bindings.*;
|
||||
import static javafx.scene.layout.AnchorPane.*;
|
||||
|
||||
/**
|
||||
@@ -141,12 +144,23 @@ public class SmartCSVController extends FXMLController {
|
||||
@FXML
|
||||
private MenuItem saveAsMenuItem;
|
||||
|
||||
@FXML
|
||||
private MenuItem deleteRowMenuItem;
|
||||
|
||||
@FXML
|
||||
private MenuItem addRowMenuItem;
|
||||
|
||||
@FXML
|
||||
private Button saveButton;
|
||||
|
||||
@FXML
|
||||
private Button saveAsButton;
|
||||
|
||||
@FXML
|
||||
private Button deleteRowButton;
|
||||
|
||||
@FXML
|
||||
private Button addRowButton;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// members
|
||||
@@ -158,8 +172,8 @@ public class SmartCSVController extends FXMLController {
|
||||
private TableView<CSVRow> tableView;
|
||||
private BooleanProperty fileChanged = new SimpleBooleanProperty(true);
|
||||
private ResourceBundle resourceBundle;
|
||||
private File currentCsvFile;
|
||||
private File currentConfigFile;
|
||||
private ObjectProperty<File> currentCsvFile = new SimpleObjectProperty<>();
|
||||
private ObjectProperty<File> currentConfigFile= new SimpleObjectProperty<>();
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -169,16 +183,30 @@ public class SmartCSVController extends FXMLController {
|
||||
@Override
|
||||
public void initialize(URL location, ResourceBundle resourceBundle) {
|
||||
this.resourceBundle = resourceBundle;
|
||||
saveFileService.setWriter(csvFileWriter);
|
||||
cellFactory = new ValidationCellFactory(resourceBundle);
|
||||
errorList.setCellFactory(param -> new ValidationErrorListCell(resourceBundle));
|
||||
errorList.getSelectionModel().selectedItemProperty().addListener(observable -> scrollToError());
|
||||
fileChanged.addListener(observable -> setStateName());
|
||||
setStateName();
|
||||
loadCsvPreferences();
|
||||
|
||||
setupTableCellFactory();
|
||||
setupErrorListCellFactory();
|
||||
setupErrorListSelectionListener();
|
||||
|
||||
bindMenuItemsToCsvFileExtistence(saveMenuItem, saveAsMenuItem, addRowMenuItem);
|
||||
bindButtonsToCsvFileExistence(saveButton, saveAsButton, addRowButton);
|
||||
bindCsvFileName();
|
||||
bindConfigFileName();
|
||||
|
||||
loadCsvPreferencesFromFile();
|
||||
}
|
||||
|
||||
private void setupErrorListSelectionListener() {
|
||||
errorList.getSelectionModel().selectedItemProperty().addListener(observable -> scrollToError());
|
||||
}
|
||||
|
||||
private void setupErrorListCellFactory() {
|
||||
errorList.setCellFactory(param -> new ValidationErrorListCell(resourceBundle));
|
||||
}
|
||||
|
||||
private void setupTableCellFactory() {
|
||||
cellFactory = new ValidationCellFactory(resourceBundle);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -198,39 +226,41 @@ public class SmartCSVController extends FXMLController {
|
||||
|
||||
@FXML
|
||||
public void openCsv(ActionEvent actionEvent) {
|
||||
currentCsvFile = loadFile(csvLoader,
|
||||
"CSV files (*.csv)",
|
||||
"*.csv",
|
||||
"Open CSV",
|
||||
currentCsvFile);
|
||||
enableSaveMenuItems();
|
||||
setCsvFileName();
|
||||
currentCsvFile.setValue(
|
||||
loadFile(
|
||||
csvLoader,
|
||||
"CSV files (*.csv)",
|
||||
"*.csv",
|
||||
"Open CSV",
|
||||
currentCsvFile.getValue()));
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void openConfig(ActionEvent actionEvent) {
|
||||
currentConfigFile = loadFile(validationLoader,
|
||||
"JSON files (*.json)",
|
||||
"*.json",
|
||||
"Open Validation Configuration",
|
||||
currentConfigFile);
|
||||
setConfigFileName();
|
||||
currentConfigFile.setValue(
|
||||
loadFile(
|
||||
validationLoader,
|
||||
"JSON files (*.json)",
|
||||
"*.json",
|
||||
"Open Validation Configuration",
|
||||
currentConfigFile.getValue()));
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void saveCsv(ActionEvent actionEvent) {
|
||||
csvFileWriter.setModel(model);
|
||||
useSaveFileService(csvFileWriter, currentCsvFile);
|
||||
useSaveFileService(csvFileWriter, currentCsvFile.getValue());
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void saveAsCsv(ActionEvent actionEvent) {
|
||||
csvFileWriter.setModel(model);
|
||||
currentCsvFile = saveFile(csvFileWriter,
|
||||
"CSV files (*.csv)",
|
||||
"*.csv",
|
||||
currentCsvFile);
|
||||
setCsvFileName();
|
||||
currentCsvFile.setValue(
|
||||
saveFile(
|
||||
csvFileWriter,
|
||||
"CSV files (*.csv)",
|
||||
"*.csv",
|
||||
currentCsvFile.getValue()));
|
||||
}
|
||||
|
||||
@FXML
|
||||
@@ -271,6 +301,25 @@ public class SmartCSVController extends FXMLController {
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void deleteRow(ActionEvent actionEvent) {
|
||||
model.getRows().removeAll(tableView.getSelectionModel().getSelectedItems());
|
||||
fileChanged.setValue(true);
|
||||
resetContent();
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void addRow(ActionEvent actionEvent) {
|
||||
CSVRow row = model.addRow();
|
||||
for (String column : model.getHeader()) {
|
||||
row.addValue(column, "");
|
||||
}
|
||||
fileChanged.setValue(true);
|
||||
resetContent();
|
||||
|
||||
selectNewRow();
|
||||
}
|
||||
|
||||
public boolean canExit() {
|
||||
boolean canExit = true;
|
||||
if (model != null && fileChanged.get()) {
|
||||
@@ -292,32 +341,46 @@ public class SmartCSVController extends FXMLController {
|
||||
// private methods
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void enableSaveMenuItems() {
|
||||
if (currentCsvFile != null) {
|
||||
saveMenuItem.setDisable(false);
|
||||
saveAsMenuItem.setDisable(false);
|
||||
saveButton.setDisable(false);
|
||||
saveAsButton.setDisable(false);
|
||||
private void selectNewRow() {
|
||||
int lastRow = tableView.getItems().size()-1;
|
||||
tableView.scrollTo(lastRow);
|
||||
tableView.requestFocus();
|
||||
tableView.getSelectionModel().select(lastRow);
|
||||
}
|
||||
|
||||
private void bindMenuItemsToCsvFileExtistence(MenuItem... items) {
|
||||
for (MenuItem item: items) {
|
||||
item.disableProperty().bind(isNull(currentCsvFile));
|
||||
}
|
||||
}
|
||||
|
||||
private void setCsvFileName() {
|
||||
if (currentCsvFile != null) {
|
||||
csvName.setText(currentCsvFile.getName());
|
||||
} else {
|
||||
csvName.setText("");
|
||||
private void bindButtonsToCsvFileExistence(Button... items) {
|
||||
for (Button item: items) {
|
||||
item.disableProperty().bind(isNull(currentCsvFile));
|
||||
}
|
||||
}
|
||||
|
||||
private void setConfigFileName() {
|
||||
if (currentConfigFile != null) {
|
||||
configurationName.setText(currentConfigFile.getName());
|
||||
} else {
|
||||
configurationName.setText("");
|
||||
private void bindMenuItemsToTableSelection(MenuItem... items) {
|
||||
for (MenuItem item: items) {
|
||||
item.disableProperty().bind(lessThan(tableView.getSelectionModel().selectedIndexProperty(), 0));
|
||||
}
|
||||
}
|
||||
|
||||
private void loadCsvPreferences() {
|
||||
private void bindButtonsToTableSelection(Button... items) {
|
||||
for (Button item: items) {
|
||||
item.disableProperty().bind(lessThan(tableView.getSelectionModel().selectedIndexProperty(), 0));
|
||||
}
|
||||
}
|
||||
|
||||
private void bindCsvFileName() {
|
||||
csvName.textProperty().bind(selectString(currentCsvFile, "name"));
|
||||
}
|
||||
|
||||
private void bindConfigFileName() {
|
||||
configurationName.textProperty().bind(selectString(currentConfigFile, "name"));
|
||||
}
|
||||
|
||||
private void loadCsvPreferencesFromFile() {
|
||||
if (PREFERENCES_FILE.exists()) {
|
||||
useLoadFileService(preferencesLoader, PREFERENCES_FILE);
|
||||
}
|
||||
@@ -432,9 +495,13 @@ public class SmartCSVController extends FXMLController {
|
||||
model.setValidator(validationLoader.getValidator());
|
||||
tableView = new TableView<>();
|
||||
|
||||
bindMenuItemsToTableSelection(deleteRowMenuItem);
|
||||
bindButtonsToTableSelection(deleteRowButton);
|
||||
|
||||
for (String column : model.getHeader()) {
|
||||
addColumn(column, tableView);
|
||||
}
|
||||
|
||||
tableView.getItems().setAll(model.getRows());
|
||||
tableView.setEditable(true);
|
||||
|
||||
@@ -484,16 +551,4 @@ public class SmartCSVController extends FXMLController {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setStateName() {
|
||||
if (model != null) {
|
||||
if (fileChanged.get()) {
|
||||
stateName.setText(resourceBundle.getString("state.changed"));
|
||||
} else {
|
||||
stateName.setText(resourceBundle.getString("state.unchanged"));
|
||||
}
|
||||
} else {
|
||||
stateName.setText("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,16 @@
|
||||
-glyph-size: 14px;
|
||||
}
|
||||
|
||||
.delete-icon {
|
||||
-glyph-name: "MINUS";
|
||||
-glyph-size: 14px;
|
||||
}
|
||||
|
||||
.add-icon {
|
||||
-glyph-name: "PLUS";
|
||||
-glyph-size: 14px;
|
||||
}
|
||||
|
||||
/* toolbar customization based on http://fxexperience.com/2012/02/customized-segmented-toolbar-buttons/ */
|
||||
|
||||
#background {
|
||||
@@ -96,6 +106,16 @@
|
||||
-fx-fill: white;
|
||||
}
|
||||
|
||||
.tool-bar .delete-icon {
|
||||
-glyph-size: 16px;
|
||||
-fx-fill: white;
|
||||
}
|
||||
|
||||
.tool-bar .add-icon {
|
||||
-glyph-size: 16px;
|
||||
-fx-fill: white;
|
||||
}
|
||||
|
||||
.segmented-button-bar .button {
|
||||
-fx-background-color:
|
||||
-darkest-black,
|
||||
|
||||
@@ -52,6 +52,20 @@
|
||||
</MenuItem>
|
||||
</items>
|
||||
</Menu>
|
||||
<Menu mnemonicParsing="false" text="%menu.edit">
|
||||
<items>
|
||||
<MenuItem fx:id="deleteRowMenuItem" disable="true" mnemonicParsing="false" onAction="#deleteRow" text="%menu.delete.row">
|
||||
<graphic>
|
||||
<FontAwesomeIconView styleClass="delete-icon" />
|
||||
</graphic>
|
||||
</MenuItem>
|
||||
<MenuItem fx:id="addRowMenuItem" disable="true" mnemonicParsing="false" onAction="#addRow" text="%menu.add.row">
|
||||
<graphic>
|
||||
<FontAwesomeIconView styleClass="add-icon" />
|
||||
</graphic>
|
||||
</MenuItem>
|
||||
</items>
|
||||
</Menu>
|
||||
<Menu mnemonicParsing="false" text="%menu.help">
|
||||
<items>
|
||||
<MenuItem mnemonicParsing="false" onAction="#about" text="%menu.about">
|
||||
@@ -98,6 +112,25 @@
|
||||
</graphic>
|
||||
</Button>
|
||||
</HBox>
|
||||
<Region styleClass="spacer" />
|
||||
<HBox styleClass="segmented-button-bar">
|
||||
<Button fx:id="deleteRowButton" disable="true" mnemonicParsing="false" onAction="#deleteRow" styleClass="first">
|
||||
<tooltip>
|
||||
<Tooltip text="%menu.delete.row" />
|
||||
</tooltip>
|
||||
<graphic>
|
||||
<FontAwesomeIconView styleClass="delete-icon" />
|
||||
</graphic>
|
||||
</Button>
|
||||
<Button fx:id="addRowButton" disable="true" mnemonicParsing="false" onAction="#addRow" styleClass="last">
|
||||
<tooltip>
|
||||
<Tooltip text="%menu.add.row" />
|
||||
</tooltip>
|
||||
<graphic>
|
||||
<FontAwesomeIconView styleClass="add-icon" />
|
||||
</graphic>
|
||||
</Button>
|
||||
</HBox>
|
||||
<Region styleClass="spacer" />
|
||||
<HBox styleClass="segmented-button-bar">
|
||||
<Button mnemonicParsing="false" onAction="#preferences" styleClass="first">
|
||||
@@ -170,11 +203,9 @@
|
||||
<FontAwesomeIconView styleClass="open-icon" GridPane.hgrow="NEVER" />
|
||||
<Label text="%stateline.csv" GridPane.columnIndex="1" GridPane.hgrow="NEVER" />
|
||||
<Label fx:id="csvName" GridPane.columnIndex="2" GridPane.hgrow="ALWAYS" />
|
||||
<Label text="%stateline.state" GridPane.columnIndex="3" GridPane.hgrow="NEVER" />
|
||||
<Label fx:id="stateName" GridPane.columnIndex="4" GridPane.hgrow="ALWAYS" />
|
||||
<FontAwesomeIconView styleClass="open-icon" GridPane.columnIndex="5" GridPane.hgrow="NEVER" />
|
||||
<Label text="%stateline.configuration" GridPane.columnIndex="6" GridPane.hgrow="NEVER" />
|
||||
<Label fx:id="configurationName" GridPane.columnIndex="7" GridPane.hgrow="ALWAYS" />
|
||||
<FontAwesomeIconView styleClass="open-icon" GridPane.columnIndex="3" GridPane.hgrow="NEVER" />
|
||||
<Label text="%stateline.configuration" GridPane.columnIndex="4" GridPane.hgrow="NEVER" />
|
||||
<Label fx:id="configurationName" GridPane.columnIndex="5" GridPane.hgrow="ALWAYS" />
|
||||
</children>
|
||||
<BorderPane.margin>
|
||||
<Insets bottom="4.0" left="8.0" right="8.0" top="4.0" />
|
||||
|
||||
@@ -8,6 +8,9 @@ menu.file = File
|
||||
menu.edit = Edit
|
||||
menu.help = Help
|
||||
menu.preferences = Preferences
|
||||
menu.delete.row = Delete row
|
||||
menu.add.row = Add row
|
||||
|
||||
title.validation.errors = Validation Errors:
|
||||
|
||||
stateline.csv = CSV:
|
||||
|
||||
@@ -16,6 +16,9 @@ menu.file = Datei
|
||||
menu.edit = Bearbeiten
|
||||
menu.help = Hilfe
|
||||
menu.preferences = Einstellungen
|
||||
menu.delete.row = Zeile l\u00f6schen
|
||||
menu.add.row = Zeile hinzuf\u00fcgen
|
||||
|
||||
title.validation.errors = Fehler in der Datei:
|
||||
|
||||
stateline.csv = CSV:
|
||||
|
||||
Reference in New Issue
Block a user