title |
---|
2. Grouping Actions |
If an implementation requires several actions, or there are simply too many actions that overload the menu, they can be joined into groups.
In this first example the action group will be available as a top-level menu item, and actions will be represented as drop-down menu items.
Grouping can be done by adding a <group>
element to the <actions>
section in
plugin.xml.
Note this example has no class
attribute in the <group>
element because we want the IntelliJ Platform framework to
supply a default implementation class for the group. Section 2.2 discusses using specialized implementations. The id
attribute
must be unique, so incorporating the plugin ID or package name is encouraged.
<actions>
<group id="org.jetbrains.tutorials.actions.GroupedActions" text="Example Grouped Actions" popup="true">
</group>
</actions>
The following sample shows how to use an <add-to-group>
element to place a custom action group relative to
an entry in the Tools menu. Note the attribute relative-to-action
references the action id
for SimpleAction
, which is not a native IntelliJ menu entry.
Rather SimpleAction
is defined in the same
plugin.xml file.
<actions>
<group id="org.jetbrains.tutorials.actions.GroupedActions" text="Example Grouped Actions" popup="true">
<add-to-group group-id="ToolsMenu" anchor="after" relative-to-action="org.jetbrains.tutorials.actions.SimpleAction"/>
</group>
</actions>
To create an action we need to extend the
AnAction.java
class. This example uses the SimplePopDialogAction
class, which pops a dialog to give users feedback when a
menu item is chosen. See the Registering an Action
page for more information about this class.
Now the SimplePopDialogAction
needs to be registered in the newly created group. Note the id
attribute is set to
something unique, and different from, the fully qualified class
attribute in the <group>
element. A unique id
supports reuse of
action classes in more than one menu or group.
<group id="org.jetbrains.tutorials.actions.GroupedActions" text="Example Grouped Actions" popup="true">
<add-to-group group-id="ToolsMenu" anchor="after" relative-to-action="org.jetbrains.tutorials.actions.SimpleAction"/>
<action class="org.jetbrains.tutorials.actions.SimplePopDialogAction"
id="org.jetbrains.tutorials.actions.SimpleGroupedAction" text="A Grouped Action" description="Grouped Action Demo">
</action>
</group>
After performing the steps described above the action group and its content will be available in the Tools menu:
In some cases we need to implement some specific behaviour of a group of actions depending on the context. The steps below show how to make a group of actions available and visible if certain conditions are met. In this case the condition is having an instance of an editor is available. This condition is needed because the custom action group will be added to an IntelliJ menu that is only enabled for editing.
DefaultActionGroup.java
is an implementation of
ActionGroup.java.
The DefaultActionGroup
class is used to add child actions and separators between them to a group.
This class is used if a set of actions belonging to the group does not change at runtime, which is the majority of all the cases.
(See section 2.3 for groups with variable child actions at runtime.)
As an example we will extend
DefaultActionGroup.java
to create the CustomDefaultActionGroup
class in the register_actions
code sample:
package org.jetbrains.tutorials.actions;
public class CustomDefaultActionGroup extends DefaultActionGroup {
@Override
public void update(AnActionEvent event) {
// Enable/disable depending on whether user is editing...
}
}
As in the case with the simple action group, the action <group>
should be declared in the <actions>
section of
plugin.xml
file. Note:
- The presence of the
class
attribute in the<group>
element, which tells the IntelliJ Platform framework to useCustomDefaultActionGroup
rather than the default implementation. - The
<add-to-group>
element specifies adding the group in the first position of the existingEditorPopupMenu
.
<actions>
<group id="org.jetbrains.tutorials.actions.ExampleCustomDefaultActionGroup"
class="org.jetbrains.tutorials.actions.CustomDefaultActionGroup" popup="true"
text="Example Custom DefaultActionGroup" description="Custom DefaultActionGroup Demo">
<add-to-group group-id="EditorPopupMenu" anchor="first"/>
</group>
</actions>
For simplicity the SimplePopDialogAction
action class will be reused.
As in Section 2.1.4, the SimplePopDialogAction
action is
added as an <action>
element in the <group>
element. Note:
- The
class
attribute in the<group>
element has the same fully qualified name as used in Section 2.1.4. - The
id
attribute is unique to distinguish it from the use of theSimplePopDialogAction
class in (Section 2.1.4)GroupedActions
.
<actions>
<group id="org.jetbrains.tutorials.actions.ExampleCustomDefaultActionGroup"
class="org.jetbrains.tutorials.actions.CustomDefaultActionGroup" popup="true"
text="Example Custom DefaultActionGroup" description="Custom DefaultActionGroup Demo">
<add-to-group group-id="EditorPopupMenu" anchor="first"/>
<action class="org.jetbrains.tutorials.actions.SimplePopDialogAction" id="org.jetbrains.tutorials.actions.CustomGroupedAction"
text="A Custom Grouped Action" description="Custom Grouped Action Demo"/>
</group>
</actions>
In this case we override the DefaultActionGroup.update(AnActionEvent event)
method to make the group visible only
if there's an instance of the editor available. Also a custom icon is set up:
public class CustomDefaultActionGroup extends DefaultActionGroup {
@Override
public void update(AnActionEvent event) {
// Enable/disable depending on whether user is editing
Editor editor = event.getData(CommonDataKeys.EDITOR);
event.getPresentation().setEnabled(editor != null);
// Always make visible.
event.getPresentation().setVisible(true);
// Take this opportunity to set an icon for the menu entry.
event.getPresentation().setIcon(AllIcons.General.Error);
}
}
After compiling and running the code sample above, and opening a file in the editor and right-clicking, the Editing menu will popup containing an new group of actions in the first position. The new group will also have an icon:
If a set of actions belonging to a custom actions group will vary depending on the context, the group must extend ActionGroup.java. In this case set of actions to be grouped are dynamically defined.
To create a group of actions with a variable number of actions we extend
ActionGroup.java
to create the DynamicActionGroup
class in the register_actions
code sample:
public class DynamicActionGroup extends ActionGroup {
}
To register the dynamic menu group, a <group>
attribute needs to be placed in the <actions>
section of
plugin.xml.
Note that when enabled this group will appear as the last entry in the Tools menu:
<actions>
<group id="org.jetbrains.tutorials.actions.DynamicActionGroup" class="org.jetbrains.tutorials.actions.DynamicActionGroup" popup="true"
text="Dynamic ActionGroup" description="Dynamic ActionGroup Demo">
<add-to-group group-id="ToolsMenu" anchor="last"/>
</group>
</actions>
Note: If a<group>
element's class
attribute names a class derived from ActionGroup
, then any static <action>
declarations in the <group>
will throw an exception. For a statically defined group of actions use DefaultActionGroup.java
.
To add actions to the DynamicActionGroup
, a non-empty array of
AnAction
instances should be returned from the DynamicActionGroup.getChildren(AnActionEvent)
method. Here again we reuse the
SimplePopDialogAction
action class.
public class DynamicActionGroup extends ActionGroup {
@NotNull
@Override
public AnAction[] getChildren(AnActionEvent anActionEvent) {
return new AnAction[]{ new SimplePopDialogAction( "Action Added at Runtime",
"Dynamic Action Demo",
null)};
}
}
After providing the implementation of DynamicActionGroup
and making it return a non-empty array of actions, the last position in the Tools Menu will contain a new group of actions: