From 297b2d0d9d07e61490642eb545be5e3616bf6d73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Przemys=C5=82aw=20Pluta?= Date: Tue, 30 Aug 2022 01:04:42 +0200 Subject: [PATCH] [Editor] Improve graphic asset import dialogs --- .../animation/asset/AnimationAssetData.kt | 10 +++- .../view/importing/ImportAnimationFragment.kt | 46 ++++++++++++++++++- .../viewmodel/AnimationAssetDataVM.kt | 6 +++ .../asset/component/GraphicAssetViewCanvas.kt | 40 +++++++++++----- .../view/select/SelectGraphicAssetView.kt | 4 -- .../view/importing/ImportAutoTileFragment.kt | 10 +++- .../asset/CharacterSetAssetData.kt | 10 +++- .../importing/ImportCharacterSetFragment.kt | 46 ++++++++++++++++++- .../viewmodel/CharacterSetAssetDataVM.kt | 6 +++ .../view/importing/ImportIconSetFragment.kt | 9 +++- .../view/importing/ImportTileSetFragment.kt | 9 +++- 11 files changed, 168 insertions(+), 28 deletions(-) diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/animation/asset/AnimationAssetData.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/animation/asset/AnimationAssetData.kt index 2585fbdf..571e8af2 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/animation/asset/AnimationAssetData.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/animation/asset/AnimationAssetData.kt @@ -14,9 +14,15 @@ class AnimationAssetData { val fileProperty = SimpleObjectProperty() var file by fileProperty - val rowsProperty = SimpleIntegerProperty() + val rowsProperty = SimpleIntegerProperty(1) var rows by rowsProperty - val columnsProperty = SimpleIntegerProperty() + val columnsProperty = SimpleIntegerProperty(1) var columns by columnsProperty + + val tileSetWidthProperty = SimpleIntegerProperty(1) + var tileWidth by tileSetWidthProperty + + val tileSetHeightProperty = SimpleIntegerProperty(1) + var tileHeight by tileSetHeightProperty } \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/animation/view/importing/ImportAnimationFragment.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/animation/view/importing/ImportAnimationFragment.kt index 3c22fc83..2d5eec25 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/animation/view/importing/ImportAnimationFragment.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/animation/view/importing/ImportAnimationFragment.kt @@ -2,6 +2,7 @@ package com.bartlomiejpluta.base.editor.animation.view.importing import com.bartlomiejpluta.base.editor.animation.asset.AnimationAssetData import com.bartlomiejpluta.base.editor.animation.viewmodel.AnimationAssetDataVM +import com.bartlomiejpluta.base.editor.asset.component.GraphicAssetViewCanvas import com.bartlomiejpluta.base.editor.util.fx.TextFieldUtil import javafx.beans.property.SimpleObjectProperty import javafx.scene.Cursor @@ -15,6 +16,8 @@ class ImportAnimationFragment : Fragment("Import Animation") { private var onCompleteConsumer: ((AnimationAssetData) -> Unit)? = null + private val canvas = GraphicAssetViewCanvas(dataVM.rowsProperty, dataVM.columnsProperty, dataVM.fileProperty) + init { dataVM.fileProperty.addListener { _, _, file -> when (file) { @@ -22,6 +25,29 @@ class ImportAnimationFragment : Fragment("Import Animation") { else -> file.inputStream().use { imagePreview.value = Image(it) } } } + + dataVM.tileSetWidthProperty.addListener { _, _, width -> + dataVM.columns = (imagePreview.value?.width?.toInt() ?: 1) / width.toInt() + } + + dataVM.tileSetHeightProperty.addListener { _, _, height -> + dataVM.rows = (imagePreview.value?.height?.toInt() ?: 1) / height.toInt() + } + + dataVM.columnsProperty.addListener { _, _, columns -> + dataVM.tileSetWidth = (imagePreview.value?.width?.toInt() ?: 1) / columns.toInt() + } + + dataVM.rowsProperty.addListener { _, _, rows -> + dataVM.tileSetHeight = (imagePreview.value?.height?.toInt() ?: 1) / rows.toInt() + } + + imagePreview.addListener { _, _, image -> + dataVM.columns = 1 + dataVM.rows = 1 + dataVM.tileSetWidth = image?.width?.toInt() ?: 0 + dataVM.tileSetHeight = image?.height?.toInt() ?: 0 + } } fun onComplete(consumer: (AnimationAssetData) -> Unit) { @@ -37,7 +63,7 @@ class ImportAnimationFragment : Fragment("Import Animation") { scrollpane { prefWidth = 300.0 prefHeightProperty().bind(this@form.heightProperty()) - imageview(imagePreview) + this += canvas tooltip = tooltip("Click to choose Animation file") cursor = Cursor.HAND @@ -69,6 +95,7 @@ class ImportAnimationFragment : Fragment("Import Animation") { } field("Animation Rows") { + enableWhen(imagePreview.isNotNull) spinner(min = 1, max = Integer.MAX_VALUE, property = dataVM.rowsProperty, editable = true) { required() editor.textFormatter = TextFieldUtil.integerFormatter(dataVM.rows) @@ -76,11 +103,28 @@ class ImportAnimationFragment : Fragment("Import Animation") { } field("Animation Columns") { + enableWhen(imagePreview.isNotNull) spinner(min = 1, max = Integer.MAX_VALUE, property = dataVM.columnsProperty, editable = true) { required() editor.textFormatter = TextFieldUtil.integerFormatter(dataVM.columns) } } + + field("Animation tile width") { + enableWhen(imagePreview.isNotNull) + spinner(min = 1, max = Integer.MAX_VALUE, property = dataVM.tileSetWidthProperty, editable = true) { + required() + editor.textFormatter = TextFieldUtil.integerFormatter(dataVM.rows) + } + } + + field("Animation tile height") { + enableWhen(imagePreview.isNotNull) + spinner(min = 1, max = Integer.MAX_VALUE, property = dataVM.tileSetHeightProperty, editable = true) { + required() + editor.textFormatter = TextFieldUtil.integerFormatter(dataVM.columns) + } + } } } } diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/animation/viewmodel/AnimationAssetDataVM.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/animation/viewmodel/AnimationAssetDataVM.kt index 28ee860e..7edf05b4 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/animation/viewmodel/AnimationAssetDataVM.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/animation/viewmodel/AnimationAssetDataVM.kt @@ -17,4 +17,10 @@ class AnimationAssetDataVM : ItemViewModel(AnimationAssetDat val columnsProperty = bind(AnimationAssetData::columnsProperty) var columns by columnsProperty + + val tileSetWidthProperty = bind(AnimationAssetData::tileSetWidthProperty) + var tileSetWidth by tileSetWidthProperty + + val tileSetHeightProperty = bind(AnimationAssetData::tileSetHeightProperty) + var tileSetHeight by tileSetHeightProperty } \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/component/GraphicAssetViewCanvas.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/component/GraphicAssetViewCanvas.kt index 285c8627..5e425097 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/component/GraphicAssetViewCanvas.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/component/GraphicAssetViewCanvas.kt @@ -2,41 +2,57 @@ package com.bartlomiejpluta.base.editor.asset.component import com.bartlomiejpluta.base.editor.asset.model.GraphicAsset import com.bartlomiejpluta.base.editor.asset.viewmodel.GraphicAssetVM +import javafx.beans.property.IntegerProperty +import javafx.beans.property.Property import javafx.scene.canvas.Canvas import javafx.scene.image.Image import javafx.scene.image.WritableImage import javafx.scene.paint.Color import javafx.scene.text.TextAlignment import tornadofx.getValue +import java.io.File -class GraphicAssetViewCanvas(asset: GraphicAssetVM) : Canvas() { +class GraphicAssetViewCanvas(val rowsProperty: IntegerProperty, val columnsProperty: IntegerProperty, val fileProperty: Property) : Canvas() { private var image: Image? = null - val rows by asset.rowsProperty - val columns by asset.columnsProperty + val rows by rowsProperty + val columns by columnsProperty - var chunkWidth: Int = 1// = //(image.width / columns).toInt() + var chunkWidth: Int = 1 private set - var chunkHeight: Int = 1// = (image.height / rows).toInt() + var chunkHeight: Int = 1 private set var singleChunk = rows == 1 && columns == 1 private set init { - asset.itemProperty.addListener { _, _, item -> updateAsset(item) } - updateAsset(asset.item) + rowsProperty.addListener { _, _, _ -> updateAsset() } + columnsProperty.addListener { _, _, _ -> updateAsset() } + fileProperty.addListener { _, _, _ -> updateAsset() } + updateAsset() } - private fun updateAsset(asset: GraphicAsset?) { - asset?.let { - image = Image(it.file.inputStream()) - width = image!!.width + OFFSET_X - height = image!!.height + OFFSET_Y + constructor(asset: GraphicAssetVM) : this(asset.rowsProperty, asset.columnsProperty, asset.fileProperty) + + private fun updateAsset() { + val file = fileProperty.value + + if (file != null) { + image = Image(fileProperty.value.inputStream()) + width = image!!.width + OFFSET_X * 2 + height = image!!.height + OFFSET_Y * 2 chunkWidth = (image!!.width / columns).toInt() chunkHeight = (image!!.height / rows).toInt() singleChunk = rows == 1 && columns == 1 + } else { + image = null + width = 0.0 + height = 0.0 + chunkWidth = 0 + chunkHeight = 0 + singleChunk = true } render() diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/view/select/SelectGraphicAssetView.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/view/select/SelectGraphicAssetView.kt index cca188e2..0608c6fb 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/view/select/SelectGraphicAssetView.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/asset/view/select/SelectGraphicAssetView.kt @@ -21,10 +21,6 @@ class SelectGraphicAssetView : View() { private var assetsListView: ListView by singleAssign() - private val image = createObjectBinding({ - asset.value?.file?.inputStream()?.use { Image(it) } ?: PLACEHOLDER_IMAGE - }, asset) - init { asset.addListener { _, _, item -> vm.item = item } } diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/autotile/view/importing/ImportAutoTileFragment.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/autotile/view/importing/ImportAutoTileFragment.kt index ed813158..7f8fb258 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/autotile/view/importing/ImportAutoTileFragment.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/autotile/view/importing/ImportAutoTileFragment.kt @@ -1,5 +1,7 @@ package com.bartlomiejpluta.base.editor.autotile.view.importing +import com.bartlomiejpluta.base.editor.asset.component.GraphicAssetViewCanvas +import com.bartlomiejpluta.base.editor.asset.viewmodel.GraphicAssetVM import com.bartlomiejpluta.base.editor.autotile.asset.AutoTileAssetData import com.bartlomiejpluta.base.editor.autotile.viewmodel.AutoTileAssetDataVM import com.bartlomiejpluta.base.editor.util.fx.TextFieldUtil @@ -15,6 +17,8 @@ class ImportAutoTileFragment : Fragment("Import Auto Tile") { private var onCompleteConsumer: ((AutoTileAssetData) -> Unit)? = null + private val canvas = GraphicAssetViewCanvas(dataVM.rowsProperty, dataVM.columnsProperty, dataVM.fileProperty) + init { dataVM.fileProperty.addListener { _, _, file -> when (file) { @@ -39,9 +43,11 @@ class ImportAutoTileFragment : Fragment("Import Auto Tile") { dataVM.tileSetHeight = (imagePreview.value?.height?.toInt() ?: 1) / rows.toInt() } - imagePreview.addListener { _, _, _ -> + imagePreview.addListener { _, _, image -> dataVM.columns = 1 dataVM.rows = 1 + dataVM.tileSetWidth = image?.width?.toInt() ?: 0 + dataVM.tileSetHeight = image?.height?.toInt() ?: 0 } } @@ -58,7 +64,7 @@ class ImportAutoTileFragment : Fragment("Import Auto Tile") { scrollpane { prefWidth = 300.0 prefHeightProperty().bind(this@form.heightProperty()) - imageview(imagePreview) + this += canvas tooltip = tooltip("Click to choose Auto Tile file") cursor = Cursor.HAND diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/characterset/asset/CharacterSetAssetData.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/characterset/asset/CharacterSetAssetData.kt index ffdd7b52..4fc76895 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/characterset/asset/CharacterSetAssetData.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/characterset/asset/CharacterSetAssetData.kt @@ -14,9 +14,15 @@ class CharacterSetAssetData { val fileProperty = SimpleObjectProperty() var file by fileProperty - val rowsProperty = SimpleIntegerProperty() + val rowsProperty = SimpleIntegerProperty(1) var rows by rowsProperty - val columnsProperty = SimpleIntegerProperty() + val columnsProperty = SimpleIntegerProperty(1) var columns by columnsProperty + + val tileSetWidthProperty = SimpleIntegerProperty(1) + var tileWidth by tileSetWidthProperty + + val tileSetHeightProperty = SimpleIntegerProperty(1) + var tileHeight by tileSetHeightProperty } \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/characterset/view/importing/ImportCharacterSetFragment.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/characterset/view/importing/ImportCharacterSetFragment.kt index e4e42939..d921d538 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/characterset/view/importing/ImportCharacterSetFragment.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/characterset/view/importing/ImportCharacterSetFragment.kt @@ -1,5 +1,6 @@ package com.bartlomiejpluta.base.editor.characterset.view.importing +import com.bartlomiejpluta.base.editor.asset.component.GraphicAssetViewCanvas import com.bartlomiejpluta.base.editor.characterset.asset.CharacterSetAssetData import com.bartlomiejpluta.base.editor.characterset.viewmodel.CharacterSetAssetDataVM import com.bartlomiejpluta.base.editor.util.fx.TextFieldUtil @@ -15,6 +16,8 @@ class ImportCharacterSetFragment : Fragment("Import Character Set") { private var onCompleteConsumer: ((CharacterSetAssetData) -> Unit)? = null + private val canvas = GraphicAssetViewCanvas(dataVM.rowsProperty, dataVM.columnsProperty, dataVM.fileProperty) + init { dataVM.fileProperty.addListener { _, _, file -> when (file) { @@ -22,6 +25,29 @@ class ImportCharacterSetFragment : Fragment("Import Character Set") { else -> file.inputStream().use { imagePreview.value = Image(it) } } } + + dataVM.tileSetWidthProperty.addListener { _, _, width -> + dataVM.columns = (imagePreview.value?.width?.toInt() ?: 1) / width.toInt() + } + + dataVM.tileSetHeightProperty.addListener { _, _, height -> + dataVM.rows = (imagePreview.value?.height?.toInt() ?: 1) / height.toInt() + } + + dataVM.columnsProperty.addListener { _, _, columns -> + dataVM.tileSetWidth = (imagePreview.value?.width?.toInt() ?: 1) / columns.toInt() + } + + dataVM.rowsProperty.addListener { _, _, rows -> + dataVM.tileSetHeight = (imagePreview.value?.height?.toInt() ?: 1) / rows.toInt() + } + + imagePreview.addListener { _, _, image -> + dataVM.columns = 1 + dataVM.rows = 1 + dataVM.tileSetWidth = image?.width?.toInt() ?: 0 + dataVM.tileSetHeight = image?.height?.toInt() ?: 0 + } } fun onComplete(consumer: (CharacterSetAssetData) -> Unit) { @@ -37,7 +63,7 @@ class ImportCharacterSetFragment : Fragment("Import Character Set") { scrollpane { prefWidth = 300.0 prefHeightProperty().bind(this@form.heightProperty()) - imageview(imagePreview) + this += canvas tooltip = tooltip("Click to choose Character Set file") cursor = Cursor.HAND @@ -69,6 +95,7 @@ class ImportCharacterSetFragment : Fragment("Import Character Set") { } field("Character Set Rows") { + enableWhen(imagePreview.isNotNull) spinner(min = 1, max = Integer.MAX_VALUE, property = dataVM.rowsProperty, editable = true) { required() editor.textFormatter = TextFieldUtil.integerFormatter(dataVM.rows) @@ -76,11 +103,28 @@ class ImportCharacterSetFragment : Fragment("Import Character Set") { } field("Character Set Columns") { + enableWhen(imagePreview.isNotNull) spinner(min = 1, max = Integer.MAX_VALUE, property = dataVM.columnsProperty, editable = true) { required() editor.textFormatter = TextFieldUtil.integerFormatter(dataVM.columns) } } + + field("Character tile width") { + enableWhen(imagePreview.isNotNull) + spinner(min = 1, max = Integer.MAX_VALUE, property = dataVM.tileSetWidthProperty, editable = true) { + required() + editor.textFormatter = TextFieldUtil.integerFormatter(dataVM.rows) + } + } + + field("Character tile height") { + enableWhen(imagePreview.isNotNull) + spinner(min = 1, max = Integer.MAX_VALUE, property = dataVM.tileSetHeightProperty, editable = true) { + required() + editor.textFormatter = TextFieldUtil.integerFormatter(dataVM.columns) + } + } } } } diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/characterset/viewmodel/CharacterSetAssetDataVM.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/characterset/viewmodel/CharacterSetAssetDataVM.kt index 82651d10..d24de41a 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/characterset/viewmodel/CharacterSetAssetDataVM.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/characterset/viewmodel/CharacterSetAssetDataVM.kt @@ -17,4 +17,10 @@ class CharacterSetAssetDataVM : ItemViewModel(CharacterSe val columnsProperty = bind(CharacterSetAssetData::columnsProperty) var columns by columnsProperty + + val tileSetWidthProperty = bind(CharacterSetAssetData::tileSetWidthProperty) + var tileSetWidth by tileSetWidthProperty + + val tileSetHeightProperty = bind(CharacterSetAssetData::tileSetHeightProperty) + var tileSetHeight by tileSetHeightProperty } \ No newline at end of file diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/iconset/view/importing/ImportIconSetFragment.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/iconset/view/importing/ImportIconSetFragment.kt index 641ae6ee..c389829c 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/iconset/view/importing/ImportIconSetFragment.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/iconset/view/importing/ImportIconSetFragment.kt @@ -1,5 +1,6 @@ package com.bartlomiejpluta.base.editor.iconset.view.importing +import com.bartlomiejpluta.base.editor.asset.component.GraphicAssetViewCanvas import com.bartlomiejpluta.base.editor.iconset.asset.IconSetAssetData import com.bartlomiejpluta.base.editor.iconset.viewmodel.IconSetAssetDataVM import com.bartlomiejpluta.base.editor.util.fx.TextFieldUtil @@ -15,6 +16,8 @@ class ImportIconSetFragment : Fragment("Import Icon Set") { private var onCompleteConsumer: ((IconSetAssetData) -> Unit)? = null + private val canvas = GraphicAssetViewCanvas(dataVM.rowsProperty, dataVM.columnsProperty, dataVM.fileProperty) + init { dataVM.fileProperty.addListener { _, _, file -> when (file) { @@ -39,9 +42,11 @@ class ImportIconSetFragment : Fragment("Import Icon Set") { dataVM.iconHeight = (imagePreview.value?.height?.toInt() ?: 1) / rows.toInt() } - imagePreview.addListener { _, _, _ -> + imagePreview.addListener { _, _, image -> dataVM.columns = 1 dataVM.rows = 1 + dataVM.iconWidth = image?.width?.toInt() ?: 0 + dataVM.iconHeight = image?.height?.toInt() ?: 0 } } @@ -58,7 +63,7 @@ class ImportIconSetFragment : Fragment("Import Icon Set") { scrollpane { prefWidth = 300.0 prefHeightProperty().bind(this@form.heightProperty()) - imageview(imagePreview) + this += canvas tooltip = tooltip("Click to choose Icon Set file") cursor = Cursor.HAND diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/tileset/view/importing/ImportTileSetFragment.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/tileset/view/importing/ImportTileSetFragment.kt index 53ef7f44..955fc564 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/tileset/view/importing/ImportTileSetFragment.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/tileset/view/importing/ImportTileSetFragment.kt @@ -1,5 +1,6 @@ package com.bartlomiejpluta.base.editor.tileset.view.importing +import com.bartlomiejpluta.base.editor.asset.component.GraphicAssetViewCanvas import com.bartlomiejpluta.base.editor.tileset.asset.TileSetAssetData import com.bartlomiejpluta.base.editor.tileset.viewmodel.TileSetAssetDataVM import com.bartlomiejpluta.base.editor.util.fx.TextFieldUtil @@ -15,6 +16,8 @@ class ImportTileSetFragment : Fragment("Import Tile Set") { private var onCompleteConsumer: ((TileSetAssetData) -> Unit)? = null + private val canvas = GraphicAssetViewCanvas(dataVM.rowsProperty, dataVM.columnsProperty, dataVM.fileProperty) + init { dataVM.fileProperty.addListener { _, _, file -> when (file) { @@ -39,9 +42,11 @@ class ImportTileSetFragment : Fragment("Import Tile Set") { dataVM.tileHeight = (imagePreview.value?.height?.toInt() ?: 1) / rows.toInt() } - imagePreview.addListener { _, _, _ -> + imagePreview.addListener { _, _, image -> dataVM.columns = 1 dataVM.rows = 1 + dataVM.tileWidth = image?.width?.toInt() ?: 0 + dataVM.tileHeight = image?.height?.toInt() ?: 0 } } @@ -58,7 +63,7 @@ class ImportTileSetFragment : Fragment("Import Tile Set") { scrollpane { prefWidth = 300.0 prefHeightProperty().bind(this@form.heightProperty()) - imageview(imagePreview) + this += canvas tooltip = tooltip("Click to choose Tile Set file") cursor = Cursor.HAND