[Editor] Extract the Scripts tree view from the Project Structure panel
This commit is contained in:
@@ -0,0 +1,22 @@
|
|||||||
|
package com.bartlomiejpluta.base.editor.code.component
|
||||||
|
|
||||||
|
import javafx.scene.control.TreeCell
|
||||||
|
import javafx.util.StringConverter
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class CodeStructureItemStringConverter(
|
||||||
|
private val cell: TreeCell<File>,
|
||||||
|
private val onUpdate: (item: File, name: String) -> File
|
||||||
|
) : StringConverter<File>() {
|
||||||
|
override fun toString(item: File?): String = when (item) {
|
||||||
|
is File -> item.name
|
||||||
|
else -> ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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?) = string?.let { onUpdate(cell.item, it) }
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package com.bartlomiejpluta.base.editor.code.component
|
||||||
|
|
||||||
|
import javafx.scene.control.ContextMenu
|
||||||
|
import javafx.scene.control.MenuItem
|
||||||
|
import javafx.scene.control.cell.TextFieldTreeCell
|
||||||
|
import org.kordamp.ikonli.javafx.FontIcon
|
||||||
|
import tornadofx.action
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class CodeStructureItemTreeCell(renameFile: (file: File, name: String) -> File, deleteFile: (file: File) -> Unit) :
|
||||||
|
TextFieldTreeCell<File>() {
|
||||||
|
private val fileMenu = ContextMenu()
|
||||||
|
|
||||||
|
init {
|
||||||
|
converter = CodeStructureItemStringConverter(this, renameFile)
|
||||||
|
MenuItem("Rename").apply {
|
||||||
|
action {
|
||||||
|
treeView.isEditable = true
|
||||||
|
startEdit()
|
||||||
|
treeView.isEditable = false
|
||||||
|
}
|
||||||
|
|
||||||
|
fileMenu.items.add(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuItem("Delete").apply {
|
||||||
|
action {
|
||||||
|
deleteFile(item as File)
|
||||||
|
}
|
||||||
|
|
||||||
|
fileMenu.items.add(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateItem(item: File?, empty: Boolean) {
|
||||||
|
super.updateItem(item, empty)
|
||||||
|
|
||||||
|
if (empty || item == null) {
|
||||||
|
text = null
|
||||||
|
graphic = null
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
contextMenu = if (isEditing) null else fileMenu
|
||||||
|
text = item.name
|
||||||
|
graphic = FontIcon(getFileIcon(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package com.bartlomiejpluta.base.editor.code.view
|
||||||
|
|
||||||
|
import com.bartlomiejpluta.base.editor.code.component.CodeStructureItemTreeCell
|
||||||
|
import com.bartlomiejpluta.base.editor.main.controller.MainController
|
||||||
|
import com.bartlomiejpluta.base.editor.project.context.ProjectContext
|
||||||
|
import javafx.scene.control.TreeItem
|
||||||
|
import javafx.scene.control.TreeView
|
||||||
|
import tornadofx.*
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class CodeStructureView : View() {
|
||||||
|
private val projectContext: ProjectContext by di()
|
||||||
|
private val mainController: MainController by di()
|
||||||
|
|
||||||
|
init {
|
||||||
|
projectContext.projectProperty.addListener { _, _, project ->
|
||||||
|
project?.let {
|
||||||
|
treeView.root = TreeItem(it.codeDirectory)
|
||||||
|
treeView.populate { item -> item.value?.listFiles()?.toList() }
|
||||||
|
root.root.expandAll()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val treeView: TreeView<File> = treeview {
|
||||||
|
setCellFactory {
|
||||||
|
CodeStructureItemTreeCell(this@CodeStructureView::renameFile, this@CodeStructureView::deleteFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
setOnMouseClicked { event ->
|
||||||
|
if (event.clickCount == 2) {
|
||||||
|
selectionModel?.selectedItem?.value
|
||||||
|
.takeIf { it?.isFile ?: false }
|
||||||
|
?.let { mainController.openScript(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
event.consume()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val root = treeView
|
||||||
|
|
||||||
|
private fun renameFile(file: File, name: String) = file.apply {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deleteFile(file: File) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,7 +10,6 @@ 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>() {
|
||||||
@@ -55,7 +54,6 @@ 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
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,21 +62,7 @@ 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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@ package com.bartlomiejpluta.base.editor.main.view
|
|||||||
|
|
||||||
import com.bartlomiejpluta.base.editor.code.model.Code
|
import com.bartlomiejpluta.base.editor.code.model.Code
|
||||||
import com.bartlomiejpluta.base.editor.code.view.CodeEditorFragment
|
import com.bartlomiejpluta.base.editor.code.view.CodeEditorFragment
|
||||||
|
import com.bartlomiejpluta.base.editor.code.view.CodeStructureView
|
||||||
import com.bartlomiejpluta.base.editor.code.viewmodel.CodeVM
|
import com.bartlomiejpluta.base.editor.code.viewmodel.CodeVM
|
||||||
import com.bartlomiejpluta.base.editor.main.controller.MainController
|
import com.bartlomiejpluta.base.editor.main.controller.MainController
|
||||||
import com.bartlomiejpluta.base.editor.map.model.map.GameMap
|
import com.bartlomiejpluta.base.editor.map.model.map.GameMap
|
||||||
@@ -20,6 +21,7 @@ class MainView : View("BASE Game Editor") {
|
|||||||
|
|
||||||
private val mainMenuView = find<MainMenuView>()
|
private val mainMenuView = find<MainMenuView>()
|
||||||
private val projectStructureView = find<ProjectStructureView>()
|
private val projectStructureView = find<ProjectStructureView>()
|
||||||
|
private val codeStructure = find<CodeStructureView>()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
projectContext.projectProperty.addListener { _, _, project ->
|
projectContext.projectProperty.addListener { _, _, project ->
|
||||||
@@ -68,6 +70,10 @@ class MainView : View("BASE Game Editor") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
left = drawer(multiselect = true) {
|
left = drawer(multiselect = true) {
|
||||||
|
item("Code Structure", expanded = true) {
|
||||||
|
this += codeStructure
|
||||||
|
}
|
||||||
|
|
||||||
item("Project Structure", expanded = true) {
|
item("Project Structure", expanded = true) {
|
||||||
this += projectStructureView
|
this += projectStructureView
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import javafx.beans.binding.Bindings
|
|||||||
import javafx.scene.control.TreeItem
|
import javafx.scene.control.TreeItem
|
||||||
import javafx.scene.control.TreeView
|
import javafx.scene.control.TreeView
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
|
|
||||||
class ProjectStructureView : View() {
|
class ProjectStructureView : View() {
|
||||||
@@ -29,16 +28,11 @@ 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
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -49,12 +43,7 @@ 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()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -62,10 +51,11 @@ class ProjectStructureView : View() {
|
|||||||
private val treeView: TreeView<Any> = treeview<Any> {
|
private val treeView: TreeView<Any> = treeview<Any> {
|
||||||
root = TreeItem(structureRoot)
|
root = TreeItem(structureRoot)
|
||||||
|
|
||||||
|
isShowRoot = false
|
||||||
|
|
||||||
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -78,7 +68,6 @@ 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) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user