parent
183c670bf3
commit
b71b0cce49
@ -0,0 +1,361 @@
|
|||||||
|
package com.olexyn.ensync;
|
||||||
|
|
||||||
|
import javafx.beans.value.ChangeListener;
|
||||||
|
import javafx.beans.value.ObservableValue;
|
||||||
|
import javafx.event.ActionEvent;
|
||||||
|
import javafx.event.Event;
|
||||||
|
import javafx.event.EventHandler;
|
||||||
|
import javafx.scene.control.*;
|
||||||
|
import javafx.scene.control.cell.TextFieldTableCell;
|
||||||
|
import javafx.scene.input.KeyCode;
|
||||||
|
import javafx.scene.input.KeyEvent;
|
||||||
|
import javafx.util.Callback;
|
||||||
|
import javafx.util.StringConverter;
|
||||||
|
import javafx.util.converter.DefaultStringConverter;
|
||||||
|
|
||||||
|
public class EditCell<S, T> extends TextFieldTableCell<S, T> {
|
||||||
|
|
||||||
|
private TextField textField;
|
||||||
|
|
||||||
|
private boolean escapePressed = false;
|
||||||
|
|
||||||
|
private TablePosition<S,
|
||||||
|
|
||||||
|
?> tablePos = null;
|
||||||
|
|
||||||
|
public EditCell(final StringConverter<T> converter) {
|
||||||
|
|
||||||
|
super(converter);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <S> Callback<TableColumn<S, String>, TableCell<S, String>> forTableColumn() {
|
||||||
|
|
||||||
|
return forTableColumn(new DefaultStringConverter());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <S,
|
||||||
|
|
||||||
|
T> Callback<TableColumn<S,
|
||||||
|
|
||||||
|
T>,
|
||||||
|
|
||||||
|
TableCell<S,
|
||||||
|
|
||||||
|
T>> forTableColumn(
|
||||||
|
|
||||||
|
final StringConverter<T> converter) {
|
||||||
|
|
||||||
|
return list -> new EditCell<S, T>(converter);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
|
||||||
|
public void startEdit() {
|
||||||
|
|
||||||
|
if (!isEditable() || !getTableView().isEditable() ||
|
||||||
|
|
||||||
|
!getTableColumn().isEditable()) {
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
super.startEdit();
|
||||||
|
|
||||||
|
if (isEditing()) {
|
||||||
|
|
||||||
|
if (textField == null) {
|
||||||
|
|
||||||
|
textField = getTextField();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
escapePressed = false;
|
||||||
|
|
||||||
|
startEdit(textField);
|
||||||
|
|
||||||
|
final TableView<S> table = getTableView();
|
||||||
|
|
||||||
|
tablePos = table.getEditingCell();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
|
||||||
|
public void commitEdit(T newValue) {
|
||||||
|
|
||||||
|
if (!isEditing())
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
final TableView<S> table = getTableView();
|
||||||
|
|
||||||
|
if (table != null) {
|
||||||
|
|
||||||
|
// Inform the TableView of the edit being ready to be committed.
|
||||||
|
|
||||||
|
TableColumn.CellEditEvent editEvent = new TableColumn.CellEditEvent(table, tablePos,
|
||||||
|
|
||||||
|
TableColumn.editCommitEvent(), newValue);
|
||||||
|
|
||||||
|
Event.fireEvent(getTableColumn(), editEvent);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// we need to setEditing(false):
|
||||||
|
|
||||||
|
super.cancelEdit(); // this fires an invalid EditCancelEvent.
|
||||||
|
|
||||||
|
// update the item within this cell, so that it represents the new value
|
||||||
|
|
||||||
|
updateItem(newValue, false);
|
||||||
|
|
||||||
|
if (table != null) {
|
||||||
|
|
||||||
|
// reset the editing cell on the TableView
|
||||||
|
|
||||||
|
table.edit(-1, null);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
|
||||||
|
public void cancelEdit() {
|
||||||
|
|
||||||
|
if (escapePressed) {
|
||||||
|
|
||||||
|
// this is a cancel event after escape key
|
||||||
|
|
||||||
|
super.cancelEdit();
|
||||||
|
|
||||||
|
setText(getItemText()); // restore the original text in the view
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// this is not a cancel event after escape key
|
||||||
|
|
||||||
|
// we interpret it as commit.
|
||||||
|
|
||||||
|
String newText = textField.getText();
|
||||||
|
|
||||||
|
// commit the new text to the model
|
||||||
|
|
||||||
|
this.commitEdit(getConverter().fromString(newText));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
setGraphic(null); // stop editing with TextField
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
|
||||||
|
public void updateItem(T item, boolean empty) {
|
||||||
|
|
||||||
|
super.updateItem(item, empty);
|
||||||
|
|
||||||
|
updateItem();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private TextField getTextField() {
|
||||||
|
|
||||||
|
final TextField textField = new TextField(getItemText());
|
||||||
|
|
||||||
|
textField.setOnAction(new EventHandler<ActionEvent>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(ActionEvent event) {
|
||||||
|
|
||||||
|
System.out.println("hi");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// Use onAction here rather than onKeyReleased (with check for Enter),
|
||||||
|
|
||||||
|
textField.setOnAction(event -> {
|
||||||
|
|
||||||
|
if (getConverter() == null) {
|
||||||
|
|
||||||
|
throw new IllegalStateException("StringConverter is null.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
this.commitEdit(getConverter().fromString(textField.getText()));
|
||||||
|
|
||||||
|
event.consume();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
textField.focusedProperty().addListener(new ChangeListener<Boolean>() {
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
|
||||||
|
|
||||||
|
if (!newValue) {
|
||||||
|
|
||||||
|
commitEdit(getConverter().fromString(textField.getText()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
textField.setOnKeyPressed(t -> {
|
||||||
|
|
||||||
|
if (t.getCode() == KeyCode.ESCAPE)
|
||||||
|
|
||||||
|
escapePressed = true;
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
escapePressed = false;
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
textField.setOnKeyReleased(t -> {
|
||||||
|
|
||||||
|
if (t.getCode() == KeyCode.ESCAPE) {
|
||||||
|
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
|
||||||
|
"did not expect esc key releases here.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
textField.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
|
||||||
|
|
||||||
|
if (event.getCode() == KeyCode.ESCAPE) {
|
||||||
|
|
||||||
|
textField.setText(getConverter().toString(getItem()));
|
||||||
|
|
||||||
|
cancelEdit();
|
||||||
|
|
||||||
|
event.consume();
|
||||||
|
|
||||||
|
} else if (event.getCode() == KeyCode.RIGHT ||
|
||||||
|
|
||||||
|
event.getCode() == KeyCode.TAB) {
|
||||||
|
|
||||||
|
getTableView().getSelectionModel().selectNext();
|
||||||
|
|
||||||
|
event.consume();
|
||||||
|
|
||||||
|
} else if (event.getCode() == KeyCode.LEFT) {
|
||||||
|
|
||||||
|
getTableView().getSelectionModel().selectPrevious();
|
||||||
|
|
||||||
|
event.consume();
|
||||||
|
|
||||||
|
} else if (event.getCode() == KeyCode.UP) {
|
||||||
|
|
||||||
|
getTableView().getSelectionModel().selectAboveCell();
|
||||||
|
|
||||||
|
event.consume();
|
||||||
|
|
||||||
|
} else if (event.getCode() == KeyCode.DOWN) {
|
||||||
|
|
||||||
|
getTableView().getSelectionModel().selectBelowCell();
|
||||||
|
|
||||||
|
event.consume();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
return textField;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getItemText() {
|
||||||
|
|
||||||
|
return getConverter() == null ?
|
||||||
|
|
||||||
|
getItem() == null ? "" : getItem().toString() :
|
||||||
|
|
||||||
|
getConverter().toString(getItem());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateItem() {
|
||||||
|
|
||||||
|
if (isEmpty()) {
|
||||||
|
|
||||||
|
setText(null);
|
||||||
|
|
||||||
|
setGraphic(null);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (isEditing()) {
|
||||||
|
|
||||||
|
if (textField != null) {
|
||||||
|
|
||||||
|
textField.setText(getItemText());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
setText(null);
|
||||||
|
|
||||||
|
setGraphic(textField);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
setText(getItemText());
|
||||||
|
|
||||||
|
setGraphic(null);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startEdit(final TextField textField) {
|
||||||
|
|
||||||
|
if (textField != null) {
|
||||||
|
|
||||||
|
textField.setText(getItemText());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
setText(null);
|
||||||
|
|
||||||
|
setGraphic(textField);
|
||||||
|
|
||||||
|
textField.selectAll();
|
||||||
|
|
||||||
|
// requesting focus so that key input can immediately go into the
|
||||||
|
|
||||||
|
// TextField
|
||||||
|
|
||||||
|
textField.requestFocus();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package com.olexyn.ensync;
|
||||||
|
|
||||||
|
import javafx.util.converter.DateStringConverter;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class MyDateStringConverter extends DateStringConverter {
|
||||||
|
|
||||||
|
public MyDateStringConverter(final String pattern) {
|
||||||
|
|
||||||
|
super(pattern);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
|
||||||
|
public Date fromString(String value) {
|
||||||
|
|
||||||
|
// catches the RuntimeException thrown by
|
||||||
|
|
||||||
|
// DateStringConverter.fromString()
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
return super.fromString(value);
|
||||||
|
|
||||||
|
} catch (RuntimeException ex) {
|
||||||
|
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package com.olexyn.ensync;
|
||||||
|
|
||||||
|
import javafx.util.converter.DoubleStringConverter;
|
||||||
|
|
||||||
|
public class MyDoubleStringConverter extends DoubleStringConverter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
|
||||||
|
public Double fromString(final String value) {
|
||||||
|
|
||||||
|
return value.isEmpty() || !isNumber(value) ? null :
|
||||||
|
|
||||||
|
super.fromString(value);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNumber(String value) {
|
||||||
|
|
||||||
|
int size = value.length();
|
||||||
|
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
|
||||||
|
if (!Character.isDigit(value.charAt(i))) {
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return size > 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package com.olexyn.ensync;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class Person {
|
||||||
|
|
||||||
|
private String firstName;
|
||||||
|
private String surname;
|
||||||
|
private Date date;
|
||||||
|
private String occupation;
|
||||||
|
private double salary;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Person(String firstName, String surname, Date date, String occupation, double salary){
|
||||||
|
this.firstName = firstName;
|
||||||
|
this.surname = surname;
|
||||||
|
this.date = date;
|
||||||
|
this.occupation = occupation;
|
||||||
|
this.salary = salary;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getSalary(){
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getDateOfBirth(){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFirstName(){
|
||||||
|
return "firstName";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSurname(){
|
||||||
|
return "surname";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOccupation(){
|
||||||
|
return "occupation";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,118 @@
|
|||||||
|
package com.olexyn.ensync;
|
||||||
|
|
||||||
|
import javafx.beans.property.SimpleDoubleProperty;
|
||||||
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
|
import javafx.scene.control.TableColumn;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class PersonTableData {
|
||||||
|
|
||||||
|
private SimpleStringProperty firstName;
|
||||||
|
|
||||||
|
private SimpleStringProperty surname;
|
||||||
|
|
||||||
|
private SimpleObjectProperty<Date> dateOfBirth;
|
||||||
|
|
||||||
|
private SimpleStringProperty occupation;
|
||||||
|
|
||||||
|
private SimpleDoubleProperty salary;
|
||||||
|
|
||||||
|
// added to create the model from the Person object, which might be data retrieved from a database
|
||||||
|
|
||||||
|
public PersonTableData(Person person) {
|
||||||
|
|
||||||
|
this.firstName = new SimpleStringProperty(person.getFirstName());
|
||||||
|
|
||||||
|
this.surname = new SimpleStringProperty(person.getSurname());
|
||||||
|
|
||||||
|
this.dateOfBirth = new SimpleObjectProperty < Date > (person.getDateOfBirth());
|
||||||
|
|
||||||
|
this.occupation = new SimpleStringProperty(person.getOccupation());
|
||||||
|
|
||||||
|
this.salary = new SimpleDoubleProperty(person.getSalary());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersonTableData(final String firstName, final String surname,
|
||||||
|
|
||||||
|
final Date dateOfBirth, final String occupation,
|
||||||
|
|
||||||
|
final double salary) {
|
||||||
|
|
||||||
|
this.firstName = new SimpleStringProperty(firstName);
|
||||||
|
|
||||||
|
this.surname = new SimpleStringProperty(surname);
|
||||||
|
|
||||||
|
this.dateOfBirth = new SimpleObjectProperty < Date > (dateOfBirth);
|
||||||
|
|
||||||
|
this.occupation = new SimpleStringProperty(occupation);
|
||||||
|
|
||||||
|
this.salary = new SimpleDoubleProperty(salary);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFirstName() {
|
||||||
|
|
||||||
|
return firstName.get();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFirstName(final String firstName) {
|
||||||
|
|
||||||
|
this.firstName.set(firstName);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSurname() {
|
||||||
|
|
||||||
|
return surname.get();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSurname(final String surname) {
|
||||||
|
|
||||||
|
this.surname.set(surname);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getDateOfBirth() {
|
||||||
|
|
||||||
|
return dateOfBirth.get();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDateOfBirth(final Date dateOfBirth) {
|
||||||
|
|
||||||
|
this.dateOfBirth.set(dateOfBirth);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOccupation() {
|
||||||
|
|
||||||
|
return occupation.get();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOccupation(final String occupation) {
|
||||||
|
|
||||||
|
this.occupation.set(occupation);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getSalary() {
|
||||||
|
|
||||||
|
return salary.get();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSalary(final double salary) {
|
||||||
|
|
||||||
|
this.salary.set(salary);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,335 @@
|
|||||||
|
package com.olexyn.ensync;
|
||||||
|
|
||||||
|
import javafx.collections.FXCollections;
|
||||||
|
import javafx.collections.ObservableList;
|
||||||
|
import javafx.event.ActionEvent;
|
||||||
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.fxml.Initializable;
|
||||||
|
import javafx.scene.control.*;
|
||||||
|
import javafx.scene.input.KeyCode;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class TableAppController implements Initializable {
|
||||||
|
|
||||||
|
private static final String DATE_PATTERN = "dd/MM/yyyy";
|
||||||
|
private static final SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat(DATE_PATTERN);
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private TableView<PersonTableData> table;
|
||||||
|
@FXML
|
||||||
|
private TextField firstNameTextField;
|
||||||
|
@FXML
|
||||||
|
private TextField surnameTextField;
|
||||||
|
@FXML
|
||||||
|
private TextField dateOfBirthTextField;
|
||||||
|
@FXML
|
||||||
|
private TextField occupationTextField;
|
||||||
|
@FXML
|
||||||
|
private TextField salaryTextField;
|
||||||
|
@FXML
|
||||||
|
private Button submitButton;
|
||||||
|
private ObservableList<PersonTableData> data = FXCollections
|
||||||
|
|
||||||
|
.observableArrayList();
|
||||||
|
@FXML
|
||||||
|
|
||||||
|
private TableColumn<PersonTableData, Date> dateOfBirthColumn;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
|
||||||
|
private TableColumn<PersonTableData, Double> salaryColumn;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(final URL url, final ResourceBundle rb) {
|
||||||
|
|
||||||
|
DATE_FORMATTER.setLenient(false);
|
||||||
|
|
||||||
|
table.setItems(data);
|
||||||
|
|
||||||
|
populate(retrieveData());
|
||||||
|
|
||||||
|
setupDateOfBirthColumn();
|
||||||
|
|
||||||
|
setupSalaryColumn();
|
||||||
|
|
||||||
|
setTableEditable();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Person> retrieveData() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
return Arrays.asList(new Person("Dan", "Newton", DATE_FORMATTER.parse("06/01/1994"), "Java Developer", 22000), new Person("George", "Newton", DATE_FORMATTER.parse("24/01/1995"), "Bro", 15021), new Person("Laura", "So", DATE_FORMATTER.parse("24/04/1995"), "Student", 0), new Person("Jamie", "Harwood", DATE_FORMATTER.parse("15/12/9999"), "Java Developer", 30000), new Person("Michael", "Collins", DATE_FORMATTER.parse("01/01/0001"), "Developer", 299), new Person("Stuart", "Kerrigan", DATE_FORMATTER.parse("06/10/1894"), "Teaching Fellow", 100000));
|
||||||
|
} catch (ParseException e) {
|
||||||
|
|
||||||
|
e.printStackTrace();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ArrayList<Person>();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void populate(final List<Person> people) {
|
||||||
|
|
||||||
|
people.forEach(p -> data.add(new PersonTableData(p)));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupDateOfBirthColumn() {
|
||||||
|
|
||||||
|
// formats the display value to display dates in the form of dd/MM/yyyy
|
||||||
|
|
||||||
|
dateOfBirthColumn.setCellFactory(EditCell.<PersonTableData, Date>forTableColumn(new MyDateStringConverter(DATE_PATTERN)));
|
||||||
|
|
||||||
|
// updates the dateOfBirth field on the com.olexyn.ensync.PersonTableData object to the
|
||||||
|
|
||||||
|
// committed value
|
||||||
|
|
||||||
|
dateOfBirthColumn.setOnEditCommit(event -> {
|
||||||
|
|
||||||
|
final Date value = event.getNewValue() != null ? event.getNewValue() :
|
||||||
|
|
||||||
|
event.getOldValue();
|
||||||
|
|
||||||
|
((PersonTableData) event.getTableView().getItems()
|
||||||
|
|
||||||
|
.get(event.getTablePosition().getRow()))
|
||||||
|
|
||||||
|
.setDateOfBirth(value);
|
||||||
|
|
||||||
|
table.refresh();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupSalaryColumn() {
|
||||||
|
|
||||||
|
// sets the cell factory to use EditCell which will handle key presses
|
||||||
|
|
||||||
|
// and firing commit events
|
||||||
|
|
||||||
|
salaryColumn.setCellFactory(
|
||||||
|
|
||||||
|
EditCell.<PersonTableData, Double>forTableColumn(
|
||||||
|
|
||||||
|
new MyDoubleStringConverter()));
|
||||||
|
|
||||||
|
// updates the salary field on the com.olexyn.ensync.PersonTableData object to the
|
||||||
|
|
||||||
|
// committed value
|
||||||
|
|
||||||
|
salaryColumn.setOnEditCommit(event -> {
|
||||||
|
|
||||||
|
final Double value = event.getNewValue() != null ?
|
||||||
|
|
||||||
|
event.getNewValue() : event.getOldValue();
|
||||||
|
|
||||||
|
((PersonTableData) event.getTableView().getItems()
|
||||||
|
|
||||||
|
.get(event.getTablePosition().getRow())).setSalary(value);
|
||||||
|
|
||||||
|
table.refresh();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setTableEditable() {
|
||||||
|
|
||||||
|
table.setEditable(true);
|
||||||
|
|
||||||
|
// allows the individual cells to be selected
|
||||||
|
|
||||||
|
table.getSelectionModel().cellSelectionEnabledProperty().set(true);
|
||||||
|
|
||||||
|
// when character or numbers pressed it will start edit in editable
|
||||||
|
|
||||||
|
// fields
|
||||||
|
|
||||||
|
table.setOnKeyPressed(event -> {
|
||||||
|
|
||||||
|
if (event.getCode().isLetterKey() || event.getCode().isDigitKey()) {
|
||||||
|
|
||||||
|
editFocusedCell();
|
||||||
|
|
||||||
|
} else if (event.getCode() == KeyCode.RIGHT ||
|
||||||
|
|
||||||
|
event.getCode() == KeyCode.TAB) {
|
||||||
|
|
||||||
|
table.getSelectionModel().selectNext();
|
||||||
|
|
||||||
|
event.consume();
|
||||||
|
|
||||||
|
} else if (event.getCode() == KeyCode.LEFT) {
|
||||||
|
|
||||||
|
// work around due to
|
||||||
|
|
||||||
|
// TableView.getSelectionModel().selectPrevious() due to a bug
|
||||||
|
|
||||||
|
// stopping it from working on
|
||||||
|
|
||||||
|
// the first column in the last row of the table
|
||||||
|
|
||||||
|
selectPrevious();
|
||||||
|
|
||||||
|
event.consume();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
|
||||||
|
private void editFocusedCell() {
|
||||||
|
|
||||||
|
final TablePosition<PersonTableData, ?> focusedCell = table
|
||||||
|
|
||||||
|
.focusModelProperty().get().focusedCellProperty().get();
|
||||||
|
|
||||||
|
table.edit(focusedCell.getRow(), focusedCell.getTableColumn());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
|
||||||
|
private void selectPrevious() {
|
||||||
|
|
||||||
|
if (table.getSelectionModel().isCellSelectionEnabled()) {
|
||||||
|
|
||||||
|
// in cell selection mode, we have to wrap around, going from
|
||||||
|
|
||||||
|
// right-to-left, and then wrapping to the end of the previous line
|
||||||
|
|
||||||
|
TablePosition<PersonTableData, ?> pos = table.getFocusModel()
|
||||||
|
|
||||||
|
.getFocusedCell();
|
||||||
|
|
||||||
|
if (pos.getColumn() - 1 >= 0) {
|
||||||
|
|
||||||
|
// go to previous row
|
||||||
|
|
||||||
|
table.getSelectionModel().select(pos.getRow(),
|
||||||
|
|
||||||
|
getTableColumn(pos.getTableColumn(), -1));
|
||||||
|
|
||||||
|
} else if (pos.getRow() < table.getItems().size()) {
|
||||||
|
|
||||||
|
// wrap to end of previous row
|
||||||
|
|
||||||
|
table.getSelectionModel().select(pos.getRow() - 1,
|
||||||
|
|
||||||
|
table.getVisibleLeafColumn(
|
||||||
|
|
||||||
|
table.getVisibleLeafColumns().size() - 1));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
int focusIndex = table.getFocusModel().getFocusedIndex();
|
||||||
|
|
||||||
|
if (focusIndex == -1) {
|
||||||
|
|
||||||
|
table.getSelectionModel().select(table.getItems().size() - 1);
|
||||||
|
|
||||||
|
} else if (focusIndex > 0) {
|
||||||
|
|
||||||
|
table.getSelectionModel().select(focusIndex - 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private TableColumn<PersonTableData, ?> getTableColumn(
|
||||||
|
|
||||||
|
final TableColumn<PersonTableData, ?> column, int offset) {
|
||||||
|
|
||||||
|
int columnIndex = table.getVisibleLeafIndex(column);
|
||||||
|
|
||||||
|
int newColumnIndex = columnIndex + offset;
|
||||||
|
|
||||||
|
return table.getVisibleLeafColumn(newColumnIndex);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
|
||||||
|
private void submit(final ActionEvent event) {
|
||||||
|
|
||||||
|
if (allFieldsValid()) {
|
||||||
|
|
||||||
|
final String firstName = firstNameTextField.getText();
|
||||||
|
|
||||||
|
final String surname = surnameTextField.getText();
|
||||||
|
|
||||||
|
Date dateOfBirth = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
dateOfBirth = DATE_FORMATTER
|
||||||
|
|
||||||
|
.parse(dateOfBirthTextField.getText());
|
||||||
|
|
||||||
|
} catch (final ParseException e) {}
|
||||||
|
|
||||||
|
final String occupation = occupationTextField.getText();
|
||||||
|
|
||||||
|
final double salary = Double.parseDouble(salaryTextField.getText());
|
||||||
|
|
||||||
|
data.add(new PersonTableData(firstName, surname, dateOfBirth,
|
||||||
|
|
||||||
|
occupation, salary));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean allFieldsValid() {
|
||||||
|
|
||||||
|
return !firstNameTextField.getText().isEmpty() &&
|
||||||
|
|
||||||
|
!surnameTextField.getText().isEmpty() &&
|
||||||
|
|
||||||
|
dateOfBirthFieldValid() &&
|
||||||
|
|
||||||
|
!occupationTextField.getText().isEmpty() &&
|
||||||
|
|
||||||
|
!salaryTextField.getText().isEmpty();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean dateOfBirthFieldValid() {
|
||||||
|
|
||||||
|
if (!dateOfBirthTextField.getText().isEmpty()) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
DATE_FORMATTER.parse(dateOfBirthTextField.getText());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} catch (ParseException e) {
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
package com.olexyn.ensync;
|
||||||
|
|
||||||
|
public class TableLogic {}
|
Loading…
Reference in new issue