[Kotlin UI DSL] Data binding does not work when the UI is being displayed

Answered

I wrote a dialog box and the code looks like this:

fun frame(data: FrameData) = panel {
row(Constant.uiBundle.getString("label_language")) {
cell {
buttonGroup {
radio("Java", Language.JAVA) { data.language1 = it }
radio("Kotlin", Language.KOTLIN) { data.language1 = it }
}
}
}

row("Data binding)Language: ") {
cell {
buttonGroup(data::language) {
radioButton("Java", Language.JAVA)
radioButton("Kotlin", Language.KOTLIN)
}
}
}

row("Data binding)Desc: ") {
textField(data::desc)
}

row {
button("data") {
Messages.showInfoMessage(data.toString(), "Info")
}
}
}

data class FrameData(
var language: Language = Language.UNKNOWN,
   var language1: Language = Language.UNKNOWN,
var desc: String = ""
)

Radio is a components that I wrapped myself in order to trigger an event when the value changes and manually modify the value of the data property

fun <T> Cell.radio(text: String, value: T, init: (JBRadioButton) -> Unit, selected: (T) -> Unit): CellBuilder<JBRadioButton> {
val radio = JBRadioButton(text).apply {
init(this)
addItemListener {
if (it.stateChange == ItemEvent.SELECTED) {
selected(value)
}
}
}
return radio()
}

RadioButton and textField are components that come with the Kotlin UI DSL and use property binding

The panel returned by the frame method will be used by DialogConstructor, a subclass of DialogWrapper (custom implementation of text and events for the custom dialog OK and Cancel buttons).

When I click on the button named "data", I can see that the values of the language and desc properties of data are always the default values, and they are assigned only after I close the dialog

I need to get the latest data property values in real time, is there any way to do that?

0
3 comments

My plugin should support 2020.3.4, can't use kotlin ui dsl version 2... And I also tried v2 and it doesn't work either

Okay, let's re-implement the components I might use based on property binding...

fun <T> Cell.radio(text: String, value: T, property: KMutableProperty<T>, init: (JBRadioButton) -> Unit = {}, changed: (T) -> Unit = {}): CellBuilder<JBRadioButton> {
    val radio = JBRadioButton(text).apply {
        init(this)
        addItemListener {
            if (it.stateChange == ItemEvent.SELECTED) {
                property.setter.call(value)
                changed(value)
            }
        }
    }
    return radio()
}

It's a little hard to figure out why you can't listen in real time...

0

Got it!

Before getting data, invoke the panel's `apply()` method, that's it!

dialogPanel.apply()
0

Please sign in to leave a comment.