CreateFileFromTemplateDialog with additional input fields

My custom language plugin is currently using CreateFileFromInputAction to facilitate template-driven source file creation.  For three of the four file types, this works great because the only real parameter is the file name (sans extension) which, like in most other languages, maps directly to the contained entity name (e.g., class name, page name, etc.).  However, the fourth file type really needs two additional inputs to be complete.  It's basically a database trigger which requires the name of the trigger itself, the name of the database object to which the trigger is attached, and the subscribed events.

In a perfect world all three of these parameters would be captured in the file creation dialog.  As far as I can tell, if I want to take advantage of CreateFileFromTemplateAction and all the functionality it offers "for free", I only get two input fields, the text field for the name and the optional combo-box for the file sub-types.  Before I implement my own file creation action that's essentially a CreateFileFromTemplateAction with a few additional inputs, I thought I'd check here and see if I'm just missing some simple way to do this in the current framework.

Thanks!

11 comments
Comment actions Permalink

Yes, as far as I know this is correct. You'll have to create your own dialog.


0
Comment actions Permalink

Hi, do you have any examples of a plugin that does this? I assume you would have to extend the CreateFileFromTemplateDialog class? The examples that I have found so far all use fields in their template that the user doesn't input (like the package name, user name, etc) but I'm looking to have the user themselves enter text to insert into the template.

0
Comment actions Permalink

It's actually pretty easy.  Create whatever dialog you want to capture user input, likely extending DialogWrapper.  Then you just do the following:

FileTemplate fileTemplate = FileTemplateManager.getInstance().getInternalTemplate(YOUR_TEMPLATE_NAME);

Properties properties = new Properties(FileTemplateManager.getInstance().getDefaultProperties(project));
properties.setProperty("YOUR_PROPERTY_1", yourProperty1Value);
properties.setProperty("YOUR_PROPERTY_2", yourProperty2Value);
...

String filenameWithoutExtension = getNameFromYourDialog();
PsiElement element = FileTemplateUtil.createFromTemplate(fileTemplate, filenameWithoutExtension, properties, dir);


Hope that helps!

0
Comment actions Permalink

Hi, thanks for the reply. Do you have an example as to how to actually create my own dialog, and how I would have to register it in my plugin.xml for it to actually be used when the user tries to make a new file of my custom language?

0
Comment actions Permalink

Sure.  First, create a form using IDEA's form builder.  Make sure it's a form and not a dialog.  Once you've created the form to your liking, make the form's bound Java class extend DialogWrapper and implement createCenterPanel() to return the top-level component in your form.  Then in plugin.xml, create an action to create your new template-driven file, e.g.:

 
<action id="MyCompany.CreateMyFile" class="com.mycompany.fileTemplate.CreateMyFileFromTemplateAction"
        text="My File" description="Create new my-file">
    <add-to-group group-id="NewGroup" anchor="first"/>
</action>


In your action you can override update(AnActionEvent) to decide when the File>New menu entry should be present:

@Override
public void update(final AnActionEvent event)
{
    DataContext dataContext = event.getDataContext();
    boolean enabled = //whatever criteria you have for when it's visible/enabled
    Presentation presentation = event.getPresentation();
    presentation.setVisible(enabled);
    presentation.setEnabled(enabled);
}


And you can implement actionPerformed(AnActionEvent) to show your dialog and then perform the template-based processing that I put in my previous post with the information gathered in that dialog:

@Override
public void actionPerformed(AnActionEvent event)
{
    DataContext dataContext = event.getDataContext();

    IdeView view = LangDataKeys.IDE_VIEW.getData(dataContext);
    if (view == null)
    {
        return;
    }

    Project project = PlatformDataKeys.PROJECT.getData(dataContext);
    CreateMyFileForm createMyFileForm = new CreateMyFileForm(project);
    createMyFileForm.setTitle(NEW_MY_FILE_TITLE);
    createMyFileForm.setResizable(false);
    createMyFileForm.pack();
    createMyFileForm.show();
    if (createMyFileForm.getExitCode() == DialogWrapper.OK_EXIT_CODE)
    {
        // Create the file as shown in my previous post
    }
}


Let me know if that doesn't give you what you need!
0
Comment actions Permalink

Thanks for all the detail. But I'm getting an error saying that actionPerformed is final in CreateFileFromTemplateAction, so I can't override it.

0
Comment actions Permalink

Your action will subclass AnAction, not CreateFileFromTemplateAction.  That's why you have to call the FileTemplateManager and FileTemplateUtil to create the file yourself as I detailed two posts back.  You're basically reimplementing a small portion of CreateFileFromTemplateAction.

0
Comment actions Permalink

I'm getting null pointer errors when I try createMyFileForm.show(): Error during dispatching of java.awt.event.ComponentEvent[COMPONENT_RESIZED (-1039,514 158x45)] on dialog0

Is your project by any chance open source? I need a complete example but I don't want to bug you with every question I have. I've thoroughly googled IntelliJ plugins but haven't been able to find any that do this.

My form class looks like this right now:

 
public class EmptyForm extends DialogWrapper {
    private JTextField test1TextField;
    private JPanel myPanel;

    protected EmptyForm(@Nullable Project project) {
        super(project);
    }

    @Nullable
    @Override
    protected
JComponent createCenterPanel() {
        return myPanel;
    }
}



In my action which extends AnAction I copy and pasted your actionPerformed and update method, but replaced the form created with mine. I haven't bothered going through the part where I actually create the form yet because I'm crashing before I reach the if statement. I also registered the action in my plugin.xml as you did (I am assuming the id I assign the action can anything random).

0
Comment actions Permalink

Unfortunately my project is not open source or I'd happily point you at the code that works.  I did take a look at my dialog for comparison with yours and see one notable difference...at the end of my constructor I call init().  I have IDEA's form builder configured to generate code for forms instead of using a compiled version, so this may not match yours exactly.  I had to do that because I'm also using a code obfuscator in my released plugin that didn't get along well with the compiled forms.  Hopefully this helps, though!

0
Comment actions Permalink

Adding init() worked, thanks for your help!

0
Comment actions Permalink

Glad to hear!  Definitely happy to give a little back to a forum that's helped me tremendously!

0

Please sign in to leave a comment.