Eclipse 4 RCP - 应用程序没有活动窗口

时间:2014-11-01 13:18:20

标签: eclipse eclipse-rcp

我希望有一些辅助函数来操作UI 我不想传递任何参数,除了我的域模型所需的参数(我不想传递EModelService,EPartService等)。

问题:问题是我异常application does not have active window. 我找到了问题所在。  它发生的原因是我通过从应用程序上下文EPartService访问的IWorkbench.getApplication().getContext().get(EPartService.class)来操作部件。

这是重要的: 目前我正在尝试修改我的UI时遇到异常 AFTER 我从对话框中读取输入。请注意,当我尝试修改UI 之前时,错误不会发生 打开对话框。看看代码,我添加了一些评论。

NewFromDirectoryDialog.java

    package cz.vutbr.fit.xhriba01.bc.handlers;

    import javax.inject.Named;

    import org.eclipse.e4.core.di.annotations.Execute;
    import org.eclipse.e4.ui.model.application.MApplication;
    import org.eclipse.e4.ui.services.IServiceConstants;
    import org.eclipse.e4.ui.workbench.modeling.EPartService;
    import org.eclipse.jface.window.Window;
    import org.eclipse.swt.widgets.Shell;

    import cz.vutbr.fit.xhriba01.bc.BcModel;
    import cz.vutbr.fit.xhriba01.bc.resolvers.filesystem.FileSystemResolver;
    import cz.vutbr.fit.xhriba01.bc.ui.dialogs.NewFromDirectoryDialog;
    import cz.vutbr.fit.xhriba01.bc.ui.UI;

    public class NewFromDirectoryHandler {

        @Execute
        public void execute(MApplication application, EPartService partService, @Named(IServiceConstants.ACTIVE_SHELL) Shell shell) {
            FileSystemResolver fsr = new FileSystemResolver("/home/jara/git/cz.vutbr.fit.xhriba01.bc/bc/src",
                            "/home/jara/git/cz.vutbr.fit.xhriba01.bc/bc/bin");
                    BcModel.setResolver(fsr);
           // THIS CALL IS OK AND EVERYTHING WORKS
            UI.changeExplorerView("bc.partdescriptor.filesystemview", fsr);
            NewFromDirectoryDialog dialog = new NewFromDirectoryDialog(shell);
            dialog.create();
            if (dialog.open() == Window.OK) {
                String sourceDir = dialog.getSourceDir();
                String classDir = dialog.getClassDir();
                FileSystemResolver fsr = new FileSystemResolver(classDir, sourceDir);
//THIS CALL LEADS TO EXCEPTION: application does not have active window             
UI.changeExplorerView("bc.partdescriptor.filesystemview", fsr);

            }
        }

    }

来自应用程序上下文的EPartService基于org.eclipse.e4.ui.internal.workbench.ApplicationPartServiceImpl 而不是org.eclipse.e4.ui.internal.workbench.PartServiceImpl 作为EPartService实例,您在@PostConstruct视图上注入Part's带注释的方法时获得。

org.eclipse.e4.ui.internal.workbench.ApplicationPartServiceImpl(不是完整的源代码)

您可以看到错误可能发生,因为在ApplicationPartServiceImpl.createPart中调用UI.changeExplorerView时,Eclipse运行时不知道哪个窗口 目前有效。

package org.eclipse.e4.ui.internal.workbench;

import java.util.Collection;
import javax.inject.Inject;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
import org.eclipse.e4.ui.model.application.ui.basic.MInputPart;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.e4.ui.workbench.modeling.EPartService;
import org.eclipse.e4.ui.workbench.modeling.IPartListener;

public class ApplicationPartServiceImpl implements EPartService {

    private MApplication application;

    @Inject
    ApplicationPartServiceImpl(MApplication application) {
        this.application = application;
    }

    private EPartService getActiveWindowService() {
        IEclipseContext activeWindowContext = application.getContext().getActiveChild();
        if (activeWindowContext == null) {
            throw new IllegalStateException("Application does not have an active window"); //$NON-NLS-1$
        }
        EPartService activeWindowPartService = activeWindowContext.get(EPartService.class);
        if (activeWindowPartService == null) {
            throw new IllegalStateException("Active window context is invalid"); //$NON-NLS-1$
        }
        if (activeWindowPartService == this) {
            throw new IllegalStateException("Application does not have an active window"); //$NON-NLS-1$
        }
        return activeWindowPartService;
    }

