PropertyTester 的触发器评估

Trigger evaluation of PropertyTester

不得不升级到E4,现在一堆东西都不行了。如果像这样使用,其中之一是 IEvaluationService

<handler class="org.acme.PrintHandler" commandId="org.eclipse.ui.file.print">
  <activeWhen>
    <with variable="activePart">
      <test property="org.acme.printable" />
    </with>
  </activeWhen>
</handler>
IEvaluationService service = (IEvaluationService) PlatformUI.getWorkbench().getService(IEvaluationService.class);
service.requestEvaluation("org.acme.printable");

如何(重新)触发 PropertyTester 的评估?由于 E4 实际上还没有接近生产就绪状态,我需要 E3(兼容层)的解决方法。

Related question - 但该用户正在搜索 E4 中的等效项,而我需要一个适用于 E3 的项。

有趣的是,如果我用 <enabledWhen> 替换 <activeWhen> 标签,它就会起作用。在那种情况下 IEventBroker#postIEventBroker#send 也可以工作。

这是一个similar question。该用户使用 Eclipse 4.2 - 我用 4.5、4.6 和 4.7 测试了这个问题。

我将分享我的变通方法,这不好,并且在所有情况下都不起作用。并且只真正起作用,因为在我的用例中我有一个 IWorkbenchPart 和一个 ISelectionProvider... 但也许它会帮助下一个人:

IWorkbenchPart activePart = // get active view or editor
ISelectionProvider selectionProvider = activePart.getSite().getSelectionProvider();
ISelection selection = selectionProvider.getSelection();
selectionProvider.setSelection(new StructuredSelection());
selectionProvider.setSelection(selection);

此代码只是重置选择,这通常会触发 PropertyTester。如果什么都不选,我认为它不会起作用。

eventBroker.post(UIEvents.REQUEST_ENABLEMENT_UPDATE_TOPIC, UIEvents.ALL_ELEMENT_ID);

另见 Eclipse bug 436755 and Eclipse Wiki: Eclipse 4 - RCP - Event Model

EvaluationService 在 E3 兼容层中 API 兼容。但是在 E4 中的实现完全不同,导致 requestEvaluation 的行为根本不同。

我能找到的解决此问题的最佳方法是手动停用和激活当前活动部件的所有上下文。这会导致内部重新评估,并在需要时重新渲染各个部分的所有 UI 元素。

有人可能会争辩说,这比请求评估非常具体的 属性 效率低,因为 EvaluationService 应该这样做。但由于评估仅限于活动部分,因此不应产生太多开销。它确实在全球范围内有效,因为不再需要特定的 属性 字符串。

唯一未涵盖的用例可能是 RCP 应用程序的主工具栏。

/**
 * Triggers evaluation of all UI elements (buttons, etc.) of the active part.
 * Also causes test of all property testers of all opened parts implicitly.
 * Workaround of the broken <code>IEvaluationService.requestEvaluation</code>.
 */
public static void triggerUIElementsEvaluation() {
    try {
        final EPartService partService = PlatformUI.getWorkbench().getService(EPartService.class);
        final MPart activePart = partService.getActivePart();

        /* Toggle context of active part to trigger re-evaluation of its UI elements. */
        if (activePart != null) {
            activePart.getContext().deactivate();
            activePart.getContext().activateBranch();
        }
    } catch (IllegalStateException e) {
        /* Ignore "Application does not have an active window" exception to allow program to continue. */
    }
}