Wizard: rework UI components for settings

#KT-35712 fixed
This commit is contained in:
Ilya Kirillov
2020-01-14 14:56:12 +03:00
parent 89199e5cc0
commit 206284d33c
9 changed files with 273 additions and 266 deletions
@@ -0,0 +1,32 @@
package org.jetbrains.kotlin.tools.projectWizard.wizard.ui.components
import com.intellij.ui.components.JBCheckBox
import com.intellij.ui.components.JBTextField
import org.jetbrains.kotlin.tools.projectWizard.core.ValuesReadingContext
import org.jetbrains.kotlin.tools.projectWizard.core.entity.SettingValidator
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.textField
class CheckboxComponent(
valuesReadingContext: ValuesReadingContext,
labelText: String? = null,
initialValue: Boolean? = null,
validator: SettingValidator<Boolean>? = null,
onValueUpdate: (Boolean) -> Unit = {}
) : UIComponent<Boolean>(
valuesReadingContext,
labelText,
validator,
onValueUpdate
) {
override val uiComponent: JBCheckBox = JBCheckBox(labelText, initialValue ?: false).apply {
addChangeListener {
fireValueUpdated(this@apply.isSelected)
}
}
override fun updateUiValue(newValue: Boolean) = safeUpdateUi {
uiComponent.isSelected = newValue
}
override fun getUiValue(): Boolean = uiComponent.isSelected
}
@@ -3,46 +3,34 @@ package org.jetbrains.kotlin.tools.projectWizard.wizard.ui.components
import com.intellij.openapi.ui.ComboBox import com.intellij.openapi.ui.ComboBox
import com.intellij.ui.ColoredListCellRenderer import com.intellij.ui.ColoredListCellRenderer
import com.intellij.ui.SimpleTextAttributes import com.intellij.ui.SimpleTextAttributes
import org.jetbrains.kotlin.tools.projectWizard.core.ValuesReadingContext
import org.jetbrains.kotlin.tools.projectWizard.core.entity.SettingValidator import org.jetbrains.kotlin.tools.projectWizard.core.entity.SettingValidator
import org.jetbrains.kotlin.tools.projectWizard.core.entity.ValidationResult import org.jetbrains.kotlin.tools.projectWizard.core.entity.ValidationResult
import org.jetbrains.kotlin.tools.projectWizard.core.ValuesReadingContext
import org.jetbrains.kotlin.tools.projectWizard.core.entity.settingValidator import org.jetbrains.kotlin.tools.projectWizard.core.entity.settingValidator
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.Component
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.panel
import java.awt.BorderLayout
import javax.swing.JComponent
import org.jetbrains.kotlin.tools.projectWizard.settings.DisplayableSettingItem import org.jetbrains.kotlin.tools.projectWizard.settings.DisplayableSettingItem
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.ValidationIndicator
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import java.awt.event.ItemEvent import java.awt.event.ItemEvent
import javax.swing.DefaultComboBoxModel
import javax.swing.Icon import javax.swing.Icon
import javax.swing.JList import javax.swing.JList
class DropDownComponent<T : DisplayableSettingItem>( class DropDownComponent<T : DisplayableSettingItem>(
private val valuesReadingContext: ValuesReadingContext, private val valuesReadingContext: ValuesReadingContext,
private val initialValues: List<T> = emptyList(), initialValues: List<T> = emptyList(),
labelText: String? = null, labelText: String? = null,
private val filter: (T) -> Boolean = { true }, filter: (T) -> Boolean = { true },
private val validator: SettingValidator<T> = settingValidator { ValidationResult.OK }, private val validator: SettingValidator<T> = settingValidator { ValidationResult.OK },
private val iconProvider: (T) -> Icon? = { null }, private val iconProvider: (T) -> Icon? = { null },
private val onAnyValueUpdate: (T) -> Unit = {} onValueUpdate: (T) -> Unit = {}
) : Component() { ) : UIComponent<T>(
valuesReadingContext,
labelText,
validator,
onValueUpdate
) {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
override val uiComponent: ComboBox<T> = ComboBox<T>(
private val validationIndicator = ValidationIndicator(defaultText = labelText, showText = true) initialValues.filter(filter).toTypedArray<DisplayableSettingItem>() as Array<T>
).apply {
private var allowFireEventWhenValueUpdated: Boolean = true
private fun withoutActionFiring(action: () -> Unit) {
val initialAllowFireEventWhenValueUpdated = allowFireEventWhenValueUpdated
allowFireEventWhenValueUpdated = false
action()
allowFireEventWhenValueUpdated = initialAllowFireEventWhenValueUpdated
}
@Suppress("UNCHECKED_CAST")
private val comboBox = ComboBox<T>().apply {
renderer = object : ColoredListCellRenderer<T>() { renderer = object : ColoredListCellRenderer<T>() {
override fun customizeCellRenderer( override fun customizeCellRenderer(
list: JList<out T>, list: JList<out T>,
@@ -69,55 +57,19 @@ class DropDownComponent<T : DisplayableSettingItem>(
} }
} }
addItemListener { e -> addItemListener { event ->
if (e?.stateChange == ItemEvent.SELECTED) { if (event?.stateChange == ItemEvent.SELECTED) {
value = e.item as T @Suppress("UNCHECKED_CAST")
(event.item as? T)?.let(::fireValueUpdated)
} }
} }
} }
override fun onInit() { override fun updateUiValue(newValue: T) = safeUpdateUi {
super.onInit() uiComponent.selectedItem = newValue
updateValues(initialValues)
}
fun updateValues(newValues: List<T>) {
val newValuesFiltered = newValues.filter(filter)
val oldValue = comboBox.selectedItem
withoutActionFiring {
@Suppress("UNCHECKED_CAST")
comboBox.model = DefaultComboBoxModel(newValuesFiltered.toTypedArray<DisplayableSettingItem>() as Array<T>)
}
if (oldValue !in newValuesFiltered) {
newValuesFiltered.firstOrNull()?.let { newValue ->
value = newValuesFiltered.first()
}
}
}
override val component: JComponent = panel {
add(validationIndicator, BorderLayout.NORTH)
add(comboBox, BorderLayout.CENTER)
} }
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
var value: T override fun getUiValue(): T = uiComponent.selectedItem as T
get() = comboBox.selectedItem as T
set(value) {
comboBox.selectedItem = value
fireValueChanged(value)
}
private fun fireValueChanged(newValue: T) {
validate(newValue)
if (allowFireEventWhenValueUpdated) {
onAnyValueUpdate(newValue)
}
}
fun validate(value: T = this.value) {
validationIndicator.validationState = validator.validate(valuesReadingContext, value)
}
} }
@@ -6,24 +6,32 @@ import com.intellij.openapi.ui.TextFieldWithBrowseButton
import org.jetbrains.kotlin.tools.projectWizard.core.entity.StringValidator import org.jetbrains.kotlin.tools.projectWizard.core.entity.StringValidator
import org.jetbrains.kotlin.tools.projectWizard.core.entity.ValidationResult import org.jetbrains.kotlin.tools.projectWizard.core.entity.ValidationResult
import org.jetbrains.kotlin.tools.projectWizard.core.ValuesReadingContext import org.jetbrains.kotlin.tools.projectWizard.core.ValuesReadingContext
import org.jetbrains.kotlin.tools.projectWizard.core.entity.SettingValidator
import org.jetbrains.kotlin.tools.projectWizard.core.entity.settingValidator
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.Component import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.Component
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.panel import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.panel
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.ValidationIndicator import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.ValidationIndicator
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.textField import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.textField
import java.awt.BorderLayout import java.awt.BorderLayout
import java.nio.file.Path
import java.nio.file.Paths
import javax.swing.Icon
import javax.swing.JComponent import javax.swing.JComponent
class PathFieldComponent( class PathFieldComponent(
private val valuesReadingContext: ValuesReadingContext, valuesReadingContext: ValuesReadingContext,
private val initialText: String = "", labelText: String? = null,
labelText: String? = "", initialValue: Path? = null,
private val validator: StringValidator = org.jetbrains.kotlin.tools.projectWizard.core.entity.settingValidator { ValidationResult.OK }, validator: SettingValidator<Path>? = null,
private val onSuccessValueUpdate: (String) -> Unit = {}, onValueUpdate: (Path) -> Unit = {}
private val onAnyValueUpdate: (String) -> Unit = {} ) : UIComponent<Path>(
) : Component() { valuesReadingContext,
private val validationIndicator = ValidationIndicator(defaultText = labelText, showText = true) labelText,
private val pathField = TextFieldWithBrowseButton( validator,
textField(initialText, this::fireValueChanged) onValueUpdate
) {
override val uiComponent: TextFieldWithBrowseButton = TextFieldWithBrowseButton(
textField(initialValue?.toString().orEmpty()) { path -> fireValueUpdated(Paths.get(path)) }
).apply { ).apply {
addBrowseFolderListener( addBrowseFolderListener(
TextBrowseFolderListener( TextBrowseFolderListener(
@@ -33,33 +41,9 @@ class PathFieldComponent(
) )
} }
override val component: JComponent = panel { override fun updateUiValue(newValue: Path)= safeUpdateUi {
add(validationIndicator, BorderLayout.NORTH) uiComponent.text = newValue.toString()
add(pathField, BorderLayout.CENTER)
} }
override fun getUiValue(): Path = Paths.get(uiComponent.text)
var value: String
get() = pathField.text
set(value) {
pathField.text = value
fireValueChanged(value)
}
private fun fireValueChanged(text: String) {
validate(text)
if (validationIndicator.validationState == ValidationResult.OK) {
onSuccessValueUpdate(text)
}
onAnyValueUpdate(text)
}
override fun onInit() {
super.onInit()
validate(initialText)
}
private fun validate(text: String) {
validationIndicator.validationState = validator.validate(valuesReadingContext, text)
}
} }
@@ -1,54 +1,27 @@
package org.jetbrains.kotlin.tools.projectWizard.wizard.ui.components package org.jetbrains.kotlin.tools.projectWizard.wizard.ui.components
import org.jetbrains.kotlin.tools.projectWizard.core.entity.StringValidator import com.intellij.ui.components.JBTextField
import org.jetbrains.kotlin.tools.projectWizard.core.entity.ValidationResult
import org.jetbrains.kotlin.tools.projectWizard.core.ValuesReadingContext import org.jetbrains.kotlin.tools.projectWizard.core.ValuesReadingContext
import org.jetbrains.kotlin.tools.projectWizard.core.entity.settingValidator import org.jetbrains.kotlin.tools.projectWizard.core.entity.SettingValidator
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.Component
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.panel
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.ValidationIndicator
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.textField import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.textField
import java.awt.BorderLayout
import javax.swing.JComponent
class TextFieldComponent( class TextFieldComponent(
private val valuesReadingContext: ValuesReadingContext, valuesReadingContext: ValuesReadingContext,
private val initialText: String = "", labelText: String? = null,
labelText: String? = "", initialValue: String? = null,
private val validator: StringValidator = settingValidator { ValidationResult.OK }, validator: SettingValidator<String>? = null,
private val onSuccessValueUpdate: (String) -> Unit = {}, onValueUpdate: (String) -> Unit = {}
private val onAnyValueUpdate: (String) -> Unit = {} ) : UIComponent<String>(
) : Component() { valuesReadingContext,
private val validationIndicator = ValidationIndicator(defaultText = labelText, showText = true) labelText,
private val textField = textField(initialText, this::fireValueChanged) validator,
onValueUpdate
) {
override val uiComponent: JBTextField = textField(initialValue.orEmpty(), ::fireValueUpdated)
override val component: JComponent = panel { override fun updateUiValue(newValue: String) = safeUpdateUi {
add(validationIndicator, BorderLayout.NORTH) uiComponent.text = newValue
add(textField, BorderLayout.CENTER)
} }
override fun getUiValue(): String = uiComponent.text
var value: String
get() = textField.text
set(value) {
textField.text = value
fireValueChanged(value)
}
private fun fireValueChanged(text: String) {
validate(text)
if (validationIndicator.validationState == ValidationResult.OK) {
onSuccessValueUpdate(text)
}
onAnyValueUpdate(text)
}
override fun onInit() {
super.onInit()
validate(initialText)
}
private fun validate(text: String) {
validationIndicator.validationState = validator.validate(valuesReadingContext, text)
}
} }
@@ -0,0 +1,69 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.tools.projectWizard.wizard.ui.components
import org.jetbrains.kotlin.tools.projectWizard.core.ValuesReadingContext
import org.jetbrains.kotlin.tools.projectWizard.core.entity.Setting
import org.jetbrains.kotlin.tools.projectWizard.core.entity.SettingType
import org.jetbrains.kotlin.tools.projectWizard.core.entity.SettingValidator
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.DynamicComponent
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.panel
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.ValidationIndicator
import java.awt.BorderLayout
import javax.swing.JComponent
abstract class UIComponent<V : Any>(
private val valuesReadingContext: ValuesReadingContext,
labelText: String? = null,
private val validator: SettingValidator<V>? = null,
private val onValueUpdate: (V) -> Unit = {}
) : DynamicComponent(valuesReadingContext) {
private val validationIndicator = if (validator != null)
ValidationIndicator(defaultText = labelText, showText = true)
else null
protected abstract val uiComponent: JComponent
abstract fun updateUiValue(newValue: V)
abstract fun getUiValue(): V
private var allowEventFiring = true
protected fun fireValueUpdated(value: V) {
if (allowEventFiring) {
onValueUpdate(value)
}
validate(value)
}
override fun onInit() {
super.onInit()
validate(getUiValue())
}
final override val component: JComponent by lazy(LazyThreadSafetyMode.NONE) {
panel {
validationIndicator?.let { add(it, BorderLayout.NORTH) }
add(uiComponent, BorderLayout.CENTER)
}
}
protected fun safeUpdateUi(updater: () -> Unit) {
val allowEventFiringSaved = allowEventFiring
allowEventFiring = false
updater()
allowEventFiring = allowEventFiringSaved
}
fun validate(value: V) {
if (validator == null) return
if (validationIndicator == null) return
validationIndicator.validationState = validator.validate(valuesReadingContext, value)
}
}
fun <V: Any> UIComponent<V>.valueForSetting(setting: Setting<V, SettingType<V>>): V =
setting.defaultValue ?: getUiValue()
@@ -11,39 +11,37 @@ import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemP
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemType import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemType
import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.KotlinPlugin import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.KotlinPlugin
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.components.DropDownComponent import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.components.DropDownComponent
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.components.valueForSetting
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.panel import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.panel
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.SettingComponent import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.SettingComponent
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.UIComponentDelegatingSettingComponent
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.ValidationIndicator import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.ValidationIndicator
import java.awt.BorderLayout import java.awt.BorderLayout
class BuildSystemTypeSettingComponent( class BuildSystemTypeSettingComponent(
private val valuesReadingContext: ValuesReadingContext private val valuesReadingContext: ValuesReadingContext
) : SettingComponent<BuildSystemType, DropDownSettingType<BuildSystemType>>( ) : UIComponentDelegatingSettingComponent<BuildSystemType, DropDownSettingType<BuildSystemType>>(
BuildSystemPlugin::type.reference, BuildSystemPlugin::type.reference,
valuesReadingContext valuesReadingContext
) { ) {
override val validationIndicator: ValidationIndicator? = null override val uiComponent: DropDownComponent<BuildSystemType> = DropDownComponent(
private val listComponent = DropDownComponent(
valuesReadingContext, valuesReadingContext,
setting.type.values, setting.type.values,
labelText = "Build System", labelText = "Build System",
filter = { value -> setting.type.filter(valuesReadingContext, reference, value) }, filter = { value -> setting.type.filter(valuesReadingContext, reference, value) },
validator = setting.validator, validator = setting.validator,
iconProvider = BuildSystemType::icon, iconProvider = BuildSystemType::icon,
onAnyValueUpdate = { value = it } onValueUpdate = { value = it }
).asSubComponent() ).asSubComponent()
override val component = panel {
add(listComponent.component, BorderLayout.CENTER)
}
override fun onValueUpdated(reference: SettingReference<*, *>?) { override fun onValueUpdated(reference: SettingReference<*, *>?) {
super.onValueUpdated(reference) super.onValueUpdated(reference)
if (reference == KotlinPlugin::projectKind.reference) { if (reference == KotlinPlugin::projectKind.reference) {
listComponent.component.updateUI() uiComponent.component.updateUI()
} }
listComponent.validate() value?.let(uiComponent::validate)
} }
} }
@@ -24,7 +24,7 @@ class ModuleSettingsComponent(valuesReadingContext: ValuesReadingContext) : Dyna
private val nameField = TextFieldComponent( private val nameField = TextFieldComponent(
valuesReadingContext, valuesReadingContext,
labelText = "Name", labelText = "Name",
onAnyValueUpdate = { value -> onValueUpdate = { value ->
module?.name = value module?.name = value
eventManager.fireListeners(null) eventManager.fireListeners(null)
}, },
@@ -52,7 +52,7 @@ class ModuleSettingsComponent(valuesReadingContext: ValuesReadingContext) : Dyna
} }
private fun updateModule(module: Module) { private fun updateModule(module: Module) {
nameField.value = module.name nameField.updateUiValue(module.name)
nameField.component.isVisible = module.kind != ModuleKind.target nameField.component.isVisible = module.kind != ModuleKind.target
|| module.configurator.moduleType != ModuleType.common || module.configurator.moduleType != ModuleType.common
@@ -1,69 +1,59 @@
package org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting package org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting
import com.intellij.openapi.ui.ComboBox import com.intellij.openapi.ui.ComboBox
import com.intellij.ui.components.JBCheckBox
import org.jetbrains.kotlin.tools.projectWizard.core.ValuesReadingContext import org.jetbrains.kotlin.tools.projectWizard.core.ValuesReadingContext
import org.jetbrains.kotlin.tools.projectWizard.settings.DisplayableSettingItem
import org.jetbrains.kotlin.tools.projectWizard.core.entity.* import org.jetbrains.kotlin.tools.projectWizard.core.entity.*
import org.jetbrains.kotlin.tools.projectWizard.settings.DisplayableSettingItem
import org.jetbrains.kotlin.tools.projectWizard.settings.version.Version import org.jetbrains.kotlin.tools.projectWizard.settings.version.Version
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.components.DropDownComponent import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.components.*
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.components.PathFieldComponent
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.components.TextFieldComponent
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.label import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.label
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.panel import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.panel
import java.awt.BorderLayout import java.awt.BorderLayout
import java.awt.event.ItemEvent import java.awt.event.ItemEvent
import java.nio.file.Path import java.nio.file.Path
import java.nio.file.Paths
import javax.swing.DefaultComboBoxModel import javax.swing.DefaultComboBoxModel
import javax.swing.JComponent import javax.swing.JComponent
sealed class DefaultSettingComponent<V : Any, T : SettingType<V>>( object DefaultSettingComponent {
reference: SettingReference<V, T>, @Suppress("UNCHECKED_CAST")
valuesReadingContext: ValuesReadingContext fun <V : Any, T : SettingType<V>> create(
) : SettingComponent<V, T>(reference, valuesReadingContext) { setting: SettingReference<V, T>,
companion object { valuesReadingContext: ValuesReadingContext
@Suppress("UNCHECKED_CAST") ): SettingComponent<V, T> = when (setting.type) {
fun <V : Any, T : SettingType<V>> create( VersionSettingType::class ->
setting: SettingReference<V, T>, VersionSettingComponent(
valuesReadingContext: ValuesReadingContext setting as SettingReference<Version, VersionSettingType>,
): DefaultSettingComponent<V, T> = when (setting.type) { valuesReadingContext
VersionSettingType::class -> ) as SettingComponent<V, T>
VersionSettingComponent( BooleanSettingType::class ->
setting as SettingReference<Version, VersionSettingType>, BooleanSettingComponent(
valuesReadingContext setting as SettingReference<Boolean, BooleanSettingType>,
) as DefaultSettingComponent<V, T> valuesReadingContext
BooleanSettingType::class -> ) as SettingComponent<V, T>
BooleanSettingComponent( DropDownSettingType::class ->
setting as SettingReference<Boolean, BooleanSettingType>, DropdownSettingComponent(
valuesReadingContext setting as SettingReference<DisplayableSettingItem, DropDownSettingType<DisplayableSettingItem>>,
) as DefaultSettingComponent<V, T> valuesReadingContext
DropDownSettingType::class -> ) as SettingComponent<V, T>
DropdownSettingComponent( StringSettingType::class ->
setting as SettingReference<DisplayableSettingItem, DropDownSettingType<DisplayableSettingItem>>, StringSettingComponent(
valuesReadingContext setting as SettingReference<String, StringSettingType>,
) as DefaultSettingComponent<V, T> valuesReadingContext
StringSettingType::class -> ) as SettingComponent<V, T>
StringSettingComponent( PathSettingType::class ->
setting as SettingReference<String, StringSettingType>, PathSettingComponent(
valuesReadingContext setting as SettingReference<Path, PathSettingType>,
) as DefaultSettingComponent<V, T> valuesReadingContext
PathSettingType::class -> ) as SettingComponent<V, T>
PathSettingComponent( else -> TODO(setting.type.qualifiedName!!)
setting as SettingReference<Path, PathSettingType>,
valuesReadingContext
) as DefaultSettingComponent<V, T>
else -> TODO(setting.type.qualifiedName!!)
}
} }
} }
class VersionSettingComponent( class VersionSettingComponent(
reference: SettingReference<Version, VersionSettingType>, reference: SettingReference<Version, VersionSettingType>,
valuesReadingContext: ValuesReadingContext valuesReadingContext: ValuesReadingContext
) : DefaultSettingComponent<Version, VersionSettingType>(reference, valuesReadingContext) { ) : SettingComponent<Version, VersionSettingType>(reference, valuesReadingContext) {
private val settingLabel = label(setting.title) private val settingLabel = label(setting.title)
private val comboBox = ComboBox<Version>().apply { private val comboBox = ComboBox<Version>().apply {
addItemListener { e -> addItemListener { e ->
@@ -98,94 +88,68 @@ class VersionSettingComponent(
} }
} }
class DropdownSettingComponent( class DropdownSettingComponent(
reference: SettingReference<DisplayableSettingItem, DropDownSettingType<DisplayableSettingItem>>, reference: SettingReference<DisplayableSettingItem, DropDownSettingType<DisplayableSettingItem>>,
private val valuesReadingContext: ValuesReadingContext private val valuesReadingContext: ValuesReadingContext
) : DefaultSettingComponent<DisplayableSettingItem, DropDownSettingType<DisplayableSettingItem>>( ) : UIComponentDelegatingSettingComponent<DisplayableSettingItem, DropDownSettingType<DisplayableSettingItem>>(
reference, reference,
valuesReadingContext valuesReadingContext
) { ) {
private val dropDownComponent = DropDownComponent( override val uiComponent = DropDownComponent(
valuesReadingContext, valuesReadingContext = valuesReadingContext,
setting.type.values, initialValues = setting.type.values,
validator = setting.validator,
filter = { value -> setting.type.filter(valuesReadingContext, reference, value) }, filter = { value -> setting.type.filter(valuesReadingContext, reference, value) },
labelText = setting.title, labelText = setting.title,
onAnyValueUpdate = { newValue -> onValueUpdate = { newValue -> value = newValue }
value = newValue
}
).asSubComponent() ).asSubComponent()
override val validationIndicator: ValidationIndicator? = null
override val component: JComponent = dropDownComponent.component
} }
class BooleanSettingComponent( class BooleanSettingComponent(
reference: SettingReference<Boolean, BooleanSettingType>, reference: SettingReference<Boolean, BooleanSettingType>,
valuesReadingContext: ValuesReadingContext valuesReadingContext: ValuesReadingContext
) : DefaultSettingComponent<Boolean, BooleanSettingType>(reference, valuesReadingContext) { ) : UIComponentDelegatingSettingComponent<Boolean, BooleanSettingType>(
private val checkBox = JBCheckBox(setting.title).apply { reference,
addChangeListener { valuesReadingContext
value = this@apply.isSelected ) {
} override val uiComponent = CheckboxComponent(
} valuesReadingContext = valuesReadingContext,
labelText = setting.title,
override fun onValueUpdated(reference: SettingReference<*, *>?) { initialValue = null,
super.onValueUpdated(reference) validator = setting.validator,
checkBox.isSelected = value ?: false onValueUpdate = { newValue -> value = newValue }
} ).asSubComponent()
override val validationIndicator = ValidationIndicator(showText = false)
override val component: JComponent by lazy(LazyThreadSafetyMode.NONE) {
panel {
// TODO add validation indicator
add(checkBox, BorderLayout.CENTER)
}
}
} }
class StringSettingComponent( class StringSettingComponent(
reference: SettingReference<String, StringSettingType>, reference: SettingReference<String, StringSettingType>,
valuesReadingContext: ValuesReadingContext, valuesReadingContext: ValuesReadingContext,
showLabel: Boolean = true showLabel: Boolean = true
) : DefaultSettingComponent<String, StringSettingType>(reference, valuesReadingContext) { ) : UIComponentDelegatingSettingComponent<String, StringSettingType>(
private val textFieldComponent = TextFieldComponent( reference,
valuesReadingContext, valuesReadingContext
setting.defaultValue.orEmpty(), ) {
override val uiComponent = TextFieldComponent(
valuesReadingContext = valuesReadingContext,
initialValue = null,
labelText = if (showLabel) setting.title else null, labelText = if (showLabel) setting.title else null,
validator = setting.validator, validator = setting.validator,
onAnyValueUpdate = { onValueUpdate = { newValue -> value = newValue }
value = it
}
).asSubComponent() ).asSubComponent()
override val validationIndicator: ValidationIndicator? = null
override fun onInit() {
super.onInit()
textFieldComponent.value = value.orEmpty()
}
override val component = textFieldComponent.component
} }
class PathSettingComponent( class PathSettingComponent(
reference: SettingReference<Path, PathSettingType>, reference: SettingReference<Path, PathSettingType>,
valuesReadingContext: ValuesReadingContext valuesReadingContext: ValuesReadingContext
) : DefaultSettingComponent<Path, PathSettingType>(reference, valuesReadingContext) { ) : UIComponentDelegatingSettingComponent<Path, PathSettingType>(
private val pathFieldComponent = PathFieldComponent( reference,
valuesReadingContext, valuesReadingContext
"", ) {
setting.title, override val uiComponent = PathFieldComponent(
validator = settingValidator { path -> valuesReadingContext = valuesReadingContext,
setting.validator.validate(this, Paths.get(path)) labelText = setting.title,
}, validator = settingValidator { path -> setting.validator.validate(this, path) },
onAnyValueUpdate = { onValueUpdate = { newValue -> value = newValue }
value = Paths.get(it)
}
).asSubComponent() ).asSubComponent()
override val validationIndicator: ValidationIndicator? = null
override val component = pathFieldComponent.component
} }
@@ -0,0 +1,35 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting
import org.jetbrains.kotlin.tools.projectWizard.core.ValuesReadingContext
import org.jetbrains.kotlin.tools.projectWizard.core.entity.SettingReference
import org.jetbrains.kotlin.tools.projectWizard.core.entity.SettingType
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.components.UIComponent
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.components.valueForSetting
import javax.swing.JComponent
abstract class UIComponentDelegatingSettingComponent<V : Any, T : SettingType<V>>(
reference: SettingReference<V, T>,
valuesReadingContext: ValuesReadingContext
) : SettingComponent<V, T>(reference, valuesReadingContext) {
abstract val uiComponent: UIComponent<V>
// As there is one in UIComponent
override val validationIndicator: ValidationIndicator? = null
override fun onInit() {
super.onInit()
if (value == null) {
if (value == null) {
value = uiComponent.valueForSetting(setting)
}
}
value?.let(uiComponent::updateUiValue)
}
override val component: JComponent by lazy(LazyThreadSafetyMode.NONE) { uiComponent.component }
}