IntelliJ插件开发-EventDispatcher

简介

java.awt包的EventQueue类提供了对EventQueue的发送(dispatch)机制,它会异步地从事件队列中拉取事件,调用dispatchEvent(AWTEvent)方法。虽然是异步去发送事件,但是它保证了事件发送的有序性。

IdeEventQueue是IntelliJ提供的事件处理类,它集成了awt的EventQueue,重写了dispatchEvent方法。它提供了EventDispatcher让我们可以对事件进行拦截处理,可以通过它提供的扩展点,或者编程式的方式来添加自己的EventDispatcher。

EventDispatcher
EventDispatcher是IntelliJ封装的函数式接口,实现它来接收AWTEvent事件,进行自定义逻辑处理。实现dispatch方法的时候,我们需要增加自己的判断逻辑,如果这个事件被我们处理了,又不想被后续其它事件处理器处理,可以返回true,否则应当返回false。

@FunctionalInterface
public interface EventDispatcher {
	// 如果不希望被后续其它事件处理器处理,则返回true
  	boolean dispatch(@NotNull AWTEvent e);
}

注册EventDispatcher

可以通过扩展点,或者编程式方式来注册自己的EventDispatcher。使用编程式方式时,需要注意注册时机和销毁机制(指定父Disposable),避免重复注册。

  • 扩展点注册EventDispatcher(扩展点定义在IdeEventQueue类)

<idea-plugin>
	<extensions defaultExtensionNs="com.intellij">
		<ideEventQueueDispatcher implementation="com.demo.MyEventDispatcher "/>
	extensions>
idea-plugin>
  • 编程式注册EventDispatcher
IdeEventQueue eventQueue = IdeEventQueue.getInstance();
eventQueue.addDispatcher(e -> {
	if (xxx) {
		// If the event meets the requirement of your condition, process it and return true to prevent it from being further processed by other EventDispatchers
		... // your process business
		return true;
	}
	return false;
}, parentDisposable);

应用示例

如果你想拦截某个指定Editor的Enter键的处理逻辑,可以通过以下代码实现。

Key<Boolean> MY_INPUT_INDICATOR = Key.create("myInputIndicator");
// create TextEditorField.
EditorTextField input = new EditorTextField();
input.addSettingsProvider(editorEx -> {
	Disposable inputDisposable = Disposer.newDisposable("inputListener");
    EditorUtil.disposeWithEditor(editorEx, inputDisposable);
    MY_INPUT_INDICATOR.set(editorEx, true);
    IdeEventQueue eventQueue = IdeEventQueue.getInstance();
    eventQueue.addDispatcher(e -> {
		if (e instanceof KeyEvent keyEvent) {
			// 如果想拦截ctrl+Enter,需要判断keyEvent.getModifiersEx() == KeyEvent.CTRL_DOWN_MASK
			if (keyEvent.getKeyCode() == KeyEvent.VK_ENTER && keyEvent.getID() == KeyEvent.KEY_PRESSED) {
			... // do your business
			return true;
		}
		return false;
	}, inputDisposable);
});

以上代码仅仅是用于展示应用场景,如果你只实现想改变某个Editor的Enter键行为,不需要通过这种方式。由于EnterAction集成自EditorAction,而该类在实现AnAction的actionPerformed方法时,使用的是getHandler()方法去处理,并提供了setupHandler方法,你可以直接修改它的Handler,并在特定的时机使用自己的逻辑。

// 也可以通过工具方法:EditorActionManager.getInstance().setActionHandler(actionId, handler)
EditorAction action = (EditorAction)ActionManager.getInstance().getAction("EditorEnter");
action.setupHandler(handler);

你可能感兴趣的:(#,Intellij插件,intellij-idea)