diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/model/layer/Layer.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/model/layer/Layer.kt index 30d320cc..80e09f83 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/model/layer/Layer.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/model/layer/Layer.kt @@ -1,6 +1,8 @@ package com.bartlomiejpluta.base.editor.map.model.layer +import javafx.beans.Observable import javafx.beans.property.StringProperty +import javafx.util.Callback interface Layer { var name: String @@ -9,4 +11,8 @@ interface Layer { fun resize(rows: Int, columns: Int) fun clone(): Layer + + companion object { + fun extractor() = Callback> { arrayOf(it.nameProperty) } + } } \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/model/map/GameMap.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/model/map/GameMap.kt index 946bf4e3..f5248e97 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/model/map/GameMap.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/model/map/GameMap.kt @@ -6,6 +6,7 @@ import javafx.beans.property.ReadOnlyStringWrapper import javafx.beans.property.SimpleDoubleProperty import javafx.beans.property.SimpleIntegerProperty import javafx.beans.property.SimpleStringProperty +import javafx.collections.FXCollections import tornadofx.getValue import tornadofx.observableListOf import tornadofx.setValue @@ -15,7 +16,7 @@ class GameMap(val tileSet: TileSet) { val uidProperty = SimpleStringProperty() var uid by uidProperty - val layers = observableListOf() + val layers = FXCollections.observableArrayList(Layer.extractor()) val tileWidth = tileSet.tileWidth.toDouble() val tileHeight = tileSet.tileHeight.toDouble() diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/view/editor/MapLayersView.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/view/editor/MapLayersView.kt index 1bd0726a..9fe3b80c 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/view/editor/MapLayersView.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/map/view/editor/MapLayersView.kt @@ -11,7 +11,11 @@ import com.bartlomiejpluta.base.editor.map.model.layer.Layer import com.bartlomiejpluta.base.editor.map.model.layer.TileLayer import com.bartlomiejpluta.base.editor.map.viewmodel.EditorStateVM import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapVM -import javafx.scene.control.TableView +import javafx.beans.value.ObservableValue +import javafx.scene.control.ListCell +import javafx.scene.control.ListView +import javafx.scene.control.cell.TextFieldListCell +import javafx.util.StringConverter import org.kordamp.ikonli.javafx.FontIcon import tornadofx.* @@ -24,11 +28,16 @@ class MapLayersView : View() { private val editorStateVM = find() - private var layersPane = TableView(mapVM.layers).apply { - column("Layer Name", Layer::nameProperty).makeEditable().setOnEditCommit { - val command = RenameLayerCommand(it.rowValue, it.newValue) - command.execute() - undoRedoService.push(command, scope) + private var layersPane = ListView(mapVM.layers).apply { + isEditable = true + + setCellFactory { + LayerListViewItem { layer, name -> + RenameLayerCommand(layer, name).let { + it.execute() + undoRedoService.push(it, scope) + } + } } editorStateVM.selectedLayerProperty.bind(selectionModel.selectedIndexProperty()) @@ -92,4 +101,45 @@ class MapLayersView : View() { } } } -} \ No newline at end of file + + private class LayerListViewItemConverter( + private val cell: ListCell, + private val onUpdate: (layer: Layer, name: String) -> Unit + ) : StringConverter() { + override fun toString(layer: Layer?) = layer?.name ?: "" + + // Disclaimer: + // Because of the fact that we want to support undo/redo mechanism + // the actual update must be done from the execute() method of the Command object + // so that the Command object has access to the actual as well as the new value of layer name. + // That's why we are running the submission logic in the converter. + override fun fromString(string: String?): Layer = cell.item.apply { + string?.takeIf { it != name }?.let { + onUpdate(this, it) + } + } + } + + private class LayerListViewItem(onUpdate: (layer: Layer, name: String) -> Unit) : TextFieldListCell() { + init { + converter = LayerListViewItemConverter(this, onUpdate) + } + + override fun updateItem(item: Layer?, empty: Boolean) { + super.updateItem(item, empty) + + if (empty || item == null) { + text = null + graphic = null + return + } + + text = item.name + + graphic = when (item) { + is TileLayer -> FontIcon("fa-th") + else -> throw IllegalStateException("Unknown layer type") + } + } + } +}