Wizard: add project name and path to the first step

This commit is contained in:
Ilya Kirillov
2020-03-13 14:35:29 +03:00
parent cf7bbdde10
commit 586b044235
6 changed files with 83 additions and 36 deletions
@@ -1,8 +1,10 @@
package org.jetbrains.kotlin.tools.projectWizard.wizard
import com.intellij.ide.RecentProjectsManager
import com.intellij.ide.projectWizard.ProjectSettingsStep
import com.intellij.ide.util.projectWizard.*
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.ApplicationNamesInfo
import com.intellij.openapi.module.ModifiableModuleModel
import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.module.ModuleType
@@ -20,14 +22,13 @@ import org.jetbrains.kotlin.idea.projectWizard.UiEditorUsageStats
import org.jetbrains.kotlin.idea.projectWizard.WizardStatsService
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.tools.projectWizard.core.Failure
import org.jetbrains.kotlin.tools.projectWizard.core.Success
import org.jetbrains.kotlin.tools.projectWizard.core.*
import org.jetbrains.kotlin.tools.projectWizard.core.entity.StringValidators
import org.jetbrains.kotlin.tools.projectWizard.core.entity.ValidationResult
import org.jetbrains.kotlin.tools.projectWizard.core.isSuccess
import org.jetbrains.kotlin.tools.projectWizard.core.onFailure
import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.reference
import org.jetbrains.kotlin.tools.projectWizard.phases.GenerationPhase
import org.jetbrains.kotlin.tools.projectWizard.plugins.Plugins
import org.jetbrains.kotlin.tools.projectWizard.plugins.StructurePlugin
import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.BuildSystemType
import org.jetbrains.kotlin.tools.projectWizard.plugins.projectTemplates.ProjectTemplatesPlugin
import org.jetbrains.kotlin.tools.projectWizard.wizard.service.IdeaServices
@@ -37,6 +38,7 @@ import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.firstStep.FirstWizardS
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.runWithProgressBar
import org.jetbrains.kotlin.tools.projectWizard.wizard.ui.secondStep.SecondStepWizardComponent
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import java.io.File
import java.nio.file.Paths
import javax.swing.JComponent
import com.intellij.openapi.module.Module as IdeaModule
@@ -117,7 +119,6 @@ class NewProjectWizardModuleBuilder : EmptyModuleBuilder() {
override fun modifySettingsStep(settingsStep: SettingsStep): ModuleWizardStep {
updateProjectNameAndPomDate(settingsStep)
return when (wizard.buildSystemType) {
BuildSystemType.Jps -> {
KotlinModuleSettingStep(
@@ -149,8 +150,8 @@ class NewProjectWizardModuleBuilder : EmptyModuleBuilder() {
ProjectTemplatesPlugin::template.settingValue.suggestedProjectName.decapitalize()
}
settingsStep.moduleNameLocationSettings?.apply {
val projectParentDirectory = moduleContentRoot.let { Paths.get(it).parent.toString() }
moduleName = ProjectWizardUtil.findNonExistingFileName(projectParentDirectory, suggestedProjectName, "")
moduleName = wizard.projectName!!
moduleContentRoot = wizard.projectPath!!.toString()
}
settingsStep.safeAs<ProjectSettingsStep>()?.bindModuleSettings()
@@ -184,7 +185,7 @@ class NewProjectWizardModuleBuilder : EmptyModuleBuilder() {
abstract class WizardStep(protected val wizard: IdeWizard, private val phase: GenerationPhase) : ModuleWizardStep() {
override fun updateDataModel() = Unit // model is updated on every UI action
override fun validate(): Boolean =
when (val result = wizard.context.read{ with(wizard) { validate(setOf(phase)) } }) {
when (val result = wizard.context.read { with(wizard) { validate(setOf(phase)) } }) {
is Success<*> -> true
is Failure -> {
throw ConfigurationException(result.asHtml(), KotlinNewProjectWizardBundle.message("error.validation"))
@@ -214,6 +215,7 @@ class ModuleNewWizardFirstStep(wizard: IdeWizard) : WizardStep(wizard, Generatio
init {
runPreparePhase()
initDefaultProjectNameAndPathValues()
component.onInit()
}
@@ -222,6 +224,26 @@ class ModuleNewWizardFirstStep(wizard: IdeWizard) : WizardStep(wizard, Generatio
ProgressManager.getInstance().progressIndicator.text = task.title ?: ""
}
}
private fun initDefaultProjectNameAndPathValues() {
val suggestedProjectParentLocation = suggestProjectLocation()
val suggestedProjectName = ProjectWizardUtil.findNonExistingFileName(suggestedProjectParentLocation, "untitled", "")
wizard.context.writeSettings {
StructurePlugin::name.reference.setValue(suggestedProjectName)
StructurePlugin::projectPath.reference.setValue(suggestedProjectParentLocation / suggestedProjectName)
}
}
// copied from com.intellij.ide.util.projectWizard.WizardContext.getProjectFileDirectory
private fun suggestProjectLocation(): String {
val lastProjectLocation = RecentProjectsManager.getInstance().lastProjectCreationLocation
if (lastProjectLocation != null) {
return lastProjectLocation.replace('/', File.separatorChar)
}
val userHome = SystemProperties.getUserHome()
val productName = ApplicationNamesInfo.getInstance().lowercaseProductName
return userHome.replace('/', File.separatorChar) + File.separator + productName.replace(" ", "") + "Projects"
}
}
class ModuleNewWizardSecondStep(
@@ -13,19 +13,19 @@ class PomWizardStepComponent(context: Context) : WizardStepComponent(context) {
private val groupIdComponent = StringSettingComponent(
StructurePlugin::groupId.reference,
context,
showLabel = true
needLabel = true
).asSubComponent()
private val artifactIdComponent = StringSettingComponent(
StructurePlugin::artifactId.reference,
context,
showLabel = true
needLabel = true
).asSubComponent()
private val versionComponent = StringSettingComponent(
StructurePlugin::version.reference,
context,
showLabel = true
needLabel = true
).asSubComponent()
@@ -1,15 +1,21 @@
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.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.ui.*
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.StringSettingComponent
import java.awt.BorderLayout
import javax.swing.Box
import javax.swing.BoxLayout
@@ -17,11 +23,18 @@ import javax.swing.JComponent
import java.awt.Component as AwtComponent
class FirstWizardStepComponent(wizard: IdeWizard) : WizardStepComponent(wizard.context) {
private val nameAndLocationComponent = SettingsList(
listOf(
StructurePlugin::name.reference,
StructurePlugin::projectPath.reference
),
wizard.context
).asSubComponent()
private val buildSystemSubStep = BuildSystemSubStep(wizard.context).asSubComponent()
private val templatesSubStep = TemplatesSubStep(wizard.context).asSubComponent()
override val component: JComponent = panel {
add(templatesSubStep.component, BorderLayout.CENTER)
add(nameAndLocationComponent.component, BorderLayout.CENTER)
add(buildSystemSubStep.component, BorderLayout.SOUTH)
}
}
@@ -23,7 +23,8 @@ object DefaultSettingComponent {
@Suppress("UNCHECKED_CAST")
fun <V : Any, T : SettingType<V>> create(
setting: SettingReference<V, T>,
context: Context
context: Context,
needLabel: Boolean = true
): SettingComponent<V, T> = when (setting.type) {
VersionSettingType::class ->
VersionSettingComponent(
@@ -33,22 +34,26 @@ object DefaultSettingComponent {
BooleanSettingType::class ->
BooleanSettingComponent(
setting as SettingReference<Boolean, BooleanSettingType>,
context
context,
needLabel
) as SettingComponent<V, T>
DropDownSettingType::class ->
DropdownSettingComponent(
setting as SettingReference<DisplayableSettingItem, DropDownSettingType<DisplayableSettingItem>>,
context
context,
needLabel
) as SettingComponent<V, T>
StringSettingType::class ->
StringSettingComponent(
setting as SettingReference<String, StringSettingType>,
context
context,
needLabel
) as SettingComponent<V, T>
PathSettingType::class ->
PathSettingComponent(
setting as SettingReference<Path, PathSettingType>,
context
context,
needLabel
) as SettingComponent<V, T>
else -> TODO(setting.type.qualifiedName!!)
}
@@ -94,7 +99,8 @@ class VersionSettingComponent(
class DropdownSettingComponent(
reference: SettingReference<DisplayableSettingItem, DropDownSettingType<DisplayableSettingItem>>,
context: Context
context: Context,
needLabel: Boolean = true
) : UIComponentDelegatingSettingComponent<DisplayableSettingItem, DropDownSettingType<DisplayableSettingItem>>(
reference,
context
@@ -106,14 +112,15 @@ class DropdownSettingComponent(
filter = { value ->
context.read { setting.type.filter(this, reference, value) }
},
labelText = setting.title,
labelText = setting.title.takeIf { needLabel },
onValueUpdate = { newValue -> value = newValue }
).asSubComponent()
}
class BooleanSettingComponent(
reference: SettingReference<Boolean, BooleanSettingType>,
context: Context
context: Context,
needLabel: Boolean = true
) : UIComponentDelegatingSettingComponent<Boolean, BooleanSettingType>(
reference,
context
@@ -130,7 +137,7 @@ class BooleanSettingComponent(
class StringSettingComponent(
reference: SettingReference<String, StringSettingType>,
context: Context,
showLabel: Boolean = true
needLabel: Boolean = true
) : UIComponentDelegatingSettingComponent<String, StringSettingType>(
reference,
context
@@ -138,7 +145,7 @@ class StringSettingComponent(
override val uiComponent = TextFieldComponent(
context = context,
initialValue = null,
labelText = if (showLabel) setting.title else null,
labelText = setting.title.takeIf { needLabel },
validator = setting.validator,
onValueUpdate = { newValue -> value = newValue }
).asSubComponent()
@@ -146,14 +153,15 @@ class StringSettingComponent(
class PathSettingComponent(
reference: SettingReference<Path, PathSettingType>,
context: Context
context: Context,
needLabel: Boolean = true
) : UIComponentDelegatingSettingComponent<Path, PathSettingType>(
reference,
context
) {
override val uiComponent = PathFieldComponent(
context = context,
labelText = setting.title,
labelText = setting.title.takeIf { needLabel },
validator = settingValidator { path -> setting.validator.validate(this, path) },
onValueUpdate = { newValue -> value = newValue }
).asSubComponent()
@@ -1,14 +1,13 @@
package org.jetbrains.kotlin.tools.projectWizard.wizard.ui.setting
import com.intellij.ui.components.panels.VerticalLayout
import com.intellij.ui.layout.panel
import com.intellij.util.ui.components.BorderLayoutPanel
import org.jetbrains.kotlin.tools.projectWizard.core.Context
import org.jetbrains.kotlin.tools.projectWizard.core.entity.ValidationResult
import org.jetbrains.kotlin.tools.projectWizard.core.entity.isSpecificError
import org.jetbrains.kotlin.tools.projectWizard.core.entity.settings.SettingReference
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 javax.swing.JComponent
interface ErrorAwareComponent {
fun findComponentWithError(error: ValidationResult.ValidationError): FocusableComponent?
@@ -18,16 +17,15 @@ class SettingsList(
settings: List<SettingReference<*, *>>,
private val context: Context
) : DynamicComponent(context), ErrorAwareComponent {
private val panel = PanelWithStatusText(VerticalLayout(5), "This module has no settings to configure")
private val ui = BorderLayoutPanel()
var settingComponents: List<SettingComponent<*, *>> = emptyList()
private set
private var settingComponents: List<SettingComponent<*, *>> = emptyList()
init {
setSettings(settings)
}
override val component: JComponent = panel
override val component get() = ui
override fun onInit() {
super.onInit()
@@ -35,12 +33,18 @@ class SettingsList(
}
fun setSettings(settings: List<SettingReference<*, *>>) {
panel.isStatusTextVisible = settings.isEmpty()
panel.removeAll()
ui.removeAll()
settingComponents = settings.map { setting ->
DefaultSettingComponent.create(setting, context)
DefaultSettingComponent.create(setting, context, needLabel = false)
}
settingComponents.forEach { setting -> setting.onInit(); panel.add(setting.component) }
ui.addToCenter(panel {
settingComponents.forEach { settingComponent ->
settingComponent.onInit()
row(settingComponent.setting.title + ":") {
settingComponent.component(growX)
}
}
})
}
override fun findComponentWithError(error: ValidationResult.ValidationError) = read {
@@ -12,7 +12,7 @@ import org.jetbrains.kotlin.tools.projectWizard.settings.version.Version
import java.nio.file.Paths
class StructurePlugin(context: Context) : Plugin(context) {
val projectPath by valueSetting("Root path", GenerationPhase.PROJECT_GENERATION, pathParser) {
val projectPath by pathSetting("Root path", GenerationPhase.PROJECT_GENERATION) {
defaultValue = value(Paths.get("."))
}
val name by stringSetting("Name", GenerationPhase.PROJECT_GENERATION)