[Editor] Enable base script management
This commit is contained in:
@@ -1,15 +1,15 @@
|
||||
package com.bartlomiejpluta.base.editor.code.component
|
||||
|
||||
import com.bartlomiejpluta.base.editor.code.model.FileSystemNode
|
||||
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
|
||||
private val cell: TreeCell<FileSystemNode>,
|
||||
private val onUpdate: (item: FileSystemNode, name: String) -> FileSystemNode
|
||||
) : StringConverter<FileSystemNode>() {
|
||||
override fun toString(item: FileSystemNode?): String = when (item) {
|
||||
is FileSystemNode -> item.file.name
|
||||
else -> ""
|
||||
}
|
||||
|
||||
|
||||
@@ -1,58 +1,95 @@
|
||||
package com.bartlomiejpluta.base.editor.code.component
|
||||
|
||||
import com.bartlomiejpluta.base.editor.code.model.FileSystemNode
|
||||
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
|
||||
import tornadofx.enableWhen
|
||||
import tornadofx.item
|
||||
import tornadofx.toProperty
|
||||
|
||||
class CodeStructureItemTreeCell(renameFile: (file: File, name: String) -> File, deleteFile: (file: File) -> Unit) :
|
||||
TextFieldTreeCell<File>() {
|
||||
private val fileMenu = ContextMenu()
|
||||
class CodeStructureItemTreeCell : TextFieldTreeCell<FileSystemNode>() {
|
||||
private val isRoot = true.toProperty()
|
||||
private val isNotRoot = isRoot.not()
|
||||
|
||||
private val fileMenu = ContextMenu().apply {
|
||||
item("Rename") {
|
||||
enableWhen(isNotRoot)
|
||||
|
||||
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)
|
||||
item("Delete") {
|
||||
enableWhen(isNotRoot)
|
||||
action { item.delete() }
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateItem(item: File?, empty: Boolean) {
|
||||
private val directoryMenu = ContextMenu().apply {
|
||||
item("Refresh") {
|
||||
action { item.refresh() }
|
||||
}
|
||||
|
||||
item("Rename") {
|
||||
enableWhen(isNotRoot)
|
||||
|
||||
action {
|
||||
treeView.isEditable = true
|
||||
startEdit()
|
||||
treeView.isEditable = false
|
||||
}
|
||||
}
|
||||
|
||||
item("Delete") {
|
||||
enableWhen(isNotRoot)
|
||||
action { item.delete() }
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
converter = CodeStructureItemStringConverter(this, this::renameFile)
|
||||
}
|
||||
|
||||
private fun renameFile(file: FileSystemNode, name: String) = file.apply {
|
||||
file.rename(name)
|
||||
}
|
||||
|
||||
override fun updateItem(item: FileSystemNode?, empty: Boolean) {
|
||||
super.updateItem(item, empty)
|
||||
|
||||
if (empty || item == null) {
|
||||
text = null
|
||||
graphic = null
|
||||
contextMenu = null
|
||||
isRoot.value = true
|
||||
return
|
||||
}
|
||||
|
||||
contextMenu = if (isEditing) null else fileMenu
|
||||
text = item.name
|
||||
graphic = FontIcon(getFileIcon(item))
|
||||
text = item.file.name
|
||||
graphic = FontIcon(getFileSystemNodeIcon(item))
|
||||
|
||||
contextMenu = when {
|
||||
isEditing -> null
|
||||
item.isFile -> fileMenu
|
||||
item.isDirectory -> directoryMenu
|
||||
else -> null
|
||||
}
|
||||
|
||||
isRoot.value = (item.parent == null)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private fun getFileIcon(file: File): String {
|
||||
private fun getFileSystemNodeIcon(file: FileSystemNode): String {
|
||||
if (file.isDirectory) {
|
||||
return "fa-folder"
|
||||
}
|
||||
|
||||
return when (file.extension.toLowerCase()) {
|
||||
return when (file.file.extension.toLowerCase()) {
|
||||
"java" -> "fa-code"
|
||||
else -> "fa-file"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.bartlomiejpluta.base.editor.code.model
|
||||
|
||||
import tornadofx.observableListOf
|
||||
import java.io.File
|
||||
|
||||
class FileSystemNode(file: File, val parent: FileSystemNode? = null) {
|
||||
var file = file
|
||||
private set
|
||||
|
||||
val isFile = file.isFile
|
||||
val isDirectory = file.isDirectory
|
||||
|
||||
val children = observableListOf<FileSystemNode>()
|
||||
|
||||
init {
|
||||
refreshChildren()
|
||||
}
|
||||
|
||||
private fun refreshChildren() {
|
||||
if (isDirectory) {
|
||||
children.clear()
|
||||
file.listFiles()?.map { FileSystemNode(it, this) }?.let { children.addAll(it) }
|
||||
}
|
||||
}
|
||||
|
||||
fun rename(name: String) {
|
||||
val newFile = File(file.parent, name)
|
||||
file.renameTo(newFile)
|
||||
file = newFile
|
||||
}
|
||||
|
||||
fun delete() {
|
||||
val deleted = when {
|
||||
isFile -> file.delete()
|
||||
isDirectory -> file.deleteRecursively()
|
||||
else -> false
|
||||
}
|
||||
|
||||
if (deleted) {
|
||||
parent?.children?.remove(this)
|
||||
}
|
||||
}
|
||||
|
||||
fun refresh() {
|
||||
refreshChildren()
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,16 @@
|
||||
package com.bartlomiejpluta.base.editor.code.view
|
||||
|
||||
import com.bartlomiejpluta.base.editor.code.component.CodeStructureItemTreeCell
|
||||
import com.bartlomiejpluta.base.editor.code.model.FileSystemNode
|
||||
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
|
||||
import javafx.scene.input.MouseButton
|
||||
import tornadofx.View
|
||||
import tornadofx.expandAll
|
||||
import tornadofx.populate
|
||||
import tornadofx.treeview
|
||||
|
||||
class CodeStructureView : View() {
|
||||
private val projectContext: ProjectContext by di()
|
||||
@@ -15,36 +19,26 @@ class CodeStructureView : View() {
|
||||
init {
|
||||
projectContext.projectProperty.addListener { _, _, project ->
|
||||
project?.let {
|
||||
treeView.root = TreeItem(it.codeDirectory)
|
||||
treeView.populate { item -> item.value?.listFiles()?.toList() }
|
||||
treeView.root = TreeItem(FileSystemNode(it.codeDirectory))
|
||||
treeView.populate { item -> item.value?.children }
|
||||
root.root.expandAll()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val treeView: TreeView<File> = treeview {
|
||||
setCellFactory {
|
||||
CodeStructureItemTreeCell(this@CodeStructureView::renameFile, this@CodeStructureView::deleteFile)
|
||||
}
|
||||
private val treeView: TreeView<FileSystemNode> = treeview {
|
||||
setCellFactory { CodeStructureItemTreeCell() }
|
||||
|
||||
setOnMouseClicked { event ->
|
||||
if (event.clickCount == 2) {
|
||||
if (event.button == MouseButton.PRIMARY && event.clickCount == 2) {
|
||||
selectionModel?.selectedItem?.value
|
||||
.takeIf { it?.isFile ?: false }
|
||||
?.let { mainController.openScript(it) }
|
||||
}
|
||||
?.let { mainController.openScript(it.file) }
|
||||
|
||||
event.consume()
|
||||
event.consume()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override val root = treeView
|
||||
|
||||
private fun renameFile(file: File, name: String) = file.apply {
|
||||
// TODO
|
||||
}
|
||||
|
||||
private fun deleteFile(file: File) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user