Update action system tutorial

Clean up structure, link from necessary places, update sample plugin
code to demonstrate best practices, fix some English
This commit is contained in:
Dmitry Jemerov 2018-03-11 21:36:42 +01:00
parent 5db5c23b34
commit ef63275be5
9 changed files with 63 additions and 112 deletions

View File

@ -30,7 +30,6 @@
* [Plugin Configuration File](basics/plugin_structure/plugin_configuration_file.md)
* [Plugin Dependencies](basics/plugin_structure/plugin_dependencies.md)
* [Project Structure](basics/project_structure.md)
* [Action System](basics/action_system.md)
* [Persisting State of Components](basics/persisting_state_of_components.md)
* [PSI Cookbook](basics/psi_cookbook.md)
* [Virtual File System](basics/virtual_file_system.md)
@ -84,7 +83,7 @@
* [Miscellaneous Swing Components](user_interface_components/misc_swing_components.md)
* [Icons and Images](reference_guide/work_with_icons_and_images.md)
* [Color Scheme Management](reference_guide/color_scheme_management.md)
* Actions
* [Actions](basics/action_system.md)
* Settings
* [Files](basics/architectural_overview/files.md)
* [Virtual Files](basics/architectural_overview/virtual_file.md)
@ -242,7 +241,7 @@
* [9. Commenter Test](tutorials/writing_tests_for_plugins/commenter_test.md)
* [10. Reference Test](tutorials/writing_tests_for_plugins/reference_test.md)
* [Action System](tutorials/action_system.md)
* [1. Working With Custom Actions](tutorials/action_system/working_with_custom_actions.md)
* [1. Registering an Action](tutorials/action_system/working_with_custom_actions.md)
* [2. Grouping Actions](tutorials/action_system/grouping_action.md)
* [Editor Basics](tutorials/editor_basics.md)
* [1. Working With Text](tutorials/editor_basics/working_with_text.md)

View File

@ -20,6 +20,8 @@ To retrieve the information about the current state of the IDE, including the ac
The `AnActionEvent` instance is also passed to the `actionPerformed` method.
For a step-by-step walkthrough of defining actions, please check out the [action system tutorial](/tutorials/action_system.md).
## Registering Actions
There are two main ways to register an action: either by listing it in the `<actions>` section of the `plugin.xml` file, or through Java code.

View File

@ -95,3 +95,8 @@ Note that you can use this wizard only to add a new action to an existing action
![New Action Page](img/new_action_page.png)
The IntelliJ Platform generates a `.java` file with the specified class name, registers the newly created action in the plugin.xml file, adds a node to the module tree view, and opens the created action class file in the editor.
## More Information
For more information on working with actions, please check out the [action system documentation](/basics/action_system.md)
and the [actions tutorial](/tutorials/action_system.md).

View File

