IntelliJ Community . PluginDocumentation

 
PluginDocumentation 

HOME INDEX SEARCH CHANGES GO  
Well, guys, there is none right now. So, it's up to us.
Please put any knowledge you've collected here, for us to share.

You are not carving pyramid stones, so don't be shy. Any piece of info is useful.
Feel free to add, correct, edit, spell check or vaporize. That's Wiki world.

Note : use <tt><pre>..</pre></tt> around code samples (to make it look good on Netscape too smile ) <--



How to: get the path of the file in the current editor?

public class HelloWorldAction extends AnAction {
  public void actionPerformed(AnActionEvent event)
  {
      final VirtualFile file = (VirtualFile)event.getDataContext().getData(DataConstants.VIRTUAL_FILE);
      if ( null != file ) {
          String msg = "\nCurrent editor file is=" + file.getPath ();
          JOptionPane.showMessageDialog(null, msg, "FilePath", JOptionPane.INFORMATION_MESSAGE);
      }


  }
}

--Alain Ravet (top)

Actually, that is true only if the action is selected from the editor popup menu. Otherwise it can be any selected file, such as in the project view tree. In case of multiple selection, you can use:

    VirtualFile files[] = VirtualFile[])event.getDataContext().getData(DataConstants.VIRTUAL_FILE_ARRAY);

-- ErbC - 06 Jun 200

