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