/* Stolen code from Github : https://gist.github.com/james-d/be5bbd6255a4640a5357#file-editcell-java-L109 */ package ovh.alexisdelhaie.endpoint.impl; import javafx.event.Event; import javafx.scene.control.ContentDisplay; import javafx.scene.control.TableCell; import javafx.scene.control.TableColumn; import javafx.scene.control.TableColumn.CellEditEvent; import javafx.scene.control.TablePosition; import javafx.scene.control.TableView; import javafx.scene.control.TextField; import javafx.scene.input.KeyCode; import javafx.scene.input.KeyEvent; import javafx.util.StringConverter; public class EditCell extends TableCell { // Text field for editing // TODO: allow this to be a plugable control. private final TextField textField = new TextField(); // Converter for converting the text in the text field to the user type, and vice-versa: private final StringConverter converter ; public EditCell(StringConverter converter) { this.converter = converter ; itemProperty().addListener((obx, oldItem, newItem) -> { if (newItem == null) { setText(null); } else { setText(converter.toString(newItem)); } }); setGraphic(textField); setContentDisplay(ContentDisplay.TEXT_ONLY); textField.setOnAction(evt -> { commitEdit(this.converter.fromString(textField.getText())); }); textField.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> { if (! isNowFocused) { commitEdit(this.converter.fromString(textField.getText())); } }); textField.addEventFilter(KeyEvent.KEY_PRESSED, event -> { if (event.getCode() == KeyCode.ESCAPE) { textField.setText(converter.toString(getItem())); cancelEdit(); event.consume(); } else if (event.getCode() == KeyCode.RIGHT) { getTableView().getSelectionModel().selectRightCell(); event.consume(); } else if (event.getCode() == KeyCode.LEFT) { getTableView().getSelectionModel().selectLeftCell(); event.consume(); } else if (event.getCode() == KeyCode.UP) { getTableView().getSelectionModel().selectAboveCell(); event.consume(); } else if (event.getCode() == KeyCode.DOWN) { getTableView().getSelectionModel().selectBelowCell(); event.consume(); } }); } /** * Convenience converter that does nothing (converts Strings to themselves and vice-versa...). */ public static final StringConverter IDENTITY_CONVERTER = new StringConverter() { @Override public String toString(String object) { return object; } @Override public String fromString(String string) { return string; } }; /** * Convenience method for creating an EditCell for a String value. * @return */ public static EditCell createStringEditCell() { return new EditCell(IDENTITY_CONVERTER); } // set the text of the text field and display the graphic @Override public void startEdit() { super.startEdit(); textField.setText(converter.toString(getItem())); setContentDisplay(ContentDisplay.GRAPHIC_ONLY); textField.requestFocus(); } // revert to text display @Override public void cancelEdit() { super.cancelEdit(); setContentDisplay(ContentDisplay.TEXT_ONLY); } // commits the edit. Update property if possible and revert to text display @Override public void commitEdit(T item) { // This block is necessary to support commit on losing focus, because the baked-in mechanism // sets our editing state to false before we can intercept the loss of focus. // The default commitEdit(...) method simply bails if we are not editing... if (! isEditing() && ! item.equals(getItem())) { TableView table = getTableView(); if (table != null) { TableColumn column = getTableColumn(); CellEditEvent event = new CellEditEvent<>(table, new TablePosition(table, getIndex(), column), TableColumn.editCommitEvent(), item); Event.fireEvent(column, event); } } super.commitEdit(item); setContentDisplay(ContentDisplay.TEXT_ONLY); } }