Eclipse 插件开发:如何在 Eclipse 编辑器中监听事件 [英] Eclipse plugin development : How to listen events in Eclipse editor

查看:99
本文介绍了Eclipse 插件开发:如何在 Eclipse 编辑器中监听事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试开发一个 Eclipse 插件.我知道这件事的基本原理.

I am trying to develop an eclipse plug-in. I am aware about the basics of this thing.

在一个示例插件模板中,当我们在eclipse的测试实例中单击菜单项(或下图中带有eclipse图标的按钮)时,sampleHandler.java的execute方法 被执行并出现如下图所示的弹出窗口.

In a sample plugin template when we click the menu entry (or button with eclipse icon in below image in this case) in testing instance of eclipse, execute method of sampleHandler.java is executed and a pop-up shown in image below appears.

每当我在代码编辑器中按下某个键(比如说退格键)而不是单击任何菜单条目(或按钮)时,我都想调用执行"方法.

I want to invoke 'execute' method whenever I press some key (lets say backspace) in code editor instead of clicking any menu entry (or button).

SampleHandler.java

 public class SampleHandler extends AbstractHandler {

    public SampleHandler() {
    }

    /**
     * the command has been executed, so extract extract the needed information
     * from the application context.
     */
    public Object execute(ExecutionEvent event) throws ExecutionException {
        IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindowChecked(event);
        MessageDialog.openInformation(
                window.getShell(),
                "Sdfsdfsadf",
                "Hello, Eclipse world");
        return null;
    }
   }

我尝试了 其他帖子中给出的建议但我无法实现所需的功能.

I tried suggestions given in other posts but I am unable to achieve the desired functionality.

根据我对上面引用帖子的理解,我尝试了下面的代码 -

As per my understanding from referenced post in above line, I tried below code -

    package eventlisten.handlers;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;


import org.eclipse.ui.handlers.HandlerUtil;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentListener;

/**
 * Our sample handler extends AbstractHandler, an IHandler base class.
 * @see org.eclipse.core.commands.IHandler
 * @see org.eclipse.core.commands.AbstractHandler
 */
public class SampleHandler extends AbstractHandler {
    /**
     * The constructor.
     */
    public SampleHandler() {
    }

    /**
     * the command has been executed, so extract extract the needed information
     * from the application context.
     */
    public Object execute(ExecutionEvent event) throws ExecutionException {

        IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindowChecked(event);
        MessageDialog.openInformation(window.getShell(),"EventListen","Trying event listen");
        IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
        IEditorPart editor = page.getActiveEditor();
        IEditorInput input = editor.getEditorInput();  
        IDocument document=(((ITextEditor)editor).getDocumentProvider()).getDocument(IDocument.class);

        document.addDocumentListener(new IDocumentListener() //**this is line 45**
        {
            @Override
            public void documentAboutToBeChanged(DocumentEvent event) {
                // TODO Auto-generated method stub
                System.out.println("Hello");
            }

            @Override
            public void documentChanged(DocumentEvent event) {
                // TODO Auto-generated method stub
                System.out.println("Hello second");

            }
        });

        return null;
    }
}

但是在显示弹窗后,它会抛出异常 -

But after showing the pop-up , it throws the exception -

java.lang.NullPointerException
at eventlisten.handlers.SampleHandler.execute(SampleHandler.java:45)
at org.eclipse.ui.internal.handlers.HandlerProxy.execute(HandlerProxy.java:290)
at org.eclipse.core.commands.Command.executeWithChecks(Command.java:499)
at org.eclipse.core.commands.ParameterizedCommand.executeWithChecks(ParameterizedCommand.java:508)
at org.eclipse.ui.internal.handlers.HandlerService.executeCommand(HandlerService.java:169)
at org.eclipse.ui.internal.handlers.SlaveHandlerService.executeCommand(SlaveHandlerService.java:241)
at org.eclipse.ui.menus.CommandContributionItem.handleWidgetSelection(CommandContributionItem.java:829)
at org.eclipse.ui.menus.CommandContributionItem.access$19(CommandContributionItem.java:815)
at org.eclipse.ui.menus.CommandContributionItem$5.handleEvent(CommandContributionItem.java:805)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1276)
at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3562)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3186)
at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2701)
at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2665)
at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2499)
at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:679)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:668)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:124)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:353)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:180)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:629)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:584)
at org.eclipse.equinox.launcher.Main.run(Main.java:1438)
at org.eclipse.equinox.launcher.Main.main(Main.java:1414)

有人可以指导我完成整个过程吗?如果需要更多信息,请告诉我.

Can someone guide me through the process? Let me know in case more information is required.

推荐答案

您的第一个问题似乎是您仅在用户按下按钮时才与文档进行交互.有更好的方法来设置它.
据我所知,您想检测用户何时修改文档(可能通过键入)、在任何地方键入任何键,或者当 AST 被修改.您可能只会发现以下一个有用或相关的解决方案.

