[Editor] Enable opening the code scripts via double-click in the Project Structure panel

This commit is contained in:
2021-02-23 21:59:10 +01:00
parent ed88836ac8
commit 2c9ad00170
7 changed files with 77 additions and 9 deletions

View File

@@ -3,11 +3,24 @@ package com.bartlomiejpluta.base.editor.code.model
import tornadofx.getValue import tornadofx.getValue
import tornadofx.setValue import tornadofx.setValue
import tornadofx.toProperty import tornadofx.toProperty
import java.io.File
class Code(codeType: CodeType, code: String) { class Code(file: File) {
val typeProperty = codeType.toProperty() val fileProperty = file.toProperty()
var type by typeProperty val file by fileProperty
val codeProperty = code.toProperty() val typeProperty = deduceCodeType(file).toProperty()
val type by typeProperty
val codeProperty = file.readText().toProperty()
var code by codeProperty var code by codeProperty
companion object {
private fun deduceCodeType(file: File): CodeType {
return when (file.extension.toLowerCase()) {
"java" -> CodeType.JAVA
else -> throw IllegalStateException("Unsupported script type")
}
}
}
} }

View File

@@ -10,6 +10,7 @@ import javafx.scene.control.MenuItem
import javafx.scene.control.cell.TextFieldTreeCell import javafx.scene.control.cell.TextFieldTreeCell
import org.kordamp.ikonli.javafx.FontIcon import org.kordamp.ikonli.javafx.FontIcon
import tornadofx.action import tornadofx.action
import java.io.File
class StructureItemTreeCell(renameAsset: (asset: Asset, name: String) -> Asset, deleteAsset: (asset: Asset) -> Unit) : class StructureItemTreeCell(renameAsset: (asset: Asset, name: String) -> Asset, deleteAsset: (asset: Asset) -> Unit) :
TextFieldTreeCell<Any>() { TextFieldTreeCell<Any>() {
@@ -54,6 +55,7 @@ class StructureItemTreeCell(renameAsset: (asset: Asset, name: String) -> Asset,
text = when (item) { text = when (item) {
is StructureCategory -> item.name is StructureCategory -> item.name
is Asset -> item.name is Asset -> item.name
is File -> item.name
else -> null else -> null
} }
@@ -62,7 +64,21 @@ class StructureItemTreeCell(renameAsset: (asset: Asset, name: String) -> Asset,
is GameMapAsset -> FontIcon("fa-map") is GameMapAsset -> FontIcon("fa-map")
is TileSetAsset -> FontIcon("fa-th") is TileSetAsset -> FontIcon("fa-th")
is ImageAsset -> FontIcon("fa-image") is ImageAsset -> FontIcon("fa-image")
is File -> FontIcon(getFileIcon(item))
else -> null else -> null
} }
} }
companion object {
private fun getFileIcon(file: File): String {
if (file.isDirectory) {
return "fa-folder"
}
return when (file.extension.toLowerCase()) {
"java" -> "fa-code"
else -> "fa-file"
}
}
}
} }

View File

