OCD fixes

This commit is contained in:
JohnHake 2019-12-14 13:32:01 -08:00
parent bb97c4213f
commit 864c6a89ae
3 changed files with 45 additions and 33 deletions

View File

@ -12,6 +12,7 @@ Registration determines where an action appears in the IDE UI.
Once implemented and registered, an action receives callbacks from the IntelliJ Platform in response to user gestures.
The [Creating Actions](/tutorials/action_system/working_with_custom_actions.md) tutorial describes the process of adding a custom action to a plugin.
The [Grouping Actions](/tutorials/action_system/grouping_action.md) tutorial demonstrates three types of groups that can contain actions.
The rest of this page is an overview of actions as an extension point.
* bullet list
@ -32,13 +33,14 @@ Every IntelliJ Platform action should override `AnAction.update()` and must over
The state (enabled, visible) of an action determines whether the action is available in the UI of an IDE.
An object of type [`AnActionEvent`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnActionEvent.java) is passed to this method, and it contains the information about the current context for the action.
Actions are made available by changing state in the [Presentation](upsource:///platform/platform-api/src/com/intellij/ide/presentation/Presentation.java) object associated with the event context.
As explained in [Overriding the `AnAction.update()` Method](#overriding-the-anactionupdate-method), it is vital `update()` works quickly and returns execution to the IntelliJ Platform.
As explained in [Overriding the `AnAction.update()` Method](#overriding-the-anactionupdate-method), it is vital `update()` methods _execute quickly_ and return execution to the IntelliJ Platform.
* An action's method `AnAction.actionPerformed()` is called by the IntelliJ Platform if it is available and selected by the user.
This method does the heavy lifting for the action - it contains the code to be executed when the action is invoked.
The `actionPerformed()` method also receives `AnActionEvent` as a parameter, which can be used to access projects, files, selection, etc.
See [Overriding the `AnAction.actionPerformed()` Method](#overriding-the-anactionactionperformed-method) for more information about overriding this method.
See [Overriding the `AnAction.actionPerformed()` Method](#overriding-the-anactionactionperformed-method) for more information.
There are other methods to override in the `AnAction` class, such as for changing the default `Presentation` object for the action.
There is also a use case for overriding action constructors when registering them with dynamic action groups, which is demonstrated in the [Grouping Actions](/tutorials/action_system/grouping_action.md#adding-child-actions-to-the-dynamic-group) tutorial.
However, the `update()` and `actionPerformed()` methods are essential to basic operation.
### Overriding the AnAction.update Method
@ -55,7 +57,7 @@ For example, checking selection in a tree or a list is considered valid, but wor
The `AnActionEvent` object passed to `update()` carries information about the current context for the action.
Context information is available from the methods of `AnActionEvent`, providing information such as the Presentation, and whether the action is triggered from a Toolbar.
Additional context information is available using the method `AnActionEvent.getData()`.
Keys defined in [`CommonDataKeys`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/CommonDataKeys.java) are passed to the `getData()` method to retrieve information about objects such as the `Project`, `Editor`, `PsiFile`, and other information.
Keys defined in [`CommonDataKeys`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/CommonDataKeys.java) are passed to the `getData()` method to retrieve objects such as `Project`, `Editor`, `PsiFile`, and other information.
Accessing this information is relatively light-weight and is suited for `AnAction.update()`.
#### Enabling and Setting Visibility for an Action
@ -74,7 +76,7 @@ If an action is enabled, the `AnAction.actionPerformed()` can be called if an ac
A menu action will be shown in the UI location specified in the registration.
A toolbar action will display its enabled (or selected) icon, depending on the user interaction.
When an action is disabled, the `AnAction.actionPerformed()` will not be called.
When an action is disabled `AnAction.actionPerformed()` will not be called.
Toolbar actions will display their respective icons for the disabled state.
The visibility of a disabled action in a menu depends on whether the host menu (e.g. "ToolsMenu") containing the action has the `compact` attribute set.
See [Grouping Actions](#grouping-actions) for more information about the `compact` attribute, and the visibility of menu actions.
@ -100,6 +102,7 @@ An example of inspecting PSI elements is demonstrated in the SDK code sample `ac
### Action IDs
Every action and action group has a unique identifier.
Basing the identifier for a custom action on the FQN of the implementation is the best practice, assuming the package incorporates the `<id>` of the plugin.
An action must have a unique identifier for each place it is used in the IDE UI, even though the FQN of the implementation is the same.
Definitions of identifiers for the standard IntelliJ Platform actions are in [`IdeActions`](upsource:///platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java).
### Grouping Actions
@ -108,6 +111,7 @@ A group of actions can form a toolbar or a menu.
Subgroups of a group can form submenus of a menu.
Actions can be included in multiple groups, and thus appear in multiple places within the IDE UI.
An action must have a unique identifier for each place it appears in the IDE UI.
The places where actions can appear are defined by constants in [`ActionPlaces`](upsource:///platform/platform-api/src/com/intellij/openapi/actionSystem/ActionPlaces.java).
Group IDs for the IntelliJ Platform are defined in [PlatformActions](upsource:///platform/platform-resources/src/idea/PlatformActions.xml).
@ -127,17 +131,17 @@ Some menus like **Tools** have the `compact` attribute set, so there isn't a way
| :-----: | :------------: | :----------------: | :----------------: | :---------------------: |
| F | T | T | T | F |
| F | T | F | F | x |
| ***F*** | F | T | ***T*** | T |
| ***F*** | F | T | ***T*** | ***T*** |
| F | F | F | F | x |
| T | T | T | T | F |
| T | T | F | F | x |
| ***T*** | F | T | ***F*** | x |
| T | F | F | F | x |
See the [Grouping Actions](/tutorials/action_system/grouping_action.md) tutorial for more information about grouping actions.
See the [Grouping Actions](/tutorials/action_system/grouping_action.md) tutorial for examples of creating action groups.
## 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.
There are two main ways to register an action: either by listing it in the `<actions>` section of a plugin's `plugin.xml` file, or through code.
### Registering Actions in plugin.xml
Registering actions in `plugin.xml` is demonstrated in the following example, which documents all elements and attributes that can be used in the `<actions>` section, and describes the meaning of each element.

View File

@ -4,7 +4,9 @@ title: Grouping Actions
If an implementation requires several actions, or there are simply too many actions that overload the menu, the actions can be placed into groups.
This tutorial demonstrates adding an action to an existing group, creating a new action group, and action groups with a variable number of actions.
The sample code discussed in this tutorial is from the code sample `action_basics`.
The sample code discussed in this tutorial is from the code sample [`action_basics`].
Some content in this tutorial assumes the reader is familiar with the tutorial for [Creating Actions](working_with_custom_actions.md).
* bullet list
{:toc}
@ -14,15 +16,15 @@ In this first example, the action group will be available as a top-level menu it
The group is based on a default IntelliJ Platform implementation.
### Creating Simple Groups
Grouping can be registered by adding a `<group>` element to the `<actions>` section in [plugin.xml](https://github.com/JetBrains/intellij-sdk-docs/blob/master/code_samples/action_basics/src/main/resources/META-INF/plugin.xml).
Grouping can be registered by adding a `<group>` element to the `<actions>` section of a plugin's `plugin.xml` file.
This example has no `class` attribute in the `<group>` element because the IntelliJ Platform framework will supply a default implementation class for the group.
This default implementation is used if a set of actions belonging to the group is static, i.e. does not change at runtime, which is the majority of cases.
The `id` attribute must be unique, so incorporating the plugin ID or package name is the best practice.
The `popup` attribute determines whether actions in the group are placed in a submenu.
The `icon` attribute specifies the FQN of an `Icon` object to be displayed.
No `compact` attribute is specified.
See []() for more information about these attributes.
The `icon` attribute specifies the FQN of an [`Icon`](https://docs.oracle.com/javase/8/docs/api/javax/swing/Icon.html) object to be displayed.
No `compact` attribute is specified, which means this group will support submenus.
See [Registering Actions in plugin.xml](/basics/action_system.md#registering-actions-in-pluginxml) for more information about these attributes.
```xml
<group id="org.intellij.sdk.action.GroupedActions" text="Static Grouped Actions" popup="true" icon="ActionBasicsIcons.Sdk_default_icon">
@ -33,7 +35,7 @@ See []() for more information about these attributes.
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.
The attribute `relative-to-action` references the action `id` for `PopupDialogAction`, which is not a native IntelliJ menu entry.
Rather `PopupDialogAction` is defined in the same [plugin.xml](https://github.com/JetBrains/intellij-sdk-docs/blob/master/code_samples/action_basics/src/main/resources/META-INF/plugin.xml) file.
The group is placed after the entry for the action `PopupDialogAction` - see [Creating Actions](working_with_custom_actions.md#registering-an-action-with-the-new-action-form) for the tutorial about placing this single action at the top of the **Tools** menu.
This group is placed after the single entry for the action `PopupDialogAction`, as defined in the tutorial [Creating Actions](working_with_custom_actions.md#registering-an-action-with-the-new-action-form).
```xml
<group id="org.intellij.sdk.action.GroupedActions" text="Static Grouped Actions" popup="true" icon="ActionBasicsIcons.Sdk_default_icon">
@ -57,19 +59,24 @@ The action in this group will display the menu text "A Group Action".
</group>
```
After performing the steps described above the action group and its content will be available in the **Tools** menu:
After performing the steps described above the action group and its content will be available in the **Tools** menu.
The underlying `PopupDialogAction` implementation is reused for two entries in the **Tools** menu:
* Once for the top menu entry **Tools \| Pop Dialog Action** with the action `id` equal to `org.intellij.sdk.action.PopupDialogAction` as set in the [Creating Actions](/tutorials/action_system/working_with_custom_actions.md#registering-an-action-with-the-new-action-form) tutorial.
* A section time for the menu entry **Tools \| Static Grouped Actions \| A Group Action** with the action `id` equal to `org.intellij.sdk.action.GroupPopDialogAction`.
![Simple Action Group](img/grouped_action.png){:width="550px"}
## Implementing Custom Action Group Classes
In some cases, the specific behavior of a group of actions needs to depend on the context.
The solution is analagous to making a [single action entry dependent on context](working_with_custom_actions.md#extending-the-update-method).
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.
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.
### Extending DefaultActionGroup
[`DefaultActionGroup`](upsource:///platform/platform-api/src/com/intellij/openapi/actionSystem/DefaultActionGroup.java) is an implementation of [`ActionGroup`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/ActionGroup.java).
The [`DefaultActionGroup`](upsource:///platform/platform-api/src/com/intellij/openapi/actionSystem/DefaultActionGroup.java) is an implementation of [`ActionGroup`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/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 cases.
@ -86,10 +93,11 @@ to create the `CustomDefaultActionGroup` class in the `action_basics` code sampl
```
### Registering the Custom Action Group
As in the case with the static action group, the action `<group>` should be declared in the *`<actions>`* section of the [plugin.xml](https://github.com/JetBrains/intellij-sdk-docs/blob/master/code_samples/action_basics/src/main/resources/META-INF/plugin.xml) file.
Note:
* The presence of the `class` attribute in the `<group>` element, which tells the IntelliJ Platform framework to use `CustomDefaultActionGroup` rather than the default implementation.
* The `<add-to-group>` element specifies adding the group in the first position of the existing `EditorPopupMenu`.
As in the case with the static action group, the action `<group>` should be declared in the `<actions>` section of the`plugin.xml` file, for example, the [action_basics](https://github.com/JetBrains/intellij-sdk-docs/blob/master/code_samples/action_basics/src/main/resources/META-INF/plugin.xml) plugin.
The declaration below shows:
* The presence of the `class` attribute in the `<group>` element, which tells the IntelliJ Platform framework to use `CustomDefaultActionGroup` rather than the default implementation.
* Setting the group's `popup` attribute to allow submenus.
* The `<add-to-group>` element specifies adding the group in the first position of the existing `EditorPopupMenu`.
```xml
<group id="org.jetbrains.tutorials.actions.ExampleCustomDefaultActionGroup"
@ -101,9 +109,9 @@ Note:
### Adding Actions to the Custom Group
As in [Static Grouped Actions](#adding-a-new-action-to-the-static-grouped-actions), the `PopupDialogAction` action is added as an `<action>` element in the `<group>` element.
Note:
In the declaration below, note:
* The `class` attribute in the `<action>` element has the same FQN to reuse this action implementation.
* The `id` attribute is unique to distinguish it from the use of the `PopupDialogAction` class in [Static Grouped Actions](#adding-a-new-action-to-the-static-grouped-actions).
* The `id` attribute is unique to distinguish it from other uses of the implementation in the Action System.
```xml
<group id="org.intellij.sdk.action.CustomDefaultActionGroup" class="org.intellij.sdk.action.CustomDefaultActionGroup" popup="true"
@ -142,7 +150,8 @@ If a set of actions belonging to a custom group will vary depending on the conte
The set of actions in the `ActionGroup` is dynamically defined.
### Creating Variable Action Group
To create a group of actions with a variable number of actions, extend `ActionGroup.java` to create the `DynamicActionGroup` class in the `action_basics` code sample:
To create a group of actions with a variable number of actions, extend `ActionGroup`.
For example, as in the `action_basics` class [`DynamicActionGroup`](https://github.com/JetBrains/intellij-sdk-docs/blob/master/code_samples/action_basics/src/main/java/org/intellij/sdk/action/DynamicActionGroup.java) code:
```java
public class DynamicActionGroup extends ActionGroup {
@ -159,12 +168,13 @@ When enabled, this group will appear at the entry just below the [Static Grouped
</group>
```
> **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.
> **Warning** If a`<group>` element's `class` attribute names a class derived from `ActionGroup`, then any static `<action>` declarations in that group will throw an exception.
For a statically defined group, use `DefaultActionGroup`.
### Adding Child Actions to the Dynamic Group
To add actions to the `DynamicActionGroup`, a non-empty array of `AnAction` instances should be returned from the `DynamicActionGroup.getChildren()` method.
Here again, reuse the `PopupDialogAction` action class as an example.
Here again, reuse the `PopupDialogAction` implementation.
This use case is why `PopupDialogAction` overrides a constructor:
```java
public class DynamicActionGroup extends ActionGroup {

View File

@ -35,7 +35,7 @@ public class PopupDialogAction extends AnAction {
}
```
> **Warning** `AnAction` classes do not have class fields of any kind to prevent memory leaks.
> **Warning** `AnAction` classes do not have class fields of any kind. This restriction prevents memory leaks.
For more information about why, see [Action Implementation](/basics/action_system.md#action-implementation).
At this stage, `update()` implicitly defaults to always enable this action.
@ -47,7 +47,7 @@ Before fleshing out those methods, to complete this minimal implementation `Popu
## Registering a Custom Action
Actions can be registered by declaring them in code or by declaring them in the `<actions>` section of a plugin configuration (`plugin.xml`) file.
This section describes using IDE tooling - the New Action Form - to add a declaration to the `plugin.xml` file, and then tuning registration attributes manually.
A more comprehensive explanation of action registration is available in the [Registering Actions](/basics/action_system.md#registering-actions) section of this guide.
A more comprehensive explanation of action registration is available in the [Action Registration](/basics/action_system.md#registering-actions) section of this guide.
### Registering an Action with the New Action Form
IntelliJ IDEA has an embedded inspection that spots unregistered actions.
@ -89,8 +89,7 @@ would contain:
The `<action>` element declares the _Action ID_ (`id`,) _Class Name_ (`class`,) _Name_ (`text`,) and _Description_ from the **New Action** form.
The `<add-to-group>` element declares where the action will appear and mirrors the names of entries from the form.
This declaration is adequate, but more attributes can be added.
These attributes are discussed in the next section.
This declaration is adequate, but adding more attributes is discussed in the next section.
### Setting Registration Attributes Manually
An action declaration can be added manually to the `plugin.xml` file.
@ -98,7 +97,7 @@ An exhaustive list of declaration elements and attributes is presented in [Regis
Attributes are added by selecting them from the **New Action** form, or by editing the registration declaration directly in the plugin.xml file.
The `<action>` declaration for `PopupDialogAction` in the `action_basics` [plugin.xml](https://github.com/JetBrains/intellij-sdk-docs/blob/master/code_samples/action_basics/src/main/resources/META-INF/plugin.xml) file.
It also contains an attribute for an [`Icon`](upsource:///plugins/javaee/core/javaee-api/com/intellij/javaee/model/xml/Icon.java), and encloses elements declaring keyboard and mouse shortcuts.
It also contains an attribute for an [`Icon`](https://docs.oracle.com/javase/8/docs/api/javax/swing/Icon.html), and encloses elements declaring keyboard and mouse shortcuts.
The full declaration is:
```xml
<action id="org.intellij.sdk.action.PopupDialogAction" class="org.intellij.sdk.action.PopupDialogAction"
@ -109,7 +108,6 @@ The full declaration is:
</action>
```
See the [Registering Actions in plugin.xml](/basics/action_system.md#registering-actions-in-pluginxml) section for the syntax requirements of these declarations.
## Testing the Minimal Custom Action Implementation
After performing the steps described above, compile and run the plugin to see the newly created action available as a Tools Menu item:
@ -125,7 +123,7 @@ However, neither method implements any code to perform useful work.
This section describes adding useful code to these methods.
The `update()` method defaults to always enable the action, which is satisfactory for intermediate testing.
So the `actionPerformed()` will be developed first.
So `actionPerformed()` will be developed first.
### Extending the actionPerformed Method
Adding code to the `PopupDialogAction.actionPerformed()` method makes the action do something useful.