Workspaces As mentioned, you never need to do this and should always use the connectWorkspaceActions call, but you might want to override one of onSave , onDelete or onRefresh to perform some action in the main editor before calling the same action inside the active tab by calling root.onXXX . Let's say that the refresh call in the main editor reloads the customer, but you also want to have the contact list refresh if that view is currently active. This could be done like this: class CustomerEditor : View() { val customerController : CustomerController by inject() val customer: CustomerModel by inject() override val root = tabpane { tab(CustomerBasicDataEditor::class) tab(ContactListEditor::class) connectWorkspaceActions() } } override val onRefresh() { runAsync { customerController.getCustomer(customer.id.value) } ui { customer.item = it root.onRefresh() } } This little trick enables you to handle the actual reload of the customer in the main view instead of reimplementing it in every tab. Forwarding button state and actions As we have seen, the currently docked View controls the Workspace buttons. Some times you dock nested Views inside the main View, and you would like that nested View to control the buttons and actions instead. This can easily be done with the forwardWorkspaceActions function. You can change the forwarding however you see fit, for example on focus or on click on some component inside the nested View. class CustomerEditor : View() { override val root = hbox { val basicDataEditor = find() add(basicDataEditor) forwardWorkspaceActions(basicDataEditor) add(ContactListEditor::class) } } 230
Workspaces Modifying the default workspace The default workspace only gives you basic functionality. As your application grows you will want to suplement the toolbar with more buttons and controls, and maybe a MenuBar above it. For small modifications you can augment it in the onBeforeFunction as we did above, but you will most probably want to subclass as the customizations become more advanced. The following code and image is taken from a real world CRM application: class CRMWorkspace : Workspace() { init { add(MainMenu::class) add(RestProgressBar::class) add(SearchView::class) } } The CRMWorkspace loads three other views into it. One providing a MenuBar , then the default RestProgressBar is added, and lastly a SearchView providing a search input field is added. The Workspace has a pretty good idea about where to place whatever you add to it. For example, buttons will by default be added after the four default buttons, while other components are added to the far right of the ToolBar. The MenuBar is automatically added above the ToolBar, at the top of the screen. Figure 16.3 shows how it looks in production, with a little bit of custom styling and a CustomerEditor docked into it. This application happens to be in Norwegian, and some of the information in the Customer card has been removed. Figure 16.3 231
Table of Contents Introduction Part
Part 1: TornadoFX Fundamentals Part
1. Why TornadoFX? how Kotlin can si
1. Why TornadoFX? tableview { items
2. Setting Up 1.8 Then this goes
3. Components However, we might wan
3. Components Specify the name of y
3. Components class MyApp: App(MyVi
3. Components import javafx.scene.c
3. Components Here is a simple exam
3. Components The VBox contains a L
3. Components Argument Type Descrip
3. Components Argument Type Descrip
3. Components import tornadofx.* cl
3. Components Sometimes it is neces
4. Basic Controls Basic Controls On
4. Basic Controls 3. The Button is
4. Basic Controls If you need to sa
4. Basic Controls Figure 4.4 You ca
4. Basic Controls You do not need t
4. Basic Controls radiobutton("Powe
4. Basic Controls ProgressBar A Pro
4. Basic Controls Like most other c
4. Basic Controls Keep in mind that
4. Basic Controls button("Commit")
4. Basic Controls 51
5. Data Controls val greekLetters =
5. Data Controls class Person(id: I
5. Data Controls tableview(persons)
5. Data Controls This more closely
5. Data Controls The rowExpander()
5. Data Controls Let's break this d
5. Data Controls data class Departm
5. Data Controls val tableData = ma
5. Data Controls val numbers = (1..
6. Type Safe CSS Type-Safe CSS Whil
6. Type Safe CSS import javafx.scen
6. Type Safe CSS You can apply styl
6. Type Safe CSS Figure 6.3 Note al
6. Type Safe CSS label("Lore Ipsum"
6. Type Safe CSS If you want the bu
6. Type Safe CSS import javafx.scen
6. Type Safe CSS Modifier Selection
6. Type Safe CSS The DangerButtonSt
7. Layouts and Menus vbox { button(
7. Layouts and Menus Notice also wh
7. Layouts and Menus borderpane { l
7. Layouts and Menus 95
7. Layouts and Menus The example ab
7. Layouts and Menus One way to use
7. Layouts and Menus columnIndex: I
7. Layouts and Menus TabPane A TabP
7. Layouts and Menus Like many buil
7. Layouts and Menus Separators You
7. Layouts and Menus Note there are
7. Layouts and Menus Attribute Buil
7. Layouts and Menus item("SomeText
7. Layouts and Menus squeezebox { f
7. Layouts and Menus class DrawerVi
7. Layouts and Menus drawer(side =
8. Charts Charts JavaFX comes with
8. Charts val items = listOf( PieCh
8. Charts In the series() and data(
8. Charts Multiseries You can strea
8. Charts BubbleChart BubbleChart i
8. Charts Summary Charts are a an e
9. Shapes and Animation class MyVie
9. Shapes and Animation CubicCurve
9. Shapes and Animation Polyline A
9. Shapes and Animation Path Path r
9. Shapes and Animation A KeyValue
9. Shapes and Animation If you want
10. FXML If you are converting an e
10. FXML We have created an FXML fi
10. FXML class CounterView : View()
10. FXML FXML is helpful to know as
11. Editing Models and Validation F
11. Editing Models and Validation }
11. Editing Models and Validation p
11. Editing Models and Validation T
11. Editing Models and Validation /
11. Editing Models and Validation m
11. Editing Models and Validation L
11. Editing Models and Validation -
11. Editing Models and Validation F
11. Editing Models and Validation E
11. Editing Models and Validation d
11. Editing Models and Validation i
12. TornadoFX IDEA Plugin 13. Torna