[Editor] Enable code editor shutdown when code editor tab is closed as well as application is being shutdown
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
package com.bartlomiejpluta.base.editor
|
||||
|
||||
import com.bartlomiejpluta.base.editor.main.controller.MainController
|
||||
import com.bartlomiejpluta.base.editor.main.view.MainView
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.boot.SpringApplication
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication
|
||||
import org.springframework.context.ConfigurableApplicationContext
|
||||
@@ -14,6 +16,9 @@ import kotlin.reflect.KClass
|
||||
open class EditorApp : App(MainView::class) {
|
||||
private lateinit var context: ConfigurableApplicationContext
|
||||
|
||||
@Autowired
|
||||
private lateinit var mainController: MainController
|
||||
|
||||
override fun init() {
|
||||
this.context = SpringApplication.run(this.javaClass)
|
||||
context.autowireCapableBeanFactory.autowireBean(this)
|
||||
@@ -27,6 +32,7 @@ open class EditorApp : App(MainView::class) {
|
||||
override fun stop() {
|
||||
super.stop()
|
||||
context.close()
|
||||
mainController.clearResources()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,18 @@ class CodeEditor(private val highlighter: ObservableValue<out SyntaxHighlighter>
|
||||
StackPane() {
|
||||
private val editor = CodeArea()
|
||||
private val executor = Executors.newSingleThreadExecutor()
|
||||
private val cleanupWhenDone = editor.multiPlainChanges()
|
||||
|
||||
private val highlightingSubscription = editor.multiPlainChanges()
|
||||
.successionEnds(Duration.ofMillis(500))
|
||||
.supplyTask(this::computeHighlightingAsync)
|
||||
.awaitLatest(editor.multiPlainChanges())
|
||||
.filterMap {
|
||||
when {
|
||||
it.isSuccess -> Optional.of(it.get())
|
||||
else -> Optional.empty()
|
||||
}
|
||||
}
|
||||
.subscribe(this::applyHighlighting)
|
||||
|
||||
init {
|
||||
editor.replaceText(0, 0, codeProperty.value)
|
||||
@@ -28,20 +39,6 @@ class CodeEditor(private val highlighter: ObservableValue<out SyntaxHighlighter>
|
||||
editor.paragraphGraphicFactory = LineNumberFactory.get(editor)
|
||||
applyHighlighting(highlighter.value.highlight(editor.text))
|
||||
|
||||
cleanupWhenDone
|
||||
.successionEnds(Duration.ofMillis(500))
|
||||
.supplyTask(this::computeHighlightingAsync)
|
||||
.awaitLatest(editor.multiPlainChanges())
|
||||
.filterMap {
|
||||
when {
|
||||
it.isSuccess -> Optional.of(it.get())
|
||||
else -> Optional.empty()
|
||||
}
|
||||
}
|
||||
.subscribe(this::applyHighlighting)
|
||||
|
||||
|
||||
|
||||
initAutoIndents()
|
||||
|
||||
children += VirtualizedScrollPane(editor)
|
||||
@@ -55,6 +52,11 @@ class CodeEditor(private val highlighter: ObservableValue<out SyntaxHighlighter>
|
||||
editor.redo()
|
||||
}
|
||||
|
||||
fun shutdownHighlighterThread() {
|
||||
highlightingSubscription.unsubscribe()
|
||||
executor.shutdownNow()
|
||||
}
|
||||
|
||||
private fun initAutoIndents() {
|
||||
editor.addEventHandler(KeyEvent.KEY_PRESSED) { event ->
|
||||
if (event.code === KeyCode.ENTER) {
|
||||
|
||||
@@ -5,5 +5,9 @@ import tornadofx.Fragment
|
||||
class CodeEditorFragment : Fragment() {
|
||||
private val editorView = find<CodeEditorView>()
|
||||
|
||||
fun shutdown() {
|
||||
editorView.shutdown()
|
||||
}
|
||||
|
||||
override val root = editorView.root
|
||||
}
|
||||
@@ -27,6 +27,10 @@ class CodeEditorView : View() {
|
||||
|
||||
private val editor = CodeEditor(highlighter, codeVM.codeProperty)
|
||||
|
||||
fun shutdown() {
|
||||
editor.shutdownHighlighterThread()
|
||||
}
|
||||
|
||||
override val root = borderpane {
|
||||
top = toolbar {
|
||||
button(graphic = FontIcon("fa-floppy-o")) {
|
||||
|
||||
@@ -69,7 +69,7 @@ class MainController : Controller() {
|
||||
title = "Load Project",
|
||||
filters = arrayOf(FileChooser.ExtensionFilter("BASE Editor Project (*.bep)", "*.bep")),
|
||||
).getOrNull(0)?.let {
|
||||
openItems.clear()
|
||||
clearResources()
|
||||
projectContext.open(it)
|
||||
}
|
||||
}
|
||||
@@ -143,4 +143,8 @@ class MainController : Controller() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun clearResources() {
|
||||
openItems.clear()
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import com.bartlomiejpluta.base.editor.map.view.editor.MapFragment
|
||||
import com.bartlomiejpluta.base.editor.map.viewmodel.GameMapVM
|
||||
import com.bartlomiejpluta.base.editor.project.context.ProjectContext
|
||||
import javafx.collections.MapChangeListener
|
||||
import javafx.event.Event
|
||||
import javafx.scene.control.Tab
|
||||
import org.kordamp.ikonli.javafx.FontIcon
|
||||
import tornadofx.*
|
||||
@@ -50,8 +51,26 @@ class MainView : View("BASE Game Editor") {
|
||||
|
||||
it.wasRemoved() -> {
|
||||
val tab = openTabs[it.key]
|
||||
tabs -= tab
|
||||
openTabs.remove(it.key)
|
||||
|
||||
// FIXME
|
||||
// This ugly hack prevents from double-firing the CLOSED EVENT
|
||||
// when user tries to close tab from the UI (cross sign).
|
||||
// When user clicks the close button, the event is fired automatically,
|
||||
// which removes the item from mainController.openItems.
|
||||
// Right here, this listener would fire the event once again,
|
||||
// so essentially we need to check if the tab exists in TabPane.tabs
|
||||
// (which means the tab wasn't be closed from UI). If so, we need to fire
|
||||
// the event manually since it won't be fired by TabPane.
|
||||
// Otherwise, if the tab does not exist in tabs anymore, the tab
|
||||
// was closed from UI and likely the event has been fired automatically.
|
||||
// The same goes for the TAB_CLOSE_REQUEST event.
|
||||
if (tab in tabs) {
|
||||
Event.fireEvent(tab, Event(Tab.CLOSED_EVENT))
|
||||
Event.fireEvent(tab, Event(Tab.TAB_CLOSE_REQUEST_EVENT))
|
||||
}
|
||||
|
||||
tabs -= tab
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -82,10 +101,15 @@ class MainView : View("BASE Game Editor") {
|
||||
is Code -> Tab().apply {
|
||||
val vm = CodeVM(item)
|
||||
setInScope(vm, scope)
|
||||
content = find<CodeEditorFragment>(scope).root
|
||||
textProperty().bindBidirectional(item.fileProperty.select { it.name.toProperty() })
|
||||
val editor = find<CodeEditorFragment>(scope)
|
||||
content = editor.root
|
||||
graphic = FontIcon("fa-code")
|
||||
setOnClosed { mainController.openItems.remove(scope) }
|
||||
textProperty().bindBidirectional(item.fileProperty.select { it.name.toProperty() })
|
||||
|
||||
setOnClosed {
|
||||
editor.shutdown()
|
||||
mainController.openItems.remove(scope)
|
||||
}
|
||||
}
|
||||
|
||||
else -> throw IllegalStateException("Unsupported tab item")
|
||||
|
||||
Reference in New Issue
Block a user