Merge remote-tracking branch 'remotes/origin/create_validation_config_based_on_csv'

This commit is contained in:
2016-07-23 00:04:01 +02:00
25 changed files with 453 additions and 251 deletions

View File

@@ -9,6 +9,11 @@ even in a "normal" CSV editor. So I decided to write this simple JavaFX applicat
##Video ##Video
[![short video about the application](http://img.youtube.com/vi/SH0UAtPG6Eg/0.jpg)](https://youtu.be/SH0UAtPG6Eg) [![short video about the application](http://img.youtube.com/vi/SH0UAtPG6Eg/0.jpg)](https://youtu.be/SH0UAtPG6Eg)
##Links
[GitHub Page](http://frosch95.github.io/SmartCSV.fx/)
[Wiki & Documentation](https://github.com/frosch95/SmartCSV.fx/wiki)
binary distribution of the [latest release (0.4)](https://drive.google.com/open?id=0BwY9gBUvn5qmREdCc0FvNDNEQTA)
##License ##License
###The MIT License (MIT) ###The MIT License (MIT)

View File

@@ -1,5 +1,5 @@
group 'ninja.javafx' group 'ninja.javafx'
version '0.3-SNAPSHOT' version '0.4-SNAPSHOT'
apply plugin: 'java' apply plugin: 'java'
apply plugin: 'groovy' apply plugin: 'groovy'
@@ -22,7 +22,12 @@ dependencies {
compile group: 'org.springframework', name:'spring-context', version: '4.3.1.RELEASE' compile group: 'org.springframework', name:'spring-context', version: '4.3.1.RELEASE'
compile group: 'net.sf.supercsv', name: 'super-csv', version: '2.4.0' compile group: 'net.sf.supercsv', name: 'super-csv', version: '2.4.0'
compile group: 'commons-validator', name: 'commons-validator', version: '1.5.1' compile group: 'commons-validator', name: 'commons-validator', version: '1.5.1'
compile group: 'de.jensd', name: 'fontawesomefx', version: '8.9' compile group: 'de.jensd', name: 'fontawesomefx-commons', version: '8.12'
compile group: 'de.jensd', name: 'fontawesomefx-fontawesome', version: '4.6.3'
compile group: 'de.jensd', name: 'fontawesomefx-materialdesignfont', version: '1.6.50'
compile group: 'de.jensd', name: 'fontawesomefx-materialicons', version: '2.2.0'
compile group: 'org.controlsfx', name: 'controlsfx', version: '8.40.11' compile group: 'org.controlsfx', name: 'controlsfx', version: '8.40.11'
compile group: 'com.google.code.gson', name: 'gson', version: '2.7' compile group: 'com.google.code.gson', name: 'gson', version: '2.7'
compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.6.2'
compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.6.2'
} }

View File

@@ -32,6 +32,7 @@ import java.io.IOException;
/** /**
* read some file * read some file
*/ */
public interface FileReader { public interface FileReader<E> {
E getContent();
void read(File filename) throws IOException; void read(File filename) throws IOException;
} }

View File

@@ -32,6 +32,7 @@ import java.io.IOException;
/** /**
* write some file * write some file
*/ */
public interface FileWriter { public interface FileWriter<E> {
void setContent(E content);
void write(File filename) throws IOException; void write(File filename) throws IOException;
} }

View File

@@ -40,8 +40,7 @@ import java.util.Map;
/** /**
* reads the csv file and stores the values in csv model * reads the csv file and stores the values in csv model
*/ */
@Service public class CSVFileReader extends CSVConfigurable implements FileReader<CSVModel> {
public class CSVFileReader extends CSVConfigurable implements FileReader {
private CSVModel model; private CSVModel model;
@@ -72,7 +71,7 @@ public class CSVFileReader extends CSVConfigurable implements FileReader {
} }
} }
public CSVModel getData() { public CSVModel getContent() {
return model; return model;
} }

View File

@@ -42,12 +42,11 @@ import static java.util.stream.Collectors.toMap;
/** /**
* filewriter for the csv * filewriter for the csv
*/ */
@Service public class CSVFileWriter extends CSVConfigurable implements ninja.javafx.smartcsv.FileWriter<CSVModel> {
public class CSVFileWriter extends CSVConfigurable implements ninja.javafx.smartcsv.FileWriter {
private CSVModel model; private CSVModel model;
public void setModel(CSVModel model) { public void setContent(CSVModel model) {
this.model = model; this.model = model;
} }

View File

@@ -0,0 +1,78 @@
package ninja.javafx.smartcsv.files;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import ninja.javafx.smartcsv.FileReader;
import ninja.javafx.smartcsv.FileWriter;
import java.io.File;
import java.io.IOException;
/**
* This class stores files and there state
* @author abi
*/
public class FileStorage<E> {
private FileReader<E> reader;
private FileWriter<E> writer;
public FileStorage(FileReader<E> reader, FileWriter<E> writer) {
this.reader = reader;
this.writer = writer;
}
private BooleanProperty fileChanged = new SimpleBooleanProperty(true);
private ObjectProperty<File> file = new SimpleObjectProperty<>();
private ObjectProperty<E> content = new SimpleObjectProperty<E>();
public boolean isFileChanged() {
return fileChanged.get();
}
public BooleanProperty fileChangedProperty() {
return fileChanged;
}
public void setFileChanged(boolean fileChanged) {
this.fileChanged.set(fileChanged);
}
public File getFile() {
return file.get();
}
public ObjectProperty<File> fileProperty() {
return file;
}
public void setFile(File file) {
this.file.set(file);
}
public E getContent() {
return content.get();
}
public ObjectProperty<E> contentProperty() {
return content;
}
public void setContent(E content) {
this.content.set(content);
}
public void load() throws IOException {
reader.read(file.get());
setContent(reader.getContent());
setFileChanged(false);
}
public void save() throws IOException {
writer.setContent(content.get());
writer.write(file.get());
setFileChanged(false);
}
}

View File

@@ -26,10 +26,6 @@
package ninja.javafx.smartcsv.fx; 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.collections.ListChangeListener; import javafx.collections.ListChangeListener;
import javafx.collections.WeakListChangeListener; import javafx.collections.WeakListChangeListener;
import javafx.concurrent.WorkerStateEvent; import javafx.concurrent.WorkerStateEvent;
@@ -41,10 +37,9 @@ import javafx.scene.control.*;
import javafx.scene.layout.AnchorPane; import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane; import javafx.scene.layout.BorderPane;
import javafx.stage.FileChooser; import javafx.stage.FileChooser;
import ninja.javafx.smartcsv.FileReader;
import ninja.javafx.smartcsv.FileWriter;
import ninja.javafx.smartcsv.csv.CSVFileReader; import ninja.javafx.smartcsv.csv.CSVFileReader;
import ninja.javafx.smartcsv.csv.CSVFileWriter; import ninja.javafx.smartcsv.csv.CSVFileWriter;
import ninja.javafx.smartcsv.files.FileStorage;
import ninja.javafx.smartcsv.fx.about.AboutController; import ninja.javafx.smartcsv.fx.about.AboutController;
import ninja.javafx.smartcsv.fx.list.ErrorSideBar; import ninja.javafx.smartcsv.fx.list.ErrorSideBar;
import ninja.javafx.smartcsv.fx.preferences.PreferencesController; import ninja.javafx.smartcsv.fx.preferences.PreferencesController;
@@ -58,6 +53,7 @@ import ninja.javafx.smartcsv.fx.util.SaveFileService;
import ninja.javafx.smartcsv.fx.validation.ValidationEditorController; import ninja.javafx.smartcsv.fx.validation.ValidationEditorController;
import ninja.javafx.smartcsv.preferences.PreferencesFileReader; import ninja.javafx.smartcsv.preferences.PreferencesFileReader;
import ninja.javafx.smartcsv.preferences.PreferencesFileWriter; import ninja.javafx.smartcsv.preferences.PreferencesFileWriter;
import ninja.javafx.smartcsv.validation.ValidationConfiguration;
import ninja.javafx.smartcsv.validation.ValidationError; import ninja.javafx.smartcsv.validation.ValidationError;
import ninja.javafx.smartcsv.validation.ValidationFileReader; import ninja.javafx.smartcsv.validation.ValidationFileReader;
import ninja.javafx.smartcsv.validation.ValidationFileWriter; import ninja.javafx.smartcsv.validation.ValidationFileWriter;
@@ -103,24 +99,6 @@ public class SmartCSVController extends FXMLController {
// injections // injections
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@Autowired
private PreferencesFileReader preferencesLoader;
@Autowired
private PreferencesFileWriter preferencesWriter;
@Autowired
private CSVFileReader csvLoader;
@Autowired
private ValidationFileReader validationLoader;
@Autowired
private CSVFileWriter csvFileWriter;
@Autowired
private ValidationFileWriter validationFileWriter;
@Autowired @Autowired
private AboutController aboutController; private AboutController aboutController;
@@ -134,7 +112,7 @@ public class SmartCSVController extends FXMLController {
private LoadFileService loadFileService; private LoadFileService loadFileService;
@Autowired @Autowired
private SaveFileService saveFileService;; private SaveFileService saveFileService;
@FXML @FXML
private BorderPane applicationPane; private BorderPane applicationPane;
@@ -157,6 +135,9 @@ public class SmartCSVController extends FXMLController {
@FXML @FXML
private MenuItem saveAsMenuItem; private MenuItem saveAsMenuItem;
@FXML
private MenuItem createConfigMenuItem;
@FXML @FXML
private MenuItem loadConfigMenuItem; private MenuItem loadConfigMenuItem;
@@ -178,6 +159,9 @@ public class SmartCSVController extends FXMLController {
@FXML @FXML
private Button saveAsButton; private Button saveAsButton;
@FXML
private Button createConfigButton;
@FXML @FXML
private Button loadConfigButton; private Button loadConfigButton;
@@ -199,13 +183,13 @@ public class SmartCSVController extends FXMLController {
private ValidationCellFactory cellFactory; private ValidationCellFactory cellFactory;
private CSVModel model;
private TableView<CSVRow> tableView; private TableView<CSVRow> tableView;
private ErrorSideBar errorSideBar; private ErrorSideBar errorSideBar;
private BooleanProperty fileChanged = new SimpleBooleanProperty(true);
private ResourceBundle resourceBundle; private ResourceBundle resourceBundle;
private ObjectProperty<File> currentCsvFile = new SimpleObjectProperty<>();
private ObjectProperty<File> currentConfigFile= new SimpleObjectProperty<>(); private FileStorage<CSVModel> currentCsvFile = new FileStorage<>(new CSVFileReader(), new CSVFileWriter());
private FileStorage<ValidationConfiguration> currentConfigFile = new FileStorage<>(new ValidationFileReader(), new ValidationFileWriter());
private FileStorage<CsvPreference> csvPreferenceFile = new FileStorage<>(new PreferencesFileReader(), new PreferencesFileWriter());
private ListChangeListener<ValidationError> errorListListener = c -> tableView.refresh(); private ListChangeListener<ValidationError> errorListListener = c -> tableView.refresh();
private WeakListChangeListener<ValidationError> weakErrorListListener = new WeakListChangeListener<>(errorListListener); private WeakListChangeListener<ValidationError> weakErrorListListener = new WeakListChangeListener<>(errorListListener);
@@ -221,15 +205,17 @@ public class SmartCSVController extends FXMLController {
setupTableCellFactory(); setupTableCellFactory();
setupErrorSideBar(resourceBundle); setupErrorSideBar(resourceBundle);
bindMenuItemsToFileExistence(currentCsvFile, saveMenuItem, saveAsMenuItem, addRowMenuItem, loadConfigMenuItem); bindMenuItemsToContentExistence(currentCsvFile, saveMenuItem, saveAsMenuItem, addRowMenuItem, createConfigMenuItem, loadConfigMenuItem);
bindButtonsToFileExistence(currentCsvFile, saveButton, saveAsButton, addRowButton, loadConfigButton); bindButtonsToContentExistence(currentCsvFile, saveButton, saveAsButton, addRowButton, createConfigButton, loadConfigButton);
bindMenuItemsToFileExistence(currentConfigFile, saveConfigMenuItem, saveAsConfigMenuItem); bindMenuItemsToContentExistence(currentConfigFile, saveConfigMenuItem, saveAsConfigMenuItem);
bindButtonsToFileExistence(currentConfigFile, saveAsConfigButton, saveConfigButton); bindButtonsToContentExistence(currentConfigFile, saveAsConfigButton, saveConfigButton);
bindCsvFileName(); bindCsvFileName();
bindConfigFileName(); bindConfigFileName();
csvPreferenceFile.setFile(PREFERENCES_FILE);
loadCsvPreferencesFromFile(); loadCsvPreferencesFromFile();
} }
@@ -263,58 +249,43 @@ public class SmartCSVController extends FXMLController {
@FXML @FXML
public void openCsv(ActionEvent actionEvent) { public void openCsv(ActionEvent actionEvent) {
currentCsvFile.setValue( loadFile(CSV_FILTER_TEXT, CSV_FILTER_EXTENSION, "Open CSV", currentCsvFile);
loadFile(
csvLoader,
CSV_FILTER_TEXT,
CSV_FILTER_EXTENSION,
"Open CSV",
currentCsvFile.getValue()));
} }
@FXML @FXML
public void openConfig(ActionEvent actionEvent) { public void openConfig(ActionEvent actionEvent) {
currentConfigFile.setValue( loadFile(JSON_FILTER_TEXT, JSON_FILTER_EXTENSION, "Open Validation Configuration", currentConfigFile);
loadFile( }
validationLoader,
JSON_FILTER_TEXT, @FXML
JSON_FILTER_EXTENSION, public void createConfig(ActionEvent actionEvent) {
"Open Validation Configuration", currentConfigFile.setContent(currentCsvFile.getContent().createValidationConfiguration());
currentConfigFile.getValue())); currentConfigFile.setFile(null);
currentConfigFile.setFileChanged(true);
} }
@FXML @FXML
public void saveCsv(ActionEvent actionEvent) { public void saveCsv(ActionEvent actionEvent) {
csvFileWriter.setModel(model); useSaveFileService(currentCsvFile);
useSaveFileService(csvFileWriter, currentCsvFile.getValue());
} }
@FXML @FXML
public void saveAsCsv(ActionEvent actionEvent) { public void saveAsCsv(ActionEvent actionEvent) {
csvFileWriter.setModel(model); saveFile(CSV_FILTER_TEXT, CSV_FILTER_EXTENSION, currentCsvFile);
currentCsvFile.setValue(
saveFile(
csvFileWriter,
CSV_FILTER_TEXT,
CSV_FILTER_EXTENSION,
currentCsvFile.getValue()));
} }
@FXML @FXML
public void saveConfig(ActionEvent actionEvent) { public void saveConfig(ActionEvent actionEvent) {
validationFileWriter.setValidationConfiguration(validationLoader.getValidationConfiguration()); if (currentConfigFile.getFile() == null) {
useSaveFileService(validationFileWriter, currentConfigFile.getValue()); saveAsConfig(actionEvent);
} else {
useSaveFileService(currentConfigFile);
}
} }
@FXML @FXML
public void saveAsConfig(ActionEvent actionEvent) { public void saveAsConfig(ActionEvent actionEvent) {
validationFileWriter.setValidationConfiguration(validationLoader.getValidationConfiguration()); saveFile(JSON_FILTER_TEXT, JSON_FILTER_EXTENSION, currentConfigFile);
currentConfigFile.setValue(
saveFile(
validationFileWriter,
JSON_FILTER_TEXT,
JSON_FILTER_EXTENSION,
currentConfigFile.getValue()));
} }
@FXML @FXML
@@ -351,24 +322,24 @@ public class SmartCSVController extends FXMLController {
setCsvPreference(csvPreference); setCsvPreference(csvPreference);
saveCsvPreferences(csvPreference); saveCsvPreferences(csvPreference);
} else { } else {
preferencesController.setCsvPreference(preferencesLoader.getCSVpreference()); preferencesController.setCsvPreference(csvPreferenceFile.getContent());
} }
} }
@FXML @FXML
public void deleteRow(ActionEvent actionEvent) { public void deleteRow(ActionEvent actionEvent) {
model.getRows().removeAll(tableView.getSelectionModel().getSelectedItems()); currentCsvFile.getContent().getRows().removeAll(tableView.getSelectionModel().getSelectedItems());
fileChanged.setValue(true); currentCsvFile.setFileChanged(true);
resetContent(); resetContent();
} }
@FXML @FXML
public void addRow(ActionEvent actionEvent) { public void addRow(ActionEvent actionEvent) {
CSVRow row = model.addRow(); CSVRow row = currentCsvFile.getContent().addRow();
for (String column : model.getHeader()) { for (String column : currentCsvFile.getContent().getHeader()) {
row.addValue(column, ""); row.addValue(column, "");
} }
fileChanged.setValue(true); currentCsvFile.setFileChanged(true);
resetContent(); resetContent();
selectNewRow(); selectNewRow();
@@ -376,7 +347,7 @@ public class SmartCSVController extends FXMLController {
public boolean canExit() { public boolean canExit() {
boolean canExit = true; boolean canExit = true;
if (model != null && fileChanged.get()) { if (currentCsvFile.getContent() != null && currentCsvFile.isFileChanged()) {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION); Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setTitle(resourceBundle.getString("dialog.exit.title")); alert.setTitle(resourceBundle.getString("dialog.exit.title"));
alert.setHeaderText(resourceBundle.getString("dialog.exit.header.text")); alert.setHeaderText(resourceBundle.getString("dialog.exit.header.text"));
@@ -404,8 +375,8 @@ public class SmartCSVController extends FXMLController {
if (result.get() == ButtonType.OK){ if (result.get() == ButtonType.OK){
runLater(() -> { runLater(() -> {
validationEditorController.updateConfiguration(); validationEditorController.updateConfiguration();
fileChanged.setValue(true); currentCsvFile.setFileChanged(true);
model.revalidate(); currentCsvFile.getContent().revalidate();
}); });
} }
} }
@@ -421,15 +392,15 @@ public class SmartCSVController extends FXMLController {
tableView.getSelectionModel().select(lastRow); tableView.getSelectionModel().select(lastRow);
} }
private void bindMenuItemsToFileExistence(ObjectProperty<File> file, MenuItem... items) { private void bindMenuItemsToContentExistence(FileStorage file, MenuItem... items) {
for (MenuItem item: items) { for (MenuItem item: items) {
item.disableProperty().bind(isNull(file)); item.disableProperty().bind(isNull(file.contentProperty()));
} }
} }
private void bindButtonsToFileExistence(ObjectProperty<File> file, Button... items) { private void bindButtonsToContentExistence(FileStorage file, Button... items) {
for (Button item: items) { for (Button item: items) {
item.disableProperty().bind(isNull(file)); item.disableProperty().bind(isNull(file.contentProperty()));
} }
} }
@@ -446,17 +417,16 @@ public class SmartCSVController extends FXMLController {
} }
private void bindCsvFileName() { private void bindCsvFileName() {
csvName.textProperty().bind(selectString(currentCsvFile, "name")); csvName.textProperty().bind(selectString(currentCsvFile.fileProperty(), "name"));
} }
private void bindConfigFileName() { private void bindConfigFileName() {
configurationName.textProperty().bind(selectString(currentConfigFile, "name")); configurationName.textProperty().bind(selectString(currentConfigFile.fileProperty(), "name"));
} }
private void loadCsvPreferencesFromFile() { private void loadCsvPreferencesFromFile() {
if (PREFERENCES_FILE.exists()) { if (csvPreferenceFile.getFile().exists()) {
useLoadFileService(preferencesLoader, PREFERENCES_FILE, useLoadFileService(csvPreferenceFile, event -> setCsvPreference(csvPreferenceFile.getContent()));
event -> setCsvPreference(preferencesLoader.getCSVpreference()));
} else { } else {
setCsvPreference(CsvPreference.EXCEL_NORTH_EUROPE_PREFERENCE); setCsvPreference(CsvPreference.EXCEL_NORTH_EUROPE_PREFERENCE);
} }
@@ -465,37 +435,34 @@ public class SmartCSVController extends FXMLController {
private void saveCsvPreferences(CsvPreference csvPreference) { private void saveCsvPreferences(CsvPreference csvPreference) {
try { try {
createPreferenceFile(); createPreferenceFile();
preferencesWriter.setCsvPreference(csvPreference); csvPreferenceFile.setContent(csvPreference);
useSaveFileService(preferencesWriter, PREFERENCES_FILE); useSaveFileService(csvPreferenceFile);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
private void createPreferenceFile() throws IOException { private void createPreferenceFile() throws IOException {
if (!PREFERENCES_FILE.exists()) { if (!csvPreferenceFile.getFile().exists()) {
createPreferencesFileFolder(); createPreferencesFileFolder();
PREFERENCES_FILE.createNewFile(); csvPreferenceFile.getFile().createNewFile();
} }
} }
private void createPreferencesFileFolder() { private void createPreferencesFileFolder() {
if (!PREFERENCES_FILE.getParentFile().exists()) { if (!csvPreferenceFile.getFile().getParentFile().exists()) {
PREFERENCES_FILE.getParentFile().mkdir(); csvPreferenceFile.getFile().getParentFile().mkdir();
} }
} }
private void setCsvPreference(CsvPreference csvPreference) { private void setCsvPreference(CsvPreference csvPreference) {
csvLoader.setCsvPreference(csvPreference);
csvFileWriter.setCsvPreference(csvPreference);
preferencesController.setCsvPreference(csvPreference); preferencesController.setCsvPreference(csvPreference);
} }
private File loadFile(FileReader fileReader, private void loadFile(String filterText,
String filterText,
String filter, String filter,
String title, String title,
File initChildFile) { FileStorage storageFile) {
final FileChooser fileChooser = new FileChooser(); final FileChooser fileChooser = new FileChooser();
//Set extension filter //Set extension filter
@@ -503,83 +470,73 @@ public class SmartCSVController extends FXMLController {
fileChooser.getExtensionFilters().add(extFilter); fileChooser.getExtensionFilters().add(extFilter);
fileChooser.setTitle(title); fileChooser.setTitle(title);
if (initChildFile != null) { if (storageFile.getFile() != null) {
fileChooser.setInitialDirectory(initChildFile.getParentFile()); fileChooser.setInitialDirectory(storageFile.getFile().getParentFile());
} }
//Show open file dialog //Show open file dialog
File file = fileChooser.showOpenDialog(applicationPane.getScene().getWindow()); File file = fileChooser.showOpenDialog(applicationPane.getScene().getWindow());
if (file != null) { if (file != null) {
useLoadFileService(fileReader, file, event -> runLater(() -> { storageFile.setFile(file);
resetContent(); useLoadFileService(storageFile, t -> resetContent());
fileChanged.setValue(false);
}));
return file;
} else {
return initChildFile;
} }
} }
private File saveFile(FileWriter writer, String filterText, String filter, File initFile) { private File saveFile(String filterText, String filter, FileStorage fileStorage) {
File file = initFile; File file = fileStorage.getFile();
if (model != null) { if (fileStorage.getContent() != null) {
final FileChooser fileChooser = new FileChooser(); final FileChooser fileChooser = new FileChooser();
//Set extension filter //Set extension filter
final FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter(filterText, filter); final FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter(filterText, filter);
fileChooser.getExtensionFilters().add(extFilter); fileChooser.getExtensionFilters().add(extFilter);
if (initFile != null) { if (fileStorage.getFile() != null) {
fileChooser.setInitialDirectory(initFile.getParentFile()); fileChooser.setInitialDirectory(fileStorage.getFile().getParentFile());
fileChooser.setInitialFileName(initFile.getName()); fileChooser.setInitialFileName(fileStorage.getFile().getName());
} }
fileChooser.setTitle("Save File"); fileChooser.setTitle("Save File");
//Show open file dialog //Show open file dialog
file = fileChooser.showSaveDialog(applicationPane.getScene().getWindow()); file = fileChooser.showSaveDialog(applicationPane.getScene().getWindow());
if (file != null) { if (file != null) {
useSaveFileService(writer, file); fileStorage.setFile(file);
useSaveFileService(fileStorage);
} }
} }
return file; return file;
} }
private void useLoadFileService(FileReader fileReader, File file, EventHandler<WorkerStateEvent> value) { private void useLoadFileService(FileStorage fileStorage, EventHandler<WorkerStateEvent> onSucceededHandler) {
loadFileService.setFile(file); loadFileService.setFileStorage(fileStorage);
loadFileService.setFileReader(fileReader);
loadFileService.restart(); loadFileService.restart();
loadFileService.setOnSucceeded(value); loadFileService.setOnSucceeded(onSucceededHandler);
} }
private void useSaveFileService(FileWriter writer, File file) { private void useSaveFileService(FileStorage fileStorage) {
saveFileService.setFile(file); saveFileService.setFileStorage(fileStorage);
saveFileService.setWriter(writer);
saveFileService.restart(); saveFileService.restart();
saveFileService.setOnSucceeded(event -> runLater(() -> { saveFileService.setOnSucceeded(t -> resetContent());
resetContent();
fileChanged.setValue(false);
}));
} }
/** /**
* Creates new table view and add the new content * Creates new table view and add the new content
*/ */
private void resetContent() { private void resetContent() {
model = csvLoader.getData(); if (currentCsvFile.getContent() != null) {
if (model != null) { currentCsvFile.getContent().getValidationError().addListener(weakErrorListListener);
model.getValidationError().addListener(weakErrorListListener); currentCsvFile.getContent().setValidationConfiguration(currentConfigFile.getContent());
model.setValidationConfiguration(validationLoader.getValidationConfiguration()); validationEditorController.setValidationConfiguration(currentConfigFile.getContent());
validationEditorController.setValidationConfiguration(validationLoader.getValidationConfiguration());
tableView = new TableView<>(); tableView = new TableView<>();
bindMenuItemsToTableSelection(deleteRowMenuItem); bindMenuItemsToTableSelection(deleteRowMenuItem);
bindButtonsToTableSelection(deleteRowButton); bindButtonsToTableSelection(deleteRowButton);
for (String column : model.getHeader()) { for (String column : currentCsvFile.getContent().getHeader()) {
addColumn(column, tableView); addColumn(column, tableView);
} }
tableView.getItems().setAll(model.getRows()); tableView.getItems().setAll(currentCsvFile.getContent().getRows());
tableView.setEditable(true); tableView.setEditable(true);
setBottomAnchor(tableView, 0.0); setBottomAnchor(tableView, 0.0);
@@ -587,7 +544,7 @@ public class SmartCSVController extends FXMLController {
setLeftAnchor(tableView, 0.0); setLeftAnchor(tableView, 0.0);
setRightAnchor(tableView, 0.0); setRightAnchor(tableView, 0.0);
tableWrapper.getChildren().setAll(tableView); tableWrapper.getChildren().setAll(tableView);
errorSideBar.setModel(model); errorSideBar.setModel(currentCsvFile.getContent());
} }
} }
@@ -612,8 +569,8 @@ public class SmartCSVController extends FXMLController {
event.getTableView().getItems().get(event.getTablePosition().getRow()). event.getTableView().getItems().get(event.getTablePosition().getRow()).
getColumns().get(header).setValue(event.getNewValue()); getColumns().get(header).setValue(event.getNewValue());
runLater(() -> { runLater(() -> {
fileChanged.setValue(true); currentCsvFile.setFileChanged(true);
model.revalidate(); currentCsvFile.getContent().revalidate();
}); });
} }
}); });
@@ -624,7 +581,7 @@ public class SmartCSVController extends FXMLController {
private ContextMenu contextMenuForColumn(String header) { private ContextMenu contextMenuForColumn(String header) {
ContextMenu contextMenu = new ContextMenu(); ContextMenu contextMenu = new ContextMenu();
MenuItem editColumnRulesMenuItem = new MenuItem(resourceBundle.getString("context.menu.edit.column.rules")); MenuItem editColumnRulesMenuItem = new MenuItem(resourceBundle.getString("context.menu.edit.column.rules"));
bindMenuItemsToFileExistence(currentConfigFile, editColumnRulesMenuItem); bindMenuItemsToContentExistence(currentConfigFile, editColumnRulesMenuItem);
editColumnRulesMenuItem.setOnAction(e -> showValidationEditor(header)); editColumnRulesMenuItem.setOnAction(e -> showValidationEditor(header));
contextMenu.getItems().addAll(editColumnRulesMenuItem); contextMenu.getItems().addAll(editColumnRulesMenuItem);
return contextMenu; return contextMenu;

View File

@@ -38,6 +38,8 @@ import javafx.scene.text.Text;
import ninja.javafx.smartcsv.fx.table.model.CSVModel; import ninja.javafx.smartcsv.fx.table.model.CSVModel;
import ninja.javafx.smartcsv.fx.util.ColorConstants; import ninja.javafx.smartcsv.fx.util.ColorConstants;
import ninja.javafx.smartcsv.validation.ValidationError; import ninja.javafx.smartcsv.validation.ValidationError;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.controlsfx.control.PopOver; import org.controlsfx.control.PopOver;
import java.util.ArrayList; import java.util.ArrayList;
@@ -54,6 +56,8 @@ import static ninja.javafx.smartcsv.fx.util.I18nValidationUtil.getI18nValidatioM
*/ */
public class ErrorSideBar extends Region { public class ErrorSideBar extends Region {
private static final Logger logger = LogManager.getLogger(ErrorSideBar.class);
private static final double WIDTH = 20.0; private static final double WIDTH = 20.0;
private static final int BORDER = 8; private static final int BORDER = 8;
private static final double STATUS_BLOCK_HEIGHT = WIDTH - BORDER; private static final double STATUS_BLOCK_HEIGHT = WIDTH - BORDER;
@@ -133,7 +137,7 @@ public class ErrorSideBar extends Region {
statusBlock.setStyle("-fx-background-color: " + ERROR_COLOR); statusBlock.setStyle("-fx-background-color: " + ERROR_COLOR);
int rows = model.get().getRows().size(); int rows = model.get().getRows().size();
double space = heightWithoutStatusBlock() / rows; double space = (double)heightWithoutStatusBlock() / rows;
for (ValidationError error : errorList) { for (ValidationError error : errorList) {
errorMarkerList.add(generateErrorMarker(space, error)); errorMarkerList.add(generateErrorMarker(space, error));
} }
@@ -147,6 +151,8 @@ public class ErrorSideBar extends Region {
} }
private Region generateErrorMarker(double space, ValidationError error) { private Region generateErrorMarker(double space, ValidationError error) {
logger.info("generate error marker for {} errors in line {}", error.getMessages().size(), error.getLineNumber());
logger.info("layout y is set to {}", (space * error.getLineNumber() + STATUS_BLOCK_OFFSET));
Region errorMarker = new Region(); Region errorMarker = new Region();
errorMarker.setLayoutY(space * error.getLineNumber() + STATUS_BLOCK_OFFSET); errorMarker.setLayoutY(space * error.getLineNumber() + STATUS_BLOCK_OFFSET);
errorMarker.setPrefSize(WIDTH, 2); errorMarker.setPrefSize(WIDTH, 2);

View File

@@ -28,9 +28,16 @@ package ninja.javafx.smartcsv.fx.table.model;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import ninja.javafx.smartcsv.validation.ValidationConfiguration; import ninja.javafx.smartcsv.validation.ValidationConfiguration;
import ninja.javafx.smartcsv.validation.ValidationError; import ninja.javafx.smartcsv.validation.ValidationError;
import ninja.javafx.smartcsv.validation.Validator; import ninja.javafx.smartcsv.validation.Validator;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.ArrayList;
import java.util.List;
/** /**
* The CSVModel is the client representation for the csv filepath. * The CSVModel is the client representation for the csv filepath.
@@ -38,10 +45,13 @@ import ninja.javafx.smartcsv.validation.Validator;
*/ */
public class CSVModel { public class CSVModel {
private static final Logger logger = LogManager.getLogger(CSVModel.class);
private Validator validator; private Validator validator;
private ObservableList<CSVRow> rows = FXCollections.observableArrayList(); private ObservableList<CSVRow> rows = FXCollections.observableArrayList();
private String[] header; private String[] header;
private ObservableList<ValidationError> validationError = FXCollections.observableArrayList(); private ObservableList<ValidationError> validationError = FXCollections.observableArrayList();
private RevalidationService revalidationService = new RevalidationService();
/** /**
* sets the validator configuration for the data revalidates * sets the validator configuration for the data revalidates
@@ -100,8 +110,61 @@ public class CSVModel {
public void revalidate() { public void revalidate() {
validationError.clear(); validationError.clear();
if (header != null && validator != null) { logger.info("revalidate: hasValidator -> {}", hasValidator());
addValidationError(validator.isHeaderValid(header));
if (!hasValidator()) return;
revalidationService.setHeader(header);
revalidationService.setRows(rows);
revalidationService.setValidator(validator);
revalidationService.setOnSucceeded(t -> validationError.setAll(revalidationService.getValue()));
revalidationService.setOnFailed(t -> logger.error("revalidation service failed!"));
revalidationService.restart();
}
private boolean hasValidator() {
return validator != null && validator.hasConfig();
}
public ValidationConfiguration createValidationConfiguration() {
ValidationConfiguration newValidationConfiguration = new ValidationConfiguration();
newValidationConfiguration.setHeaderNames(this.header);
this.validator = new Validator(newValidationConfiguration);
this.revalidate();
return newValidationConfiguration;
}
private static class RevalidationService extends Service<List<ValidationError>> {
private Validator validator;
private List<CSVRow> rows;
private String[] header;
public void setValidator(Validator validator) {
this.validator = validator;
}
public void setRows(List<CSVRow> rows) {
this.rows = rows;
}
public void setHeader(String[] header) {
this.header = header;
}
@Override
protected Task<List<ValidationError>> createTask() {
return new Task<List<ValidationError>>() {
@Override
protected List<ValidationError> call() throws Exception {
List<ValidationError> errors = new ArrayList<>();
if (header != null) {
ValidationError headerError = validator.isHeaderValid(header);
if (headerError != null) {
logger.info("revalidate: header error found");
errors.add(headerError);
}
} }
for (int lineNumber = 0; lineNumber < rows.size(); lineNumber++) { for (int lineNumber = 0; lineNumber < rows.size(); lineNumber++) {
@@ -113,7 +176,8 @@ public class CSVModel {
if (validator != null) { if (validator != null) {
ValidationError validationError = validator.isValid(column, value.getValue(), lineNumber); ValidationError validationError = validator.isValid(column, value.getValue(), lineNumber);
if (validationError != null) { if (validationError != null) {
addValidationError(validationError); logger.info("revalidate: {} errors found in line {}", validationError.getMessages().size(), lineNumber);
errors.add(validationError);
value.setValidationError(validationError); value.setValidationError(validationError);
} else { } else {
value.setValidationError(null); value.setValidationError(null);
@@ -123,11 +187,9 @@ public class CSVModel {
} }
} }
} }
return errors;
} }
};
private void addValidationError(ValidationError validationError) {
if (validationError != null) {
this.validationError.add(validationError);
} }
} }

View File

@@ -29,6 +29,7 @@ package ninja.javafx.smartcsv.fx.util;
import javafx.concurrent.Service; import javafx.concurrent.Service;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import ninja.javafx.smartcsv.FileReader; import ninja.javafx.smartcsv.FileReader;
import ninja.javafx.smartcsv.files.FileStorage;
import java.io.File; import java.io.File;
@@ -38,14 +39,10 @@ import java.io.File;
@org.springframework.stereotype.Service @org.springframework.stereotype.Service
public class LoadFileService extends Service { public class LoadFileService extends Service {
private File file; private FileStorage file;
private FileReader fileReader;
public void setFile(File value) { public void setFileStorage(FileStorage file) {
file = value; this.file = file;
}
public void setFileReader(FileReader fileReader) {
this.fileReader = fileReader;
} }
@Override @Override
@@ -54,7 +51,7 @@ public class LoadFileService extends Service {
@Override @Override
protected Void call() throws Exception { protected Void call() throws Exception {
if (file != null) { if (file != null) {
fileReader.read(file); file.load();
} }
return null; return null;
} }

View File

@@ -30,6 +30,7 @@ import javafx.concurrent.Service;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import ninja.javafx.smartcsv.FileWriter; import ninja.javafx.smartcsv.FileWriter;
import ninja.javafx.smartcsv.csv.CSVFileWriter; import ninja.javafx.smartcsv.csv.CSVFileWriter;
import ninja.javafx.smartcsv.files.FileStorage;
import java.io.File; import java.io.File;
@@ -41,14 +42,9 @@ import static javafx.application.Platform.runLater;
@org.springframework.stereotype.Service @org.springframework.stereotype.Service
public class SaveFileService extends Service { public class SaveFileService extends Service {
private File file; private FileStorage file;
private FileWriter writer;
public void setWriter(FileWriter writer) { public void setFileStorage(FileStorage value) {
this.writer = writer;
}
public void setFile(File value) {
file = value; file = value;
} }
@@ -58,7 +54,7 @@ public class SaveFileService extends Service {
@Override @Override
protected Void call() throws Exception { protected Void call() throws Exception {
try { try {
writer.write(file); file.save();
} catch (Throwable ex) { } catch (Throwable ex) {
ex.printStackTrace(); ex.printStackTrace();
} }

View File

@@ -42,8 +42,7 @@ import static ninja.javafx.smartcsv.preferences.QuoteModeHelper.getQuoteMode;
/** /**
* file reader for the preferences * file reader for the preferences
*/ */
@Service public class PreferencesFileReader implements FileReader<CsvPreference> {
public class PreferencesFileReader implements FileReader {
private Map config; private Map config;
private CsvPreference csvPreference; private CsvPreference csvPreference;
@@ -74,7 +73,7 @@ public class PreferencesFileReader implements FileReader {
} }
} }
public CsvPreference getCSVpreference() { public CsvPreference getContent() {
return csvPreference; return csvPreference;
} }

View File

@@ -41,12 +41,11 @@ import java.util.Map;
/** /**
* Save preferences to configuration file * Save preferences to configuration file
*/ */
@Service public class PreferencesFileWriter implements FileWriter<CsvPreference> {
public class PreferencesFileWriter implements FileWriter {
private CsvPreference csvPreference; private CsvPreference csvPreference;
public void setCsvPreference(CsvPreference csvPreference) { public void setContent(CsvPreference csvPreference) {
this.csvPreference = csvPreference; this.csvPreference = csvPreference;
} }

View File

@@ -39,4 +39,8 @@ public class HeaderConfiguration {
public String[] getNames() { public String[] getNames() {
return names; return names;
} }
public void setNames(String[] names) {
this.names = names;
}
} }

View File

@@ -32,8 +32,6 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static java.lang.Boolean.FALSE;
/** /**
* validation configuration * validation configuration
*/ */
@@ -50,6 +48,10 @@ public class ValidationConfiguration {
return headerConfiguration.getNames(); return headerConfiguration.getNames();
} }
public void setHeaderNames(String[] headerNames) {
headerConfiguration.setNames(headerNames);
}
public Boolean getIntegerRuleFor(String column) { public Boolean getIntegerRuleFor(String column) {
return (Boolean)getValue(column, "integer"); return (Boolean)getValue(column, "integer");
} }

View File

@@ -36,8 +36,7 @@ import java.io.IOException;
/** /**
* This class loads the constraints as json config * This class loads the constraints as json config
*/ */
@Service public class ValidationFileReader implements FileReader<ValidationConfiguration> {
public class ValidationFileReader implements FileReader {
private ValidationConfiguration config; private ValidationConfiguration config;
@@ -46,7 +45,7 @@ public class ValidationFileReader implements FileReader {
config = new GsonBuilder().create().fromJson(new java.io.FileReader(file), ValidationConfiguration.class); config = new GsonBuilder().create().fromJson(new java.io.FileReader(file), ValidationConfiguration.class);
} }
public ValidationConfiguration getValidationConfiguration() { public ValidationConfiguration getContent() {
return config; return config;
} }
} }

View File

@@ -38,12 +38,11 @@ import java.nio.file.Files;
/** /**
* file writer for the validation configuration * file writer for the validation configuration
*/ */
@Service public class ValidationFileWriter implements FileWriter<ValidationConfiguration> {
public class ValidationFileWriter implements FileWriter {
private ValidationConfiguration validationConfiguration; private ValidationConfiguration validationConfiguration;
public void setValidationConfiguration(ValidationConfiguration validationConfiguration) { public void setContent(ValidationConfiguration validationConfiguration) {
this.validationConfiguration = validationConfiguration; this.validationConfiguration = validationConfiguration;
} }

View File

@@ -67,7 +67,7 @@ public class Validator {
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// oublic methods // public methods
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/** /**
@@ -78,7 +78,7 @@ public class Validator {
*/ */
public ValidationError isValid(String column, String value, Integer lineNumber) { public ValidationError isValid(String column, String value, Integer lineNumber) {
ValidationError result = null; ValidationError result = null;
if (validationConfig != null) { if (hasConfig()) {
ValidationError error = ValidationError.withLineNumber(lineNumber); ValidationError error = ValidationError.withLineNumber(lineNumber);
checkBlankOrNull(column, value, error); checkBlankOrNull(column, value, error);
@@ -101,6 +101,9 @@ public class Validator {
return result; return result;
} }
public boolean hasConfig() {
return validationConfig != null;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// private methods // private methods

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="error">
<Properties>
<Property name="filename">smartcsv.log</Property>
</Properties>
<ThresholdFilter level="trace"/>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
<File name="File" fileName="${filename}" bufferedIO="true">
<PatternLayout>
<pattern>%d %p %C{1.} [%t] %m%n</pattern>
</PatternLayout>
</File>
</Appenders>
<Loggers>
<Root level="error">
<AppenderRef ref="File"/>
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>

View File

@@ -57,6 +57,7 @@
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints> </rowConstraints>
<children> <children>
<Label text="junit" /> <Label text="junit" />
@@ -77,6 +78,8 @@
<Hyperlink onAction="#openLinkInBrowser" text="https://bitbucket.org/Jerady/fontawesomefx" GridPane.columnIndex="1" GridPane.rowIndex="7" /> <Hyperlink onAction="#openLinkInBrowser" text="https://bitbucket.org/Jerady/fontawesomefx" GridPane.columnIndex="1" GridPane.rowIndex="7" />
<Label text="ControlsFX" GridPane.rowIndex="8" /> <Label text="ControlsFX" GridPane.rowIndex="8" />
<Hyperlink onAction="#openLinkInBrowser" text="http://fxexperience.com/controlsfx/" GridPane.columnIndex="1" GridPane.rowIndex="8" /> <Hyperlink onAction="#openLinkInBrowser" text="http://fxexperience.com/controlsfx/" GridPane.columnIndex="1" GridPane.rowIndex="8" />
<Label text="Apache Log4j 2" GridPane.rowIndex="9" />
<Hyperlink onAction="#openLinkInBrowser" text="http://logging.apache.org/log4j/2.x/" GridPane.columnIndex="1" GridPane.rowIndex="9" />
</children> </children>
<padding> <padding>

View File

@@ -15,48 +15,68 @@
} }
.open-icon { .open-icon {
-glyph-name: "FILE_TEXT_ALT"; -glyph-name: "FILE_IMPORT";
-glyph-size: 14px; -glyph-size: 16px;
}
.file-document-icon {
-glyph-name: "FILE_DOCUMENT";
-glyph-size: 16px;
} }
.config-icon { .config-icon {
-glyph-name: "CHECK"; -glyph-name: "CLIPBOARD";
-glyph-size: 14px; -glyph-size: 16px;
}
.create-config-icon {
-glyph-name: "STAR";
-glyph-size: 10px;
}
.load-config-icon {
-glyph-name: "ARROW_UP_BOLD";
-glyph-size: 10px;
}
.save-config-icon {
-glyph-name: "ARROW_DOWN_BOLD";
-glyph-size: 10px;
} }
.save-icon { .save-icon {
-glyph-name: "FLOPPY_ALT"; -glyph-name: "FILE_EXPORT";
-glyph-size: 14px; -glyph-size: 16px;
} }
.exit-icon { .exit-icon {
-glyph-name: "SIGN_OUT"; -glyph-name: "EXIT_TO_APP";
-glyph-size: 14px; -glyph-size: 16px;
} }
.info-icon { .info-icon {
-glyph-name: "INFO"; -glyph-name: "INFORMATION_OUTLINE";
-glyph-size: 14px; -glyph-size: 16px;
} }
.error-title-icon { .config-check-icon {
-glyph-name: "EXCLAMATION_TRIANGLE"; -glyph-name: "CLIPBOARD_CHECK";
-glyph-size: 14px; -glyph-size: 16px;
} }
.preferences-icon { .preferences-icon {
-glyph-name: "COG"; -glyph-name: "SETTINGS";
-glyph-size: 14px; -glyph-size: 16px;
} }
.delete-icon { .delete-icon {
-glyph-name: "MINUS"; -glyph-name: "TABLE_ROW_REMOVE";
-glyph-size: 14px; -glyph-size: 16px;
} }
.add-icon { .add-icon {
-glyph-name: "PLUS"; -glyph-name: "TABLE_ROW_PLUS_AFTER";
-glyph-size: 14px; -glyph-size: 16px;
} }
/* 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/ */
@@ -91,6 +111,13 @@
-fx-fill: white; -fx-fill: white;
} }
.menu-item .load-config-icon,
.menu-item .save-config-icon,
.menu-item .create-config-icon
{
-fx-fill: white;
}
.tool-bar .save-icon { .tool-bar .save-icon {
-glyph-size: 16px; -glyph-size: 16px;
-fx-fill: white; -fx-fill: white;

View File

@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<?import de.jensd.fx.glyphs.GlyphsStack?> <?import de.jensd.fx.glyphs.GlyphsStack?>
<?import de.jensd.fx.glyphs.fontawesome.FontAwesomeIconView?>
<?import java.net.URL?> <?import java.net.URL?>
<?import javafx.geometry.Insets?> <?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?> <?import javafx.scene.control.Button?>
@@ -22,6 +21,7 @@
<?import javafx.scene.layout.RowConstraints?> <?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIconView?>
<BorderPane fx:id="applicationPane" maxHeight="-Infinity" maxWidth="1000.0" minHeight="700.0" minWidth="-Infinity" prefHeight="700.0" prefWidth="1000.0" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1"> <BorderPane fx:id="applicationPane" maxHeight="-Infinity" maxWidth="1000.0" minHeight="700.0" minWidth="-Infinity" prefHeight="700.0" prefWidth="1000.0" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1">
<top> <top>
<VBox id="background" prefWidth="100.0" BorderPane.alignment="CENTER"> <VBox id="background" prefWidth="100.0" BorderPane.alignment="CENTER">
@@ -32,32 +32,47 @@
<items> <items>
<MenuItem mnemonicParsing="false" onAction="#openCsv" text="%menu.open.csv"> <MenuItem mnemonicParsing="false" onAction="#openCsv" text="%menu.open.csv">
<graphic> <graphic>
<FontAwesomeIconView styleClass="open-icon" /> <MaterialDesignIconView styleClass="open-icon" />
</graphic> </graphic>
</MenuItem> </MenuItem>
<MenuItem fx:id="saveMenuItem" disable="true" mnemonicParsing="false" onAction="#saveCsv" text="%menu.save"> <MenuItem fx:id="saveMenuItem" disable="true" mnemonicParsing="false" onAction="#saveCsv" text="%menu.save">
<graphic> <graphic>
<FontAwesomeIconView styleClass="save-icon" /> <MaterialDesignIconView styleClass="save-icon" />
</graphic> </graphic>
</MenuItem> </MenuItem>
<MenuItem fx:id="saveAsMenuItem" disable="true" mnemonicParsing="false" onAction="#saveAsCsv" text="%menu.save.as"> <MenuItem fx:id="saveAsMenuItem" disable="true" mnemonicParsing="false" onAction="#saveAsCsv" text="%menu.save.as">
<graphic> <graphic>
<FontAwesomeIconView styleClass="save-icon" /> <MaterialDesignIconView styleClass="save-icon" />
</graphic> </graphic>
</MenuItem> </MenuItem>
<SeparatorMenuItem mnemonicParsing="false" /> <SeparatorMenuItem mnemonicParsing="false" />
<MenuItem fx:id="createConfigMenuItem" disable="true" mnemonicParsing="false" onAction="#createConfig" text="%menu.create.config">
<graphic>
<GlyphsStack>
<children>
<MaterialDesignIconView styleClass="config-icon" />
<MaterialDesignIconView style="-fx-opacity: 0.7;" styleClass="create-config-icon" />
</children>
</GlyphsStack>
</graphic>
</MenuItem>
<MenuItem fx:id="loadConfigMenuItem" disable="true" mnemonicParsing="false" onAction="#openConfig" text="%menu.open.config"> <MenuItem fx:id="loadConfigMenuItem" disable="true" mnemonicParsing="false" onAction="#openConfig" text="%menu.open.config">
<graphic> <graphic>
<FontAwesomeIconView styleClass="config-icon" /> <GlyphsStack>
<children>
<MaterialDesignIconView styleClass="config-icon" />
<MaterialDesignIconView style="-fx-opacity: 0.7;" styleClass="load-config-icon" />
</children>
</GlyphsStack>
</graphic> </graphic>
</MenuItem> </MenuItem>
<MenuItem fx:id="saveConfigMenuItem" disable="true" mnemonicParsing="false" onAction="#saveConfig" text="%menu.save.config"> <MenuItem fx:id="saveConfigMenuItem" disable="true" mnemonicParsing="false" onAction="#saveConfig" text="%menu.save.config">
<graphic> <graphic>
<GlyphsStack> <GlyphsStack>
<children> <children>
<FontAwesomeIconView style="-fx-opacity: 0.7;" styleClass="save-icon" /> <MaterialDesignIconView styleClass="config-icon" />
<FontAwesomeIconView styleClass="config-icon" /> <MaterialDesignIconView style="-fx-opacity: 0.7;" styleClass="save-config-icon" />
</children> </children>
</GlyphsStack> </GlyphsStack>
</graphic> </graphic>
@@ -66,8 +81,8 @@
<graphic> <graphic>
<GlyphsStack> <GlyphsStack>
<children> <children>
<FontAwesomeIconView style="-fx-opacity: 0.7;" styleClass="save-icon" /> <MaterialDesignIconView styleClass="config-icon" />
<FontAwesomeIconView styleClass="config-icon" /> <MaterialDesignIconView style="-fx-opacity: 0.7;" styleClass="save-config-icon" />
</children> </children>
</GlyphsStack> </GlyphsStack>
</graphic> </graphic>
@@ -76,13 +91,13 @@
<SeparatorMenuItem mnemonicParsing="false" /> <SeparatorMenuItem mnemonicParsing="false" />
<MenuItem mnemonicParsing="false" onAction="#preferences" text="%menu.preferences"> <MenuItem mnemonicParsing="false" onAction="#preferences" text="%menu.preferences">
<graphic> <graphic>
<FontAwesomeIconView styleClass="preferences-icon" /> <MaterialDesignIconView styleClass="preferences-icon" />
</graphic> </graphic>
</MenuItem> </MenuItem>
<SeparatorMenuItem mnemonicParsing="false" /> <SeparatorMenuItem mnemonicParsing="false" />
<MenuItem mnemonicParsing="false" onAction="#close" text="%menu.close"> <MenuItem mnemonicParsing="false" onAction="#close" text="%menu.close">
<graphic> <graphic>
<FontAwesomeIconView styleClass="exit-icon" /> <MaterialDesignIconView styleClass="exit-icon" />
</graphic> </graphic>
</MenuItem> </MenuItem>
</items> </items>
@@ -91,12 +106,12 @@
<items> <items>
<MenuItem fx:id="deleteRowMenuItem" disable="true" mnemonicParsing="false" onAction="#deleteRow" text="%menu.delete.row"> <MenuItem fx:id="deleteRowMenuItem" disable="true" mnemonicParsing="false" onAction="#deleteRow" text="%menu.delete.row">
<graphic> <graphic>
<FontAwesomeIconView styleClass="delete-icon" /> <MaterialDesignIconView styleClass="delete-icon" />
</graphic> </graphic>
</MenuItem> </MenuItem>
<MenuItem fx:id="addRowMenuItem" disable="true" mnemonicParsing="false" onAction="#addRow" text="%menu.add.row"> <MenuItem fx:id="addRowMenuItem" disable="true" mnemonicParsing="false" onAction="#addRow" text="%menu.add.row">
<graphic> <graphic>
<FontAwesomeIconView styleClass="add-icon" /> <MaterialDesignIconView styleClass="add-icon" />
</graphic> </graphic>
</MenuItem> </MenuItem>
</items> </items>
@@ -105,7 +120,7 @@
<items> <items>
<MenuItem mnemonicParsing="false" onAction="#about" text="%menu.about"> <MenuItem mnemonicParsing="false" onAction="#about" text="%menu.about">
<graphic> <graphic>
<FontAwesomeIconView styleClass="info-icon" /> <MaterialDesignIconView styleClass="info-icon" />
</graphic> </graphic>
</MenuItem> </MenuItem>
</items> </items>
@@ -119,7 +134,7 @@
<Tooltip text="%menu.open.csv" /> <Tooltip text="%menu.open.csv" />
</tooltip> </tooltip>
<graphic> <graphic>
<FontAwesomeIconView styleClass="open-icon" /> <MaterialDesignIconView styleClass="open-icon" />
</graphic> </graphic>
</Button> </Button>
<Button fx:id="saveButton" disable="true" mnemonicParsing="false" onAction="#saveCsv"> <Button fx:id="saveButton" disable="true" mnemonicParsing="false" onAction="#saveCsv">
@@ -127,7 +142,7 @@
<Tooltip text="%menu.save" /> <Tooltip text="%menu.save" />
</tooltip> </tooltip>
<graphic> <graphic>
<FontAwesomeIconView styleClass="save-icon" /> <MaterialDesignIconView styleClass="save-icon" />
</graphic> </graphic>
</Button> </Button>
<Button fx:id="saveAsButton" disable="true" mnemonicParsing="false" onAction="#saveAsCsv" styleClass="last" text="..."> <Button fx:id="saveAsButton" disable="true" mnemonicParsing="false" onAction="#saveAsCsv" styleClass="last" text="...">
@@ -135,18 +150,36 @@
<Tooltip text="%menu.save.as" /> <Tooltip text="%menu.save.as" />
</tooltip> </tooltip>
<graphic> <graphic>
<FontAwesomeIconView styleClass="save-icon" /> <MaterialDesignIconView styleClass="save-icon" />
</graphic> </graphic>
</Button> </Button>
</HBox> </HBox>
<Region styleClass="spacer" /> <Region styleClass="spacer" />
<HBox styleClass="segmented-button-bar"> <HBox styleClass="segmented-button-bar">
<Button fx:id="createConfigButton" disable="true" mnemonicParsing="false" onAction="#createConfig">
<tooltip>
<Tooltip text="%menu.create.config" />
</tooltip>
<graphic>
<GlyphsStack>
<children>
<MaterialDesignIconView styleClass="config-icon" />
<MaterialDesignIconView style="-fx-opacity: 0.7;" styleClass="create-config-icon" />
</children>
</GlyphsStack>
</graphic>
</Button>
<Button fx:id="loadConfigButton" disable="true" mnemonicParsing="false" onAction="#openConfig"> <Button fx:id="loadConfigButton" disable="true" mnemonicParsing="false" onAction="#openConfig">
<tooltip> <tooltip>
<Tooltip text="%menu.open.config" /> <Tooltip text="%menu.open.config" />
</tooltip> </tooltip>
<graphic> <graphic>
<FontAwesomeIconView styleClass="config-icon" /> <GlyphsStack>
<children>
<MaterialDesignIconView styleClass="config-icon" />
<MaterialDesignIconView style="-fx-opacity: 0.7;" styleClass="load-config-icon" />
</children>
</GlyphsStack>
</graphic> </graphic>
</Button> </Button>
<Button fx:id="saveConfigButton" disable="true" mnemonicParsing="false" onAction="#saveConfig"> <Button fx:id="saveConfigButton" disable="true" mnemonicParsing="false" onAction="#saveConfig">
@@ -156,8 +189,8 @@
<graphic> <graphic>
<GlyphsStack> <GlyphsStack>
<children> <children>
<FontAwesomeIconView style="-fx-opacity: 0.7;" styleClass="save-icon" /> <MaterialDesignIconView styleClass="config-icon" />
<FontAwesomeIconView styleClass="config-icon" /> <MaterialDesignIconView style="-fx-opacity: 0.7;" styleClass="save-config-icon" />
</children> </children>
</GlyphsStack> </GlyphsStack>
</graphic> </graphic>
@@ -169,8 +202,8 @@
<graphic> <graphic>
<GlyphsStack> <GlyphsStack>
<children> <children>
<FontAwesomeIconView style="-fx-opacity: 0.7;" styleClass="save-icon" /> <MaterialDesignIconView styleClass="config-icon" />
<FontAwesomeIconView styleClass="config-icon" /> <MaterialDesignIconView style="-fx-opacity: 0.7;" styleClass="save-config-icon" />
</children> </children>
</GlyphsStack> </GlyphsStack>
@@ -184,7 +217,7 @@
<Tooltip text="%menu.delete.row" /> <Tooltip text="%menu.delete.row" />
</tooltip> </tooltip>
<graphic> <graphic>
<FontAwesomeIconView styleClass="delete-icon" /> <MaterialDesignIconView styleClass="delete-icon" />
</graphic> </graphic>
</Button> </Button>
<Button fx:id="addRowButton" disable="true" mnemonicParsing="false" onAction="#addRow" styleClass="last"> <Button fx:id="addRowButton" disable="true" mnemonicParsing="false" onAction="#addRow" styleClass="last">
@@ -192,7 +225,7 @@
<Tooltip text="%menu.add.row" /> <Tooltip text="%menu.add.row" />
</tooltip> </tooltip>
<graphic> <graphic>
<FontAwesomeIconView styleClass="add-icon" /> <MaterialDesignIconView styleClass="add-icon" />
</graphic> </graphic>
</Button> </Button>
</HBox> </HBox>
@@ -203,7 +236,7 @@
<Tooltip text="%menu.preferences" /> <Tooltip text="%menu.preferences" />
</tooltip> </tooltip>
<graphic> <graphic>
<FontAwesomeIconView styleClass="preferences-icon" /> <MaterialDesignIconView styleClass="preferences-icon" />
</graphic> </graphic>
</Button> </Button>
<Button mnemonicParsing="false" onAction="#close" styleClass="last"> <Button mnemonicParsing="false" onAction="#close" styleClass="last">
@@ -211,7 +244,7 @@
<Tooltip text="%menu.close" /> <Tooltip text="%menu.close" />
</tooltip> </tooltip>
<graphic> <graphic>
<FontAwesomeIconView styleClass="exit-icon" /> <MaterialDesignIconView styleClass="exit-icon" />
</graphic> </graphic>
</Button> </Button>
</HBox> </HBox>
@@ -248,10 +281,10 @@
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints> </rowConstraints>
<children> <children>
<FontAwesomeIconView styleClass="open-icon" GridPane.hgrow="NEVER" /> <MaterialDesignIconView styleClass="file-document-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" />
<FontAwesomeIconView styleClass="open-icon" GridPane.columnIndex="3" GridPane.hgrow="NEVER" /> <MaterialDesignIconView styleClass="config-check-icon" GridPane.columnIndex="3" GridPane.hgrow="NEVER" />
<Label text="%stateline.configuration" GridPane.columnIndex="4" GridPane.hgrow="NEVER" /> <Label text="%stateline.configuration" GridPane.columnIndex="4" GridPane.hgrow="NEVER" />
<Label fx:id="configurationName" GridPane.columnIndex="5" GridPane.hgrow="ALWAYS" /> <Label fx:id="configurationName" GridPane.columnIndex="5" GridPane.hgrow="ALWAYS" />
</children> </children>

View File

@@ -1,5 +1,6 @@
menu.open.csv = Open CSV File menu.open.csv = Open CSV File
menu.open.config = Open Validation Config menu.open.config = Open Validation Config
menu.create.config = Create Validation Config
menu.save = Save menu.save = Save
menu.save.as = Save As ... menu.save.as = Save As ...
menu.save.config = Save Validation Config menu.save.config = Save Validation Config

View File

@@ -8,6 +8,7 @@
menu.open.csv = CSV Datei \u00f6ffnen menu.open.csv = CSV Datei \u00f6ffnen
menu.open.config = Pr\u00fcfkonfiguration \u00f6ffnen menu.open.config = Pr\u00fcfkonfiguration \u00f6ffnen
menu.create.config = Pr\u00fcfkonfiguration erzeugen
menu.save = Speichern menu.save = Speichern
menu.save.as = Speichern als ... menu.save.as = Speichern als ...
menu.save.config = Pr\u00fcfkonfiguration speichern menu.save.config = Pr\u00fcfkonfiguration speichern