-->

Open Perspective programmatically

2019-08-17 01:09发布

问题:

I am trying to provide a command/ handler to switch to a specific Perspective.

I came up with the following class:

public class OpenPerspectiveHandler {

    private static final Logger logger = Logger.getLogger(OpenPerspectiveHandler.class);
    @Inject
    private MApplication application;
    @Inject
    private EModelService modelService;
    @Inject
    private EPartService partService;
    private final String perspectiveId;

    public OpenPerspectiveHandler(String perspectiveId) {
        super();
        this.perspectiveId = perspectiveId;
    }

    public void changePerspective(String perspectiveId) {

        Optional<MPerspective> perspective = findPerspective();
        if(perspective.isPresent()) {
            partService.switchPerspective(perspective.get());
        } else {
            logger.debug("Perspective not found (" + perspectiveId + ")");
        }
    }

    @Execute
    public void execute() {

        changePerspective(perspectiveId);
    }

    private Optional<MPerspective> findPerspective() {

        MUIElement element = modelService.find(perspectiveId, application);
        if(element instanceof MPerspective) {
            return Optional.of((MPerspective)element);
        } else {
            logger.debug("Wrong type " + element);
        }
        return Optional.empty();
    }

    @Override
    public String toString() {

        return "OpenPerspectiveHandler [application=" + application + ", modelService=" + modelService + ", partService=" + partService + ", perspectiveId=" + perspectiveId + "]";
    }
}

Interestingly, this works only once. A workaround is to cache MPerspective once it was found and not to use modelService.find(perspectiveId, application) again.

Why does it work only once? modelService.find(perspectiveId, application) returns null after the first execution.

EDIT:

Another approach (as suggested by greg-449) is the following:

public class OpenPerspectiveHandler {

    private static final Logger logger = Logger.getLogger(OpenPerspectiveHandler.class);
    private final String perspectiveId;

    public OpenPerspectiveHandler(String perspectiveId) {
        super();
        this.perspectiveId = perspectiveId;
    }

    @Execute
    public void changePerspective(MApplication application, EModelService modelService, EPartService partService) {

        Optional<MPerspective> perspective = findPerspective(application, modelService);
        if(perspective.isPresent()) {
            partService.switchPerspective(perspective.get());
        } else {
            logger.debug("Perspective not found (" + perspectiveId + ")");
        }
    }

    private Optional<MPerspective> findPerspective(MApplication application, EModelService modelService) {

        MUIElement element = modelService.find(perspectiveId, application);
        if(element instanceof MPerspective) {
            return Optional.of((MPerspective)element);
        } else {
            logger.debug("Wrong type " + element);
        }
        return Optional.empty();
    }
}

But this approach also changes the perspective only once. modelService.find(perspectiveId, application); returns null after the first execution.

回答1:

The EPartService varies depending on the context that the handler runs in. In some cases you get the Application part service which only works if there is an active window.

You can get the part service for that window using something like:

MWindow window = (MWindow)modelService.find("top window id", application);

IEclipseContext windowContext = window.getContext();

EPartService windowPartService = windowContext.get(EPartService.class);