[Editor] Add support for in-memory executable scripts
This commit is contained in:
@@ -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) }
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
Reference in New Issue
Block a user