    @Override
    public MPart createPart(String id) {
        return getActiveWindowService().createPart(id);
    }

}

LifeCycleManager.java(我如何初始化UI助手类)

您可以看到我正在向IWorkbench课程注入UI IWorkbench允许我访问MApplication,这就是我应该做的 需要修改应用UI。

package cz.vutbr.fit.xhriba01.bc;

import javax.inject.Inject;

import org.eclipse.e4.core.contexts.ContextInjectionFactory;
import org.eclipse.e4.core.di.annotations.Optional;
import org.eclipse.e4.ui.di.UIEventTopic;
import org.eclipse.e4.ui.workbench.IWorkbench;
import org.eclipse.e4.ui.workbench.UIEvents;

import cz.vutbr.fit.xhriba01.bc.ui.UI;


public class LifeCycleManager {

    @Inject
    @Optional
    private void appCompleted(@UIEventTopic(UIEvents.UILifeCycle.APP_STARTUP_COMPLETE) Object event, IWorkbench workbench) {
        ContextInjectionFactory.inject(UI.getDefault(), workbench.getApplication().getContext());
    }

}

UI.java

package cz.vutbr.fit.xhriba01.bc.ui;

import javax.inject.Inject;

import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
import org.eclipse.e4.ui.workbench.IWorkbench;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.e4.ui.workbench.modeling.EPartService;
import org.eclipse.e4.ui.workbench.modeling.EPartService.PartState;
import org.eclipse.jface.text.IDocument;

import cz.vutbr.fit.xhriba01.bc.BcModel;
import cz.vutbr.fit.xhriba01.bc.resolvers.ISourceAndClassResolver;

public class UI {

    public static final String PART_EXPLORER_ID = "bc.part.inspector";
    public static final String PART_EXPLORER_CONTAINER_ID = "bc.partstack.explorer_stack";
    public static final String PART_JAVA_SOURCE_VIEWER_ID = "bc.part.javasourceview";

    private static UI fInstance = new UI();

    @Inject
    private IWorkbench fWorkbench;

    private UI() {

    }

    public static void changeExplorerView(String partDescriptorId, ISourceAndClassResolver resolver) {

        EModelService modelService = fInstance.fWorkbench.getApplication().getContext().get(EModelService.class);
        EPartService partService = fInstance.fWorkbench.getApplication().getContext().get(EPartService.class);
        MApplication application = fInstance.fWorkbench.getApplication();

        MPart part = partService.createPart(partDescriptorId);
        MPart oldPart = partService.findPart(UI.PART_EXPLORER_ID);

        MPartStack partStack =  (MPartStack) modelService.find(UI.PART_EXPLORER_CONTAINER_ID, application);
        partStack.setVisible(true);

        if (oldPart != null) {
            partService.hidePart(oldPart);
        }

        part.setElementId(UI.PART_EXPLORER_ID);
        partStack.getChildren().add(part);

        BcModel.setResolver(resolver);

        partService.showPart(part, PartState.VISIBLE);

    }

    public static UI getDefault() {
        return fInstance;
    }

    public static void setJavaSourceLabel(String label, EPartService partService) {
        MPart part = partService.findPart(UI.PART_JAVA_SOURCE_VIEWER_ID);
        if (part != null) {
            part.setLabel(label);
        }
    }

    public static void setJavaSourceText(String source) {
        IDocument document = BcModel.getJavaDocument();
        if (document != null) {
            document.set(source);
        }
    }

}

我认为问题是当我打开对话框时,activeChild以某种方式更改为新打开的对话框,当我关闭它并尝试立即更改我的UI时,它不起作用,因为activeChild仍然没有正确设置回来。其他我不知道为什么它在我打开对话框之前工作正常,并且在对话框关闭后不起作用。

有人知道这是不是错误?

0 个答案:

没有答案