Views
8 months ago

tornadofx-guide

5. Data Controls Notice

5. Data Controls Notice how we cannot simply reference the property. We need to access the value provided in the callback to get to the actual instance and nest call to the nameProperty . While this works, it has one major drawback. If the parent changes, the TableView will not be updated. We can partially remedy this by defining the value for the property as the parent itself, and formatting its name: column("Parent name", Person::parentProperty).cellFormat { } textProperty().bind(it.parentProperty.value.nameProperty) It might still not update right away, even though it would eventually become consistent as the TableView refreshes. To create a binding that would reflect a change to the parent property immediately, consider using a select binding, which we will cover later. column("Parent name", { it.value.parentProperty.select(Person::namePro perty) }) Declaring Column Values Functionally If you need to map a column's value to a non-property (such as a function), you can use a non-reflection means to extract the values for that column. Say you have a WeeklyReport type that has a getTotal() function accepting a DayOfWeek argument (an enum of Monday, Tuesday... Sunday). abstract class WeeklyReport(val startDate: LocalDate) { } abstract fun getTotal(dayOfWeek: DayOfWeek): BigDecimal Let's say you wanted to create a column for each DayOfWeek . You cannot map to properties, but you can map each WeeklyReport item explicitly to extract each value for that DayOfWeek . tableview { for (dayOfWeek in DayOfWeek.values()) { column(dayOfWeek.toString()) { ReadOnlyObjectWrapper(it.value.getTotal(dayOfWeek)) } } } 58

5. Data Controls This more closely resembles the traditional setCellValueFactory() for the JavaFX TableColumn . Row Expanders Later we will learn about the TreeTableView which has a notion of "parent" and "child" rows, but the constraint with this control is the parent and child must have the same columns. Fortunately, TornadoFX comes with an awesome utility to not only reveal a "child table" for a given row, but any kind of Node control. Say we have two domain types: Region and Branch . A Region is a geographical zone, and it contains one or more Branch items which are specific business operation locations (warehouses, distribution centers, etc). Here is a declaration of these types and some given instances. class Region(val id: Int, val name: String, val country: String, val branches: Observa bleList) class Branch(val id: Int, val facilityCode: String, val city: String, val stateProvince : String) val regions = listOf( Region(1,"Pacific Northwest", "USA",listOf( Branch(1,"D","Seattle","WA"), Branch(2,"W","Portland","OR") ).observable()), Region(2,"Alberta", "Canada",listOf( Branch(3,"W","Calgary","AB") ).observable()), Region(3,"Midwest", "USA", listOf( Branch(4,"D","Chicago","IL"), Branch(5,"D","Frankfort","KY"), Branch(6, "W","Indianapolis", "IN") ).observable()) ).observable() We can create a TableView where each row has a rowExpander() function defined, and there we can arbitrarily create any Node control built off that particular row's item. In this case, we can nest another TableView for a given Region to show all the Branch items belonging to it. It will have a "+" button column to expand and show this expanded control (Figure 5.5). Figure 5.5 59

Guide
Guide
GUIDE
GUIDE
Guide
GUIDE
GUIDE
Guide
GUIDE
Guide
GUIDE
GUIDE
GUIDE
guide
Guide
GUIDE
Guide
The Guide
GUIDE
Guide to
GUIDE
GUIDE
GUIDE
Guide
Guide
Guide
GUIDE
GUIDE
SELECTION GUIDE SELECTION GUIDE
The Ultimate Guide The Ultimate Guide