Kotlin DSL 2 field validation in `Configurable`

Answered

Hi, I'm writing a plugin that requires configuring a path for a language server. I want to add validation to the settings menu when the user changes the path value.

I have tried many things without success. The way I managed to do it is to imperatively change attributes of a predefined label depending on a validation function that runs with `onApply`

    private val gleamPathSelect = GleamPathSelect()

    private fun runPathValidation() {
        if (!gleamPathSelect.isEnabled) return

        LOG.warn("Running path validation")

        val path = gleamPathSelect.text
        val valid = FsUtils.validateGleamPath(path)
        if (!valid) {
            errorLabel.foreground = JBColor.RED
            errorLabel.text = "Invalid path"
        } else {
            errorLabel.foreground = JBColor.GREEN
            errorLabel.text = "Valid path"
        }
    }
    /* ... */
    override fun Panel.createContent() {
            row(GleamBundle.message("gleam.settings.lsp.configurable.lsp.path")) {
            	/* private val gleamPathSelect = GleamPathSelect() */
                cell(gleamPathSelect)
                    .align(AlignX.FILL)
//                    .errorOnApply("Gleam path is invalid") { true }
                    .onApply { runPathValidation() }
                    .bindText(settings::lspPath)
            }

I would like to hook into the existing validation system, but I cannot seem to make it work. I looked at the Kotlin DSL UI demo source code but the validation section only covers live input validation. I have tried with apply, but even then ideally I would prefer to do the validation whenever the value has changed, in a debounced fashion.

Can someone give me some guidance?

0
2 comments

Hi,

Try creating a validator and passing it to validationOnApply and validationOnInput, for example (I'm not sure what GleamPathSelect, so showing textField):

row(GleamBundle.message("gleam.settings.lsp.configurable.lsp.path") {
    val lspPathValidator: ValidationInfoBuilder.(JBTextField) -> ValidationInfo? = {
        when {
            !FsUtils.validateGleamPath(it.text) -> ValidationInfo("Invalid path", it)
            else -> null
        }
    }
    textField().bindText(settings::lspPath)
        .validationOnApply(lspPathValidator)
        .validationOnInput(lspPathValidator)
}
0

Hello,

I perform the above example on JBTextField in plugin settings configurable for an acceptable integer range. Even though the input value is out of range, and error message is displayed, the invalid value is accepted and stored in settings persistent storage XML. Is this normal? Is there a way to reject the invalid value? 

0

Please sign in to leave a comment.