Wizard: group project templates into the categories on the first step

#KT-39700 fixed
This commit is contained in:
Ilya Kirillov
2020-06-18 20:40:23 +03:00
parent bfedeed2c1
commit 11a680d7d8
4 changed files with 107 additions and 15 deletions
@@ -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<V>(
private val groups: List<ListGroup<V>>,
render: ColoredListCellRenderer<V>.(V) -> Unit,
onValueSelected: (V?) -> Unit
) : JBList<V>() {
private val values: List<V> = groups.flatMap { it.values }
@OptIn(ExperimentalStdlibApi::class)
private val elementIndexToPreviousSeparator: Map<Int, ListGroup<V>> = groups
.scan(0) { startElement, group -> startElement + group.values.size }
.dropLast(1)
.mapIndexed { groupIndex, startElement -> startElement to groups[groupIndex] }
.toMap()
private fun updateValues(newValues: List<V>) {
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<V> {
val separator = SeparatorWithText()
private val simpleRenderer = object : ColoredListCellRenderer<V>() {
public override fun customizeCellRenderer(
list: JList<out V>,
value: V?,
index: Int,
selected: Boolean,
hasFocus: Boolean
) {
render(value ?: return)
}
}
override fun getListCellRendererComponent(
list: JList<out V>?,
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<V>(
val title: String,
val values: List<V>
)
}
@@ -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
}
}
@@ -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.
@@ -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