From 11a680d7d8d6df2585e00e024346092affe7d14d Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Thu, 18 Jun 2020 20:40:23 +0300 Subject: [PATCH] Wizard: group project templates into the categories on the first step #KT-39700 fixed --- .../wizard/ui/ListWithSeparators.kt | 85 +++++++++++++++++++ .../ProjectTemplateSettingComponent.kt | 15 +++- .../KotlinNewProjectWizardBundle.properties | 20 ++--- .../JsModuleConfigurator.kt | 2 +- 4 files changed, 107 insertions(+), 15 deletions(-) create mode 100644 idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/ListWithSeparators.kt diff --git a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/ListWithSeparators.kt b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/ListWithSeparators.kt new file mode 100644 index 00000000000..d4c29b1a7f0 --- /dev/null +++ b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/ListWithSeparators.kt @@ -0,0 +1,85 @@ +/* + * 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 + +import com.intellij.ui.ColoredListCellRenderer +import com.intellij.ui.SeparatorWithText +import com.intellij.ui.components.JBList +import java.awt.Component +import javax.swing.JList +import javax.swing.ListCellRenderer + +class ListWithSeparators( + private val groups: List>, + render: ColoredListCellRenderer.(V) -> Unit, + onValueSelected: (V?) -> Unit +) : JBList() { + private val values: List = groups.flatMap { it.values } + + @OptIn(ExperimentalStdlibApi::class) + private val elementIndexToPreviousSeparator: Map> = groups + .scan(0) { startElement, group -> startElement + group.values.size } + .dropLast(1) + .mapIndexed { groupIndex, startElement -> startElement to groups[groupIndex] } + .toMap() + + private fun updateValues(newValues: List) { + setModel(createDefaultListModel(newValues)) + if (newValues.isNotEmpty()) { + selectedIndex = 0 + } + } + + init { + updateValues(values) + + selectionModel.addListSelectionListener { e -> + if (e.valueIsAdjusting) return@addListSelectionListener + val selectedValue = when (selectedIndex) { + -1 -> null + else -> this.model.getElementAt(selectedIndex) + } + onValueSelected(selectedValue) + } + + cellRenderer = object : ListCellRenderer { + val separator = SeparatorWithText() + private val simpleRenderer = object : ColoredListCellRenderer() { + public override fun customizeCellRenderer( + list: JList, + value: V?, + index: Int, + selected: Boolean, + hasFocus: Boolean + ) { + render(value ?: return) + } + } + + override fun getListCellRendererComponent( + list: JList?, + value: V, + index: Int, + isSelected: Boolean, + cellHasFocus: Boolean + ): Component { + return borderPanel { + background = this@ListWithSeparators.background + elementIndexToPreviousSeparator[index]?.let { group -> + addToTop(separator.apply { caption = group.title }) + } + addToCenter(simpleRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus)) + } + } + } + } + + data class ListGroup( + val title: String, + val values: List + ) +} + diff --git a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/firstStep/ProjectTemplateSettingComponent.kt b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/firstStep/ProjectTemplateSettingComponent.kt index b1b4afc363b..1b158bb286a 100644 --- a/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/firstStep/ProjectTemplateSettingComponent.kt +++ b/idea/idea-new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/wizard/ui/firstStep/ProjectTemplateSettingComponent.kt @@ -1,6 +1,7 @@ package org.jetbrains.kotlin.tools.projectWizard.wizard.ui.firstStep import com.intellij.ui.ScrollPaneFactory +import com.intellij.ui.SeparatorWithText import com.intellij.util.ui.JBUI import org.jetbrains.kotlin.idea.KotlinIcons import org.jetbrains.kotlin.tools.projectWizard.core.Context @@ -27,9 +28,15 @@ class ProjectTemplateSettingComponent( override val forceLabelCenteringOffset: Int? = 4 private val templateDescriptionComponent = TemplateDescriptionComponent().asSubComponent() - private val list = ImmutableSingleSelectableListWithIcon( - setting.type.values, - renderValue = { value -> + private val templateGroups = setting.type.values + .groupBy { it.projectKind } + .map { (group, templates) -> + ListWithSeparators.ListGroup(group.text, templates) + } + + private val list = ListWithSeparators( + templateGroups, + render = { value -> icon = value.icon append(value.title) }, @@ -69,7 +76,7 @@ class ProjectTemplateSettingComponent( } companion object { - private const val HEIGHT = 230 + private const val HEIGHT = 310 } } diff --git a/libraries/tools/new-project-wizard/resources/messages/KotlinNewProjectWizardBundle.properties b/libraries/tools/new-project-wizard/resources/messages/KotlinNewProjectWizardBundle.properties index 18fac67c828..42b53160525 100644 --- a/libraries/tools/new-project-wizard/resources/messages/KotlinNewProjectWizardBundle.properties +++ b/libraries/tools/new-project-wizard/resources/messages/KotlinNewProjectWizardBundle.properties @@ -23,7 +23,7 @@ module.kind.mpp.module=MPP Module module.kind.target=Target plugin.buildsystem.setting.type=Build System -plugin.buildsystem.setting.type.error.wrong.project.kind={0} cannot be generated using {1} +plugin.buildsystem.setting.type.error.wrong.project.kind={0} project cannot be generated using {1} plugin.kotlin.downloading.kotlin.versions=Downloading list of Kotlin versions plugin.kotlin.setting.modules=Modules @@ -32,10 +32,10 @@ plugin.kotlin.setting.modules.error.duplicated.targets=There are {0} targets wit plugin.kotlin.setting.project.kind=Project Kind -project.kind.android=Android project -project.kind.kotlin.js=Kotlin/JS project -project.kind.multiplatform=Multiplatform project -project.kind.singleplatform=Singleplatform project +project.kind.android=Android +project.kind.kotlin.js=Kotlin/JS +project.kind.multiplatform=Multiplatform +project.kind.singleplatform=JVM project=Project @@ -103,16 +103,16 @@ module.configurator.tests.setting.framework.common=Common module.configurator.tests.setting.framework.none=None module.configurator.native.for.current.system=Your system -project.template.empty.singleplatform.title=Backend Application +project.template.empty.singleplatform.title=Application project.template.empty.singleplatform.description=Backend application with Kotlin/JVM. -project.template.empty.mpp.title=Multiplatform Application +project.template.empty.mpp.title=Application project.template.empty.mpp.description=Applications for different platforms that support sharing common code. project.template.empty.jvm.console.title=Console Application project.template.empty.jvm.console.description=Console application with Kotlin/JVM. Use it for prototyping or testing purposes. -project.template.mpp.lib.title=Multiplatform Library +project.template.mpp.lib.title=Library project.template.mpp.lib.description=Library for sharing common code among different platforms. project.template.full.stack.title=Full-Stack Web Application @@ -124,10 +124,10 @@ project.template.native.console.description=Application with Kotlin/Native that project.template.frontend.title=Frontend Application project.template.frontend.description=Frontend application with Kotlin/JS if you already have a backend. -project.template.mpp.mobile.title=Multiplatform Mobile Application +project.template.mpp.mobile.title=Mobile Application project.template.mpp.mobile.description=Mobile applications for iOS and Android with Kotlin Multiplatform Mobile, which supports sharing common code between platforms. -project.template.mpp.mobile.lib.title=Multiplatform Mobile Library +project.template.mpp.mobile.lib.title=Mobile Library project.template.mpp.mobile.lib.description=Library that supports sharing code between iOS and Android. diff --git a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/JsModuleConfigurator.kt b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/JsModuleConfigurator.kt index 36b68947f77..94a702593b6 100644 --- a/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/JsModuleConfigurator.kt +++ b/libraries/tools/new-project-wizard/src/org/jetbrains/kotlin/tools/projectWizard/moduleConfigurators/JsModuleConfigurator.kt @@ -21,7 +21,7 @@ interface JSConfigurator : ModuleConfiguratorWithModuleType { override val moduleType: ModuleType get() = ModuleType.js } -object JsSingleplatformModuleConfigurator : JSConfigurator, ModuleConfiguratorWithTests, SinglePlatformModuleConfigurator { +object JsSingleplatformModuleConfigurator : JSConfigurator, ModuleConfiguratorWithTests, SinglePlatformModuleConfigurator, ModuleConfiguratorWithSettings { override val moduleKind = ModuleKind.singleplatformJs @NonNls