@ -2,9 +2,6 @@ package org.jetbrains.tutorials.actions;
import com.intellij.openapi.actionSystem.*;
/**
* @author Anna Bulenkova
*/
public class CustomGroupedAction extends AnAction {
@Override
public void actionPerformed(AnActionEvent anActionEvent) {

View File

@ -2,13 +2,9 @@ package org.jetbrains.tutorials.actions;
import com.intellij.openapi.actionSystem.*;
/**
* @author Anna Bulenkova
*/
public class GroupedAction extends AnAction {
@Override
public void update(AnActionEvent event) {
event.getPresentation().setEnabledAndVisible(true);
}
@Override

View File

@ -1,27 +1,26 @@
package org.jetbrains.tutorials.actions;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.pom.Navigatable;
/**
* @author Anna Bulenkova
*/
public class SimpleAction extends AnAction {
@Override
public void actionPerformed(AnActionEvent anActionEvent) {
Object navigatable = anActionEvent.getData(CommonDataKeys.NAVIGATABLE);
if (navigatable != null) {
Messages.showDialog(navigatable.toString(), "Selected Element:", new String[]{"OK"}, -1, null);
Project project = anActionEvent.getProject();
Navigatable navigatable = anActionEvent.getData(CommonDataKeys.NAVIGATABLE);
if (project != null && navigatable != null) {
Messages.showMessageDialog(project, navigatable.toString(), "Selected Element", Messages.getInformationIcon());
}
}
@Override
public void update(AnActionEvent anActionEvent) {
final Project project = anActionEvent.getData(CommonDataKeys.PROJECT);
if (project != null)
return;
Object navigatable = anActionEvent.getData(CommonDataKeys.NAVIGATABLE);
anActionEvent.getPresentation().setVisible(navigatable != null);
Project project = anActionEvent.getProject();
Navigatable navigatable = anActionEvent.getData(CommonDataKeys.NAVIGATABLE);
anActionEvent.getPresentation().setEnabledAndVisible(project != null && navigatable != null);
}
}

View File

@ -2,14 +2,12 @@
title: IntelliJ Action System
---
This tutorial is meant to give general information about the IntelliJ Platform Action System and lead you through a series of steps
which show how to create, register, and customize custom actions and action groups.
Action system provides an option to handle certain events in a desired way.
Action can either be simply a response to some state, or be bound to UI element and could be invoked on demand.
These UI elements include main menu, context menus, and toolbars.
This tutorial leads you through a series of steps which show how to create, register, and customize custom actions
and action groups. By registering actions, you can add your own menu items, toolbar buttons and keyboard shortcuts
to the IntelliJ IDEA user interface. For more information, please refer to the [IntelliJ Platform Action System](/basics/action_system.md)
documentation.
* [Working With Custom Actions](action_system/working_with_custom_actions.md)
* [Registering Actions](action_system/working_with_custom_actions.md)
* [Grouping Action](action_system/grouping_action.md)

View File

@ -6,13 +6,12 @@ If some part of the functionality requires to implement several actions or actio
### 2.1. Simple action groups
In this case the group will be available as a top-level menu item, action will be represented as drop-down menu items.
In this case the group will be available as a top-level menu item, and actions will be represented as drop-down menu items.
#### 2.1.1. Creating simple action groups
Grouping can be done by extending adding `<group>` attribute to `<actions>`
[plugin.xml](https://github.com/JetBrains/intellij-sdk-docs/blob/master/code_samples/register_actions/resources/META-INF/plugin.xml)
file.
Grouping can be done by adding a `<group>` tag to the `<actions>` section in
[plugin.xml](https://github.com/JetBrains/intellij-sdk-docs/blob/master/code_samples/register_actions/resources/META-INF/plugin.xml).
```xml
<actions>
@ -21,7 +20,7 @@ file.
</actions>
```
#### 2.1.2. Binding action groups to UI component
#### 2.1.2. Binding action groups to UI components
The following sample shows how to place a custom action group on top of the editor popup menu:
@ -35,17 +34,12 @@ The following sample shows how to place a custom action group on top of the edit
#### 2.1.3. Adding actions to the group
To create an action we need to extend
Just as usual, to create an action we need to extend
[AnAction.java](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java)
class:
```java
public class GroupedAction extends AnAction {
@Override
public void update(AnActionEvent event) {
event.getPresentation().setEnabledAndVisible(true);
}
@Override
public void actionPerformed(AnActionEvent event) {
//Does nothing
@ -59,9 +53,9 @@ And then the actions needs to be registered in the newly created group:
<actions>
<group id="SimpleGroup" text="Custom Action Group" popup="true">
<add-to-group group-id="EditorPopupMenu" anchor="first"/>
<action class="org.jetbrains.tutorials.actions.GroupedAction" id="org.jetbrains.tutorials.actions.GroupedAction"
text="Grouped Action" description="Grouped Action Demo">
</action>
<action class="org.jetbrains.tutorials.actions.GroupedAction" id="org.jetbrains.tutorials.actions.GroupedAction"
text="Grouped Action" description="Grouped Action Demo">
</action>
</group>
</actions>
```
@ -70,7 +64,7 @@ After performing the steps described above the action group and its content will
![Simple Action Group](img/grouped_action.png)
### 2.2. Working with DefaultActionGroup
### 2.2. Implementing custom action group classes
In some cases we need to implement some specific behaviour of a group of actions dependently on the context.
The steps below are meant to show how to make a group of actions available and visible if a certain condition is met and how to set up a group icon dynamically.
@ -84,9 +78,8 @@ is a default implementations of
and used to add children actions and separators between them to a group.
This class is used if a set of actions belonging to the group is fixed, which is the majority of all the cases.
Firstly,
[DefaultActionGroup.java](upsource:///platform/platform-api/src/com/intellij/openapi/actionSystem/DefaultActionGroup.java)
should be derived:
Firstly, you need to create a class extending
[DefaultActionGroup.java](upsource:///platform/platform-api/src/com/intellij/openapi/actionSystem/DefaultActionGroup.java):
```java
public class CustomDefaultActionGroup extends DefaultActionGroup {
@ -98,11 +91,10 @@ public class CustomDefaultActionGroup extends DefaultActionGroup {
#### 2.2.2. Registering action group
As in case with the simple action group, the inheritor of
[DefaultActionGroup.java](upsource:///platform/platform-api/src/com/intellij/openapi/actionSystem/DefaultActionGroup.java)
As in case with the simple action group, the action group class
should be declared in
[plugin.xml](https://github.com/JetBrains/intellij-sdk-docs/blob/master/code_samples/register_actions/resources/META-INF/plugin.xml)
file:
file, as the `class` attribute of the `<group>` tag:
```xml
<actions>
@ -198,7 +190,7 @@ For statically defined group of action use
#### 2.3.3. Accessing children actions
An array of children actions should be returned by the method `public AnAction[] getChildren(AnActionEvent anActionEvent);` of the a created group:
An array of children actions should be returned by the method `public AnAction[] getChildren(AnActionEvent anActionEvent);` of the created group:
```java
public class BaseActionGroup extends ActionGroup {
@ -212,7 +204,7 @@ public class BaseActionGroup extends ActionGroup {
#### 2.3.4. Adding children actions to the group
To make the group contain actions a non-empty array of
To make the group contain actions, a non-empty array of
[AnAction.java](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java)
elements should be returned:
@ -223,6 +215,7 @@ public class BaseActionGroup extends ActionGroup {
public AnAction[] getChildren(AnActionEvent anActionEvent) {
return new AnAction[]{new MyAction()};
}
class MyAction extends AnAction {
public MyAction() {
super("Dynamically Added Action");
@ -236,6 +229,6 @@ public class BaseActionGroup extends ActionGroup {
After providing an implementation of
[AnAction.java](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java)
and making it return a non-empty array of action Tools Menu should contain an extra group of action:
and making it return a non-empty array of actions, the Tools Menu should contain an extra group of actions:
![Dynamic Action Group](img/dynamic_action_group.png)

View File

@ -1,12 +1,12 @@
---
title: 1. Working With Custom Actions
title: 1. Registering an Action
---
An action is technically a class, derived from the
[AnAction](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java)
class.
To update the state of the action, the method AnAction.update() is periodically called by IDEA.
To update the state of the action, the method `AnAction.update()` is periodically called by IDEA.
The object of type
[AnActionEvent](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnActionEvent.java)
passed to this method carries the information about the current context for the action,
@ -15,7 +15,7 @@ and in particular, the specific presentation which needs to be updated.
### 1.1. Creating actions
To create a new we need to extend
To create a new action we need to extend
[AnAction](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java)
class:
@ -28,7 +28,7 @@ public class SimpleAction extends AnAction {
The only method of an inheritor of
[AnAction](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java)
which needs to be overridden is `public void actionPerformed(AnActionEvent anActionEvent);`, and it should contain a part of code to be executed after the action has been invoked.
which is required to be overridden is `public void actionPerformed(AnActionEvent anActionEvent);`, and it should contain the code to be executed when the action has been invoked.
In this case the action does nothing.
```java
@ -71,46 +71,9 @@ file will look like this:
### 1.4. Setting attributes manually
Full list of action's attributes can also be set manually in
[plugin.xml](https://github.com/JetBrains/intellij-sdk-docs/blob/master/code_samples/register_actions/resources/META-INF/plugin.xml)
configuration file like the following code sample shows:
```xml
<actions>
<!-- Add your actions here -->
<!-- The <action> element defines an action to register.
The mandatory "id" attribute specifies an unique identifier for the action.
The mandatory "class" attribute specifies the full-qualified name of the class implementing the action.
The mandatory "text" attribute specifies the text of the action (tooltip for toolbar button or text for menu item).
The optional "use-shortcut-of" attribute specifies the ID of the action whose keyboard shortcut this action will use.
The optional "description" attribute specifies the text which is displayed in the status bar when the action is focused.
The optional "icon" attribute specifies the icon which is displayed on the toolbar button or next to the menu item. -->
<action id="org.jetbrains.tutorials.actions.SimpleAction" class="org.jetbrains.tutorials.actions.SimpleAction"
text="Simple Action" description="IntelliJ Action System Demo">
<!-- The <keyboard-shortcut> node specifies the keyboard shortcut for the action. An action can have several keyboard shortcuts.
The mandatory "first-keystroke" attribute specifies the first keystroke of the action. The key strokes are specified according to the regular Swing rules.
The optional "second-keystroke" attribute specifies the second keystroke of the action.
The mandatory "keymap" attribute specifies the keymap for which the action is active. IDs of the standard keymaps are defined as
constants in the com.intellij.openapi.keymap.KeymapManager class. -->
<keyboard-shortcut first-keystroke="control alt A" second-keystroke="C" keymap="$default"/>
<!-- The <mouse-shortcut> node specifies the mouse shortcut for the action. An action can have several mouse shortcuts.
The mandatory "keystroke" attribute specifies the clicks and modifiers for the action. It is defined as a sequence of words separated by spaces:
"button1", "button2", "button3" for the mouse buttons; "shift", "control", "meta", "alt", "altGraph" for the modifier keys;
"doubleClick" if the action is activated by a double-click of the button.
The mandatory "keymap" attribute specifies the keymap for which the action is active. IDs of the standard keymaps are defined as
constants in the com.intellij.openapi.keymap.KeymapManager class. -->
<mouse-shortcut keystroke="control button3 doubleClick" keymap="$default"/>
<!-- The <add-to-group> node specifies that the action should be added to an existing group. An action can be added to several groups.
The mandatory "group-id" attribute specifies the ID of the group to which the action is added.
The group must be implemented by an instance of the DefaultActionGroup class.
The mandatory "anchor" attribute specifies the position of the action in the group relative to other actions. It can have the values
"first", "last", "before" and "after".
The "relative-to-action" attribute is mandatory if the anchor is set to "before" and "after", and specifies the action before or after which
the current action is inserted. -->
<add-to-group group-id="ToolsMenu" anchor="first"/>
</action>
</actions>
```
You can configure additional attributes of the action by editing its registration in the plugin.xml file.
Please refer to the [Action System documentation](/basics/action_system.html#registering-actions) for the full list
of supported attributes.
After performing the steps described above we need to compile and run the plugin to the the newly created action available as a Tools Menu item:
@ -124,9 +87,10 @@ In the following example action invokes a dialog that shows information about a
```java
@Override
public void actionPerformed(AnActionEvent anActionEvent) {
Object navigatable = anActionEvent.getData(CommonDataKeys.NAVIGATABLE);
if (navigatable != null) {
Messages.showDialog(navigatable.toString(), "Selected Element:", new String[]{"OK"}, -1, null);
Project project = anActionEvent.getProject();
Navigatable navigatable = anActionEvent.getData(CommonDataKeys.NAVIGATABLE);
if (project != null && navigatable != null) {
Messages.showMessageDialog(project, navigatable.toString(), "Selected Element", Messages.getInformationIcon());
}
}
```
@ -162,25 +126,23 @@ public class SimpleAction extends AnAction {
//...
}
@Override
public void update(AnActionEvent anActionEvent) {
final Project project = anActionEvent.getData(CommonDataKeys.PROJECT);
if (project == null)
return;
Object navigatable = anActionEvent.getData(CommonDataKeys.NAVIGATABLE);
anActionEvent.getPresentation().setEnabledAndVisible(navigatable != null);
}
@Override
public void update(AnActionEvent anActionEvent) {
Project project = anActionEvent.getProject();
Navigatable navigatable = anActionEvent.getData(CommonDataKeys.NAVIGATABLE);
anActionEvent.getPresentation().setEnabledAndVisible(project != null && navigatable != null);
}
}
```
Parameter anActionEvent carries information on the invocation place and data available.
Parameter `anActionEvent` carries information on the invocation place and data available.
**Note** This method can be called frequently, for instance, if an action is added to a toolbar, it will be updated twice a second.
**Note** This method can be called frequently: for instance, if an action is added to a toolbar, it will be updated twice a second.
This means that this method is supposed to work really fast, no real work should be done at this phase.
For example, checking selection in a tree or a list, is considered valid, but working with a file system is not.
For example, checking selection in a tree or a list, is considered valid but working with the file system is not.
If you cannot understand the state of the action fast you should do it in the
[AnActionEvent](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnActionEvent.java)
method and notify the user that action cannot be executed if it's the case.
method and notify the user that the action cannot be executed if it's the case.
After compiling and running the plugin project and invoking the action, the dialog will pop up: