diff --git a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/Component.kt b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/Component.kt index 988176a73a5..eb451b7e060 100644 --- a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/Component.kt +++ b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/Component.kt @@ -60,6 +60,10 @@ abstract class DynamicComponent(private val context: Context) : Component() { open fun onValueUpdated(reference: SettingReference<*, *>?) {} } +abstract class TitledComponent(context: Context) : DynamicComponent(context) { + abstract val title: String? +} + interface FocusableComponent { fun focusOn() {} } \ No newline at end of file diff --git a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/components/DropDownComponent.kt b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/components/DropDownComponent.kt index c16ff969307..db03ebd5481 100644 --- a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/components/DropDownComponent.kt +++ b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/components/DropDownComponent.kt @@ -17,6 +17,7 @@ import javax.swing.JList class DropDownComponent( context: Context, initialValues: List = emptyList(), + initiallySelectedValue: T? = null, labelText: String? = null, private val filter: (T) -> Boolean = { true }, private val validator: SettingValidator = settingValidator { ValidationResult.OK }, @@ -29,9 +30,10 @@ class DropDownComponent( onValueUpdate ) { @Suppress("UNCHECKED_CAST") - override val uiComponent: ComboBox = ComboBox( + override val uiComponent: ComboBox = ComboBox( initialValues.filter(filter).toTypedArray() as Array ).apply { + selectedItem = initiallySelectedValue renderer = object : ColoredListCellRenderer() { override fun customizeCellRenderer( list: JList, diff --git a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/firstStep/FirstWizardStepComponent.kt b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/firstStep/FirstWizardStepComponent.kt index dea78305b56..51d8fd61a40 100644 --- a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/firstStep/FirstWizardStepComponent.kt +++ b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/firstStep/FirstWizardStepComponent.kt @@ -10,7 +10,7 @@ import org.jetbrains.kotlin.tools.projectWizard.plugins.projectTemplates.Project import org.jetbrains.kotlin.tools.projectWizard.wizard.IdeWizard import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.* import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.secondStep.modulesEditor.ModulesEditorComponent -import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.SettingsList +import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.TitledComponentsList import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.createSettingComponent import javax.swing.JComponent @@ -29,7 +29,7 @@ class ProjectSettingsComponent(context: Context) : DynamicComponent(context) { private val projectTemplateComponent = ProjectTemplateSettingComponent(context).asSubComponent() private val buildSystemSetting = BuildSystemTypeSettingComponent(context).asSubComponent() - private val nameAndLocationComponent = SettingsList( + private val nameAndLocationComponent = TitledComponentsList( listOf( StructurePlugin::name.reference.createSettingComponent(context), StructurePlugin::projectPath.reference.createSettingComponent(context), @@ -39,8 +39,10 @@ class ProjectSettingsComponent(context: Context) : DynamicComponent(context) { context ).asSubComponent() - override val component: JComponent = nameAndLocationComponent.component.apply { - border = JBUI.Borders.empty(10) + override val component: JComponent by lazy(LazyThreadSafetyMode.NONE) { + nameAndLocationComponent.component.apply { + border = JBUI.Borders.empty(10) + } } } diff --git a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/secondStep/ModuleSettingsComponent.kt b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/secondStep/ModuleSettingsComponent.kt index 8cda08b9d4f..e8e32413d17 100644 --- a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/secondStep/ModuleSettingsComponent.kt +++ b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/secondStep/ModuleSettingsComponent.kt @@ -1,60 +1,34 @@ package org.jetbrains.kotlin.tools.projectWizard.wizard.ui.secondStep -import com.intellij.ui.components.JBTabbedPane import org.jetbrains.kotlin.idea.projectWizard.UiEditorUsageStats import org.jetbrains.kotlin.tools.projectWizard.core.Context +import org.jetbrains.kotlin.tools.projectWizard.core.Reader 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.getConfiguratorSettings import org.jetbrains.kotlin.tools.projectWizard.moduleConfigurators.moduleType import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.ModuleType +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.Companion.ALLOWED_SPECIAL_CHARS_IN_MODULE_NAMES -import org.jetbrains.kotlin.tools.projectWizard.settings.buildsystem.ModuleKind +import org.jetbrains.kotlin.tools.projectWizard.templates.Template +import org.jetbrains.kotlin.tools.projectWizard.templates.settings import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.DynamicComponent +import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.TitledComponent +import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.borderPanel +import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.components.DropDownComponent 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.setting.SettingsList -import java.awt.BorderLayout +import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.TitledComponentsList +import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.createSettingComponent import javax.swing.JComponent class ModuleSettingsComponent( - context: Context, + private val context: Context, uiEditorUsagesStats: UiEditorUsageStats ) : DynamicComponent(context) { - private val validateModuleName = - StringValidators.shouldNotBeBlank("Module name") and - StringValidators.shouldBeValidIdentifier("Module Name", ALLOWED_SPECIAL_CHARS_IN_MODULE_NAMES) + private val settingsList = TitledComponentsList(emptyList(), context).asSubComponent() - private val moduleConfiguratorSettingsList = SettingsList(emptyList(), context).asSubComponent() - private val templateComponent = TemplatesComponent(context, uiEditorUsagesStats).asSubComponent() - - private val tabPanel = JBTabbedPane().apply { - add("Template", templateComponent.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( - context, - labelText = "Name", - onValueUpdate = { value -> - module?.name = value - context.write { eventManager.fireListeners(null) } - }, - validator = validateModuleName - ).asSubComponent() - - - override val component: JComponent = panel { - add(nameField.component, BorderLayout.NORTH) - add(tabPanel, BorderLayout.CENTER) + override val component: JComponent = borderPanel { + addToCenter(settingsList.component) } var module: Module? = null @@ -65,13 +39,82 @@ class ModuleSettingsComponent( } } + @OptIn(ExperimentalStdlibApi::class) private fun updateModule(module: Module) { - nameField.updateUiValue(module.name) - nameField.component.isVisible = module.kind != ModuleKind.target - || module.configurator.moduleType != ModuleType.common + val moduleSettingComponents = buildList { + add(ModuleNameComponent(context, module)) + createTemplatesListComponentForModule(module)?.let(::add) + addAll(module.getConfiguratorSettings().map { it.createSettingComponent(context) }) + module.template?.let { template -> + addAll(template.settings(module).map { it.createSettingComponent(context) }) + } + } - moduleConfiguratorSettingsList.setSettings(module.getConfiguratorSettings()) - templateComponent.module = module + settingsList.setComponents(moduleSettingComponents) + } + + private fun createTemplatesListComponentForModule(module: Module) = + read { availableTemplatesFor(module) }.takeIf { it.isNotEmpty() }?.let { templates -> + ModuleTemplateComponent(context, module, templates) { + updateModule(module) + component.updateUI() + } + } +} + +private class ModuleNameComponent(context: Context, module: Module) : TitledComponent(context) { + override val component: JComponent = TextFieldComponent( + context, + labelText = null, + initialValue = module.name, + validator = validateModuleName + ) { value -> + module.name = value + context.write { eventManager.fireListeners(null) } + }.component + + override val title: String = "Name" + + companion object { + private val validateModuleName = + StringValidators.shouldNotBeBlank("Module name") and + StringValidators.shouldBeValidIdentifier("Module Name", ALLOWED_SPECIAL_CHARS_IN_MODULE_NAMES) } } +private class ModuleTemplateComponent( + context: Context, + module: Module, + templates: List