Dynamically replacing dialog input components using the DSL UI

Answered

I have a text input field whose type (plain text vs file path) depends on the value of a combo box field. When the user changes the combo box field, I would like to the text input field to be modified immediately: 

 

 

I am using the Kotlin DSL UI. I am using the onChange handler on the comboBox  component, but I have tried several approaches and cannot figure out how to replace the textField component from there.

 

This is the relevant method of the AnsibleSettingsConfigurable class (see mdklatt/idea-ansible-plugin). What needs to happen in comboBox.onChanged() to replace the adjacent textField component?

 

    /**
     * Create the UI component for defining settings.
     */
    override fun Panel.createContent() {
        row {
            comboBox(installTypeOptions.values).let {
                it.bindItem(
                    getter = { installTypeOptions[installType] },
                    setter = { installType = installTypeOptions.findFirstKey(it)!! }
                )
                it.onChanged {
                    // Various attempts to implement this have failed, such as
                    // reassigning the value of locationField (see below),
                    // calling createContent() on the parent component, and
                    // removing locationField before createLocationField() is
                    // called.

                    // Update the location input field to reflect the new
                    // install type. Cannot use `installType` property here
                    // because changes have not been applied yet.
                    // TODO: Would that it were this simple, but it is not.
                    //val newInstallType = installTypeOptions.findFirstKey(it.selectedItem)!!
                    //locationField = createLocationField(newInstallType)
                }
            }

            // This should be a dynamic field based on the install type, but
            // attempts to update this dynamically when installType changes
            // have not been successful (see above). For now, use the least
            // common denominator, a plain text field.
            // TODO: createLocationField(this, installType)
            textField().bindText(::ansibleLocation)
        }
        row("Config file:") {
            textFieldWithBrowseButton(
                "Ansible Config File",
                fileChooserDescriptor = FileChooserDescriptorFactory.createSingleFileDescriptor(),
            ).bindText(::configFile)
        }
    }

 

 

 

0
2 comments

Hi Michael,

I suggest creating two components and using visibleIf(comboBox.component.selectedValueMatches {…}).

A similar approach is used here: https://github.com/JetBrains/intellij-community/blob/241/plugins/coverage/src/com/intellij/coverage/JavaCoverageOptions.kt

0

This works well, thank you.

0

Please sign in to leave a comment.