启用“显示在”>“系统资源管理器”的条件是什么?

What are the conditions for Show In > System Explorer to be enabled?

我们正在开发一个 eclipse 插件来帮助管理客户站点的产品套件。

此插件包含多个视图,我们通过 'Show In' 菜单在它们之间建立了链接机制。由于客户站点可能有多个许可证在使用,我们有一个实现 IShowInTargetLicenseDetail 视图,因此我们可以利用 'Show In' 菜单快速识别软件实例的许可证并获得它的信息。

除生成的 'Show In' 菜单还包含禁用的 'System Explorer' 条目外,所有这些都很好用。在大多数情况下,这很好,但 InstanceExplorer 视图还包含实例主目录的项目,尽管有人可能认为它应该可用,但仍未启用该条目。

首先我假设它是禁用的,因为我们的InstanceExplorer提供的ShowInContext在其选择中有专有接口不适用于IResource。然而,一些调试显示尝试在这样的文件夹源上执行 'Show In (License Detail)' 最终会导致 LicenseDetail#show 返回 false,但 'Show In' 菜单中的条目仍处于启用状态。查看底层实现证实了这一点。

// excerpt of 'org.eclipse.ui.internal.ShowInHandler#execute'
try {
    IViewPart view = page.showView(targetId);
    IShowInTarget target = getShowInTarget(view);
    if (!(target != null && target.show(context)) {
        // this is the only location where the return value of 'ShowInTarget#show' is used
        page.getWorkbenchWindow().getShell().getDisplay().beep();
    }
    ((WorkbenchPage) page).performedShowIn(targetId);
} catch (PartInitException e) {
    throw new ExecutionException("Failed to show in", e);
}

因此我看不出有什么办法可以通过ShowInContext的内容来判断菜单项的启用状态。那么 'System Explorer' 的菜单条目如何确定这一点,我该如何利用它?


工作观点摘录类

除其他外,该插件包含一个视图,用于跟踪系统上可用的实例,类似于 egit 的 'Repostitory View'。此视图实现 IShowInSource 并将 'Show In' 菜单添加到其弹出菜单。

public class InstanceExplorer extends ViewPart implements IShowInSource {

    @Override
    public void createPartControl(Composite parent) {
        mMainViewer = InstanceExplorerViewerFactory.createViewer(parent);
        // omitted further viewer customization

        MenuManager contextMenu = new MenuManager();
        contextMenu.setRemoveAllWhenShown(true);
        contextMenu.addMenuListener(this::fillContextMenu);
        mMainViewer.getControl().setMenu(contextMenu.createContextMenu(mMainViewer.getControl());
        getSite().registerContextMenu(contextMenu, mMainViewer);
    }

    private void fillContextMenu(IMenuManager menu) {
        // omitted other context menu entries
        MenuManager showInMenu = new MenuManager("Show In");
        showInMenu.setActionDefinitionId("org.eclipse.ui.navigate.showInQuickMenu");
        menu.add(showInMenu);
        showInMenu.add(ContributionItemFactory.VIEWS_SHOW_IN.create(getSite().getWorkbenchWindow()));
    }

    @Override
    public void setFocus() {
         mMainViewer.getControl().setFocus();
    }

    @Override
    public ShowInContext getShowInContext() {
        return new ShowInContext(mMainViewer.getInput(), mMainViewer.getSelection());
    }

    private TreeViewer mMainViewer;

}

此外,它还包含一个显示有关产品许可证信息的视图。由于客户站点可能有多个许可证在使用,它实现了IShowInTarget,因此我们可以利用'Show In'菜单快速识别实例的许可证并获取其信息。

public class LicenseDetail extends ViewPart implements IShowInTarget {

    @Override
    public void createPartControl(Composite parent) {
        mMainViewer = LicenseDetailViewerFactory.createViewer(parent);
        // omitted further viewer customization
    }

    @Override
    public void setFocus() {
         mMainViewer.getControl().setFocus();
    }

    @Override
    public boolean show(ShowInContext context) {
        // LicenseInfo is a proprietary interface, modelling a license of our product
        LicenseInfo input = null;
        if (context.getSelection() instanceof IStructuredSelection) {
            input = findInput(((IStructuredSelection)context.getSelection()).getFirstElement());
        }
        if (null == input) {
            input = findInput(context.getInput());
        }
        if (null != input) {
            setInput(LicenseDetailViewerFactory.getInputs(input));
            return true;
        }
        return false;
    }

    private void setInput(Object input) {
        mMainViewer.setInput(input);
        // omitted: determines enabled states for actions and controls based on the new input
        validate();
    }

    private TreeViewer mMainViewer;

}

最后,LicenseDetail 视图在我们的透视工厂中被声明为 'Show In' 目标。

public class PerspectiveFactory implements IPerspectiveFactory {

    @Override
    public void createInitialLayout(IPageLayout layout) {
        // omitted page layout and shortcuts and more
        layout.addShowInPart("com.spell.moreen.suite.licenseDetail");
    }

}

为了完成,plugin.xml 文件。

<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
    <!-- omitted other extensions provided by the plugin -->
    <extension point="org.eclipse.ui.perspectives">
        <perspective
            class="com.spell.moreen.suite.gui.PerspectiveFactory"
            id="com.spell.moreen.suite.main"
            name="moreen Suite" />
    </extension>
    <extension point="org.eclipse.ui.views">
        <view
            class="com.spell.moreen.suite.gui.part.InstanceExplorer"
            id="com.spell.moreen.suite.instanceExplorer"
            name="Instance Explorer"
            restorable="true" />
        <view
            class="com.spell.moreen.suite.gui.part.LicenseDetail"
            id="com.spell.moreen.suite.licenseDetail"
            name="License Detail"
            restorable="true" />
    </extension>
</plugin>

在系统资源管理器中显示在 org.eclipse.ui.ide plugin.xml 中定义,并受此表达式控制:

   <extension
         point="org.eclipse.core.expressions.definitions">
      <definition
            id="org.eclipse.ui.ide.showInDefinition">
            <or>
            <with variable="selection">
                    <count value="1" />
                    <iterate ifEmpty="false">
                        <adapt type="org.eclipse.core.resources.IResource" />
                    </iterate>
             </with>
            <with
                  variable="activePart">
               <test
                     property="org.eclipse.ui.ide.editor.input">
               </test>
            </with>
            <with
                  variable="activeShell">
               <test
                     property="org.eclipse.ui.ide.page.activePreferencePage"
                     value="org.eclipse.ui.internal.ide.dialogs.ResourceInfoPage">
               </test>
            </with>
             </or>
      </definition>
   </extension>

这允许三种可能性:

  1. 当前选择是一个IResource或者可以“适应”一个(文件、文件夹、项目)

  2. 活动部分org.eclipse.ui.ide.editor.input测试returns正确。此测试器 returns 适用于具有 IFileEditorInput 或其他可以“适应”IResource

    的编辑器
  3. 资源信息 属性 页面处于活动状态(由该页面上的按钮使用)

代码中实际显示的是org.eclipse.ui.internal.ide.handlers.ShowInSystemExplorerHandler。查看源代码,它只有在找到 IResource.

时才会起作用