编辑器事件
编辑器事件
本教程主要是介绍处理编辑器按键事件 的 Editor Action 系统。示例插件editor_basics 主要使用了下面2个类:
使用 EditorActionHandler 操纵 文本插入符(caret)
创建和注册TypedActionHandler 来拦截铵键和修改Document
EditorActionHandler介绍
示例插件editor_basics 演示了克隆文本插入符(caret) 。一个自定义的 Action 使用 EditorActionManager 获取到的 EditorActionHandler 对象来克隆文本插入符(caret) 。示例插件editor_basics 注册了一个 Editor Add Caret Action
创建"Editor Add Caret" Action
看这部分内容之前,需要了解如何创建和注册Actions,可以查看Action教程
在示例插件editor_basics 中定义了 AnAction 的子类 EditorHandlerIllustration ,并在 plugin.xml 里进行了注册,注册代码如下:
<actions>
<action
id="EditorBasics.EditorHandlerIllustration"
class="org.intellij.sdk.editor.EditorHandlerIllustration"
text="Editor Add Caret"
description="Adds a second caret below the existing one."
icon="SdkIcons.Sdk_default_icon">
<add-to-group group-id="EditorPopupMenu" anchor="first"/>
</action>
</action>
下面分步介绍EditorHandlerIllustration
启用"Editor Add Caret" Action
只有同时满足下面的条件,才能启用"Editor Add Caret" Action
- 存在一个打开的项目
- 存在一个可用的编辑器(editor)
- 编辑器上至少存在一个文本插入符(caret)
代码如下:
public class EditorHandlerIllustration extends AnAction {
@Override
public void update(@NotNull AnActionEvent event) {
Project project = event.getProject();
Editor editor = event.getData(CommonDataKeys.EDITOR);
// 确定是否至少存在一个文本插入符(caret)
boolean menuAllowed = false;
if (editor != null && project != null) {
// 确定 文本插入符(caret) 数组不为空
menuAllowed = !editor.getCaretModel().getAllCarets().isEmpty();
}
event.getPresentation().setEnabledAndVisible(menuAllowed);
}
}
获取正确的 EditorActionHandler
克隆文本插入符(caret) 时,可以从 EditorActionManager 中获取正确的 EditorActionHandler ,代码如下:
// Snippet from EditorHandlerIllustration.actionPerformed()
EditorActionManager actionManager = EditorActionManager.getInstance();
// 实际返回的的EditorActionHandler 的子类 CloneCaretActionHandler
EditorActionHandler actionHandler =
actionManager.getActionHandler(IdeActions.ACTION_EDITOR_CLONE_CARET_BELOW);
使用EditorActionHandler克隆文本插入符(caret)
public class EditorHandlerIllustration extends AnAction {
@Override
public void actionPerformed(@NotNull AnActionEvent event) {
Editor editor = event.getRequiredData(CommonDataKeys.EDITOR);
EditorActionManager actionManager = EditorActionManager.getInstance();
EditorActionHandler actionHandler =
actionManager.getActionHandler(IdeActions.ACTION_EDITOR_CLONE_CARET_BELOW);
//克隆文本插入符(caret)
actionHandler.execute(editor,
editor.getCaretModel().getPrimaryCaret(), event.getDataContext());
}
}
创建TypedActionHandler
TypedActionHandler 接口是处理编辑器中按键事件的基础接口。自定义并注册该接口的实现类来处理编辑器按键事件,并接收每一次按键的回调。下面进行详细介绍。
实现TypedActionHandler接口
第一步,定义TypedActionHandler 的子类 MyTypedHandler ,重写处理编辑器按键事件的回调方法:TypedActionHandler.execute()
开发回调事件处理逻辑
在编辑器中每一次按键都会调用 MyTypedHandler.execute() 方法,代码如下:
class MyTypedHandler implements TypedActionHandler {
@Override
public void execute(@NotNull Editor editor,
char c,
@NotNull DataContext dataContext) {
Document document = editor.getDocument();
Project project = editor.getProject();
//每一次按键都在 Document 的开头插入 ”editor_basics“ 字符串
Runnable runnable = () -> document.insertString(0, "editor_basics\n");
//写操作必须保证线程安全,所以使用 WriteCommandAction.runWriteCommandAction()
WriteCommandAction.runWriteCommandAction(project, runnable);
}
}
注册TypedActionHandler
自定义的TypedActionHandler 子类需要进行注册,以替换已存在的TypedActionHandler ,可以使用 TypedAction 进行注册。
注册可以使用代码注册,也可以在 plugin.xml 里注册
使用代码注册
public class EditorHandlerIllustration extends AnAction {
//静态代码将在系统启动时执行
static {
//获取 actionManager
EditorActionManager actionManager = EditorActionManager.getInstance();
TypedAction typedAction = actionManager.getTypedAction();
// 注册TypedActionHandler
typedAction.setupHandler(new MyTypedHandler());
}
}
在 plugin.xml 里注册
<extensions defaultExtensionNs="com.intellij">
<typedHandler implementation="org.intellij.sdk.editor.MyTypedHandler"/>
</extensions>