package tornadofx.control; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.scene.control.DatePicker; import javafx.scene.control.TableCell; import javafx.scene.control.TableColumn; import javafx.scene.input.KeyCode; import javafx.util.Callback; import javafx.util.StringConverter; import java.time.LocalDate; public class DatePickerTableCell<S> extends TableCell<S, LocalDate> { private ObjectProperty<StringConverter<LocalDate>> converter = new SimpleObjectProperty<>(this, "converter"); private DatePicker datePicker; public DatePickerTableCell(StringConverter<LocalDate> converter) { setConverter(converter); this.getStyleClass().add("datepicker-table-cell"); } public static <S> Callback<TableColumn<S, LocalDate>, TableCell<S, LocalDate>> forTableColumn() { return column -> new DatePickerTableCell<>(new DefaultLocalDateConverter()); } public static <S> Callback<TableColumn<S, LocalDate>, TableCell<S, LocalDate>> forTableColumn(StringConverter<LocalDate> converter) { return column -> new DatePickerTableCell<>(converter); } public void startEdit() { if (!isEditable() || !getTableView().isEditable() || !getTableColumn().isEditable()) return; super.startEdit(); if (isEditing()) { if (datePicker == null) createDatePicker(); setText(null); setGraphic(datePicker); datePicker.requestFocus(); } } public void cancelEdit() { super.cancelEdit(); setText(getItemText()); setGraphic(null); } private String getItemText() { return getConverter().toString(getItem()); } private void createDatePicker() { datePicker = new DatePicker(getItem()); datePicker.converterProperty().bind(converterProperty()); datePicker.setOnAction(event -> { commitEdit(datePicker.getValue()); event.consume(); }); datePicker.setOnKeyReleased(t -> { if (t.getCode() == KeyCode.ESCAPE) { cancelEdit(); t.consume(); } }); } protected void updateItem(LocalDate item, boolean empty) { super.updateItem(item, empty); if (isEmpty()) { setText(null); setGraphic(null); } else { if (isEditing()) { datePicker.setValue(getItem()); setText(null); setGraphic(datePicker); } else { setText(getItemText()); setGraphic(null); } } } public StringConverter<LocalDate> getConverter() { return converter.get(); } public ObjectProperty<StringConverter<LocalDate>> converterProperty() { return converter; } public void setConverter(StringConverter<LocalDate> converter) { this.converter.set(converter); } public DatePicker getDatePicker() { return datePicker; } public void setDatePicker(DatePicker datePicker) { this.datePicker = datePicker; } public static class DefaultLocalDateConverter extends StringConverter<LocalDate> { public String toString(LocalDate date) { return date != null ? date.toString() : ""; } public LocalDate fromString(String string) { return string == null || string.isEmpty() ? null : LocalDate.parse(string); } } }