new feature: clickable error list

This commit is contained in:
Andreas Billmann
2015-12-07 22:41:59 +01:00
parent 873a880971
commit 11fb9b1094
13 changed files with 226 additions and 79 deletions

View File

@@ -32,27 +32,26 @@ import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.*;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.stage.FileChooser;
import ninja.javafx.smartcsv.FileReader;
import ninja.javafx.smartcsv.csv.CSVFileReader;
import ninja.javafx.smartcsv.csv.CSVFileWriter;
import ninja.javafx.smartcsv.fx.list.ValidationErrorListCell;
import ninja.javafx.smartcsv.fx.table.ObservableMapValueFactory;
import ninja.javafx.smartcsv.fx.table.ValidationCellFactory;
import ninja.javafx.smartcsv.fx.table.model.CSVModel;
import ninja.javafx.smartcsv.fx.table.model.CSVValue;
import ninja.javafx.smartcsv.fx.table.model.CSVRow;
import ninja.javafx.smartcsv.validation.ValidationError;
import ninja.javafx.smartcsv.validation.ValidationFileReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
@@ -83,6 +82,12 @@ public class SmartCSVController extends FXMLController {
@FXML
private Label stateline;
@FXML
private ListView errorList;
@FXML
private AnchorPane tableWrapper;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// injections
@@ -92,6 +97,7 @@ public class SmartCSVController extends FXMLController {
private final LoadCSVService loadCSVService = new LoadCSVService();
private final SaveCSVService saveCSVService = new SaveCSVService();
private CSVModel model;
private TableView<CSVRow> tableView;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -101,6 +107,10 @@ public class SmartCSVController extends FXMLController {
@Override
public void initialize(URL location, ResourceBundle resources) {
stateline.setVisible(false);
errorList.setCellFactory(param -> new ValidationErrorListCell());
errorList.getSelectionModel().selectedItemProperty().addListener(
observable -> scrollToError()
);
}
@@ -215,7 +225,7 @@ public class SmartCSVController extends FXMLController {
model = csvLoader.getData();
model.setValidator(validationLoader.getValidator());
TableView<CSVRow> tableView = new TableView<>();
tableView = new TableView<>();
for (String column: model.getHeader()) {
addColumn(column, tableView);
@@ -223,7 +233,14 @@ public class SmartCSVController extends FXMLController {
tableView.getItems().setAll(model.getRows());
tableView.setEditable(true);
applicationPane.setCenter(tableView);
AnchorPane.setBottomAnchor(tableView, 0.0);
AnchorPane.setTopAnchor(tableView, 0.0);
AnchorPane.setLeftAnchor(tableView, 0.0);
AnchorPane.setRightAnchor(tableView, 0.0);
tableWrapper.getChildren().setAll(tableView);
errorList.setItems(model.getValidationError());
}
/**
@@ -248,6 +265,17 @@ public class SmartCSVController extends FXMLController {
tableView.getColumns().add(column);
}
private void scrollToError() {
ValidationError entry = (ValidationError)errorList.getSelectionModel().getSelectedItem();
if (entry != null) {
if (entry.getLineNumber() != null) {
tableView.scrollTo(entry.getLineNumber());
tableView.getSelectionModel().select(entry.getLineNumber());
} else {
tableView.scrollTo(0);
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// inner class
@@ -277,7 +305,7 @@ public class SmartCSVController extends FXMLController {
try {
fileReader.read(file);
runLater(SmartCSVController.this::resetContent);
} catch (IOException ex) {
} catch (Throwable ex) {
ex.printStackTrace();
}
}
@@ -300,7 +328,7 @@ public class SmartCSVController extends FXMLController {
try {
csvFileWriter.saveFile(model);
runLater(SmartCSVController.this::resetContent);
} catch (IOException ex) {
} catch (Throwable ex) {
ex.printStackTrace();
}
return null;

View File

@@ -0,0 +1,62 @@
/*
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015 javafx.ninja <info@javafx.ninja>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package ninja.javafx.smartcsv.fx.list;
import javafx.scene.control.ListCell;
import javafx.scene.text.Text;
import ninja.javafx.smartcsv.validation.ValidationError;
/**
* TODO: DESCRIPTION!!!
*/
public class ValidationErrorListCell extends ListCell<ValidationError> {
private Text text;
@Override
public void updateItem(ValidationError validationError, boolean empty) {
super.updateItem(validationError, empty);
if (empty) {
clearContent();
} else {
addContent(validationError);
}
}
private void clearContent() {
setText(null);
setGraphic(null);
}
private void addContent(ValidationError validationError) {
setText(null);
text = new Text(validationError.getMessage());
text.setWrappingWidth(180);
setGraphic(text);
}
}

View File

@@ -64,12 +64,12 @@ public class EditableValidationCell extends TableCell<CSVRow, CSVValue> {
protected void updateItem(CSVValue item, boolean empty) {
super.updateItem(item, empty);
if (item == null || item.getValid().isValid() || isEditing()) {
if (item == null || item.getValidationError() == null || isEditing()) {
setStyle("");
setTooltip(null);
} else if (!item.getValid().isValid()) {
} else if (item.getValidationError() != null) {
setStyle("-fx-background-color: #ff8888");
setTooltip(new Tooltip(item.getValid().error()));
setTooltip(new Tooltip(item.getValidationError().getMessage()));
}
if (item == null || empty) {

View File

@@ -28,7 +28,7 @@ package ninja.javafx.smartcsv.fx.table.model;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import ninja.javafx.smartcsv.validation.ValidationState;
import ninja.javafx.smartcsv.validation.ValidationError;
import ninja.javafx.smartcsv.validation.Validator;
/**
@@ -41,6 +41,7 @@ public class CSVModel {
private ObservableList<CSVRow> rows = FXCollections.observableArrayList();
private String[] header;
private String filepath;
private ObservableList<ValidationError> validationError = FXCollections.observableArrayList();
public CSVModel(String filepath) {
this.filepath = filepath;
@@ -71,6 +72,10 @@ public class CSVModel {
return rows;
}
public ObservableList<ValidationError> getValidationError() {
return validationError;
}
/**
* adds a new and empty row
* @return the new row
@@ -105,22 +110,37 @@ public class CSVModel {
* walks through the data and validates each value
*/
private void revalidate() {
validationError.clear();
if (header != null && validator != null) {
validator.isHeaderValid(header);
addValidationError(validator.isHeaderValid(header));
}
for (CSVRow row: rows) {
for (int lineNumber = 0; lineNumber < rows.size(); lineNumber++) {
CSVRow row = rows.get(lineNumber);
row.setValidator(validator);
for (String column: row.getColumns().keySet()) {
CSVValue value = row.getColumns().get(column).getValue();
value.setValidator(validator);
if (validator != null) {
value.setValid(validator.isValid(column, value.getValue()));
ValidationError validationError = validator.isValid(column, value.getValue(), lineNumber);
if (validationError != null) {
addValidationError(validationError);
value.setValidationError(validationError);
} else {
value.setValidationError(null);
}
} else {
value.setValid(new ValidationState());
value.setValidationError(null);
}
}
}
}
private void addValidationError(ValidationError validationError) {
if (validationError != null) {
this.validationError.add(validationError);
}
}
}

View File

@@ -28,7 +28,7 @@ package ninja.javafx.smartcsv.fx.table.model;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import ninja.javafx.smartcsv.validation.ValidationState;
import ninja.javafx.smartcsv.validation.ValidationError;
import ninja.javafx.smartcsv.validation.Validator;
/**
@@ -41,7 +41,7 @@ public class CSVValue {
private int rowNumber;
private String column;
private StringProperty value = new SimpleStringProperty();
private ValidationState valid = new ValidationState();
private ValidationError valid;
/**
* single value of a cell
@@ -89,7 +89,7 @@ public class CSVValue {
*/
public void setValue(String value) {
if (validator != null) {
valid = validator.isValid(column, value);
valid = validator.isValid(column, value, rowNumber);
}
this.value.set(value);
}
@@ -98,7 +98,7 @@ public class CSVValue {
* returns if the value is valid to the rules of the validator
* @return
*/
public ValidationState getValid() {
public ValidationError getValidationError() {
return valid;
}
@@ -106,7 +106,7 @@ public class CSVValue {
* sets the state if a value is valid or not
* @param valid the validation state
*/
protected void setValid(ValidationState valid) {
protected void setValidationError(ValidationError valid) {
this.valid = valid;
}
}