mirror of
https://github.com/frosch95/SmartCSV.fx.git
synced 2026-04-11 13:38:23 +02:00
show state and allow exit based on state
This commit is contained in:
@@ -27,9 +27,12 @@
|
||||
package ninja.javafx.smartcsv.fx;
|
||||
|
||||
import javafx.application.Application;
|
||||
import javafx.application.Platform;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.WindowEvent;
|
||||
import org.springframework.context.annotation.*;
|
||||
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
|
||||
|
||||
@@ -46,6 +49,8 @@ public class SmartCSV extends Application {
|
||||
String name = appContext.getEnvironment().getProperty("application.name");
|
||||
String version = appContext.getEnvironment().getProperty("application.version");
|
||||
|
||||
Platform.setImplicitExit(false);
|
||||
|
||||
try {
|
||||
showUI(primaryStage, name, version);
|
||||
} catch (Exception e) {
|
||||
@@ -80,6 +85,12 @@ public class SmartCSV extends Application {
|
||||
primaryStage.setTitle(String.format("%s %s", name, version));
|
||||
primaryStage.show();
|
||||
primaryStage.setMaximized(true);
|
||||
|
||||
primaryStage.setOnCloseRequest(event -> {
|
||||
if (!smartCVSController.canExit()) {
|
||||
event.consume();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,6 +27,12 @@
|
||||
package ninja.javafx.smartcsv.fx;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.InvalidationListener;
|
||||
import javafx.beans.Observable;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.concurrent.Service;
|
||||
import javafx.concurrent.Task;
|
||||
import javafx.event.ActionEvent;
|
||||
@@ -53,6 +59,7 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.util.Optional;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import static java.lang.Math.max;
|
||||
@@ -81,7 +88,13 @@ public class SmartCSVController extends FXMLController {
|
||||
private BorderPane applicationPane;
|
||||
|
||||
@FXML
|
||||
private Label stateline;
|
||||
private Label csvName;
|
||||
|
||||
@FXML
|
||||
private Label configurationName;
|
||||
|
||||
@FXML
|
||||
private Label stateName;
|
||||
|
||||
@FXML
|
||||
private ListView errorList;
|
||||
@@ -100,6 +113,8 @@ public class SmartCSVController extends FXMLController {
|
||||
private CSVModel model;
|
||||
private TableView<CSVRow> tableView;
|
||||
private File lastDirectory;
|
||||
private BooleanProperty fileChanged = new SimpleBooleanProperty(true);
|
||||
private ResourceBundle resourceBundle;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -108,12 +123,13 @@ public class SmartCSVController extends FXMLController {
|
||||
|
||||
@Override
|
||||
public void initialize(URL location, ResourceBundle resourceBundle) {
|
||||
this.resourceBundle = resourceBundle;
|
||||
saveCSVService.setWriter(csvFileWriter);
|
||||
cellFactory = new ValidationCellFactory(resourceBundle);
|
||||
stateline.setVisible(false);
|
||||
errorList.setCellFactory(param -> new ValidationErrorListCell(resourceBundle));
|
||||
errorList.getSelectionModel().selectedItemProperty().addListener(
|
||||
observable -> scrollToError()
|
||||
);
|
||||
errorList.getSelectionModel().selectedItemProperty().addListener(observable -> scrollToError());
|
||||
fileChanged.addListener(observable -> setStateName());
|
||||
setStateName();
|
||||
}
|
||||
|
||||
|
||||
@@ -134,12 +150,12 @@ public class SmartCSVController extends FXMLController {
|
||||
|
||||
@FXML
|
||||
public void openCsv(ActionEvent actionEvent) {
|
||||
loadFile(csvLoader, "CSV files (*.csv)", "*.csv", "Open CSV");
|
||||
loadFile(csvLoader, "CSV files (*.csv)", "*.csv", "Open CSV", csvName);
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void openConfig(ActionEvent actionEvent) {
|
||||
loadFile(validationLoader, "JSON files (*.json)", "*.json", "Open Validation Configuration");
|
||||
loadFile(validationLoader, "JSON files (*.json)", "*.json", "Open Validation Configuration", configurationName);
|
||||
}
|
||||
|
||||
@FXML
|
||||
@@ -154,8 +170,10 @@ public class SmartCSVController extends FXMLController {
|
||||
|
||||
@FXML
|
||||
public void close(ActionEvent actionEvent) {
|
||||
if (canExit()) {
|
||||
Platform.exit();
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void about(ActionEvent actionEvent) {
|
||||
@@ -176,13 +194,30 @@ public class SmartCSVController extends FXMLController {
|
||||
|
||||
|
||||
alert.showAndWait();
|
||||
|
||||
}
|
||||
|
||||
public boolean canExit() {
|
||||
boolean canExit = true;
|
||||
if (model != null && fileChanged.get()) {
|
||||
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
|
||||
alert.setTitle(resourceBundle.getString("dialog.exit.title"));
|
||||
alert.setHeaderText(resourceBundle.getString("dialog.exit.header.text"));
|
||||
alert.setContentText(resourceBundle.getString("dialog.exit.text"));
|
||||
|
||||
Optional<ButtonType> result = alert.showAndWait();
|
||||
if (result.get() != ButtonType.OK){
|
||||
canExit = false;
|
||||
}
|
||||
}
|
||||
|
||||
return canExit;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// private methods
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void loadFile(FileReader fileReader, String filterText, String filter, String title) {
|
||||
private void loadFile(FileReader fileReader, String filterText, String filter, String title, Label fileLabel) {
|
||||
final FileChooser fileChooser = new FileChooser();
|
||||
|
||||
//Set extension filter
|
||||
@@ -197,6 +232,7 @@ public class SmartCSVController extends FXMLController {
|
||||
//Show open file dialog
|
||||
final File file = fileChooser.showOpenDialog(applicationPane.getScene().getWindow());
|
||||
if (file != null) {
|
||||
loadCSVService.setFileLabel(fileLabel);
|
||||
loadCSVService.setFile(file);
|
||||
loadCSVService.setFileReader(fileReader);
|
||||
loadCSVService.restart();
|
||||
@@ -220,6 +256,7 @@ public class SmartCSVController extends FXMLController {
|
||||
final File file = fileChooser.showOpenDialog(applicationPane.getScene().getWindow());
|
||||
if (file != null) {
|
||||
model.setFilepath(file.getAbsolutePath());
|
||||
saveCSVService.setWriter(writer);
|
||||
saveCSVService.restart();
|
||||
}
|
||||
}
|
||||
@@ -265,7 +302,10 @@ public class SmartCSVController extends FXMLController {
|
||||
public void handle(TableColumn.CellEditEvent<CSVRow, CSVValue> event) {
|
||||
event.getTableView().getItems().get(event.getTablePosition().getRow()).
|
||||
getColumns().get(header).setValue(event.getNewValue());
|
||||
runLater(() -> model.revalidate());
|
||||
runLater(() -> {
|
||||
fileChanged.setValue(true);
|
||||
model.revalidate();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -284,6 +324,19 @@ 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("");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// inner class
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -295,6 +348,7 @@ public class SmartCSVController extends FXMLController {
|
||||
|
||||
private File file = null;
|
||||
private FileReader fileReader;
|
||||
private Label fileLabel;
|
||||
|
||||
public void setFile(File value) {
|
||||
file = value;
|
||||
@@ -302,6 +356,9 @@ public class SmartCSVController extends FXMLController {
|
||||
public void setFileReader(FileReader fileReader) {
|
||||
this.fileReader = fileReader;
|
||||
}
|
||||
public void setFileLabel(Label fileLabel) {
|
||||
this.fileLabel = fileLabel;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Task createTask() {
|
||||
@@ -312,7 +369,11 @@ public class SmartCSVController extends FXMLController {
|
||||
try {
|
||||
lastDirectory = file.getParentFile();
|
||||
fileReader.read(file);
|
||||
runLater(SmartCSVController.this::resetContent);
|
||||
runLater(() -> {
|
||||
fileLabel.setText(file.getName());
|
||||
resetContent();
|
||||
fileChanged.setValue(false);
|
||||
});
|
||||
} catch (Throwable ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
@@ -321,6 +382,7 @@ public class SmartCSVController extends FXMLController {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -328,14 +390,23 @@ public class SmartCSVController extends FXMLController {
|
||||
*/
|
||||
private class SaveCSVService extends Service {
|
||||
|
||||
private CSVFileWriter writer;
|
||||
|
||||
public void setWriter(CSVFileWriter writer) {
|
||||
this.writer = writer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Task createTask() {
|
||||
return new Task() {
|
||||
@Override
|
||||
protected Void call() throws Exception {
|
||||
try {
|
||||
csvFileWriter.saveFile(model);
|
||||
runLater(SmartCSVController.this::resetContent);
|
||||
writer.saveFile(model);
|
||||
runLater(() -> {
|
||||
resetContent();
|
||||
fileChanged.setValue(false);
|
||||
});
|
||||
} catch (Throwable ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
@@ -343,5 +414,6 @@ public class SmartCSVController extends FXMLController {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import java.net.*?>
|
||||
<?import javafx.geometry.*?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import java.lang.*?>
|
||||
@@ -55,19 +56,35 @@
|
||||
</items>
|
||||
</SplitPane>
|
||||
</center>
|
||||
<bottom>
|
||||
<HBox spacing="8.0" BorderPane.alignment="CENTER">
|
||||
<children>
|
||||
<Label fx:id="stateline" text="Status" HBox.hgrow="ALWAYS" />
|
||||
</children>
|
||||
<BorderPane.margin>
|
||||
<Insets bottom="4.0" left="4.0" right="4.0" top="4.0" />
|
||||
</BorderPane.margin>
|
||||
</HBox>
|
||||
</bottom>
|
||||
<left>
|
||||
</left>
|
||||
<stylesheets>
|
||||
<URL value="@/ninja/javafx/smartcsv/fx/smartcsv.css" />
|
||||
</stylesheets>
|
||||
<bottom>
|
||||
<GridPane hgap="8.0" BorderPane.alignment="CENTER">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="NEVER" minWidth="10.0" />
|
||||
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
|
||||
<ColumnConstraints hgrow="NEVER" minWidth="10.0" />
|
||||
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
|
||||
<ColumnConstraints hgrow="NEVER" minWidth="10.0" />
|
||||
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<Label text="%stateline.csv" GridPane.hgrow="NEVER" />
|
||||
<Label fx:id="csvName" GridPane.columnIndex="1" GridPane.hgrow="ALWAYS" />
|
||||
<Label text="%stateline.state" GridPane.columnIndex="2" GridPane.hgrow="NEVER" />
|
||||
<Label fx:id="stateName" GridPane.columnIndex="3" GridPane.hgrow="ALWAYS" />
|
||||
<Label text="%stateline.configuration" GridPane.columnIndex="4" GridPane.hgrow="NEVER" />
|
||||
<Label fx:id="configurationName" GridPane.columnIndex="5" GridPane.hgrow="ALWAYS" />
|
||||
</children>
|
||||
<BorderPane.margin>
|
||||
<Insets top="4.0" left="8.0" bottom="4.0" right="8.0" />
|
||||
</BorderPane.margin>
|
||||
</GridPane>
|
||||
</bottom>
|
||||
</BorderPane>
|
||||
|
||||
@@ -9,6 +9,17 @@ menu.edit = Edit
|
||||
menu.help = Help
|
||||
title.validation.errors = Validation Errors:
|
||||
|
||||
stateline.csv = CSV:
|
||||
stateline.configuration = Validation Configuration:
|
||||
stateline.state = State:
|
||||
|
||||
state.changed = changed
|
||||
state.unchanged = unchanged
|
||||
|
||||
dialog.exit.title = Close Application
|
||||
dialog.exit.header.text = Do you want to close application?
|
||||
dialog.exit.text = There are changes made to the csv file. If you close now, the changes are lost!
|
||||
|
||||
# validaton messages
|
||||
validation.message.not.empty = should not be empty
|
||||
validation.message.integer = should be an integer
|
||||
|
||||
@@ -17,6 +17,17 @@ menu.edit = Bearbeiten
|
||||
menu.help = Hilfe
|
||||
title.validation.errors = Fehler in der Datei:
|
||||
|
||||
stateline.csv = CSV:
|
||||
stateline.configuration = Pr\u00fcfkonfiguration:
|
||||
stateline.state = Status:
|
||||
|
||||
state.changed = Ge\u00e4ndert
|
||||
state.unchanged = Unver\u00e4ndert
|
||||
|
||||
dialog.exit.title = Anwendung beenden
|
||||
dialog.exit.header.text = M\u00f6chten Sie wirklich die Anwendung beenden?
|
||||
dialog.exit.text = Es gibt noch ungespeicherte \u00c4nderungen, die verloren gehen, wenn Sie die Anwendung jetzt beenden.
|
||||
|
||||
# validaton messages
|
||||
validation.message.not.empty = Darf nicht leer sein.
|
||||
validation.message.integer = Muss eine Zahl sein.
|
||||
|
||||
Reference in New Issue
Block a user