Copy code from lankydan.

Credit: https://github.com/lankydan .
pull/1/head
Ivan Olexyn 5 years ago
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…
Cancel
Save