How can I create a custom right click menu that contains a couple of actions, and attach the menu to each element in a JTree in my plugin?


In short I want the user to be able to right click any node in the tree and invoke one of the actions with the selected node as a parameter. I have read through the documentation about creating actions, but I don't fully understand how I can create and associate an action menu with each node. I am fairly new to kotlin so any help is appretiated.

Comment actions Permalink

Hi Kaiwalya,

Please clarify what tree you mean and describe your use case.

Comment actions Permalink

Hi Karol Lewandowski

Thanks for responding. I mean a 


I am building a JTree object and populating it with 


 My use case is that I have a ToolWindow that contains the above JTree and want to allow the user to right-click on any of the Tree nodes, which should open a context menu. In the menu, I want to have a few actions, that should be invoked when a user clicks them. Additionally, the actions themselved need to know which node was right-clicked upon. Does this help? Apologies, I am very new to java/kotlin world. Thanks in advance

Comment actions Permalink

Thanks for the clarification.

I suggest taking a look at:

Key points:

  • It installs actions popup on the tree in line 335:
    PopupHandler.installPopupMenu(tree, createTreePopupActions(isRightTree), "DependenciesPopup");
  • It implements DataProvider and getData(), returning the data requested from the triggered action based on the selected tree item.


Comment actions Permalink

Thanks for the help, I could get the popup menu and the invocation of the action working now.

As for the DataProvider implementation - My main plugin tool window class looks something like this :-

class MyToolWindow {
var content: JPanel
private lateinit var myTree: JTree

PopupHandler.installPopupMenu(myTree, createTreePopupActions(), "My Actions")

However, since `myTree` needs to implement DataProvider, as I understand I can't use JTree as the type anymore and will need to create class `MyTree` similar to the one in the example. Having done that, I now get errors from the corresponding `.form` file saying "Incompatible types. Found 'MyTree', but required 'JTree'". Is there any obvious mistake I am making with respect to the form?

Comment actions Permalink

I think I might have figured out how to get my tree class into the form. 

Let me rephrase my question about the data provider part.

Consider the following scenario: I have setup the tool window and the tree. I run the plugin. I right clicked on `node A` in the tree, opened the context menu and invoked MyAction() as expected.

Now I am inside

MyAction.actionPerformed(p0: AnActionEvent)

My question now, is that inside this actionPerformed(), how to I get "node A"  using p0 ? If it helps, all I really care about is getting the string "node A". I don't rally need the node itself.

Comment actions Permalink

In your component implementing DataProvider you should implement getData() method that will return the selected element information for a given data key. The data key may be your custom key to retrieve this specific information (see com.intellij.openapi.actionSystem.CommonDataKeys to see common data keys).

Let's say you have MyDataKeys.SELECTED_NODE_TEXT key.

In your DataProvider.getData(dataId: String):

if (MyKeys.SELECTED_NODE_TEXT.`is`(dataId)) {
    return mySelectedNode.text // or whatever you want to return

In your AnAction.actionPerformed(event: AnActionEvent) method do something like:

val nodeText = event.getData(MyKeys.SELECTED_NODE_TEXT)
Comment actions Permalink

Karol Lewandowski Thanks for the quick response and a simplified explanation. I appreciate it. This works just the way I intended!!

I am still seeing some errors like the getData() method returning a null value when the key isn't my custom key. But I will debug and figure it out.


Please sign in to leave a comment.