Wizard: place all settings of first step into one setting list

This commit is contained in:
Ilya Kirillov
2020-03-13 15:43:46 +03:00
parent 586b044235
commit cbfe05efc8
8 changed files with 71 additions and 125 deletions
@@ -24,7 +24,7 @@ class BuildSystemTypeSettingComponent(
override val uiComponent: DropDownComponent<BuildSystemType> = DropDownComponent( override val uiComponent: DropDownComponent<BuildSystemType> = DropDownComponent(
context, context,
setting.type.values, setting.type.values,
labelText = "Build System", labelText = null,
filter = { value -> read { setting.type.filter(this, reference, value) } }, filter = { value -> read { setting.type.filter(this, reference, value) } },
validator = setting.validator, validator = setting.validator,
iconProvider = BuildSystemType::icon, iconProvider = BuildSystemType::icon,
@@ -1,111 +1,27 @@
package org.jetbrains.kotlin.tools.projectWizard.wizard.ui.firstStep package org.jetbrains.kotlin.tools.projectWizard.wizard.ui.firstStep
import TemplateTag
import com.intellij.ide.plugins.newui.VerticalLayout
import com.intellij.util.ui.JBUI
import org.jetbrains.kotlin.tools.projectWizard.core.Context
import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.SettingReference
import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.reference import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.reference
import org.jetbrains.kotlin.tools.projectWizard.plugins.StructurePlugin import org.jetbrains.kotlin.tools.projectWizard.plugins.StructurePlugin
import org.jetbrains.kotlin.tools.projectWizard.plugins.kotlin.KotlinPlugin
import org.jetbrains.kotlin.tools.projectWizard.plugins.projectTemplates.ProjectTemplatesPlugin
import org.jetbrains.kotlin.tools.projectWizard.plugins.projectTemplates.applyProjectTemplate
import org.jetbrains.kotlin.tools.projectWizard.projectTemplates.ProjectTemplate
import org.jetbrains.kotlin.tools.projectWizard.wizard.IdeWizard import org.jetbrains.kotlin.tools.projectWizard.wizard.IdeWizard
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.* import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.WizardStepComponent
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.PathSettingComponent
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.SettingsList import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.SettingsList
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.StringSettingComponent import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.createSettingComponent
import java.awt.BorderLayout
import javax.swing.Box
import javax.swing.BoxLayout
import javax.swing.JComponent import javax.swing.JComponent
import java.awt.Component as AwtComponent
class FirstWizardStepComponent(wizard: IdeWizard) : WizardStepComponent(wizard.context) { class FirstWizardStepComponent(wizard: IdeWizard) : WizardStepComponent(wizard.context) {
private val context = wizard.context
private val projectTemplateComponent = ProjectTemplateSettingComponent(context).asSubComponent()
private val buildSystemSetting = BuildSystemTypeSettingComponent(context).asSubComponent()
private val nameAndLocationComponent = SettingsList( private val nameAndLocationComponent = SettingsList(
listOf( listOf(
StructurePlugin::name.reference, StructurePlugin::name.reference.createSettingComponent(context),
StructurePlugin::projectPath.reference StructurePlugin::projectPath.reference.createSettingComponent(context),
projectTemplateComponent,
buildSystemSetting
), ),
wizard.context wizard.context
).asSubComponent() ).asSubComponent()
private val buildSystemSubStep = BuildSystemSubStep(wizard.context).asSubComponent()
private val templatesSubStep = TemplatesSubStep(wizard.context).asSubComponent()
override val component: JComponent = panel { override val component: JComponent = nameAndLocationComponent.component
add(nameAndLocationComponent.component, BorderLayout.CENTER)
add(buildSystemSubStep.component, BorderLayout.SOUTH)
}
} }
class BuildSystemSubStep(context: Context) : SubStep(context) {
private val buildSystemSetting = BuildSystemTypeSettingComponent(context).asSubComponent()
override fun buildContent(): JComponent = panel {
add(buildSystemSetting.component, BorderLayout.CENTER)
}
}
class TemplatesSubStep(context: Context) : SubStep(context) {
private val projectTemplateSettingComponent =
ProjectTemplateSettingComponent(context) { projectTemplate ->
templateDescriptionComponent.setTemplate(projectTemplate)
}.asSubComponent()
private val templateDescriptionComponent = TemplateDescriptionComponent().asSubComponent()
override fun buildContent(): JComponent = panel {
add(projectTemplateSettingComponent.component, BorderLayout.CENTER)
add(templateDescriptionComponent.component, BorderLayout.SOUTH)
}
override fun onInit() {
super.onInit()
applySelectedTemplate()
}
private fun applySelectedTemplate() {
modify {
val selectedProjectTemplate = projectTemplateSettingComponent.value ?: return@modify
applyProjectTemplate(selectedProjectTemplate)
}
}
override fun onValueUpdated(reference: SettingReference<*, *>?) {
super.onValueUpdated(reference)
if (reference == ProjectTemplatesPlugin::template.reference) {
applySelectedTemplate()
}
}
}
class TemplateDescriptionComponent : Component() {
private val tagsPanel = panel {
layout = BoxLayout(this, BoxLayout.X_AXIS)
alignmentX = AwtComponent.LEFT_ALIGNMENT
alignmentY = AwtComponent.TOP_ALIGNMENT
border = JBUI.Borders.emptyBottom(6)
}
private val descriptionPanel = DescriptionPanel()
fun setTemplate(template: ProjectTemplate) {
addTagsToPanel(template.tags)
descriptionPanel.updateText(template.htmlDescription)
}
private fun addTagsToPanel(tags: List<TemplateTag>) {
tagsPanel.removeAll()
for (tag in tags) {
tagsPanel.add(TemplateTagUIComponent(tag))
tagsPanel.add(Box.createHorizontalStrut(6))
}
tagsPanel.updateUI()
}
override val component: JComponent = panel {
bordered()
add(tagsPanel, BorderLayout.NORTH)
add(descriptionPanel, BorderLayout.CENTER)
}
}
@@ -1,25 +1,28 @@
package org.jetbrains.kotlin.tools.projectWizard.wizard.ui.firstStep package org.jetbrains.kotlin.tools.projectWizard.wizard.ui.firstStep
import com.intellij.util.ui.JBUI
import com.intellij.util.ui.UIUtil
import org.jetbrains.kotlin.tools.projectWizard.core.Context import org.jetbrains.kotlin.tools.projectWizard.core.Context
import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.DropDownSettingType import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.DropDownSettingType
import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.SettingReference
import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.reference import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.reference
import org.jetbrains.kotlin.tools.projectWizard.plugins.projectTemplates.ProjectTemplatesPlugin import org.jetbrains.kotlin.tools.projectWizard.plugins.projectTemplates.ProjectTemplatesPlugin
import org.jetbrains.kotlin.tools.projectWizard.plugins.projectTemplates.applyProjectTemplate
import org.jetbrains.kotlin.tools.projectWizard.projectTemplates.ProjectTemplate import org.jetbrains.kotlin.tools.projectWizard.projectTemplates.ProjectTemplate
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.* import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.*
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.ValidationIndicator import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting.ValidationIndicator
import java.awt.BorderLayout import java.awt.BorderLayout
import javax.swing.BorderFactory
import javax.swing.JComponent import javax.swing.JComponent
class ProjectTemplateSettingComponent( class ProjectTemplateSettingComponent(
context: Context, context: Context
private val onSelected: (ProjectTemplate) -> Unit
) : SettingComponent<ProjectTemplate, DropDownSettingType<ProjectTemplate>>( ) : SettingComponent<ProjectTemplate, DropDownSettingType<ProjectTemplate>>(
ProjectTemplatesPlugin::template.reference, ProjectTemplatesPlugin::template.reference,
context context
) { ) {
override val validationIndicator: ValidationIndicator? get() = null override val validationIndicator: ValidationIndicator? get() = null
private val templateDescriptionComponent = TemplateDescriptionComponent().asSubComponent()
private val list = ImmutableSingleSelectableListWithIcon( private val list = ImmutableSingleSelectableListWithIcon(
setting.type.values, setting.type.values,
@@ -27,33 +30,47 @@ class ProjectTemplateSettingComponent(
icon = value.projectKind.icon icon = value.projectKind.icon
append(value.title) append(value.title)
}, },
onValueSelected = { onValueSelected = { value = it }
onValueSelected(it!!) ).bordered(needTopEmptyBorder = false, needInnerEmptyBorder = false, needBottomEmptyBorder = false)
}
).apply {
border = BorderFactory.createEmptyBorder( override val component: JComponent = panel {
UiConstants.GAP_BORDER_SIZE, add(list, BorderLayout.CENTER)
UiConstants.GAP_BORDER_SIZE, add(
UiConstants.GAP_BORDER_SIZE, templateDescriptionComponent.component.withBorder(JBUI.Borders.emptyTop(5)),
UiConstants.GAP_BORDER_SIZE BorderLayout.SOUTH
) )
} }
private fun onValueSelected(selected: ProjectTemplate) { private fun applySelectedTemplate() = modify {
value = selected value?.let(::applyProjectTemplate)
onSelected(selected)
} }
override val component: JComponent = panel { override fun onValueUpdated(reference: SettingReference<*, *>?) {
bordered(needTopEmptyBorder = false, needInnerEmptyBorder = false) super.onValueUpdated(reference)
add(list, BorderLayout.CENTER) if (reference == ProjectTemplatesPlugin::template.reference) {
applySelectedTemplate()
value?.let(templateDescriptionComponent::setTemplate)
}
} }
override fun onInit() { override fun onInit() {
super.onInit() super.onInit()
if (setting.type.values.isNotEmpty()) { if (setting.type.values.isNotEmpty()) {
list.selectedIndex = 0 list.selectedIndex = 0
onValueSelected(setting.type.values.first()) value = setting.type.values.firstOrNull()
} }
} }
}
class TemplateDescriptionComponent : Component() {
private val descriptionLabel = label("").apply {
fontColor = UIUtil.FontColor.BRIGHTER
}
fun setTemplate(template: ProjectTemplate) {
descriptionLabel.text = template.htmlDescription
}
override val component: JComponent = descriptionLabel
} }
@@ -59,6 +59,9 @@ object DefaultSettingComponent {
} }
} }
fun <V : Any, T : SettingType<V>> SettingReference<V, T>.createSettingComponent(context: Context) =
DefaultSettingComponent.create(this, context, needLabel = false)
class VersionSettingComponent( class VersionSettingComponent(
reference: SettingReference<Version, VersionSettingType>, reference: SettingReference<Version, VersionSettingType>,
context: Context context: Context
@@ -14,15 +14,13 @@ interface ErrorAwareComponent {
} }
class SettingsList( class SettingsList(
settings: List<SettingReference<*, *>>, private var settingComponents: List<SettingComponent<*, *>>,
private val context: Context private val context: Context
) : DynamicComponent(context), ErrorAwareComponent { ) : DynamicComponent(context), ErrorAwareComponent {
private val ui = BorderLayoutPanel() private val ui = BorderLayoutPanel()
private var settingComponents: List<SettingComponent<*, *>> = emptyList()
init { init {
setSettings(settings) setSettingComponents(settingComponents)
} }
override val component get() = ui override val component get() = ui
@@ -32,11 +30,9 @@ class SettingsList(
settingComponents.forEach { it.onInit() } settingComponents.forEach { it.onInit() }
} }
fun setSettings(settings: List<SettingReference<*, *>>) { private fun setSettingComponents(settingComponents: List<SettingComponent<*, *>>) {
this.settingComponents = settingComponents
ui.removeAll() ui.removeAll()
settingComponents = settings.map { setting ->
DefaultSettingComponent.create(setting, context, needLabel = false)
}
ui.addToCenter(panel { ui.addToCenter(panel {
settingComponents.forEach { settingComponent -> settingComponents.forEach { settingComponent ->
settingComponent.onInit() settingComponent.onInit()
@@ -47,6 +43,15 @@ class SettingsList(
}) })
} }
fun setSettings(settings: List<SettingReference<*, *>>) {
setSettingComponents(
settings.map { setting ->
DefaultSettingComponent.create(setting, context, needLabel = false)
}
)
}
override fun findComponentWithError(error: ValidationResult.ValidationError) = read { override fun findComponentWithError(error: ValidationResult.ValidationError) = read {
settingComponents.firstOrNull { component -> settingComponents.firstOrNull { component ->
val value = component.value ?: return@firstOrNull false val value = component.value ?: return@firstOrNull false
@@ -31,6 +31,7 @@ import javax.swing.BorderFactory
import javax.swing.Icon import javax.swing.Icon
import javax.swing.JComponent import javax.swing.JComponent
import javax.swing.JPanel import javax.swing.JPanel
import javax.swing.border.Border
import javax.swing.event.DocumentEvent import javax.swing.event.DocumentEvent
import javax.swing.event.DocumentListener import javax.swing.event.DocumentListener
@@ -170,6 +171,10 @@ fun <C : JComponent> C.bordered(
) )
} }
fun <C : JComponent> C.withBorder(border: Border): C = apply {
this.border = BorderFactory.createCompoundBorder(border, this.border)
}
class TemplateTagUIComponent(tag: TemplateTag) : TagComponent(tag.text) { class TemplateTagUIComponent(tag: TemplateTag) : TagComponent(tag.text) {
override fun isInClickableArea(pt: Point?) = false override fun isInClickableArea(pt: Point?) = false
@@ -12,7 +12,7 @@ import org.jetbrains.kotlin.tools.projectWizard.settings.version.Version
import java.nio.file.Paths import java.nio.file.Paths
class StructurePlugin(context: Context) : Plugin(context) { class StructurePlugin(context: Context) : Plugin(context) {
val projectPath by pathSetting("Root path", GenerationPhase.PROJECT_GENERATION) { val projectPath by pathSetting("Location", GenerationPhase.PROJECT_GENERATION) {
defaultValue = value(Paths.get(".")) defaultValue = value(Paths.get("."))
} }
val name by stringSetting("Name", GenerationPhase.PROJECT_GENERATION) val name by stringSetting("Name", GenerationPhase.PROJECT_GENERATION)
@@ -9,7 +9,7 @@ import org.jetbrains.kotlin.tools.projectWizard.projectTemplates.ProjectTemplate
class ProjectTemplatesPlugin(context: Context) : Plugin(context) { class ProjectTemplatesPlugin(context: Context) : Plugin(context) {
val template by dropDownSetting<ProjectTemplate>( val template by dropDownSetting<ProjectTemplate>(
"Template", "Project template",
GenerationPhase.INIT_TEMPLATE, GenerationPhase.INIT_TEMPLATE,
parser = valueParserM { _, _ -> parser = valueParserM { _, _ ->
Failure(ParseError("Project templates is not supported in yaml for now")) Failure(ParseError("Project templates is not supported in yaml for now"))