Your first problem seems to be that you only interact with the documents when the user presses the button. There are better ways to set this up.
As far as I can tell, you want to either detect when a user modifies a document (probably by typing), any key is typed anywhere, or when the AST of the code is modified. You will probably only find one of the solutions below useful or relevant.

收听文档更改

您尝试的解决方案最接近第一个,所以我将从那里开始.我做了这样的事情(在你链接的帖子中,事实证明).首先让您的插件扩展 org.eclipse.ui.startup 扩展点,并定义一个类来覆盖 IStartup

The solution you attempted is closest to the first one, so I'll start there. I did something like this (in the post you linked, as it turns out). Start by making your plugin extend the org.eclipse.ui.startup extension point, and define a class to override IStartup

earlyStartup() 看起来像:

@Override
public void earlyStartup() {
    IWorkbench wb = PlatformUI.getWorkbench();
    wb.addWindowListener(generateWindowListener());
}

我们会监听窗口是否打开,当它们打开时,

We'll listen for windows to open, and when they do,

private IWindowListener generateWindowListener() 
{
    return new IWindowListener() {
        @Override
        public void windowOpened(IWorkbenchWindow window) {
            IWorkbenchPage activePage = window.getActivePage(); 
            activePage.addPartListener(generateIPartListener2());
        }

        @Override
        public void windowDeactivated(IWorkbenchWindow window) {}

        @Override
        public void windowClosed(IWorkbenchWindow window) {}

        @Override
        public void windowActivated(IWorkbenchWindow window) {}
    };
}

这个部分监听器是你应该得到EditorPart的地方,这意味着你可以添加文档监听器:

This part listener is where you should get the EditorPart, which means you can add the document listener:

private IPartListener2 generateIPartListener2() 
{
    return new IPartListener2() {

        private void checkPart(IWorkbenchPartReference partRef) {
        IWorkbenchPart part = partRef.getPart(false);
            if (part instanceof IEditorPart)
            {
                IEditorPart editor = (IEditorPart) part;
                IEditorInput input = editor.getEditorInput();
                if (editor instanceof ITextEditor && input instanceof FileEditorInput)  //double check.  Error Editors can also bring up this call
                {
                    IDocument document=(((ITextEditor)editor).getDocumentProvider()).getDocument(input);
                    document.addDocumentListener(/* your listener from above*/);
                }
            }
        }

        @Override
        public void partOpened(IWorkbenchPartReference partRef) {
            checkPart(partRef);
        }

        @Override
        public void partInputChanged(IWorkbenchPartReference partRef) 
        {
            checkPart(partRef);
        }           

        @Override
        public void partVisible(IWorkbenchPartReference partRef){}

        @Override
        public void partHidden(IWorkbenchPartReference partRef) {}

        @Override
        public void partDeactivated(IWorkbenchPartReference partRef)  {}

        @Override
        public void partClosed(IWorkbenchPartReference partRef) {}

        @Override
        public void partBroughtToTop(IWorkbenchPartReference partRef) {}

        @Override
        public void partActivated(IWorkbenchPartReference partRef) {}
    };
}

只听按键

这最终实现起来更简单,但可能非常嘈杂.我们将查看 显示Listener,直接进入 SWT 事件循环.

This ends up being simpler to implement, but may be very noisy. We'll be looking at the Display and the Listener, which gets right into the SWT event loop.

你会想要再次做 earlyStartup() 扩展,并且有类似的东西:

You'll want to do the earlyStartup() extension again, and have something like:

@Override
public void earlyStartup() {
    Display display = Display.getDefault();
    display.setFilter(SWT.KeyUp, new Listener() {
        @Override
        public void handleEvent(Event event) {
            //do stuff here.  Be careful, this may cause lag
        }
     });
}

监听 Java AST 变化最后一个具有原始 keyup 方法的简单性,但可能与我建议的第一个在语义上一样有用.我们将收听 JavaCore 直接.

Listening to Java AST changes The final one has the simplicity of the raw keyup approach, but will probably be as semantically useful as the first one I suggested. We will be listening to the JavaCore directly.

再次,在 earlyStartup 方法中()

Again, in the earlyStartup method()

 JavaCore.addElementChangedListener(new IElementChangedListener() {

        @Override
        public void elementChanged(ElementChangedEvent event)
        {
            //do stuff with the event
        }
    });

结论:运气好的话,这三种方法中的一种对你很有用.我有理由在我的 Eclipse 开发生涯中使用每一个——每一个都有自己的用途.

Conclusion: With luck, one of these three methods is useful to you. I've had reason to use each in my Eclipse development career -- each is useful in its own way.

我希望这会有所帮助.

这篇关于Eclipse 插件开发:如何在 Eclipse 编辑器中监听事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