09.04.2018 Views

tornadofx-guide

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Workspaces<br />

class MyApp: App(MyWorkspace::class) {<br />

override fun onBeforeShow(view: UIComponent) {<br />

workspace.dock()<br />

}<br />

}<br />

class MyWorkspace: Workspace() {<br />

override fun onRefresh() {<br />

customerTable.asyncItems { customerController.listCustomers() }<br />

}<br />

}<br />

Same goes for the Delete button. We will revisit the Save button and introduce a neat trick<br />

to only activate it when there are dirty changes later in this chapter.<br />

Tabbed Views<br />

You may at one point dock a View containing a TabPane inside of a Workspace , and then<br />

add tabs which represents further UIComponents. You can quite easily proxy the savable,<br />

refreshable and deletable state and actions from the Workspace onto the View represented<br />

by the currently active Tab. Consider a Customer Editor which has tabs for editing customer<br />

data, and one for editing contacts for that customer. Whenever the user selects one of the<br />

tabs, the buttons in the Workspace should interact with the state and actions from the<br />

selected tab view.<br />

class CustomerEditor : View("Customer Editor") {<br />

override val root = tabpane {<br />

tab(CustomerBasicDataEditor::class)<br />

tab(ContactListEditor::class)<br />

connectWorkspaceActions()<br />

}<br />

}<br />

That single call to connectWorkspaceActions() takes care of everything for us. The actual<br />

implementation of the two sub views are omitted for brevity, but you can imagine that they<br />

share a CustomerViewModel injected into the scope they share for example.<br />

The actual implementation of connectWorkspaceActions is quite simple, and reveals what's<br />

going on under the cover:<br />

228

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!