Overhaul of spreadsheet user interface

This commit is contained in:
Brendan Robert 2018-09-15 16:24:24 -05:00
parent e7c702136c
commit 8fd55f6230
4 changed files with 89 additions and 101 deletions

View File

@ -167,5 +167,10 @@
<artifactId>poi-ooxml</artifactId>
<version>3.16</version>
</dependency>
<dependency>
<groupId>org.controlsfx</groupId>
<artifactId>controlsfx</artifactId>
<version>8.40.14</version>
</dependency>
</dependencies>
</project>

View File

@ -23,6 +23,8 @@ import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import org.badvision.outlaweditor.data.xml.Rows.Row;
import org.badvision.outlaweditor.data.xml.UserType;
import org.controlsfx.control.spreadsheet.SpreadsheetColumn;
import org.controlsfx.control.spreadsheet.SpreadsheetView;
/**
*
@ -35,10 +37,10 @@ public abstract class SheetEditorController implements Initializable {
protected URL location;
@FXML
protected TableColumn<UserType, String> addColumn;
protected SpreadsheetColumn addColumn;
@FXML
protected TableView<Row> table;
protected SpreadsheetView table;
@FXML
protected TextField sheetNameField;

View File

@ -17,25 +17,20 @@ package org.badvision.outlaweditor.ui.impl;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.stage.FileChooser;
import javafx.util.converter.DefaultStringConverter;
import javax.xml.bind.JAXBException;
import org.badvision.outlaweditor.SheetEditor;
import org.badvision.outlaweditor.TransferHelper;
@ -49,12 +44,16 @@ import org.badvision.outlaweditor.data.xml.UserType;
import org.badvision.outlaweditor.ui.ApplicationUIController;
import org.badvision.outlaweditor.ui.SheetEditorController;
import org.badvision.outlaweditor.ui.UIAction;
import org.controlsfx.control.spreadsheet.GridBase;
import org.controlsfx.control.spreadsheet.SpreadsheetCell;
import org.controlsfx.control.spreadsheet.SpreadsheetCellBase;
public class SheetEditorControllerImpl extends SheetEditorController {
private SheetEditor editor;
private ObservableList<Row> tableData;
private final ListChangeListener columnChangeListener = c -> syncData();
private ObservableList<ObservableList<SpreadsheetCell>> tableData;
private int lastEditRow = 0;
private int lastEditCol = 0;
/**
* Initializes the controller class.
@ -62,9 +61,9 @@ public class SheetEditorControllerImpl extends SheetEditorController {
@Override
public void initialize(URL url, ResourceBundle rb) {
super.initialize();
tableData = FXCollections.observableArrayList();
table.setItems(tableData);
tableData = table.getGrid().getRows();
table.setEditable(true);
/*
table.setRowFactory(tableView -> {
final TableRow<Row> row = new TableRow<>();
@ -75,11 +74,12 @@ public class SheetEditorControllerImpl extends SheetEditorController {
);
row.contextMenuProperty().bind(
Bindings.when(row.emptyProperty())
.then((ContextMenu) null)
.otherwise(contextMenu)
.then((ContextMenu) null)
.otherwise(contextMenu)
);
return row;
});
*/
}
@Override
@ -132,8 +132,8 @@ public class SheetEditorControllerImpl extends SheetEditorController {
if (editor.getSheet().getColumns() == null) {
editor.getSheet().setColumns(new Columns());
}
editor.getSheet().getColumns().getColumn().add(col);
insertViewColumn(col);
rebuildGridUI();
}
}
@ -144,19 +144,14 @@ public class SheetEditorControllerImpl extends SheetEditorController {
//--------
private void buildTableFromSheet() {
table.getColumns().removeListener(columnChangeListener);
if (editor.getSheet().getColumns() != null) {
editor.getSheet().getColumns().getColumn().stream().forEach(this::insertViewColumn);
}
if (editor.getSheet().getRows() != null) {
tableData.setAll(editor.getSheet().getRows().getRow());
rebuildGridUI();
}
sheetNameField.textProperty().set(editor.getSheet().getName());
sheetNameField.textProperty().addListener((value, oldValue, newValue) -> {
editor.getSheet().setName(newValue);
ApplicationUIController.getController().updateSelectors();
});
table.getColumns().addListener(columnChangeListener);
}
private void insertViewColumn(UserType col) {
@ -164,54 +159,18 @@ public class SheetEditorControllerImpl extends SheetEditorController {
}
private void insertViewColumn(UserType col, int pos) {
if (pos < 0) {
pos = table.getColumns().size();
table.getGrid().getColumnHeaders().clear();
if (pos < 0 || pos >= editor.getSheet().getColumns().getColumn().size()) {
editor.getSheet().getColumns().getColumn().add(col);
} else {
editor.getSheet().getColumns().getColumn().add(pos, col);
}
TableColumn<Row, String> tableCol = new TableColumn<>(col.getName());
tableCol.setCellValueFactory((features) -> {
String val = getValue(features.getValue().getOtherAttributes(), col.getName());
if (val == null) {
val = "";
}
return new SimpleObjectProperty(val);
});
tableCol.setCellFactory((TableColumn<Row, String> param) -> {
TextFieldTableCell<Row, String> myCell = new TextFieldTableCell<Row, String>(new DefaultStringConverter()) {
@Override
/**
* Patch behavior so that any change is immediately persisted,
* enter is not required.
*/
public void startEdit() {
super.startEdit();
TextField textField = (TextField) getGraphic();
textField.textProperty().addListener((p, o, n) -> {
setItem(n);
int index = this.getTableRow().getIndex();
Row row = tableData.get(index);
setValue(row.getOtherAttributes(), col.getName(), n);
});
}
};
return myCell;
});
tableCol.setOnEditCommit((event) -> {
table.requestFocus();
table.getSelectionModel().clearSelection();
});
tableCol.setEditable(true);
tableCol.setContextMenu(new ContextMenu(
createMenuItem("Rename Column", () -> renameColumn(col)),
createMenuItem("Delete Column", () -> deleteColumnWithConfirmation(col))
));
table.getColumns().add(pos, tableCol);
rebuildColumnHeaders();
}
private void insertViewRow(Row row) {
tableData.add(row);
syncData();
editor.getSheet().getRows().getRow().add(new Row());
rebuildGridUI();
}
private MenuItem createMenuItem(String text, Runnable action) {
@ -232,60 +191,81 @@ public class SheetEditorControllerImpl extends SheetEditorController {
UserType newCol = new UserType();
newCol.setName(newColName);
editor.getSheet().getColumns().getColumn().add(newCol);
tableData.forEach(row -> setValue(row.getOtherAttributes(), newColName, getValue(row.getOtherAttributes(), col.getName())));
// tableData.forEach(row -> setValue(row.getOtherAttributes(), newColName, getValue(row.getOtherAttributes(), col.getName())));
int oldPos = deleteColumn(col);
insertViewColumn(newCol, oldPos);
}
}
private int deleteColumn(UserType col) {
editor.getSheet().getColumns().getColumn().remove(col);
tableData.stream()
.map(Row::getOtherAttributes)
.forEach(
m -> m.keySet().removeIf(n -> n.getLocalPart().equals(col.getName()))
);
int colNumber = findColumn(col);
if (colNumber >= 0) {
table.getColumns().remove(colNumber);
}
return colNumber;
// editor.getSheet().getColumns().getColumn().remove(col);
// tableData.stream()
// .map(Row::getOtherAttributes)
// .forEach(
// m -> m.keySet().removeIf(n -> n.getLocalPart().equals(col.getName()))
// );
// int colNumber = findColumn(col);
// if (colNumber >= 0) {
// table.getColumns().remove(colNumber);
// }
// return colNumber;
return 0;
}
private void deleteRowWithConfirmation(Row row) {
UIAction.confirm("Delete row, are you sure?", ()->{
tableData.remove(row);
syncData();
}, ()->{});
UIAction.confirm("Delete row, are you sure?", () -> {
editor.getSheet().getRows().getRow().remove(row);
rebuildGridUI();
}, () -> {
});
}
private void cloneRow(Row row) {
try {
Row newRow = TransferHelper.cloneObject(row, Row.class, "row");
tableData.add(tableData.lastIndexOf(row), newRow);
syncData();
editor.getSheet().getRows().getRow().add(newRow);
rebuildGridUI();
} catch (JAXBException ex) {
Logger.getLogger(SheetEditorControllerImpl.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void syncData() {
if (editor.getSheet().getRows() == null) {
editor.getSheet().setRows(new Rows());
private void rebuildGridUI() {
int numCols = editor.getSheet().getColumns().getColumn().size();
int numRows = editor.getSheet().getRows().getRow().size();
table.setGrid(new GridBase(numRows, numCols));
rebuildColumnHeaders();
tableData = FXCollections.observableList(new ArrayList(numRows));
int rowNum = 0;
for (Row row : editor.getSheet().getRows().getRow()) {
int colNum = 0;
ObservableList<SpreadsheetCell> rowUi = FXCollections.observableList(new ArrayList<>(numCols));
tableData.add(rowUi);
for (UserType col : editor.getSheet().getColumns().getColumn()) {
String value = getValue(row.getOtherAttributes(), col.getName());
SpreadsheetCellBase cell = new SpreadsheetCellBase(rowNum, colNum, 1, 1);
cell.setItem(value);
cell.itemProperty().addListener((ObservableValue<? extends Object> val, Object oldVal, Object newVal) -> {
setValue(row.getOtherAttributes(), col.getName(), String.valueOf(newVal));
});
rowUi.add(cell);
colNum++;
}
rowNum++;
}
editor.getSheet().getRows().getRow().clear();
editor.getSheet().getRows().getRow().addAll(tableData);
editor.getSheet().getColumns().getColumn().sort((t1, t2) -> {
return Integer.compare(findColumn(t1), findColumn(t2));
});
table.getGrid().setRows(tableData);
}
private int findColumn(UserType col) {
for (int i = 0; i < table.getColumns().size(); i++) {
if (table.getColumns().get(i).getText().equals(col.getName())) {
return i;
}
}
return -1;
private void rebuildColumnHeaders() {
int numCols = editor.getSheet().getColumns().getColumn().size();
table.getGrid().getColumnHeaders().addAll(
editor.getSheet().getColumns().getColumn().stream()
.map(UserType::getName)
.collect(Collectors.toCollection(
() -> FXCollections.observableList(new ArrayList<String>(numCols))
))
);
}
}

View File

@ -12,6 +12,7 @@
<?import javafx.scene.control.ToolBar?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.VBox?>
<?import org.controlsfx.control.spreadsheet.SpreadsheetView?>
<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" styleClass="sheetEditor" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.badvision.outlaweditor.ui.impl.SheetEditorControllerImpl">
<stylesheets>
@ -48,7 +49,7 @@
<Button mnemonicParsing="false" onAction="#addRowAction" text="Add Row" />
</items>
</ToolBar>
<TableView fx:id="table" editable="true" prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS" />
<SpreadsheetView fx:id="table" editable="true" prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS" />
</children>
</VBox>
</children>