Prokash Sarkar
Prokash Sarkar

Reputation: 11873

How to create Sub-Menu for File Templates in Intellij IDEA Plugin DevKit?

Background

I'm working on a plugin where users can create new files from an existing file template. The goal is to consolidate multiple file templates inside a new sub-menu under the primary file menu. If possible, I would like to create a nested sub-menu based on the template category. For example:

New -> New Option -> Option A ->
                                  Sub-Option A
                                  Sub-Option B
                                  Sub-Option C
                     Option B ->
                     Option C ->

Current Progress

Till now, I could successfully add the file templates under the file menu. However, all of them are ungrouped and placed directly inside the file menu. As the number of templates keeps growing, it becomes difficult to manage.

New -> Option A 
       Option B 
       Option C

To create the file templates, I've used the CreateFileFromTemplateAction class

class NewFile : CreateFileFromTemplateAction(TEXT, TEST_DESCRIPTION, ICON) {

    companion object {
        fun createProperties(project: Project, className: String): Properties {
            val properties = FileTemplateManager.getInstance(project).defaultProperties
            properties += "VERSION" to "1.0.0"
            properties += "NAME" to className
            return properties
        }
    }

    override fun buildDialog(project: Project, directory: PsiDirectory, builder: CreateFileFromTemplateDialog.Builder) {
        builder.addKind("Option A", null, "Option A.kt.ft")
        builder.addKind("Option B", null, "Option B.kt.ft")
        builder.addKind("Option C", null, "Option C.kt.ft")
    }

    override fun getActionName(project: PsiDirectory?, directory: String, builder: String?): String {
        return NEW_FILE_ACTION
    }

    override fun createFileFromTemplate(name: String, template: FileTemplate, dir: PsiDirectory) = try {
        val className = FileUtilRt.getNameWithoutExtension(name)
        val project = dir.project
        val properties = createProperties(project, className)
        CreateFromTemplateDialog(project, dir, template, AttributesDefaults(className).withFixedName(true), properties)
            .create()
            .containingFile
    } catch (e: Exception) {
        LOG.error("Error while creating new file", e)
        null
    }

}

And later registered the action and internalFileTemplate inside the plugin.xml file

<idea-plugin>

    <extensions defaultExtensionNs="com.intellij">
        <internalFileTemplate name="Option A"/>
        <internalFileTemplate name="Option B"/>
        <internalFileTemplate name="Option C"/>
    </extensions>

    <actions>
        <action
                id="NewFileAction"
                class="NewFile">
            <add-to-group group-id="NewGroup" anchor="after" relative-to-action="NewFile"/>
        </action>
    </actions>

</idea-plugin>

Expectations

I will highly appreciate any suggestions or a code snippet. If the requirement isn't feasible, I can also use an alternative solution, e.g., a popup dialog.

Update

After modifying the plugin.xml code, The Menu + Sub-Menu is showing correctly.

<actions>
        <group id="MyGroup.FileMenu"
               popup="true"
               class="com.intellij.ide.actions.NonTrivialActionGroup"
               text="New Option"
               description="New Option Description">
            <add-to-group group-id="NewGroup" anchor="after" relative-to-action="NewFile"/>
            <separator/>
            <action id="NewFileAction"
                    class="NewFile"
                    text="My Action"
                    description="My Action Description"/>
        </group>
    </actions>

The file menus are displaying in the following way:

New -> New Option -> Option A
                     Option B
                     Option C

However:

The default input dialog takes the custom variables separately. E.g. it takes the input for class name $NAME variable first and later takes the additional variables

enter image description here

I was looking for a way to take the input for all custom variables inside a single dialog. Here's a sample of the input dialog when using a regular file template without using the plugin.

enter image description here

Upvotes: 1

Views: 640

Answers (1)

Bas Leijdekkers
Bas Leijdekkers

Reputation: 26492

You can register your own group to the NewGroup in the plugin.xml file and add your actions to it. For example:

<group id="MyNewGroup" popup="true" class="com.intellij.ide.actions.NonTrivialActionGroup">
  <add-to-group group-id="NewGroup"/>
</group>

Upvotes: 2

Related Questions