Erb is right - the above code fetches files from any selected items. In case the focused component is the editor (in paricular, when invoking from editor's popup menu) the returned file is the current editor's file.

If you wish to get file of the current editor independently of the focus use:

    Project project = (Project)event.getDataContext().getData(DataConstants.PROJECT);
    VirtualFile file = FileEditorManager.getInstance(project).getSelectedFile();

-- ValentinKipiatkov - 06 Aug 2002


How to: get the current project in an action

public class HelloWorldAction extends AnAction {
  public void actionPerformed(AnActionEvent event)
  {
        Project project = (Project)event.getDataContext().getData(DataConstants.PROJECT);

  }
}

-- ErbC - 06 Jun 2002 (top)

This may return null in case there is no open project.

-- ValentinKipiatkov - 06 Aug 2002


Presentations

An action can be inserted in multiple groups, or in a group that is present in several different menus. An action can be presented in different ways in each context, or "Action Place". An action maintains a template presentation, as well as a presentation for each action place. The getTemplatePresentation() method in the AnAction class returns a template in which you can set default values. These include the menu text, the icon, and whether the item is visible (present in the menu). When you create an action using the constructor with text, description, and icon arguments, those values get put in the template presentation.

You can also call getPresentation(place), where place is a String value from the ActionPlaces class. The returned presentation by default has the settings from the template, but they can be changed. [ The way it works: if the presentation for that action place is not found, it is cloned from the template, and then cached for later retrieval. So it starts out with the values the template had at the first time the presentation is accessed. After that it can be changed only by the plugin. ] So, for example, if you place the action in an existing group, but want it to be visible only in one place, you could say:

      action.getTemplatePresentation().setVisible(false);
      action.getPresentation(ActionPlaces.EDITOR_POPUP).setVisible(true);
If you want it to be visible everywhere BUT the editor popup, you would do the opposite: set it visible in the template, not visible in the specified action place.

-- ErbC - 06 Jun 2002 (top)


ToolWindow

ToolWindows are that "moving" things that hold a special tool like Cvs, ToDo, Project...

Itīs quite easy to create your own.

All you need, is to create a JComponent that holds your ui and the following line:

    ToolWindow myToolWindow = ToolWindowManager.getInstance()
              .registerToolWindow( TOOL_WINDOW_ID, myComponent, ToolWindowAnchor.BOTTOM );

The constant TOOL_WINDOW_ID represents a String that you can choose on your own.

The right place to create your ToolWindow is in the method projectOpened() of a ProjectComponent (or ApplicationComponent). And, of course, it is also good style to unregister your ToolWindow on project close, when

Project.Component.projectClosed()
is called:

    ToolWindowManager.getInstance( project ).unregisterToolWindow( TOOL_WINDOW_ID );

To stay conform with the default implementations of the Intellij-guys, create an Action and add it to the ToolWindowsGroup. Use your plugin.xml for that: e.g.

    <action ...>
        <add-to-group group-id="ToolWindowsGroup" anchor="after" relative-to-action="ViewInspectionWindow"/>
    </action>

--

There is no need to do this anymore. The corresponding action is added automatically into "Window" menu for each registered tool window.

-- ValentinKipiatkov - 06 Aug 2002

Actions in a ToolWindow

If you want to add your own Action-Bar into your ToolWindow (and you surely want smile ) try the following code. Therefore, of course, it is necessary to create your own ActionGroup in the plugin.xml or use an existing one.

    ActionGroup actionGroup = ( ActionGroup ) ActionManager.getInstance().getAction( "MyActionGroup" );
    ActionToolBar toolBar = ActionManager.getInstance().createActionToolBar( "MyActionPlace", actionGroup, false );

You can add it to your ToolWindow-Component now:

    toolWindowComponent.add( toolBar.getComponent());

-- JohannesSchneider - 07 Jun 2002


Custom Popups

If you want to create your own Popups (e.g. for your ToolWindows) try the following code into a MouseListener (e is the MouseEvent):

    ActionGroup actionGroup = ( ActionGroup ) ActionManager.getInstance().getAction( "MyActionGroup" );
    ActionPopupMenu popup = ActionManager.getInstance().createActionPopupMenu( "MyPlace", actionGroup );
    JPopupMenu jPopupMenu = popup.getComponent();
    jPopupMenu.show( e.getComponent(), e.getX(), e.getY() );

-- JohannesSchneider - 07 Jun 2002

But I think you should create the popup menu beforehand, rather than each time you mouse-click.

-- ErbC - 07 Jun 2002

Yes, of course some kind of caching should be implemented smile .

-- JohannesSchneider - 07 Jun 2002


Dirty "Project-Singleton"

I had the following problem: I had to get an instance of my Manager (implements ProjectComponent), but I didnīt want to push the active project through all my objects.

So I created a "Project-Singleton" It has a static field called

defaultProject
, where the constructor saves the project.

And I created the following static methods:

    public static IssueManager getInstance( Project project ) {
        if ( project == null ) {
            return null;
        }
        return ( IssueManager ) project.getComponent( COMPONENT_INTERFACE );
    }

    public static IssueManager getDefaultInstance() {
        return getInstance( defaultProject );
    }

Ok, I know. Nothing super-special. But it helped me out. Tell me your opinion about it. Is it allowed? Has it big disadvanteges?

-- JohannesSchneider - 07 Jun 2002

In fact this might not work. You are assuming here that your project component will be created first for default project and than for opened project. In generall it's not true. And if/when IDEA supports multiproject this code won't work!

It is recommended to push the project through your classes.

-- MikeAizatsky - 07 Jun 2002

Also it may hold referense to closed project object, becose it static. For example, it may not be work if you switch bitween projects (even not multiproject supported yet). So, simple you must pass project object through your classes. I resolve this problem by CurrentProjectComponent but it maybe not exactly right, becose "current project/selected current project" must be controled by IntelliJ itself, not through custom user classes ant tricks, i guess.

Let's look at how IntelliJ now controls project's switching. For this looking you must implements ProjectManagerListener? interface. This interface have only two (by now, maybe future change symantic) methods. Method for signaling that project state is changed - project is opened and project is closed. The singleton above still holds reference to closed project object. IntelliJ already does not control it, but singleton still know not a null project until new project opened, as i can see. It is place of error.

I think that your singleton must also be an implementation of ProjectManagerListener? or ProjectManagerAdapter?.

-- AlexeyEfimov - 24 Jun 2002

Grml, I feared for that frown Much work waiting now... -- JohannesSchneider - 07 Jun 2002

In general singleton like the one you introduced are just a short term solution and problems will eventually come up (reuse, testing, thread safety, singleton invalidating enhancements like multi-projects will make your life very unpleasant). These singletons are no different than global variables and as you know, they are evil! May the force be with you Young Skywalker!

Better to bite the bullet now and pass it around or add it as a field of your class initialized in your constructor. Passing it around as the benefit of making your data flow explicit.

BTW It would be nice to have 2 new refactorings to support when you have more than one object to pass down: Introduce Object Parameter and Preserve Whole Object, potentially as one refactoring.

-- JacquesMorel - 31 Aug 2002


How to: use JDOMExternalizable

Want to save state... this is how... to the best of my knowledge smile

obviously you can get fancier...

public class MyComponent  implements ProjectComponent, JDOMExternalizable {
    private Map someMap = new HashMap();

    /**
     * you need to write all your state to the element passed in. you "own"
     * this element.       this method writes your state out whenever IDEA 
     * decides it's time... make it run as fast as you can :)
     */ 
    public void writeExternal(Element element) throws WriteExternalException {
        // iterate over keys
        Iterator keyIterator = someMap.keySet().iterator();
        while (keyIterator.hasNext()) {
            String key = (String)keyIterator.next();
            
            //create a new element named "map_entry"
            Element entryElement = new Element("map_entry");
            // add an attribute named "name" and put your key in as the value
            entryElement = entryElement.setAttribute("name", key);
            // likewise with "value"
            entryElement = entryElement.setAttribute("value", someMap.get(key).toString());
            // add your new element back to what was passed in.
            element.addContent(entryElement);
        }
    }
    
    /**
     * the Element passed in is the root of your configuration... you "own"
     * this element. this method is run once when your component is first 
     * created.. so get all your goodies at once.
     */
    public void readExternal(Element element) throws InvalidDataException {
        // get all elements named "map_entries" 
        List entries = element.getChildren("map_entries");
        for (int i = 0; i < entries.size(); i++) {
            Element entry = (Element) entries.get(i);

            // get the attributes from the entry 
            String name = entry.getAttribute("name").getValue();
            String value = entry.getAttribute("value").getValue();
            // put them in the map for the plugin to use later
            someMap.put(name, value);
        }
}

-- DanBachelder - 11 Jun 2002

There is also an utility class DefaultJDOMExternalizer? which automatically externalizes all public fields in a given object. It's quite useful when you wish to store/load a couple of settings for your plugin.

-- ValentinKipiatkov - 06 Aug 2002


How to: keep track of changes to the root paths

  public void projectOpened() {
    // get paths when project has changed
    ProjectRootManager
      prjRootMgr = ProjectRootManager.getInstance(myProject);
      prjRootMgr.addProjectRootListener(new ProjectRootAdapter() {
        public void rootsChanged(ProjectRootEvent event) {
          // filter out types of interest
          if (event.getRootsType() == ProjectRootType.CLASS  ||
              event.getRootsType() == ProjectRootType.SOURCE
          )
          {
            doSomething(event.getNewRoots());
          }
        }
      });
    // get paths when project has opened
    doSomething(prjRootMgr.getRoots(ProjectRootType.CLASS));
    doSomething(prjRootMgr.getRoots(ProjectRootType.SOURCE));
    ...
  }

-- AntiHeld - 11 Jun 2002


How to make the plugin configuration be saved in the iws file

Essentially, add:

 
<option name="workspace" value="true"/>
to the component in plugin.xml

-- JacquesMorel - 14 Jun 2002

Example of configurable application component description:

<idea-plugin>
  <name>Example</name>
  <description></description>
  <version></version>
  <vendor></vendor>
  <idea-version min="3.0" max="3.1"/>
  <application-components>
    <component>
      <implementation-class>com.acme.plugin.MyConfigurablePlugin</implementation-class>
      <option name="workspace" value="true" />
    </component>
  </application-components>
</idea-plugin>

-- AlexeyEfimov - 24 Jun 2002


Long log file(s) for recursive errors in plugins

Sometimes recursive exceptions happend. And by default log file are cicled by 1M. But this not enought to see start of exceptions flame. Set MaxBackupIndex to 10 files. This allow you see start point of exceptions recurent stream.

The changes must be maked in $IDEA_HOME$/bin/log.xml file.

  <appender name="FILE" class="org.apache.log4j.RollingFileAppender">
    <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern" value="%d [%7r] %6p - %30.30c - %m%n"/>
    </layout>
    <param name="MaxFileSize" value="1Mb"/>
    <param name="MaxBackupIndex" value="10"/>
    <param name="file" value="../log/idea.log"/>
  </appender>

-- AlexeyEfimov - 24 Jun 2002


How to show a dialog during Check In Project

It appears that while the regular Check In command in the VCS submenu runs on the event thread, Check In Project does not, so the progress dialog can use it. So code like the following should be used within checkinFile or any other AbstractVcs method to show a dialog (where showDialog is a method where you actually call setVisible on the dialog):

        if (EventQueue.isDispatchThread()) {
            showDialog();
        }
        else {
            try {
                EventQueue.invokeAndWait(new Runnable() {
                    public void run() {
                        showDialog();
                    }
                });
            }
            catch(Exception x) {
                throw new AbstractVcsException(x);
            }
        }

-- ErbC - 01 Aug 2002


How to use DialogWrapper

DialogWrapper is an abstract class which you subclass to create a dialog. It is not itself a subclass of JDialog, but "wraps" it. The purpose of it would seem to be to provide a standard Look and Feel for dialogs in IDEA, except that the plugin developer still must create most of the content, so its intention is not fully clear to me. What it mostly gives you is an easy way to manage buttons in the dialog.

DialogWrapper gives you, by default, an OK and Cancel button. Closing the dialog window through the window manager (in UNIX) or title bar (in Windows/mac) is interpreted by default as a cancel.

The attached source file is an example of a use of Dialog Wrapper. It adds some complexity by adding extra buttons, and changing the text on the OK and Cancel buttons that already exist. Note that having a button action call close(n) where n is an integer closes the dialog and sets a unique code that is retrieved from getExitCode(). So code that uses the subclass would be like:

        CheckOutDialog dialog = new CheckOutDialog(project, file);
        dialog.show();
        int dialogResult = dialog.getExitCode();

CheckOutDialog.java

-- ErbC - 05 Aug 2002


How to: get a reference to the active Idea JFrame?

I haven't tried to get the main JFrame, but you can get the active editor JComponent by:

FileEditorManager mgr = FileEditorManager.getInstance(...);
Editor editor = mgr.getSelectedEditor();
JComponent editorComp = editor.getComponent();

-- RickVestal - 31 Aug 2002

This might work:

JFrame frame = (JFrame)SwingUtilities.getRoot(editorComp);
The actual type of this object is an IntelliJ specific (obfuscated) subclass of JFrame.

-- ThomasVollmer - 29 Nov 2002

There is also an API call that 'suggests' a Window. It returned a JFrame when I tried it:

WindowManager.getInstance().suggestParentWindow(project)

-- EdwinHautus - 20 March 2003


How to: simulate a clipboard paste with code reformatting, etc.

This was given to me by IntelliJ support: http://www.intellij.net/tracker/idea/viewSCR?publicId=5390

   public class handler extends EditorWriteActionHandler
   {
      public void executeWriteAction(Editor editor, DataContext dataContext)
      {
         EditorActionHandler      pasteHandler = EditorActionManager.getInstance().getActionHandler("EditorPaste");
         pasteHandler.execute(editor, dataContext);
      }
   }

-- JordanZimmerman - 10 Oct 2002 (top)

How to: get the current selected javafile in the editor.


    /**
     * Get's the javafile that's currently selected in the editor. Returns null if it's not a javafile.
     * @param dataContext data context.
     * @return  The current javafile. Null if not a javafile.
     */
    public static PsiJavaFile getSelectedJavaFile(DataContext dataContext) {
        Project project = dataContext.getData(DataConstants.PROJECT);
        PsiManager manager = PsiManager.getInstance(project);
        VirtualFile vFile = FileEditorManager.getInstance(project).getSelectedFile();
        PsiFile psiFile = manager.findFile(vFile);

        if (!(psiFile instanceof PsiJavaFile))
            return null;
        else
            return (PsiJavaFile) psiFile;
    }

How to: reuse IDEA's own dialogs for class/member/etc. and other choosers.

Look at the package: com.intellij.ide.util As there is alot of xxxChooser's

-- DavsClaus - 20 Nov 2002 (top)


How to: use extension points.

There's a little bit of info in the plugin.xml documentation inside "Plugin Structure.html" that came with the Plugin SDK. For anything beyond that, or that isn't obvious (which is most of it), see the unofficial documentation being put together at PluginExtensionPoints.

-- DavidBeattie - 10 Mar 2006 (top)


Combined JavaDoc for Aurora

It's hard getting a comprehensive overview of the open or partially-open API's for Aurora - I've put some reverse engineered javadoc from Aurora build 833 into AuroraJavaDoc. It's just the non-obfuscated stuff, but it helped me a bit.

-- PaulMclachlan - 09 Jul 2003

e d i t a t t a c h r e f - b y d i f f s m o r e
Have ideas, requests, problems regarding this site? Send feedback.
Copyright © 2000-2003 by the contributing authors. All materials at intellij.org are the property of the contributing authors.