简介
AnAction是IntelliJ提供的菜单项,可以添加到Menu或者ToolBar(底部状态栏)中
使用
- 定义逻辑
public class MyAction extends AnAction {
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
Project project = e.getProject();
Editor editor = e.getData(CommonDataKeys.EDITOR);
... // your business
}
@Override
public void update(@NotNull AnActionEvent e) {
// 设置AnAction的启用状态,如果为false,可以传递给其他内置AnAction的逻辑处理
e.getPresentation().setEnabled(CompletionServiceImpl.getCurrentCompletionProgressIndicator() == null);
}
@Override
public @NotNull ActionUpdateThread getActionUpdateThread() {
// 设置AnAction的执行线程,使用Event Dispatch Thread或者Background Thread
return ActionUpdateThread.EDT;
}
}
- 注册,如果你的AnAction只需要监听快捷键,也可以不绑定IDE菜单。
<idea-plugin>
<actions>
<action id="MyAction1" class="com.demo.MyAction1" text="MyAction">
<!-- 全局快捷键, 可以指定多个 -->
<keyboard-shortcut first-keystroke="ctrl PERIOD" keymap="$default" />
<keyboard-shortcut first-keystroke="TAB" keymap="$default" />
<!-- 可以指定绑定到不同菜单时展示不同的文字 -->
<override-text place="MainMenu" text="text in main menu" />
<override-text place="EditorPopup" text="text in eidtor popup" />
</action>
<separator/> <!--分隔符-->
<action id="MyAction2" class="com.demo.MyAction1" text="MyAction"/>
<!-- 添加到编辑器右键菜单组 -->
<add-to-group group-id="EditorPopupMenu" anchor="first"/>
</actions>
</idea-plugin>
给指定组件绑定快捷键
在xml中配置的AnAction子类的快捷键是全局性的,如果你只想给某个JComponent组件绑定事件,可以继承DumbAwareAction。
DumbAwareAction myAction = new DumbAwareAction() {
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
... //your business
}
};
myAction.registerCustomShortcutSet(CommonShortcuts.CTRL_ENTER, editor.getComponent());
AnAction监听点
<idea-plugin>
<applicationListeners>
<listener class="com.demo.MyAnActionListener" topic="com.intellij.openapi.actionSystem.ex.AnActionListener"/>
</applicationListeners>
</idea-plugin>
如果你的AnAction和其他AnAction快捷键一样,且某些场景下被其它AnAction冲突掉了,可以监听这个事件,获取快捷键,手动触发自己的Anction.
public void afterActionPerformed(@NotNull AnAction action, @NotNull AnActionEvent event
, @NotNull AnActionResult result) {
if (event.getInputEvent() instanceof KeyEvent) {
KeyEvent keyEvent = (KeyEvent) event.getInputEvent();
// IDE有的AnAction优先级高于自定义的,导致无法触发自定义的AnAction,这里手动触发
if (keyEvent != null && keyEvent.getKeyCode() == KeyEvent.VK_ESCAPE) {
AnAction myAction = ActionManager.getInstance().getAction("<your action id>");
if (myAction != action) {
ActionManager.getInstance().getAction("<your action id>").actionPerformed(event);
}
}
}
}
ActionPromoter
当你定义的AnAction与其它AnAction快捷键一样时,可能会导致你的AnAction不能被触发。我们可以注册ActionPromoter扩展点,它允许为相同的键盘快捷键分配多个动作,并定义这些动作的顺序。
- 注册扩展点
<idea-plugin>
<extensions defaultExtensionNs="com.intellij">
<!-- "last" overrides previous promoters -->
<actionPromoter order="last" implementation="com.demo.MyActionPromoter"/>
</extensions>
</idea-plugin>
- 实现扩展点
如果你的AnAction实现了ActionPromoter接口,则不需要第一步的注册扩展点。
import com.intellij.openapi.actionSystem.ActionPromoter;
class MyActionPromoter implements ActionPromoter {
public List<AnAction> promote(@NotNull List<? extends AnAction> actions, @NotNull DataContext context) {
// 如果actions不包含你定义的AnAntion (可以让自己的AnAction都实现一个自定义的接口YourAction), 直接返回null,表示不干预
if (actions.stream().noneMatch(action -> action instanceof YourAction)) {
return null;
}
// 在属于自己定义的action的处理场景时,把自己的action放在前面
Editor editor = CommonDataKeys.EDITOR.getData(context);
if (editor xxx) {
return actions.sort((x, y) -> {
boolean xIsYourAction = x instance of YourAction;
boolean yIsYourAction = y instance of YourAction;
if (x && y) {
return 0;
}
return x ? -1 : y ? 1 : 0;
});
}
}
}
工具方法
// 调用指定action的逻辑
ActionManager.getInstance().getAction("<actionId>").actionPerformed(event);