[Editor] Add support for in-memory executable scripts

This commit is contained in:
2021-03-24 21:03:20 +01:00
parent 9fd8e84fea
commit 0b5ea55b87
8 changed files with 92 additions and 11 deletions

View File

@@ -6,7 +6,13 @@ import tornadofx.getValue
import tornadofx.setValue
import tornadofx.toProperty
class Code(fileNode: FileNode, val typeProperty: Property<CodeType>, code: String) {
class Code(
fileNode: FileNode,
val typeProperty: Property<CodeType>,
code: String,
saveable: Boolean = true,
execute: ((String) -> Unit)? = null
) {
val fileNodeProperty = fileNode.toProperty()
val fileNode by fileNodeProperty
@@ -14,4 +20,13 @@ class Code(fileNode: FileNode, val typeProperty: Property<CodeType>, code: Strin
val codeProperty = code.toProperty()
var code by codeProperty
val saveableProperty = saveable.toProperty()
val saveable by saveableProperty
val executeProperty = execute.toProperty()
fun execute() {
executeProperty.value?.let { it(code) }
}
}

View File

@@ -7,6 +7,7 @@ import com.bartlomiejpluta.base.editor.code.model.CodeScope
import com.bartlomiejpluta.base.editor.code.model.CodeType
import com.bartlomiejpluta.base.editor.code.viewmodel.CodeVM
import com.bartlomiejpluta.base.editor.file.model.FileSystemNode
import com.bartlomiejpluta.base.editor.file.model.InMemoryStringFileNode
import com.bartlomiejpluta.base.editor.file.model.ScriptAssetFileNode
import com.bartlomiejpluta.base.editor.project.context.ProjectContext
import javafx.beans.binding.Bindings
@@ -31,7 +32,7 @@ class CodeEditorView : View() {
}, codeVM.typeProperty)
private val editable = Bindings.createBooleanBinding(
{ codeVM.fileNode is FileSystemNode || codeVM.fileNode is ScriptAssetFileNode },
{ codeVM.fileNode is FileSystemNode || codeVM.fileNode is ScriptAssetFileNode || codeVM.fileNode is InMemoryStringFileNode },
codeVM.itemProperty
)
@@ -50,9 +51,12 @@ class CodeEditorView : View() {
override val root = borderpane {
top = toolbar {
button(graphic = FontIcon("fa-floppy-o")) {
enableWhen(codeVM.dirty.and(editable))
action { save() }
if (codeVM.saveable && editable.value) {
button(graphic = FontIcon("fa-floppy-o")) {
enableWhen(codeVM.dirty)
action { save() }
}
}
button(graphic = FontIcon("fa-undo")) {
@@ -64,6 +68,12 @@ class CodeEditorView : View() {
enableWhen(editable)
action { redo() }
}
if (codeVM.executeProperty.isNotNull.value) {
button(graphic = FontIcon("fa-play")) {
action { execute() }
}
}
}
center = editor
@@ -73,8 +83,13 @@ class CodeEditorView : View() {
fun undo() = editor.undo()
fun save() = codeVM.item?.let {
fun save() = codeVM.takeIf { editable.value && it.saveable }?.item?.let {
codeVM.commit(codeVM.codeProperty)
projectContext.saveScript(it)
}
fun execute() {
codeVM.commit(codeVM.codeProperty)
codeVM.execute()
}
}

View File

@@ -14,4 +14,13 @@ class CodeVM(code: Code) : ItemViewModel<Code>(code) {
val codeProperty = bind(Code::codeProperty)
var code by codeProperty
val saveableProperty = bind(Code::saveableProperty)
val saveable by saveableProperty
val executeProperty = bind(Code::executeProperty)
fun execute() {
item?.execute()
}
}

View File

@@ -0,0 +1,30 @@
package com.bartlomiejpluta.base.editor.file.model
import javafx.beans.property.SimpleLongProperty
import tornadofx.getValue
import tornadofx.toProperty
class InMemoryStringFileNode(name: String, extension: String, val content: String) : FileNode {
override val nameProperty = "$name.$extension".toProperty()
override val name by nameProperty
override val extensionProperty = extension.toProperty()
override val extension by extensionProperty
override val nameWithoutExtensionProperty = name.toProperty()
override val nameWithoutExtension by nameWithoutExtensionProperty
override val absolutePathProperty = "".toProperty()
override val absolutePath by absolutePathProperty
override val type = FileType.FILE
override val parent = null
override val children = emptyList<FileNode>()
override val lastModifiedProperty = SimpleLongProperty(0)
override val lastModified by lastModifiedProperty
override fun inputStream() = content.byteInputStream()
}

View File

@@ -98,12 +98,18 @@ class MainController : Controller() {
}
}
fun openScript(fsNode: FileNode, line: Int = 1, column: Int = 1) {
fun openScript(
fsNode: FileNode,
line: Int = 1,
column: Int = 1,
execute: ((String) -> Unit)? = null,
saveable: Boolean = true
) {
val findScript = { script: Code -> script.fileNode.absolutePath == fsNode.absolutePath }
val updateExistingScope = { scope: CodeScope -> scope.setCaretPosition(line, column) }
openItem(findScript, updateExistingScope) {
val code = projectContext.loadScript(fsNode)
val code = projectContext.loadScript(fsNode, execute, saveable)
val vm = CodeVM(code)
val scope = CodeScope(line, column)
setInScope(vm, scope)

View File

@@ -6,6 +6,7 @@ import com.bartlomiejpluta.base.editor.code.view.build.BuildLogsView
import com.bartlomiejpluta.base.editor.code.view.editor.CodeEditorFragment
import com.bartlomiejpluta.base.editor.code.view.list.ScriptFilesView
import com.bartlomiejpluta.base.editor.code.viewmodel.CodeVM
import com.bartlomiejpluta.base.editor.database.view.list.TablesListView
import com.bartlomiejpluta.base.editor.event.AppendBuildLogsEvent
import com.bartlomiejpluta.base.editor.event.AppendProcessLogsEvent
import com.bartlomiejpluta.base.editor.event.SelectMainViewTabEvent
@@ -36,6 +37,7 @@ class MainView : View("BASE Game Editor") {
private val buildLogsView = find<BuildLogsView>()
private val processLogsView = find<ProcessLogsView>()
private val projectPropertiesView = find<ProjectParametersView>()
private val databaseTablesListView = find<TablesListView>()
private val openTabs = mutableMapOf<Scope, Tab>()
@@ -123,6 +125,10 @@ class MainView : View("BASE Game Editor") {
this += assetsView
}
item("Database", expanded = false) {
this += databaseTablesListView
}
item("Project Parameters") {
enableWhen(projectContext.projectProperty.isNotNull)
this += projectPropertiesView

View File

@@ -247,7 +247,7 @@ class DefaultProjectContext : ProjectContext {
} ?: throw IllegalStateException("There is no open project in the context")
}
override fun loadScript(fileNode: FileNode): Code {
override fun loadScript(fileNode: FileNode, execute: ((String) -> Unit)?, saveable: Boolean): Code {
val typeProperty = SimpleObjectProperty<CodeType>().apply {
bind(createObjectBinding({
when (fileNode.extension.toLowerCase()) {
@@ -261,7 +261,7 @@ class DefaultProjectContext : ProjectContext {
val code = fileNode.readText()
return Code(fileNode, typeProperty, code)
return Code(fileNode, typeProperty, code, saveable, execute)
}
override fun saveScript(code: Code) {

View File

@@ -49,6 +49,6 @@ interface ProjectContext {
fun importSound(data: SoundAssetData)
fun deleteAsset(asset: Asset)
fun loadScript(fileNode: FileNode): Code
fun loadScript(fileNode: FileNode, execute: ((String) -> Unit)?, saveable: Boolean): Code
fun saveScript(code: Code)
}