1+ package ladysnake.translationhelper.view
2+
3+ import javafx.beans.property.ObjectProperty
4+ import javafx.beans.property.SimpleObjectProperty
5+ import javafx.event.EventHandler
6+ import javafx.scene.control.TableCell
7+ import javafx.scene.control.TextArea
8+ import javafx.scene.input.KeyCode
9+ import javafx.scene.input.KeyEvent
10+ import javafx.scene.text.Text
11+ import javafx.util.StringConverter
12+
13+ class TextAreaTableCell <S , T >(converter : StringConverter <T >? = null ) : TableCell<S, T>() {
14+
15+ private fun resizeToFitText () {
16+ // Hack: to find out the text's actual height, we use a temporary Text widget
17+ val txt = Text (" ${this .text} \n " )
18+ txt.wrappingWidth = this .tableColumn.width // not using this cell's width, it can be 0 during init
19+ this .prefHeight = txt.layoutBounds.height
20+ }
21+
22+ private var textArea: TextArea ? = null
23+ private val converter: ObjectProperty <StringConverter <T >? > = SimpleObjectProperty (this , " converter" )
24+ fun converterProperty (): ObjectProperty <StringConverter <T >? > {
25+ return converter
26+ }
27+
28+ fun setConverter (value : StringConverter <T >? ) {
29+ converterProperty().set(value)
30+ }
31+
32+ fun getConverter (): StringConverter <T >? {
33+ return converterProperty().get()
34+ }
35+
36+ override fun startEdit () {
37+ if (! isEditable || ! tableView.isEditable || ! tableColumn.isEditable) {
38+ return
39+ }
40+ super .startEdit()
41+ if (isEditing) {
42+ val textArea = this .textArea ? : this .createTextArea().also { this .textArea = it }
43+ textArea.text = getItemText()
44+ this .text = null
45+ this .graphic = textArea
46+ textArea.selectAll()
47+ textArea.requestFocus()
48+ }
49+ }
50+
51+ private fun getItemText () = getConverter()?.toString(this .item) ? : this .item?.toString() ? : " "
52+
53+ private fun createTextArea (): TextArea {
54+ val converter = getConverter()
55+ val textArea = TextArea (getItemText())
56+ textArea.addEventFilter(KeyEvent .KEY_PRESSED ) { t: KeyEvent ->
57+ if (t.code == KeyCode .ENTER && ! t.isShiftDown) {
58+ checkNotNull(converter) {
59+ (" Attempting to convert text input into Object, but provided "
60+ + " StringConverter is null. Be sure to set a StringConverter "
61+ + " in your cell factory." )
62+ }
63+ this .commitEdit(converter.fromString(textArea.text))
64+ t.consume()
65+ }
66+ }
67+ textArea.onKeyReleased = EventHandler { t: KeyEvent ->
68+ if (t.code == KeyCode .ESCAPE ) {
69+ this .cancelEdit()
70+ t.consume()
71+ }
72+ }
73+ textArea.isWrapText = true
74+ return textArea
75+ }
76+
77+ override fun cancelEdit () {
78+ super .cancelEdit()
79+ this .text = getItemText()
80+ this .graphic = null
81+ }
82+
83+ override fun updateItem (item : T , empty : Boolean ) {
84+ super .updateItem(item, empty)
85+ if (this .isEmpty) {
86+ this .text = null
87+ this .setGraphic(null )
88+ } else {
89+ if (this .isEditing) {
90+ val textArea = textArea
91+ if (textArea != null ) {
92+ textArea.text = getItemText()
93+ }
94+ this .text = null
95+ this .setGraphic(textArea)
96+ } else {
97+ this .text = getItemText()
98+ this .setGraphic(null )
99+ }
100+ }
101+ this .resizeToFitText()
102+ }
103+
104+ init {
105+ styleClass.add(" text-area-table-cell" )
106+ setConverter(converter)
107+ }
108+ }
0 commit comments