Eclipse RCP:如何观察剪切/复制/粘贴命令的状态?

时间:2022-06-01 20:01:54

I'm currently struggling with the following Eclipse RCP commands:

我目前正在努力使用以下Eclipse RCP命令:

  • org.eclipse.ui.edit.cut
  • org.eclipse.ui.edit.copy
  • org.eclipse.ui.edit.paste

I'm using them as command contributions in the toolbar, but the UIElements (toolbar items) are not updated when the 'handled' state of those commands changes.

我在工具栏中将它们用作命令贡献,但是当这些命令的“已处理”状态发生更改时,UIElements(工具栏项)不会更新。

For testing I used a polling mechanism to verify that the state of those commands really changes depending on the currently focussed element, and I found out that the handler remains the same but the handler's 'handled' state changes properly, causing the commands 'handled' state to also change properly.

为了测试,我使用轮询机制来验证这些命令的状态是否真的根据当前聚焦的元素而改变,并且我发现处理程序保持不变但处理程序的“处理”状态正确更改,导致命令“处理”国家也要改变。

The only problem is, that neither one of those state changes causes a notification (neither on the command's ICommandListener, nor on the handler's IHandlerListener), so the UIElements won't get updated.

唯一的问题是,这些状态更改都不会导致通知(既不在命令的ICommandListener上,也不在处理程序的IHandlerListener上),因此UIElements不会更新。

Here's some testing code to observe the states of a Command:

这是一些用于观察命令状态的测试代码:

ICommandService commandService = (ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class);

final String commandId="org.eclipse.ui.edit.copy";
Command command = commandService.getCommand(commandId);
command.addCommandListener(new ICommandListener() {

    public void commandChanged (CommandEvent commandEvent) {
        System.out.println(">> Command changed: " + commandId);
    }
});

Am I missing something, or is this an bug in the cut/copy/paste handler implementations? Any insights?

我错过了什么,或者这是剪切/复制/粘贴处理程序实现中的错误?任何见解?

EDIT: The commands are enabled all the time, and the handler is never exchanged, only the handler's 'handled' state (and thus also the commmand's 'handled' state) changes depending on which ui element has the focus. There is however no notification when this state changes. This results in the toolbar buttons always being enabled, and pressing them will cause a org.eclipse.core.commands.NotHandledException: There is no handler to execute for command.

编辑:命令一直处于启用状态,处理程序永远不会被交换,只有处理程序的“处理”状态(因此也就是命令的“处理”状态)会根据哪个ui元素具有焦点而改变。但是,当状态发生变化时,没有通知。这导致工具栏按钮始终处于启用状态,按下它们将导致org.eclipse.core.commands.NotHandledException:没有为命令执行的处理程序。

3 个解决方案

#1


The handler which is registered for the cut/copy/paste commands is org.eclipse.ui.internal.handlers.WidgetMethodHandler. This handler checks if a given method is declared on the current display's focus control. When executed, that handler will invoke the method using reflection.

为cut / copy / paste命令注册的处理程序是org.eclipse.ui.internal.handlers.WidgetMethodHandler。此处理程序检查是否在当前显示的焦点控件上声明了给定方法。执行时,该处理程序将使用反射调用该方法。

Snippet from WidgetMethodHandler:

来自WidgetMethodHandler的片段:

 public final boolean isHandled() {
     return getMethodToExecute() != null;
 }

The getMethodToExecute() will locate the current focus control using Display.getCurrent().getFocusControl(), and then check if the given trigger method is declared on it.

getMethodToExecute()将使用Display.getCurrent()。getFocusControl()定位当前焦点控件,然后检查是否在其上声明了给定的触发器方法。

Widgets such as org.eclipse.swt.widgets.Text have cut(), copy() and paste() methods, so when the focus is on such a widget, the handler will return 'true' for isHandled().

诸如org.eclipse.swt.widgets.Text之类的小部件具有cut(),copy()和paste()方法,因此当焦点在这样的小部件上时,处理程序将为isHandled()返回'true'。

