tornadofx icon indicating copy to clipboard operation
tornadofx copied to clipboard

workspace.dockInNewScope with custom scope?

Open SKeeneCode opened this issue 5 years ago • 5 comments

From the documentation I know we can use a dockInNewScope call to prevent needing to set the workspace of the new scope. Can I use the same call when I want the new scope to be my own custom one? At the moment I am needing to do this:

val scope = PageScope()
scope.workspace = myWorkspace
val newPage = find<WikiPage>(scope)
myWorkspace.dock(newPage)

I would like to be able to replace the above lines with something such as:

dockInNewScope<WikiPage>(PageScope())

or (this would be even more useful for me):

dockInNewScope(WikiPage(), PageScope())

I can see the call accepts a ScopedInstance but I don't understand what this is, could someone help explain it for me please?

SKeeneCode avatar Mar 07 '20 18:03 SKeeneCode

If you really have a use case for subclassing Scope, you can call the constructor that accepts a workspace:

class PageScope(workspace: Workspace) : Scope(workspace)

However, I suspect you have no need to actually subclass scope, so please revisit the reason you're creating a subclass.

If you really want to do this, this is the simplest way:

workspace.dock(find<WikiPage>(PageScope(workspace)))

Note that you must never instantiate UIComponents (Views/Fragments) manually, as they will miss out on important life cycle calls.

ScopedInstance is a superclass for "anything that can live in a scope", for example ViewModel, View, Controller etc.

edvin avatar Mar 07 '20 19:03 edvin

However, I suspect you have no need to actually subclass scope, so please revisit the reason you're creating a subclass.

I'm using it based on the examples given in the scope part of the guide. I need multiple editors open at the same time so using scopes to group them apart made sense.

SKeeneCode avatar Mar 07 '20 20:03 SKeeneCode

There's no need, just put a PersonModel in the scope, no need to subclass it. I can't actually think of any good use cases to subclass Scope in a normal app, so it might be best to remove that section from the guide. Sorry about the confusion :)

edvin avatar Mar 07 '20 21:03 edvin

Fair enough, I'll look into refactoring those parts of my application.

I have run into another unrelated problem which I don't understand. So if you're still around I'd love a pointer here... I have a SimpleListProperty in my model:

val wikiNodeList = SimpleListProperty<TextNodeModel>(FXCollections.observableArrayList())

And I bind that in the view model:

val nodeList = bind(PageModel::wikiNodeList)

However when I try to call:

pageViewModel.nodeList.add(textNode.viewModel.item)

I get the following error:

Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: public fun EventTarget.add(node: Node): Unit defined in tornadofx

Any idea about this?

Edit:

pageViewModel.item.wikiNodeList.add(textNode.viewModel.item) works but my understanding is this is bad practice in View-viewmodel architecture

SKeeneCode avatar Mar 07 '20 21:03 SKeeneCode

You're getting an extension function called add which is intented to be used to add UI elements to parent elements. Without seeing a complete example, I'm guessing, but I think you need to write nodeList.items.add().

edvin avatar Mar 09 '20 08:03 edvin