August 4, 2018
Form, Fieldset, and Field are TornadoFX classes that conveniently match UI input controls with Labels. This article presents a sample program that applies Type Safe CSS rules to align the Labels to the top left.
The panel on the left is a Form containing a pair of Fields "Arbeit" and "Details". There is one Fieldset grouping both Fields. The Details Field is a TextArea. The Arbeit Field is a composed of two ComboBoxes, a TextField, and additional Labels. The Labels in the Arbeit Field "bei", "in", and "als" are styled through the builder and not through Type Safe CSS.
The righthand panel is a Form with Type Safe CSS applied. A rule is established "righthandForm" to disambiguate the right and left Forms. According to the "Styling With CSS" section at this link, two of the classes that you can define for a Form are "label-container" and "input-container". These classes will be the targets of the alignment setting.s Notice that there is a naming convention to map the CSS names like "label-container" and "input-container" to valid Java names like "labelContainer" and "inputContainer".
This is the Type Safe CSS class. A companion object describes a rule that will be referenced in the View class. The init{} method applies a style "alignment" which is further restricted by both the labelContainer and inputContainer style classes known to the Form. If you wanted to apply this alignment style to all Form objects, you could omit the custom class "rightsideForm". Then, the remaining unwrapped labelContainer or inputContainer style would not be restricted to only those objects carrying a particular class ("rightsideForm" in this example).
class FormAlignmentDemoStylesheet : Stylesheet() {
companion object {
val rightsideForm by cssclass()
}
init {
rightsideForm {
s(labelContainer, inputContainer) {
alignment = Pos.TOP_LEFT
}
}
}
}
The s function is used to apply the TOP_LEFT setting to both Form style classes using one style. This is so that the alignment will only need to be maintained in one place.
This class is the View. There are two similar Forms defined, right and left. The left form does not contain the rightsideForm class so it is using the default Label positioning for form which is CENTER_LEFT.
class FormAlignmentDemoView : View("Form Alignment Demo") {
override val root = hbox {
form {
fieldset {
field("Arbeit") {
label("bei")
combobox<String>()
label("in")
combobox<String>()
label("als")
textfield()
}
field("Details") {
textarea()
}
}
}
separator(Orientation.VERTICAL)
form {
addClass( FormAlignmentDemoStylesheet.rightsideForm )
fieldset {
field("Arbeit") {
label("bei")
combobox<String>()
label("in")
combobox<String>()
label("als")
textfield()
}
field("Details") {
textarea()
}
}
}
padding = Insets(10.0)
spacing = 4.0
}
}
The righthand Form uses the same object graph as the lefthand one. However, the righthand Form has the rightsideForm CSS class applied. The Labels "Arbeit" and "Details" are using the alignment from the rightsideForm labelContainer rule. The Labels "bei", "in", and "als" are aligned from the rightsideForm inputContainer rule.
The following trivial App and main() are combined with the previously-listed View and Stylesheet classes to form the running program.
class FormAlignmentDemo : App(FormAlignmentDemoView::class, FormAlignmentDemoStylesheet::class)
fun main(args: Array<String>) { launch<FormAlignmentDemo>(args) }
Here's a link to the source file which can be pasted in your IDE: FormAlignmentDemo.kt.
This example applied an alignment rule to a custom form. Creating business forms is a prime use case for TornadoFX. The Form, Fieldset, and Field classes are convenient ways to structure the UI. When supplemented with Type Safe CSS, these forms can be customized.
By Carl Walker
President and Principal Consultant of Bekwam, Inc