Last active
April 8, 2023 08:07
-
-
Save eckig/30abf0d7d51b7756c2e7 to your computer and use it in GitHub Desktop.
TextAreaTableCell, see Stack Overflow question: http://stackoverflow.com/questions/27666382/editable-multiline-cell-in-tableview
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import javafx.beans.binding.Bindings; | |
import javafx.beans.property.ObjectProperty; | |
import javafx.beans.property.SimpleObjectProperty; | |
import javafx.scene.control.Cell; | |
import javafx.scene.control.TableCell; | |
import javafx.scene.control.TableColumn; | |
import javafx.scene.control.TextArea; | |
import javafx.scene.input.KeyCode; | |
import javafx.util.Callback; | |
import javafx.util.StringConverter; | |
import javafx.util.converter.DefaultStringConverter; | |
public class TextAreaTableCell<S, T> extends TableCell<S, T> { | |
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 TextAreaTableCell<>(converter); | |
} | |
private static <T> String getItemText(Cell<T> cell, StringConverter<T> converter) { | |
return converter == null ? cell.getItem() == null ? "" : cell.getItem() | |
.toString() : converter.toString(cell.getItem()); | |
} | |
private static <T> TextArea createTextArea(final Cell<T> cell, final StringConverter<T> converter) { | |
TextArea textArea = new TextArea(getItemText(cell, converter)); | |
textArea.setOnKeyReleased(t -> { | |
if (t.getCode() == KeyCode.ESCAPE) { | |
cell.cancelEdit(); | |
t.consume(); | |
} | |
else if(t.getCode() == KeyCode.ENTER && t.isShiftDown()) { | |
if (converter == null) { | |
throw new IllegalStateException( | |
"Attempting to convert text input into Object, but provided " | |
+ "StringConverter is null. Be sure to set a StringConverter " | |
+ "in your cell factory."); | |
} | |
cell.commitEdit(converter.fromString(textArea.getText())); | |
t.consume(); | |
} | |
}); | |
textArea.prefRowCountProperty().bind(Bindings.size(textArea.getParagraphs())); | |
return textArea; | |
} | |
private void startEdit(final Cell<T> cell, final StringConverter<T> converter) { | |
textArea.setText(getItemText(cell, converter)); | |
cell.setText(null); | |
cell.setGraphic(textArea); | |
textArea.selectAll(); | |
textArea.requestFocus(); | |
} | |
private static <T> void cancelEdit(Cell<T> cell, final StringConverter<T> converter) { | |
cell.setText(getItemText(cell, converter)); | |
cell.setGraphic(null); | |
} | |
private void updateItem(final Cell<T> cell, final StringConverter<T> converter) { | |
if (cell.isEmpty()) { | |
cell.setText(null); | |
cell.setGraphic(null); | |
} else { | |
if (cell.isEditing()) { | |
if (textArea != null) { | |
textArea.setText(getItemText(cell, converter)); | |
} | |
cell.setText(null); | |
cell.setGraphic(textArea); | |
} else { | |
cell.setText(getItemText(cell, converter)); | |
cell.setGraphic(null); | |
} | |
} | |
} | |
private TextArea textArea; | |
private ObjectProperty<StringConverter<T>> converter = new SimpleObjectProperty<>(this, "converter"); | |
public TextAreaTableCell() { | |
this(null); | |
} | |
public TextAreaTableCell(StringConverter<T> converter) { | |
this.getStyleClass().add("text-area-table-cell"); | |
setConverter(converter); | |
} | |
public final ObjectProperty<StringConverter<T>> converterProperty() { | |
return converter; | |
} | |
public final void setConverter(StringConverter<T> value) { | |
converterProperty().set(value); | |
} | |
public final StringConverter<T> getConverter() { | |
return converterProperty().get(); | |
} | |
@Override | |
public void startEdit() { | |
if (!isEditable() || !getTableView().isEditable() || !getTableColumn().isEditable()) { | |
return; | |
} | |
super.startEdit(); | |
if (isEditing()) { | |
if (textArea == null) { | |
textArea = createTextArea(this, getConverter()); | |
} | |
startEdit(this, getConverter()); | |
} | |
} | |
@Override | |
public void cancelEdit() { | |
super.cancelEdit(); | |
cancelEdit(this, getConverter()); | |
} | |
@Override | |
public void updateItem(T item, boolean empty) { | |
super.updateItem(item, empty); | |
updateItem(this, getConverter()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks for this! I adapted it for a kotlin implementation that also wraps the text in the cell.
https://gist.github.com/maroc81/6c60d5ae11fdf79099e50fe308509a27