@@ -1,6 +1,8 @@
package com.bartlomiejpluta.base.editor.main.controller package com.bartlomiejpluta.base.editor.main.controller
import com.bartlomiejpluta.base.editor.asset.model.Asset import com.bartlomiejpluta.base.editor.asset.model.Asset
import com.bartlomiejpluta.base.editor.code.model.Code
import com.bartlomiejpluta.base.editor.code.viewmodel.CodeVM
import com.bartlomiejpluta.base.editor.command.context.UndoableScope import com.bartlomiejpluta.base.editor.command.context.UndoableScope
import com.bartlomiejpluta.base.editor.image.view.importing.ImportImageFragment import com.bartlomiejpluta.base.editor.image.view.importing.ImportImageFragment
import com.bartlomiejpluta.base.editor.image.viewmodel.ImageAssetDataVM import com.bartlomiejpluta.base.editor.image.viewmodel.ImageAssetDataVM
@@ -18,6 +20,7 @@ import com.bartlomiejpluta.base.editor.tileset.viewmodel.TileSetAssetDataVM
import javafx.stage.FileChooser import javafx.stage.FileChooser
import org.springframework.stereotype.Component import org.springframework.stereotype.Component
import tornadofx.* import tornadofx.*
import java.io.File
import kotlin.collections.set import kotlin.collections.set
@Component @Component
@@ -82,6 +85,17 @@ class MainController : Controller() {
} }
} }
fun openScript(file: File) {
if (openItems.count { (_, item) -> item is Code && item.file.absolutePath == file.absolutePath } == 0) {
val code = Code(file)
val vm = CodeVM(code)
val scope = UndoableScope()
setInScope(vm, scope)
openItems[scope] = code
}
}
fun importTileSet() { fun importTileSet() {
val vm = TileSetAssetDataVM() val vm = TileSetAssetDataVM()
val scope = Scope() val scope = Scope()

View File

@@ -4,9 +4,12 @@ import javafx.collections.ObservableList
import javafx.scene.Node import javafx.scene.Node
import javafx.scene.control.ContextMenu import javafx.scene.control.ContextMenu
import javafx.scene.control.MenuItem import javafx.scene.control.MenuItem
import tornadofx.* import tornadofx.action
import tornadofx.getValue
import tornadofx.observableListOf
import tornadofx.toProperty
class StructureCategory(name: String = "", var items: ObservableList<out Any> = observableListOf()) { class StructureCategory(name: String = "", var items: ObservableList<in Any> = observableListOf()) {
val nameProperty = name.toProperty() val nameProperty = name.toProperty()
val name by nameProperty val name by nameProperty
val menu = ContextMenu() val menu = ContextMenu()

View File

@@ -48,7 +48,7 @@ class MainView : View("BASE Game Editor") {
val vm = CodeVM(item) val vm = CodeVM(item)
setInScope(vm, scope) setInScope(vm, scope)
content = find<CodeEditorFragment>(scope).root content = find<CodeEditorFragment>(scope).root
text = "Test.java" textProperty().bindBidirectional(item.fileProperty.select { it.name.toProperty() })
graphic = FontIcon("fa-code") graphic = FontIcon("fa-code")
setOnClosed { mainController.openItems.remove(scope) } setOnClosed { mainController.openItems.remove(scope) }
} }

View File

@@ -8,7 +8,9 @@ import com.bartlomiejpluta.base.editor.map.asset.GameMapAsset
import com.bartlomiejpluta.base.editor.project.context.ProjectContext import com.bartlomiejpluta.base.editor.project.context.ProjectContext
import javafx.beans.binding.Bindings import javafx.beans.binding.Bindings
import javafx.scene.control.TreeItem import javafx.scene.control.TreeItem
import javafx.scene.control.TreeView
import tornadofx.* import tornadofx.*
import java.io.File
class ProjectStructureView : View() { class ProjectStructureView : View() {
@@ -27,11 +29,16 @@ class ProjectStructureView : View() {
menuitem("Import Image...") { mainController.importImage() } menuitem("Import Image...") { mainController.importImage() }
} }
private val structureCode = StructureCategory("Code").apply {
menuitem("Refresh") { this@ProjectStructureView.treeView.refresh() }
}
private val structureRoot = StructureCategory( private val structureRoot = StructureCategory(
name = "Project", items = observableListOf( name = "Project", items = observableListOf(
structureMaps, structureMaps,
structureTileSets, structureTileSets,
structureImages structureImages,
structureCode
) )
) )
@@ -42,18 +49,23 @@ class ProjectStructureView : View() {
Bindings.bindContent(structureMaps.items, it.maps) Bindings.bindContent(structureMaps.items, it.maps)
Bindings.bindContent(structureTileSets.items, it.tileSets) Bindings.bindContent(structureTileSets.items, it.tileSets)
Bindings.bindContent(structureImages.items, it.images) Bindings.bindContent(structureImages.items, it.images)
structureCode.items.clear()
structureCode.items.add(it.codeDirectory)
root.root.expandAll() root.root.expandAll()
root.refresh() root.refresh()
} }
} }
} }
override val root = treeview<Any> { private val treeView: TreeView<Any> = treeview<Any> {
root = TreeItem(structureRoot) root = TreeItem(structureRoot)
populate { populate {
when (val value = it.value) { when (val value = it.value) {
is StructureCategory -> value.items is StructureCategory -> value.items
is File -> value.listFiles()?.toList() ?: observableListOf()
else -> null else -> null
} }
} }
@@ -66,6 +78,7 @@ class ProjectStructureView : View() {
if (event.clickCount == 2) { if (event.clickCount == 2) {
when (val item = selectionModel?.selectedItem?.value) { when (val item = selectionModel?.selectedItem?.value) {
is GameMapAsset -> mainController.openMap(item.uid) is GameMapAsset -> mainController.openMap(item.uid)
is File -> item.takeIf { it.isFile }?.let { mainController.openScript(item) }
} }
} }
@@ -73,6 +86,8 @@ class ProjectStructureView : View() {
} }
} }
override val root = treeView
private fun renameAsset(asset: Asset, name: String) = asset.apply { private fun renameAsset(asset: Asset, name: String) = asset.apply {
this.name = name this.name = name
projectContext.save() projectContext.save()

View File

@@ -35,12 +35,17 @@ class Project {
var imagesDirectory by imagesDirectoryProperty var imagesDirectory by imagesDirectoryProperty
private set private set
val codeDirectoryProperty = SimpleObjectProperty<File>()
var codeDirectory by codeDirectoryProperty
private set
init { init {
sourceDirectoryProperty.addListener { _, _, dir -> sourceDirectoryProperty.addListener { _, _, dir ->
dir?.let { dir?.let {
mapsDirectory = File(it, MAPS_DIR) mapsDirectory = File(it, MAPS_DIR)
tileSetsDirectory = File(it, TILESETS_DIR) tileSetsDirectory = File(it, TILESETS_DIR)
imagesDirectory = File(it, IMAGES_DIR) imagesDirectory = File(it, IMAGES_DIR)
codeDirectory = File(it, CODE_DIR)
} }
} }
} }
@@ -50,11 +55,13 @@ class Project {
mapsDirectory?.mkdirs() mapsDirectory?.mkdirs()
tileSetsDirectory?.mkdirs() tileSetsDirectory?.mkdirs()
imagesDirectory?.mkdirs() imagesDirectory?.mkdirs()
codeDirectory?.mkdirs()
} }
companion object { companion object {
const val MAPS_DIR = "maps" const val MAPS_DIR = "maps"
const val TILESETS_DIR = "tilesets" const val TILESETS_DIR = "tilesets"
const val IMAGES_DIR = "images" const val IMAGES_DIR = "images"
const val CODE_DIR = "code"
} }
} }