I'm using the Workspace
feature of TornadoFX and I'm trying to make them work with Scopes
. When I'm starting up the application I need to set some things up and when it is done I start the TornadoFX application and I supply a Scope
to my first view. After that I want to be able to dock
other views into my Workspace
in a new Scope
but this doesn't work for some reason: the original View
doesn't get undocked but the new View
gets docked I just don't see it on the screen. What could be the problem? Here is my code to reproduce the problem:
fun main(args: Array<String>) {
Application.launch(TestApp::class.java, *args)
}
class ParentScope : Scope() {
val id = UUID.randomUUID().toString().substring(0, 4)
}
class ChildScope : Scope() {
val id = UUID.randomUUID().toString().substring(0, 4)
}
class TestApp : App(Workspace::class) {
override fun onBeforeShow(view: UIComponent) {
workspace.dock<ParentView>(ParentScope())
}
}
class ParentView : View("parent") {
override val scope = super.scope as ParentScope
override val root = hbox {
button("new child") {
action {
workspace.dock<ChildView>(ChildScope())
}
}
}
override fun onDock() {
logger.info("Docking parent (${scope.id})")
}
override fun onUndock() {
logger.info("Undocking parent (${scope.id})")
}
}
class ChildView : View("child") {
override val scope = super.scope as ChildScope
override val root = hbox {
text("In child")
}
override fun onDock() {
logger.info("Docking child (${scope.id})")
}
override fun onUndock() {
logger.info("Undocking child (${scope.id})")
}
}
The output after I click thew new child
button is this:
10:56:19.415 [JavaFX Application Thread] INFO Test - Docking parent (d202)
10:56:23.967 [JavaFX Application Thread] INFO Test - Docking child (cbc5)
What I see is the same ParentView
. If I click new child
again the ChildView
gets undocked and a new ChildView
gets docked but I still only see the ParentView
:
10:56:31.228 [JavaFX Application Thread] INFO Test - Undocking child (cbc5)
10:56:31.228 [JavaFX Application Thread] INFO Test - Docking child (1dd8)
The App
already defines a Scope
with a corresponding Workspace
instance, so while your initial View
is docked in the Workspace
, your new ParentScope
defines a new Workspace
instance. When you dock the ChildView
into that Workspace
it does exactly that, but the Workspace in question is not shown on screen.
To remedy this you can override the primary scope of the your application like this:
class TestApp : WorkspaceApp(ParentView::class) {
init {
scope = ParentScope()
}
}
Notice also that I use the WorkspaceApp
subclass so I don't need to dock the ParentView
manually.
While looking at this issue I realized that if you dock a UIComponent into a Workspace, it should assume the Workspace it has been docked in. For that reason, I've committed a fix so that your initial code will work without modification.