繁体   English   中英

如何在Eclipse RCP e4中制作多个窗口

[英]How to make multiple windows in Eclipse RCP e4

我们想要实现一个RCP应用程序,该应用程序可能具有用于不同数据的多个窗口( MWindow )。 Windows必须是独立的(与Eclipse IDE的新窗口菜单项不同),但是必须可以将内容从一个窗口复制并粘贴,拖放到另一个窗口中。 想象一下像Word这样的应用程序,您可以在其中打开多个文档。 我们尝试了各种方法,但是很难找到正确的e4方法:

1.为每个窗口创建一个新的E4Application

我们的第一种方法是为每个新窗口创建并运行一个完整的新E4Application。 但这听起来不是正确的e4方法。 也是有问题的:按键绑定无法正常工作,而且还为每个新应用程序调用了LifecycleManager ,因此为每个新窗口调用了LifecycleManager ,因此不应如此。

E4Application application = new E4Application();
BundleContext context = InternalPlatform.getDefault().getBundleContext();
ServiceReference<?> appContextService = context.getServiceReference(IApplicationContext.class);
IApplicationContext iac = (IApplicationContext) context.getService(appContextService);
IWorkbench workbench = application.createE4Workbench(iac, display);
 final E4Workbench implementation = (E4Workbench) workbench;
implementation.createAndRunUI(workbench.getApplication());

这似乎不是正确的方法。

2. Eclipse IDE方法

在Eclipse IDE中,您可以转到菜单并单击Window -> New Window ,这将打开一个完整的新顶层窗口。 但是它是同步的:在两个窗口中打开相同的文本文件,然后在第一个窗口中对其进行编辑也会在另一个窗口中对其进行更改。 尽管我们通过简单地从org.eclipse.ui.actions.OpenInNewWindowAction#run()复制并粘贴来尝试了该方法:

// Does not work because we do not have the RCP3 workbench in RCP4.
final IWorkbench workbench = PlatformUI.getWorkbench();
final IWorkbenchWindow workbenchWindow = workbench.getActiveWorkbenchWindow();
final IWorkbenchPage activePage = workbenchWindow.getActivePage();
final String perspectiveId;

if (activePage != null && activePage.getPerspective() != null) {
    perspectiveId = activePage.getPerspective().getId();
} else {
    perspectiveId = workbenchWindow.getWorkbench().getPerspectiveRegistry().getDefaultPerspective();
}

workbenchWindow.getWorkbench().openWorkbenchWindow(perspectiveId, null);

看来Eclipse IDE使用RCP3兼容性层。 我们没有找到获取IWorkbench对象的方法。 既不是通过PlatformUI#getWorkbench() ,也不是通过应用程序上下文,也不是通过捆绑软件上下文。

3.克隆主窗口

我们偶然发现了一个打开MTrimmedWindow的多个实例的实例,这些实例带有透视图等 n-mtrimmedwindow-complete-with-perspectives-etc等,并进行了大量的试验和错误,并得出了以下代码:

class ElementCloningBasedCreator {

    EModelService models = ...; // injected
    MApplication app = ...; // injected

    public void openNewWindow() {
        MWindow originWindow = (MWindow) models.find("the.main.window.id", app);
        MWindow newWindow = (MWindow) models.cloneElement(originWindow, null);

        MPerspectiveStack newPerspectiveStack =
            (MPerspectiveStack) models.find(the.main.perspective.stack.id, newWindow);
        newPerspectiveStack.setParent((MElementContainer) newWindow);

        addTo(app, newWindow);

        // Clone the shared elements. If we don't do that the rendering somewhere 
        // deep in the rabbit hole throws assertion erros because the recurisve 
        // finding of an element fails because the search root is null.
        for (final MUIElement originSharedElement : originWindow.getSharedElements()) {
            final MUIElement clonedSharedElement = models.cloneElement(originSharedElement, null);
            clonedSharedElement.setParent((MElementContainer) newWindow);
            newWindow.getSharedElements().add(clonedSharedElement);
        }

        cloneSnippets(app, originWindow, newPerspectiveStack, newWindow);
        newWindow.setContext(createContextForNewWindow(originWindow, newWindow));
        newWindow.setToBeRendered(true);
        newWindow.setVisible(true);
        newWindow.setOnTop(true);
        models.bringToTop(newWindow);
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    private void addTo(MElementContainer target, MUIElement child) {
        child.setParent(target);
        target.getChildren().add(child);
    }

    /**
     * Clone each snippet that is a perspective and add the cloned perspective 
     * into the main PerspectiveStack.
     */
    private void cloneSnippets(MApplication app, MWindow originWindow,
        MPerspectiveStack newPerspectiveStack, MWindow newWindow) {
        boolean isFirstSnippet = true;

        for (MUIElement snippet : app.getSnippets()) {
            if (ignoreSnippet(snippet)) {
                continue;
            }

            String snipetId = snippet.getElementId();
            MPerspective clonedPerspective = 
                (MPerspective) models.cloneSnippet(app, snipetId, originWindow);
            findPlaceholdersAndCloneReferencedParts(clonedPerspective, newWindow);
            addTo(newPerspectiveStack, clonedPerspective);

            if (isFirstSnippet) {
                newPerspectiveStack.setSelectedElement(clonedPerspective);
                isFirstSnippet = false;
            }
        }
    }

    private boolean ignoreSnippet(MUIElement snippet) {
        return !(snippet instanceof MPerspective);
    }

    private void findPlaceholdersAndCloneReferencedParts(MPerspective clonedPerspective, MWindow newWindow) {
        List<MPlaceholder> placeholders = 
            models.findElements(clonedPerspective, null, MPlaceholder.class, null);

        for (MPlaceholder placeholder : placeholders) {
            MUIElement reference = placeholder.getRef();

            if (reference != null) {
                placeholder.setRef(models.cloneElement(placeholder.getRef(), null));
                placeholder.getRef().setParent((MElementContainer) newWindow);
            }
        }
    }
}

由于缺乏官方文档,因此此代码无法真正起作用,我们确实需要一些提示/建议以正确执行操作。 打开的问题是:

  1. 我们是否需要克隆共享对象,如果不需要,我们如何防止在渲染过程中出现错误?
  2. 我们只看到了通过getChildren().add()将克隆的元素添加到父元素的代码,但是我们发现子元素不会自动获取父元素,尽管它为null 将父级添加到子级也是正确的模式吗?
  3. 我们深感我们做错了。 我们在这里所做的事情看起来太复杂了。 有没有更简单/更好的方法?

您可以使用EModelService cloneSnippet方法来执行此操作。

在Application.e4xmi的“ Snippets部分中设计MTrimmedWindow (或所需的任何窗口类型)。 确保已选中“ To Be RenderedVisible标志。 您可能需要设置宽度和高度范围(并且可能还需要设置x和y位置)。

您用于创建新窗口的命令处理程序将是:

@Execute
public void execute(EModelService modelService, MApplication app)
{
  MTrimmedWindow newWin = (MTrimmedWindow)modelService.cloneSnippet(app, "id of the snippet", null);

  app.getChildren().add(newWin);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM