Wizard: make error messages in ui clickable
#KT-36162 fixed
This commit is contained in:
+4
@@ -47,4 +47,8 @@ abstract class DynamicComponent(private val valuesReadingContext: ValuesReadingC
|
|||||||
reader(valuesReadingContext)
|
reader(valuesReadingContext)
|
||||||
|
|
||||||
open fun onValueUpdated(reference: SettingReference<*, *>?) {}
|
open fun onValueUpdated(reference: SettingReference<*, *>?) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FocusableComponent {
|
||||||
|
fun focusOn() {}
|
||||||
}
|
}
|
||||||
+4
@@ -46,4 +46,8 @@ class PathFieldComponent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getUiValue(): Path = Paths.get(uiComponent.text.trim())
|
override fun getUiValue(): Path = Paths.get(uiComponent.text.trim())
|
||||||
|
|
||||||
|
override fun focusOn() {
|
||||||
|
uiComponent.textField.requestFocus()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+13
-4
@@ -6,11 +6,12 @@
|
|||||||
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.ValuesReadingContext
|
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.*
|
||||||
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.DynamicComponent
|
||||||
|
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.FocusableComponent
|
||||||
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.ErrorAwareComponent
|
||||||
|
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.SettingComponent
|
||||||
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
|
||||||
import javax.swing.JComponent
|
import javax.swing.JComponent
|
||||||
@@ -20,7 +21,7 @@ abstract class UIComponent<V : Any>(
|
|||||||
labelText: String? = null,
|
labelText: String? = null,
|
||||||
private val validator: SettingValidator<V>? = null,
|
private val validator: SettingValidator<V>? = null,
|
||||||
private val onValueUpdate: (V) -> Unit = {}
|
private val onValueUpdate: (V) -> Unit = {}
|
||||||
) : DynamicComponent(valuesReadingContext) {
|
) : DynamicComponent(valuesReadingContext), ErrorAwareComponent, FocusableComponent {
|
||||||
private val validationIndicator = if (validator != null)
|
private val validationIndicator = if (validator != null)
|
||||||
ValidationIndicator(defaultText = labelText, showText = true)
|
ValidationIndicator(defaultText = labelText, showText = true)
|
||||||
else null
|
else null
|
||||||
@@ -63,6 +64,14 @@ abstract class UIComponent<V : Any>(
|
|||||||
if (validationIndicator == null) return
|
if (validationIndicator == null) return
|
||||||
validationIndicator.validationState = validator.validate(valuesReadingContext, value)
|
validationIndicator.validationState = validator.validate(valuesReadingContext, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun focusOn() {
|
||||||
|
uiComponent.requestFocus()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun findComponentWithError(error: ValidationResult.ValidationError): FocusableComponent? = takeIf {
|
||||||
|
getUiValue()?.let { validator?.validate?.invoke(valuesReadingContext, it)?.isSpecificError(error) } == true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <V : Any> UIComponent<V>.valueForSetting(setting: Setting<V, SettingType<V>>): V? =
|
fun <V : Any> UIComponent<V>.valueForSetting(setting: Setting<V, SettingType<V>>): V? =
|
||||||
|
|||||||
+9
@@ -4,6 +4,7 @@ import com.intellij.ui.components.JBTabbedPane
|
|||||||
import org.jetbrains.kotlin.idea.projectWizard.UiEditorUsageStats
|
import org.jetbrains.kotlin.idea.projectWizard.UiEditorUsageStats
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.core.ValuesReadingContext
|
import org.jetbrains.kotlin.tools.projectWizard.core.ValuesReadingContext
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.core.entity.StringValidators
|
import org.jetbrains.kotlin.tools.projectWizard.core.entity.StringValidators
|
||||||
|
import org.jetbrains.kotlin.tools.projectWizard.core.entity.ValidationResult
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.configuratorSettings
|
import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.configuratorSettings
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.moduleType
|
import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.moduleType
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModuleType
|
import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModuleType
|
||||||
@@ -11,6 +12,7 @@ import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Module
|
|||||||
import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Module.Companion.ALLOWED_SPECIAL_CHARS_IN_MODULE_NAMES
|
import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Module.Companion.ALLOWED_SPECIAL_CHARS_IN_MODULE_NAMES
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.ModuleKind
|
import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.ModuleKind
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.DynamicComponent
|
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.DynamicComponent
|
||||||
|
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.FocusableComponent
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.components.TextFieldComponent
|
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.components.TextFieldComponent
|
||||||
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.SettingsList
|
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.SettingsList
|
||||||
@@ -33,6 +35,13 @@ class ModuleSettingsComponent(
|
|||||||
add("Module Settings", moduleConfiguratorSettingsList.component)
|
add("Module Settings", moduleConfiguratorSettingsList.component)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun selectSettingWithError(error: ValidationResult.ValidationError) {
|
||||||
|
val componentWithError = nameField.findComponentWithError(error)
|
||||||
|
?: moduleConfiguratorSettingsList.findComponentWithError(error)?.also { tabPanel.selectedIndex = 1 }
|
||||||
|
?: templateComponent.findComponentWithError(error)?.also { tabPanel.selectedIndex = 0 }
|
||||||
|
componentWithError?.focusOn()
|
||||||
|
}
|
||||||
|
|
||||||
private val nameField = TextFieldComponent(
|
private val nameField = TextFieldComponent(
|
||||||
valuesReadingContext,
|
valuesReadingContext,
|
||||||
labelText = "Name",
|
labelText = "Name",
|
||||||
|
|||||||
+12
-3
@@ -2,6 +2,7 @@ package org.jetbrains.kotlin.tools.projectWizard.wizard.ui.secondStep
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.idea.projectWizard.UiEditorUsageStats
|
import org.jetbrains.kotlin.idea.projectWizard.UiEditorUsageStats
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.core.ValuesReadingContext
|
import org.jetbrains.kotlin.tools.projectWizard.core.ValuesReadingContext
|
||||||
|
import org.jetbrains.kotlin.tools.projectWizard.core.entity.ValidationResult
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.settings.DisplayableSettingItem
|
import org.jetbrains.kotlin.tools.projectWizard.settings.DisplayableSettingItem
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Module
|
import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Module
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Sourceset
|
import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Sourceset
|
||||||
@@ -17,7 +18,9 @@ class SecondStepWizardComponent(
|
|||||||
uiEditorUsagesStats: UiEditorUsageStats
|
uiEditorUsagesStats: UiEditorUsageStats
|
||||||
) : WizardStepComponent(wizard.valuesReadingContext) {
|
) : WizardStepComponent(wizard.valuesReadingContext) {
|
||||||
private val moduleEditorSubStep =
|
private val moduleEditorSubStep =
|
||||||
ModulesEditorSubStep(wizard.valuesReadingContext, uiEditorUsagesStats, ::onNodeSelected).asSubComponent()
|
ModulesEditorSubStep(wizard.valuesReadingContext, uiEditorUsagesStats, ::onNodeSelected) {
|
||||||
|
templatesSubStep.selectSettingWithError(it)
|
||||||
|
}.asSubComponent()
|
||||||
private val templatesSubStep = ModuleSettingsSubStep(wizard, uiEditorUsagesStats).asSubComponent()
|
private val templatesSubStep = ModuleSettingsSubStep(wizard, uiEditorUsagesStats).asSubComponent()
|
||||||
|
|
||||||
override val component = splitterFor(
|
override val component = splitterFor(
|
||||||
@@ -34,12 +37,14 @@ class SecondStepWizardComponent(
|
|||||||
class ModulesEditorSubStep(
|
class ModulesEditorSubStep(
|
||||||
valuesReadingContext: ValuesReadingContext,
|
valuesReadingContext: ValuesReadingContext,
|
||||||
uiEditorUsagesStats: UiEditorUsageStats,
|
uiEditorUsagesStats: UiEditorUsageStats,
|
||||||
onNodeSelected: (data: DisplayableSettingItem?) -> Unit
|
onNodeSelected: (data: DisplayableSettingItem?) -> Unit,
|
||||||
|
selectSettingWithError: (ValidationResult.ValidationError) -> Unit
|
||||||
) : SubStep(valuesReadingContext) {
|
) : SubStep(valuesReadingContext) {
|
||||||
private val moduleSettingComponent = ModulesEditorComponent(
|
private val moduleSettingComponent = ModulesEditorComponent(
|
||||||
valuesReadingContext,
|
valuesReadingContext,
|
||||||
uiEditorUsagesStats,
|
uiEditorUsagesStats,
|
||||||
onNodeSelected
|
onNodeSelected,
|
||||||
|
selectSettingWithError
|
||||||
).asSubComponent()
|
).asSubComponent()
|
||||||
|
|
||||||
override fun buildContent(): JComponent = panel {
|
override fun buildContent(): JComponent = panel {
|
||||||
@@ -74,6 +79,10 @@ class ModuleSettingsSubStep(
|
|||||||
changeComponent()
|
changeComponent()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun selectSettingWithError(error: ValidationResult.ValidationError) {
|
||||||
|
moduleSettingsComponent.selectSettingWithError(error)
|
||||||
|
}
|
||||||
|
|
||||||
private fun changeComponent() {
|
private fun changeComponent() {
|
||||||
panel.removeAll()
|
panel.removeAll()
|
||||||
val component = when (selectedNode) {
|
val component = when (selectedNode) {
|
||||||
|
|||||||
+12
-2
@@ -10,6 +10,7 @@ import com.intellij.util.ui.UIUtil
|
|||||||
import org.jetbrains.kotlin.idea.KotlinIcons
|
import org.jetbrains.kotlin.idea.KotlinIcons
|
||||||
import org.jetbrains.kotlin.idea.projectWizard.UiEditorUsageStats
|
import org.jetbrains.kotlin.idea.projectWizard.UiEditorUsageStats
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.core.ValuesReadingContext
|
import org.jetbrains.kotlin.tools.projectWizard.core.ValuesReadingContext
|
||||||
|
import org.jetbrains.kotlin.tools.projectWizard.core.entity.ValidationResult
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.moduleType
|
import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.moduleType
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.plugins.templates.TemplatesPlugin
|
import org.jetbrains.kotlin.tools.projectWizard.plugins.templates.TemplatesPlugin
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Module
|
import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Module
|
||||||
@@ -17,6 +18,8 @@ import org.jetbrains.kotlin.tools.projectWizard.templates.Template
|
|||||||
import org.jetbrains.kotlin.tools.projectWizard.templates.settings
|
import org.jetbrains.kotlin.tools.projectWizard.templates.settings
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.*
|
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.*
|
||||||
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.setting.ErrorAwareComponent
|
||||||
|
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.SettingComponent
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.SettingsList
|
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.SettingsList
|
||||||
import java.awt.*
|
import java.awt.*
|
||||||
import javax.swing.JComponent
|
import javax.swing.JComponent
|
||||||
@@ -25,7 +28,7 @@ import javax.swing.JPanel
|
|||||||
class TemplatesComponent(
|
class TemplatesComponent(
|
||||||
valuesReadingContext: ValuesReadingContext,
|
valuesReadingContext: ValuesReadingContext,
|
||||||
uiEditorUsagesStats: UiEditorUsageStats
|
uiEditorUsagesStats: UiEditorUsageStats
|
||||||
) : DynamicComponent(valuesReadingContext) {
|
) : DynamicComponent(valuesReadingContext), ErrorAwareComponent {
|
||||||
private val chooseTemplateComponent: ChooseTemplateComponent =
|
private val chooseTemplateComponent: ChooseTemplateComponent =
|
||||||
ChooseTemplateComponent(valuesReadingContext) { template ->
|
ChooseTemplateComponent(valuesReadingContext) { template ->
|
||||||
uiEditorUsagesStats.moduleTemplatesSet++
|
uiEditorUsagesStats.moduleTemplatesSet++
|
||||||
@@ -49,6 +52,9 @@ class TemplatesComponent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun findComponentWithError(error: ValidationResult.ValidationError): SettingComponent<*, *>? =
|
||||||
|
templateSettingsComponent.findComponentWithError(error)
|
||||||
|
|
||||||
private fun switchState(selectedTemplate: Template?) {
|
private fun switchState(selectedTemplate: Template?) {
|
||||||
panel.removeAll()
|
panel.removeAll()
|
||||||
when (selectedTemplate) {
|
when (selectedTemplate) {
|
||||||
@@ -243,7 +249,7 @@ class TemplateDescriptionComponent(
|
|||||||
private class TemplateSettingsComponent(
|
private class TemplateSettingsComponent(
|
||||||
valuesReadingContext: ValuesReadingContext,
|
valuesReadingContext: ValuesReadingContext,
|
||||||
removeTemplate: () -> Unit
|
removeTemplate: () -> Unit
|
||||||
) : DynamicComponent(valuesReadingContext) {
|
) : DynamicComponent(valuesReadingContext), ErrorAwareComponent {
|
||||||
private val templateDescriptionComponent = TemplateDescriptionComponent(
|
private val templateDescriptionComponent = TemplateDescriptionComponent(
|
||||||
needRemoveButton = true,
|
needRemoveButton = true,
|
||||||
nonDefaultBackgroundColor = UIUtil.getEditorPaneBackground(),
|
nonDefaultBackgroundColor = UIUtil.getEditorPaneBackground(),
|
||||||
@@ -256,6 +262,10 @@ private class TemplateSettingsComponent(
|
|||||||
component.bordered()
|
component.bordered()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun findComponentWithError(error: ValidationResult.ValidationError): SettingComponent<*, *>? =
|
||||||
|
settings.findComponentWithError(error)
|
||||||
|
|
||||||
|
|
||||||
fun setTemplate(module: Module, selectedTemplate: Template) {
|
fun setTemplate(module: Module, selectedTemplate: Template) {
|
||||||
settings.setSettings(selectedTemplate.settings(module))
|
settings.setSettings(selectedTemplate.settings(module))
|
||||||
templateDescriptionComponent.updateSelectedTemplate(selectedTemplate)
|
templateDescriptionComponent.updateSelectedTemplate(selectedTemplate)
|
||||||
|
|||||||
+8
-2
@@ -4,6 +4,7 @@ import com.intellij.ui.JBColor
|
|||||||
import org.jetbrains.kotlin.idea.projectWizard.UiEditorUsageStats
|
import org.jetbrains.kotlin.idea.projectWizard.UiEditorUsageStats
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.core.entity.ListSettingType
|
import org.jetbrains.kotlin.tools.projectWizard.core.entity.ListSettingType
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.core.ValuesReadingContext
|
import org.jetbrains.kotlin.tools.projectWizard.core.ValuesReadingContext
|
||||||
|
import org.jetbrains.kotlin.tools.projectWizard.core.entity.ValidationResult
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.core.entity.reference
|
import org.jetbrains.kotlin.tools.projectWizard.core.entity.reference
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.KotlinPlugin
|
import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.KotlinPlugin
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ProjectKind
|
import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ProjectKind
|
||||||
@@ -20,7 +21,8 @@ import javax.swing.JComponent
|
|||||||
class ModulesEditorComponent(
|
class ModulesEditorComponent(
|
||||||
valuesReadingContext: ValuesReadingContext,
|
valuesReadingContext: ValuesReadingContext,
|
||||||
uiEditorUsagesStats: UiEditorUsageStats,
|
uiEditorUsagesStats: UiEditorUsageStats,
|
||||||
oneEntrySelected: (data: DisplayableSettingItem?) -> Unit
|
oneEntrySelected: (data: DisplayableSettingItem?) -> Unit,
|
||||||
|
selectSettingWithError: (ValidationResult.ValidationError) -> Unit
|
||||||
) : SettingComponent<List<Module>, ListSettingType<Module>>(KotlinPlugin::modules.reference, valuesReadingContext) {
|
) : SettingComponent<List<Module>, ListSettingType<Module>>(KotlinPlugin::modules.reference, valuesReadingContext) {
|
||||||
private val tree: ModulesEditorTree =
|
private val tree: ModulesEditorTree =
|
||||||
ModulesEditorTree(
|
ModulesEditorTree(
|
||||||
@@ -64,7 +66,11 @@ class ModulesEditorComponent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override val validationIndicator = ValidationIndicator(showText = true).apply {
|
override val validationIndicator = ValidationIndicator(showText = true) { error ->
|
||||||
|
val module = error.target as? Module ?: return@ValidationIndicator
|
||||||
|
tree.selectModule(module)
|
||||||
|
selectSettingWithError(error)
|
||||||
|
}.apply {
|
||||||
background = tree.background
|
background = tree.background
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+13
@@ -7,12 +7,14 @@ import com.intellij.ui.treeStructure.Tree
|
|||||||
import org.jetbrains.kotlin.tools.projectWizard.settings.DisplayableSettingItem
|
import org.jetbrains.kotlin.tools.projectWizard.settings.DisplayableSettingItem
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Module
|
import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Module
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Sourceset
|
import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.Sourceset
|
||||||
|
import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.path
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.icon
|
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.icon
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
import javax.swing.JComponent
|
import javax.swing.JComponent
|
||||||
import javax.swing.JTree
|
import javax.swing.JTree
|
||||||
import javax.swing.tree.DefaultMutableTreeNode
|
import javax.swing.tree.DefaultMutableTreeNode
|
||||||
import javax.swing.tree.DefaultTreeModel
|
import javax.swing.tree.DefaultTreeModel
|
||||||
|
import javax.swing.tree.TreePath
|
||||||
import javax.swing.tree.TreeSelectionModel
|
import javax.swing.tree.TreeSelectionModel
|
||||||
|
|
||||||
class ModulesEditorTree(
|
class ModulesEditorTree(
|
||||||
@@ -32,6 +34,17 @@ class ModulesEditorTree(
|
|||||||
openPaths.forEach(::expandPath)
|
openPaths.forEach(::expandPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun selectModule(moduleToSelect: Module) {
|
||||||
|
for (value in (model.root as DefaultMutableTreeNode).depthFirstEnumeration().iterator()) {
|
||||||
|
val node = value as? DefaultMutableTreeNode ?: continue
|
||||||
|
val module = node.userObject as? Module ?: continue
|
||||||
|
if (module.path == moduleToSelect.path) {
|
||||||
|
selectionPath = TreePath(node.path)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val selectedSettingItem
|
val selectedSettingItem
|
||||||
get() = selectedNode?.userObject?.safeAs<DisplayableSettingItem>()
|
get() = selectedNode?.userObject?.safeAs<DisplayableSettingItem>()
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -4,11 +4,12 @@ import org.jetbrains.kotlin.tools.projectWizard.core.ValuesReadingContext
|
|||||||
import org.jetbrains.kotlin.tools.projectWizard.core.entity.*
|
import org.jetbrains.kotlin.tools.projectWizard.core.entity.*
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.Displayable
|
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.Displayable
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.DynamicComponent
|
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.DynamicComponent
|
||||||
|
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.FocusableComponent
|
||||||
|
|
||||||
abstract class SettingComponent<V : Any, T: SettingType<V>>(
|
abstract class SettingComponent<V : Any, T: SettingType<V>>(
|
||||||
val reference: SettingReference<V, T>,
|
val reference: SettingReference<V, T>,
|
||||||
val valuesReadingContext: ValuesReadingContext
|
val valuesReadingContext: ValuesReadingContext
|
||||||
) : DynamicComponent(valuesReadingContext), Displayable {
|
) : DynamicComponent(valuesReadingContext), Displayable, FocusableComponent {
|
||||||
var value: V?
|
var value: V?
|
||||||
get() = reference.value
|
get() = reference.value
|
||||||
set(value) {
|
set(value) {
|
||||||
|
|||||||
+17
-3
@@ -3,18 +3,25 @@ package org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting
|
|||||||
import com.intellij.ui.components.panels.VerticalLayout
|
import com.intellij.ui.components.panels.VerticalLayout
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.core.ValuesReadingContext
|
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.SettingReference
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.Component
|
import org.jetbrains.kotlin.tools.projectWizard.core.entity.ValidationResult
|
||||||
|
import org.jetbrains.kotlin.tools.projectWizard.core.entity.isSpecificError
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.DynamicComponent
|
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.DynamicComponent
|
||||||
|
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.FocusableComponent
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.PanelWithStatusText
|
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.PanelWithStatusText
|
||||||
import javax.swing.JComponent
|
import javax.swing.JComponent
|
||||||
|
|
||||||
|
interface ErrorAwareComponent {
|
||||||
|
fun findComponentWithError(error: ValidationResult.ValidationError): FocusableComponent?
|
||||||
|
}
|
||||||
|
|
||||||
class SettingsList(
|
class SettingsList(
|
||||||
settings: List<SettingReference<*, *>>,
|
settings: List<SettingReference<*, *>>,
|
||||||
private val valuesReadingContext: ValuesReadingContext
|
private val valuesReadingContext: ValuesReadingContext
|
||||||
) : DynamicComponent(valuesReadingContext) {
|
) : DynamicComponent(valuesReadingContext), ErrorAwareComponent {
|
||||||
private val panel = PanelWithStatusText(VerticalLayout(5), "This module has no settings to configure")
|
private val panel = PanelWithStatusText(VerticalLayout(5), "This module has no settings to configure")
|
||||||
|
|
||||||
private var settingComponents: List<Component> = emptyList()
|
var settingComponents: List<SettingComponent<*, *>> = emptyList()
|
||||||
|
private set
|
||||||
|
|
||||||
init {
|
init {
|
||||||
setSettings(settings)
|
setSettings(settings)
|
||||||
@@ -35,4 +42,11 @@ class SettingsList(
|
|||||||
}
|
}
|
||||||
settingComponents.forEach { setting -> setting.onInit(); panel.add(setting.component) }
|
settingComponents.forEach { setting -> setting.onInit(); panel.add(setting.component) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun findComponentWithError(error: ValidationResult.ValidationError) =
|
||||||
|
settingComponents.firstOrNull { component ->
|
||||||
|
val value = component.value ?: return@firstOrNull false
|
||||||
|
val result = component.setting.validator.validate(valuesReadingContext, value)
|
||||||
|
result isSpecificError error
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+4
@@ -29,5 +29,9 @@ abstract class UIComponentDelegatingSettingComponent<V : Any, T : SettingType<V>
|
|||||||
value?.let(uiComponent::updateUiValue)
|
value?.let(uiComponent::updateUiValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun focusOn() {
|
||||||
|
uiComponent.focusOn()
|
||||||
|
}
|
||||||
|
|
||||||
override val component: JComponent by lazy(LazyThreadSafetyMode.NONE) { uiComponent.component }
|
override val component: JComponent by lazy(LazyThreadSafetyMode.NONE) { uiComponent.component }
|
||||||
}
|
}
|
||||||
+29
-3
@@ -2,28 +2,49 @@ package org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting
|
|||||||
|
|
||||||
import com.intellij.icons.AllIcons
|
import com.intellij.icons.AllIcons
|
||||||
import com.intellij.ui.JBColor
|
import com.intellij.ui.JBColor
|
||||||
import com.intellij.ui.components.JBLabel
|
|
||||||
import com.intellij.util.ui.EmptyIcon
|
import com.intellij.util.ui.EmptyIcon
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.core.entity.ValidationResult
|
import org.jetbrains.kotlin.tools.projectWizard.core.entity.ValidationResult
|
||||||
|
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.asHtml
|
||||||
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.label
|
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.label
|
||||||
import java.awt.BorderLayout
|
import java.awt.BorderLayout
|
||||||
|
import java.awt.Cursor
|
||||||
|
import java.awt.event.MouseEvent
|
||||||
|
import java.awt.event.MouseListener
|
||||||
import javax.swing.BorderFactory
|
import javax.swing.BorderFactory
|
||||||
import javax.swing.Icon
|
import javax.swing.Icon
|
||||||
import javax.swing.JPanel
|
import javax.swing.JPanel
|
||||||
|
|
||||||
class ValidationIndicator(
|
class ValidationIndicator(
|
||||||
defaultText: String? = null,
|
defaultText: String? = null,
|
||||||
private val showText: Boolean
|
private val showText: Boolean,
|
||||||
|
private val onClickAction: ((ValidationResult.ValidationError) -> Unit)? = null
|
||||||
) : JPanel(BorderLayout()) {
|
) : JPanel(BorderLayout()) {
|
||||||
private val textLabel = defaultText?.let { label("$it: ") }
|
private val textLabel = defaultText?.let { label("$it: ") }
|
||||||
private val errorLabel = label(" ").apply {
|
private val errorLabel = label(" ").apply {
|
||||||
foreground = JBColor.red
|
foreground = JBColor.red
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var currentError: ValidationResult.ValidationError? = null
|
||||||
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
border = BorderFactory.createEmptyBorder(3, 3, 3, 3)
|
border = BorderFactory.createEmptyBorder(3, 3, 3, 3)
|
||||||
textLabel?.let { add(it, BorderLayout.WEST) }
|
textLabel?.let { add(it, BorderLayout.WEST) }
|
||||||
add(errorLabel, BorderLayout.CENTER)
|
add(errorLabel, BorderLayout.CENTER)
|
||||||
|
|
||||||
|
if (onClickAction != null) {
|
||||||
|
cursor = Cursor(Cursor.HAND_CURSOR)
|
||||||
|
addMouseListener(object : MouseListener {
|
||||||
|
override fun mouseReleased(p0: MouseEvent?) {}
|
||||||
|
override fun mouseEntered(p0: MouseEvent?) {}
|
||||||
|
override fun mouseExited(p0: MouseEvent?) {}
|
||||||
|
override fun mousePressed(p0: MouseEvent?) {}
|
||||||
|
|
||||||
|
override fun mouseClicked(p0: MouseEvent?) {
|
||||||
|
currentError?.let(onClickAction)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setIcon(icon: Icon?) {
|
private fun setIcon(icon: Icon?) {
|
||||||
@@ -31,6 +52,9 @@ class ValidationIndicator(
|
|||||||
else errorLabel.icon = icon ?: EmptyIcon.ICON_16
|
else errorLabel.icon = icon ?: EmptyIcon.ICON_16
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun String.linkifyErrorText() =
|
||||||
|
if (onClickAction == null) this
|
||||||
|
else "<u>$this</u>".asHtml()
|
||||||
|
|
||||||
var validationState: ValidationResult = ValidationResult.OK
|
var validationState: ValidationResult = ValidationResult.OK
|
||||||
set(value) {
|
set(value) {
|
||||||
@@ -40,12 +64,14 @@ class ValidationIndicator(
|
|||||||
setIcon(null)
|
setIcon(null)
|
||||||
errorLabel.text = " "
|
errorLabel.text = " "
|
||||||
toolTipText = null
|
toolTipText = null
|
||||||
|
currentError = null
|
||||||
}
|
}
|
||||||
is ValidationResult.ValidationError -> {
|
is ValidationResult.ValidationError -> {
|
||||||
setIcon(AllIcons.General.Error)
|
setIcon(AllIcons.General.Error)
|
||||||
val errors = value.messages.firstOrNull().orEmpty()
|
val errors = value.messages.firstOrNull().orEmpty()
|
||||||
toolTipText = errors
|
toolTipText = errors
|
||||||
if (showText) errorLabel.text = errors
|
if (showText) errorLabel.text = errors.linkifyErrorText()
|
||||||
|
currentError = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -354,7 +354,7 @@ class ListSettingType<V : Any>(private val parser: Parser<V>) : SettingType<List
|
|||||||
validate { values ->
|
validate { values ->
|
||||||
values.fold(ValidationResult.OK as ValidationResult) { result, value ->
|
values.fold(ValidationResult.OK as ValidationResult) { result, value ->
|
||||||
result and when (value) {
|
result and when (value) {
|
||||||
is Validatable<*> -> (value.validator as SettingValidator<Any>).validate(this, value)
|
is Validatable<*> -> (value.validator as SettingValidator<Any>).validate(this, value).withTargetIfNull(value)
|
||||||
else -> ValidationResult.OK
|
else -> ValidationResult.OK
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-3
@@ -55,8 +55,8 @@ sealed class ValidationResult {
|
|||||||
override val isOk = true
|
override val isOk = true
|
||||||
}
|
}
|
||||||
|
|
||||||
class ValidationError(val messages: List<String>) : ValidationResult() {
|
data class ValidationError(val messages: List<String>, val target: Any? = null) : ValidationResult() {
|
||||||
constructor(message: String) : this(listOf(message))
|
constructor(message: String, target: Any? = null) : this(listOf(message), target)
|
||||||
|
|
||||||
override val isOk = false
|
override val isOk = false
|
||||||
}
|
}
|
||||||
@@ -73,6 +73,19 @@ sealed class ValidationResult {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
infix fun ValidationResult.isSpecificError(error: ValidationResult.ValidationError) =
|
||||||
|
this is ValidationResult.ValidationError && messages.firstOrNull() == error.messages.firstOrNull()
|
||||||
|
|
||||||
|
fun ValidationResult.withTarget(target: Any) = when (this) {
|
||||||
|
ValidationResult.OK -> this
|
||||||
|
is ValidationResult.ValidationError -> copy(target = target)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ValidationResult.withTargetIfNull(target: Any) = when (this) {
|
||||||
|
ValidationResult.OK -> this
|
||||||
|
is ValidationResult.ValidationError -> if (this.target == null) copy(target = target) else this
|
||||||
|
}
|
||||||
|
|
||||||
fun ValidationResult.toResult() = when (this) {
|
fun ValidationResult.toResult() = when (this) {
|
||||||
ValidationResult.OK -> UNIT_SUCCESS
|
ValidationResult.OK -> UNIT_SUCCESS
|
||||||
is ValidationResult.ValidationError -> Failure(messages.map { ValidationError(it) })
|
is ValidationResult.ValidationError -> Failure(messages.map { ValidationError(it) })
|
||||||
@@ -85,7 +98,7 @@ interface Validatable<out V> {
|
|||||||
|
|
||||||
fun <V, Q : Validatable<Q>> ValuesReadingContext.validateList(list: List<Q>) = settingValidator<V> {
|
fun <V, Q : Validatable<Q>> ValuesReadingContext.validateList(list: List<Q>) = settingValidator<V> {
|
||||||
list.fold(ValidationResult.OK as ValidationResult) { result, value ->
|
list.fold(ValidationResult.OK as ValidationResult) { result, value ->
|
||||||
result and value.validator.validate(this, value)
|
result and value.validator.validate(this, value).withTarget(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user