New Project Wizard API
The New Project wizard items can be grouped into two main types:
Language Project Generators
Language project generators allow for creating general-purpose projects without specific frameworks (they can be added to the project by users later). Examples:
a Kotlin project
a Python project
These items are displayed at the top in the left sidebar of the New Project dialog.
Language project generators implement LanguageGeneratorNewProjectWizard
and are registered in com.intellij.newProjectWizard.languageGenerator
extension point.
The generator implementation must provide:
name
andicon
used in UIordinal
that is used to sort the generator in the generator listisEnabled(WizardContext)
that allows controlling displaying the item depending on the current contextcreateStep(NewProjectWizardStep)
that creates the tree of steps that users go through during the project creation. Note the provided parent step, which exposes the wizard context, data holder, and other shared properties. See Wizard Steps for details.
Examples:
KotlinNewProjectWizard
generating Kotlin projectsPythonNewProjectWizard
generating Python projects
Framework Project Generators
Framework project wizards allow for creating projects related to a specific technology, for example:
a Spring Boot project
a project generated from a Maven Archetype
a React project
These items are displayed under language generator items in the left sidebar of the New Project dialog.
Framework project wizards implement GeneratorNewProjectWizard
and are registered in com.intellij.newProjectWizard.generator
extension point.
The interface exposes:
unique
id
name
andicon
used in UIordinal
that is used to sort the generator in the generator listisEnabled()
that allows controlling displaying the item depending on the current IDE contextcreateStep(WizardContext)
that creates the tree of steps that users go through during the project creation. See Wizard Steps for details.
Example: MavenArchetypeNewProjectWizard
creating Maven projects from a selected archetype
Wizard Steps
Every project wizard consists of one or more steps that users go through during project creation. Each step contains UI elements for data necessary to create a project. All the steps are displayed on a single screen in the project wizard dialog, which displays the Create button that creates the project.
A project wizard step implements NewProjectWizardStep
. The most important methods are:
setupUI()
— defines the UI components for the step. Step UI is built with Kotlin UI DSL Version 2setupProject()
— applies the parameters provided in UI to the generated project
See the example implementations in the intellij-community
repository.
Steps build a tree structure (read the rest of this section for details), as some steps can be displayed depending on previously selected options. setupUI()
and setupProject()
of steps building the tree are applied in the order from root to leaf. Note that setupProject()
won't be called for hidden steps.
For convenience, the platform provides AbstractNewProjectWizardStep
, which is a base step class that takes a parent step and delegates common property accessors to the parent. It allows sharing the root step's properties by all descendant steps.
Chaining Steps
As mentioned before, all steps are rendered on a single screen. Merging multiple steps into a chain displayed as a single screen step is achieved with NewProjectWizardChainStep
. Its companion object exposes a helper method NewProjectWizardChainStep.nextStep()
, which allows chaining steps in fluent form, for example:
All the steps above will be created inside a single NewProjectWizardChainStep
and will be displayed (except the root step, which exists to hold shared data) in a single dialog page:
Root Step
The root project wizard step initializes a data holder and other properties shared with all descendant steps in the wizard.
In the case of language project generators, the LanguageGeneratorNewProjectWizard.createStep(NewProjectWizardStep)
receives a parent step, and there is no need to initialize these values and create a root step.
In the case of framework project generators, the root step can be created with RootNewProjectWizardStep
, which initializes shared properties.
Common Steps
Almost every project requires providing the project name and the location where it should be created. Also, projects are often shared in a Git repository. The IntelliJ Platform provides:
NewProjectWizardBaseStep
, which handles the project Name and Location fieldsGitNewProjectWizardStep
, which is responsible for handling Git repository initialization if the user enables it
Note that language project generators already include these steps out of the box, and there is no need to create them in the wizard implementation.
Asset Steps
It is often required to populate a created project with initial assets like:
directory structure, for example, src/main/java, src/main/resources, src/test/java, src/test/resources in a Gradle Java project
a build-tool-specific .gitignore file ignoring build and other directories and files
sample code
This can be achieved by creating a step extending AssetsNewProjectWizardStep
. It allows for adding directories, static assets, assets generated from Freemarker templates, and granting them proper file permissions.
See example implementations in the intellij-community
repository.
Steps Forking the Wizard Flow
Sometimes, a wizard requires displaying different options depending on the user's selection. For example, depending on the selected build tool, different fields specific to the selected build tool are displayed.
Such a behavior can be implemented with AbstractNewProjectWizardMultiStep
.
AbstractNewProjectWizardMultiStep
internally handles steps forking the wizard flow. It is responsible for:
setting up the switcher
setting up the selected step's UI
applying the selected step's options to the created project
Forking steps are provided with an extension point implementing NewProjectWizardMultiStepFactory
. Besides the parent step, AbstractNewProjectWizardMultiStep
's constructor receives the name of the extension point implementing NewProjectWizardMultiStepFactory
and uses registered extensions to create steps.
The Adding Support for Custom Build Systems in Language Project Wizards section lists example implementations of AbstractNewProjectWizardMultiStep
.
Adding Support for Custom Build Systems in Language Project Wizards
Some language project generators contain the Build system field that allows for choosing a build system used by a project. This is achieved by implementing AbstractNewProjectWizardMultiStep
described above. Example implementations are:
JavaNewProjectWizard.Step
— for Java languageKotlinNewProjectWizard.Step
— for Kotlin languageGroovyNewProjectWizard.Step
— for Groovy language
It is possible to add support for custom build systems by implementing extensions specific to these languages. The table below shows the supported languages with corresponding interfaces and extension points:
Sharing Data Between Steps
Project wizards with multiple steps may require sharing data between them. The recommended approach includes the following implementation steps:
Create an interface exposing step's shared properties, for example,
ExampleData
:interface ExampleData { val value: String }Add a companion object with the data key and a helper
NewProjectWizardStep.exampleData
extension property.interface ExampleData { // ... companion object { val KEY: Key<ExampleData> = Key.create(ExampleData::class.java.name) @JvmStatic val NewProjectWizardStep.exampleData: ExampleData? get() = data.getUserData(KEY) } }Make the step implement the created interface and implement the data property and a graph property (see Property Graph for details):
class ExampleStep(parent: NewProjectWizardStep) : AbstractNewProjectWizardStep(parent), ExampleData { private val valueProperty = propertyGraph.property(false) override var value: String by valueProperty // ... }The graph property is used for binding value with UI components. Consider exposing it via the data interface if it is possible that other steps may depend on it.
During step instance initialization, store data in the data holder shared with all steps:
class ExampleStep(parent: NewProjectWizardStep) : AbstractNewProjectWizardStep(parent), ExampleData { // ... init { data.putUserData(ExampleData.KEY, this) } }
Shared data can be accessed in another step in the following way:
Property Graph
PropertyGraph
creates an observable dependency graph that automatically propagates changes between related properties. It is created in the root step and shared between all descendant steps via AbstractNewProjectWizardStep.propertyGraph
.
PropertyGraph
is widely used in wizard steps to create a responsive UI that dynamically updates depending on the user's actions. It allows for:
conditional visibility of fields based on other selections
dynamic validation of user inputs
automatic updates to dependent properties when primary properties change
and more
Consider NewProjectWizardBaseStep
. It implements two graph properties for the project name and path:
Both properties are lazily initialized with default values based on the current context.
Data properties delegate to the graph properties:
Any read or update of a data or graph property will update its counterpart.
Dependencies between properties are defined during step instance initialization:
It means that whenever pathProperty
is changed, the nameProperty
will be updated using the provided suggestUniqueName()
function.
Properties are also bound to the UI allowing for synchronizing them with the UI in both directions:
In addition, there is another graph property created from path and name graph properties:
locationProperty
will be updated whenever pathProperty
or nameProperty
is updated, and it will contain a path built of the path and name. The value of the property is bound to the comment component displayed under the location row:
PropertyGraph
has many possibilities that are hard to describe in detail. It is recommended to experiment with existing project wizards and exploring their implementations.
Persisting Default Settings
It is convenient for users to remember commonly used settings, so they don't need to fill them again. Consider the checkbox initializing a Git repository in a created project. When the user selects it for the first time, and later they create another project, the checkbox will be automatically selected.
This behavior can be implemented by binding graph properties to persistent storage via methods from BindUtil
, for example:
Under the hood, properties are stored at the application level via PropertiesComponent under the GIT_PROPERTY_NAME
key.
Example Project Wizard Steps Structure
The following diagram presents the steps flow of the Kotlin language project wizard implemented by KotlinNewProjectWizard
.
The following steps are always present in language project generators and are created by the platform under the hood:
RootNewProjectWizardStep
— initializes shared properties like data holder and property graphNewProjectWizardBaseStep
— displays project name and location optionsGitNewProjectWizardStep
— allows for creating a Git repository for the new projectNewProjectWizardLanguageStep
— invisible step holding information about the chosen language (this step is deprecated and is used only for technical reasons; it shouldn't be used by plugins)
All steps are enclosed within NewProjectWizardChainStep
, which renders them on a single screen.
KotlinNewProjectWizard.Step
is a multistep that forks the wizard flow into two paths depending on the user selection in the Build system switcher:
Maven-specific, if the user selected Maven
Gradle-specific, if the user selected Gradle
It creates the actual steps by using registered step factory extensions (MavenKotlinNewProjectWizard
and GradleKotlinNewProjectWizard
).
Depending on the selection, the platform executes setupUI()
and setupProject()
methods of enabled steps.
FAQ
How to determine whether the current context is a project or a module creation?
Use WizardContext.isCreatingNewProject()
. The wizard context is available in every step via NewProjectWizardStep.context
.
How to add a project wizard hint?
Sometimes, a project wizard requires an explanation about the purpose of the wizard or links to an alternative item. To add a simple comment, use CommentNewProjectWizardStep
, for example, EmptyProjectGeneratorNewProjectWizard.CommentStep
To additionally render a clickable link to another wizard, use LinkNewProjectWizardStep
, for example, MavenArchetypeNewProjectWizard.CommentStep
.
How to implement a project wizard for non-Java IDEs?
To create project wizards for non-Java IDEs (for example, PyCharm), implement DirectoryProjectGenerator
and register it in the com.intellij.directoryProjectGenerator
extension point.