This handler is however not aware when the current focus control changes (I think there isn't even a way to observe this on the Display), and thus can't notify about changes on its dynamic 'isHandled' state.

然而,此处理程序不知道当前焦点控件何时更改(我认为甚至没有在显示器上观察此方法),因此无法通知其动态“isHandled”状态的更改。

This results in the cut/copy/paste commands being fine for popup menus, but they're quite problematic when used in toolbars, as their UI elements can't be updated properly when the handler does no notifications.

这导致剪切/复制/粘贴命令适用于弹出菜单,但是当在工具栏中使用时它们很成问题,因为当处理程序不通知时,它们的UI元素无法正确更新。

This leaves me with either not using those commands in the toolbar, or having a polling mechansim to update the ui elements (which is also bad and error prone). :-(

这使我不在工具栏中使用这些命令,或者使用轮询机制更新ui元素(这也很糟糕并且容易出错)。 :-(

#2


Your problem is that you need to register a handler for anything that is not a text because Eclipse needs to know how to copy the currently selected "something" to the clipboard. That's what a handler does. This article in the Eclipse wiki will get you started how to create and register a handler.

您的问题是您需要为非文本的任何内容注册处理程序,因为Eclipse需要知道如何将当前选定的“某些东西”复制到剪贴板。这就是处理程序的作用。 Eclipse wiki中的这篇文章将帮助您了解如何创建和注册处理程序。

#3


I could be wrong, but the source of the problem is that the handler is always enabled.

我可能是错的,但问题的根源是始终启用处理程序。

See Platform Plug-in Developer Guide > Programmer's Guide > Plugging into the workbench > Basic workbench extension points using commands > Handlers.

请参阅平台插件开发人员指南>程序员指南>使用命令>处理程序插入工作台>基本工作台扩展点。

The <activeWhen/> expressions in the plugin.xml and programmatic core expressions are used to help determine the scope of a handlers activation. For example, a specific window, a specific Shell, an active part type or active part.

plugin.xml和程序化核心表达式中的 表达式用于帮助确定处理程序激活的范围。例如,特定窗口,特定Shell,活动部件类型或活动部件。

   <extension
         point="org.eclipse.ui.handlers">
      ...
      <handler
            class="org.eclipse.ui.examples.contributions.view.SwapInfoHandler"
            commandId="org.eclipse.ui.examples.contributions.view.swap">
         <activeWhen>
            <reference
                  definitionId="org.eclipse.ui.examples.contributions.view.inView">
            </reference>
         </activeWhen>
         <enabledWhen>
            <count
                  value="2">
            </count>
         </enabledWhen>
      </handler>
      ...

#1


The handler which is registered for the cut/copy/paste commands is org.eclipse.ui.internal.handlers.WidgetMethodHandler. This handler checks if a given method is declared on the current display's focus control. When executed, that handler will invoke the method using reflection.

为cut / copy / paste命令注册的处理程序是org.eclipse.ui.internal.handlers.WidgetMethodHandler。此处理程序检查是否在当前显示的焦点控件上声明了给定方法。执行时,该处理程序将使用反射调用该方法。

Snippet from WidgetMethodHandler:

来自WidgetMethodHandler的片段:

 public final boolean isHandled() {
     return getMethodToExecute() != null;
 }

The getMethodToExecute() will locate the current focus control using Display.getCurrent().getFocusControl(), and then check if the given trigger method is declared on it.

getMethodToExecute()将使用Display.getCurrent()。getFocusControl()定位当前焦点控件,然后检查是否在其上声明了给定的触发器方法。

Widgets such as org.eclipse.swt.widgets.Text have cut(), copy() and paste() methods, so when the focus is on such a widget, the handler will return 'true' for isHandled().

诸如org.eclipse.swt.widgets.Text之类的小部件具有cut(),copy()和paste()方法,因此当焦点在这样的小部件上时,处理程序将为isHandled()返回'true'。

This handler is however not aware when the current focus control changes (I think there isn't even a way to observe this on the Display), and thus can't notify about changes on its dynamic 'isHandled' state.

然而,此处理程序不知道当前焦点控件何时更改(我认为甚至没有在显示器上观察此方法),因此无法通知其动态“isHandled”状态的更改。

This results in the cut/copy/paste commands being fine for popup menus, but they're quite problematic when used in toolbars, as their UI elements can't be updated properly when the handler does no notifications.

这导致剪切/复制/粘贴命令适用于弹出菜单,但是当在工具栏中使用时它们很成问题,因为当处理程序不通知时,它们的UI元素无法正确更新。

This leaves me with either not using those commands in the toolbar, or having a polling mechansim to update the ui elements (which is also bad and error prone). :-(

这使我不在工具栏中使用这些命令,或者使用轮询机制更新ui元素(这也很糟糕并且容易出错)。 :-(

#2


Your problem is that you need to register a handler for anything that is not a text because Eclipse needs to know how to copy the currently selected "something" to the clipboard. That's what a handler does. This article in the Eclipse wiki will get you started how to create and register a handler.

您的问题是您需要为非文本的任何内容注册处理程序,因为Eclipse需要知道如何将当前选定的“某些东西”复制到剪贴板。这就是处理程序的作用。 Eclipse wiki中的这篇文章将帮助您了解如何创建和注册处理程序。

#3


I could be wrong, but the source of the problem is that the handler is always enabled.

我可能是错的,但问题的根源是始终启用处理程序。

See Platform Plug-in Developer Guide > Programmer's Guide > Plugging into the workbench > Basic workbench extension points using commands > Handlers.

请参阅平台插件开发人员指南>程序员指南>使用命令>处理程序插入工作台>基本工作台扩展点。

The <activeWhen/> expressions in the plugin.xml and programmatic core expressions are used to help determine the scope of a handlers activation. For example, a specific window, a specific Shell, an active part type or active part.

plugin.xml和程序化核心表达式中的 表达式用于帮助确定处理程序激活的范围。例如,特定窗口,特定Shell,活动部件类型或活动部件。

   <extension
         point="org.eclipse.ui.handlers">
      ...
      <handler
            class="org.eclipse.ui.examples.contributions.view.SwapInfoHandler"
            commandId="org.eclipse.ui.examples.contributions.view.swap">
         <activeWhen>
            <reference
                  definitionId="org.eclipse.ui.examples.contributions.view.inView">
            </reference>
         </activeWhen>
         <enabledWhen>
            <count
                  value="2">
            </count>
         </enabledWhen>
      </handler>
      ...