如何在启动 E4 应用程序后以编程方式切换透视图?

How can I switch perspective programmatically after starting an E4 application?

场景

我有一个纯 E4 应用程序,我想在其中 select 根据用户的角色为用户提供初始视角。因此,我有一个仅包含一部分的观点。在那部分,我使用@PostConstruct-Method 来检查用户的角色,然后触发切换视角的命令:


初始视图

@Inject
private IEclipseContext eclipseContext;

@PostConstruct
public void initialize() {
  // checking credentials and retrieving roles come here which is pretty long
  // that's why switching perspective is a seperate method 
  // and EclipseContext is injected to instance instead of method
  this.switchPerspective(_usersInitialPerspectiveId)
}

private void switchPerspective(String pTargetPerspectiveId) {
  final ECommandService _commandService = this.eclipseContext.get(ECommandService.class);
  final EHandlerService _handlerService = this.eclipseContext.get(EHandlerService.class);

  final Map<String, Object> _commandParameter = new HashMap<>();
  _commandParameter.put(PluginIdConstants.ID_OF_PARAMETER_FOR_SWITCH_PERSPEKTIVE,
     pZielPerspektiveId);

  final ParameterizedCommand _switchPerspectiveCommand =
     _commandService.createCommand(COMMAND_ID_FOR_SWITCH_PERSPECTIVE,
        _commandParameter);
  _handlerService.executeHandler(_switchPerspectiveCommand);
}

为了从此处切换视角,我使用与 Application.e4xmi 中配置的菜单项完全相同的处理程序,如下所示:


透视切换处理程序

@Execute
public void execute(final MWindow pWindow,
                    final EPartService pPartService,
                    final EModelService pModelService,
                    @Named(PluginIdConstants.ID_OF_PARAMETER_FOR_SWITCH_PERSPEKTIVE)
                    final String pPerspectiveId) {

  final List<MPerspective> _perspectives =
       pModelService.findElements(pWindow, pPerspectiveId, MPerspective.class, null);
  if (!(_perspectives.isEmpty())) {
     // Show perspective for looked up id
     pPartService.switchPerspective(_perspectives.get(0));
  }
}

问题

问题很简单:当使用由菜单项触发的上述处理程序时,它按预期工作并切换视角。但是我的初始视图使用相同的处理程序(以编程方式触发它)不会切换视角。我调试了代码以检查处理程序在两种情况下是否获得相同的信息并且它确实如此。

也许我的应用程序尚未完成启动,这就是处理程序无效的原因,但如果这是问题所在,我该如何检查?

欢迎就我可能遗漏的内容提出任何想法!

根据 Christoph Keimel 的提示,我可以创建一个可行的解决方案(非常感谢!)。这是解决问题的代码:

@ProcessAdditions
private void switchPerspective(final MApplication pApplication,
                               final IApplicationContext pApplicationContext,
                               final EModelService pModelService) {

  final MWindow _window =
     (MWindow) pModelService.find(PluginIdConstants.WINDOW_ID_FOR_MAIN, pApplication);

  final String _appName = pApplicationContext.getBrandingName();
  initializeWindowTitle(_window, _appName);

  final MPerspectiveStack pPerspectiveStack =
     (MPerspectiveStack) pModelService.find(PluginIdConstants.PERSPECTIVE_STACK_ID_FOR_MAIN,
        pAnwendung);

  for (final MPerspective _perspective : pPerspectiveStack.getChildren()) {
     if (_perspektive.getElementId().equalsIgnoreCase(this.startingPerspectiveId)) {
        pPerspectiveStack.setSelectedElement(_perspective);
        break;
     }
  }
}

关于如何注册LifeCycleHandler你可以看看Lars Vogel's Tutorial

我找到这个解决方案的主要问题是如何访问透视堆栈。由于 UI 没有启动,而用 ProcessAdditions 注释的方法是 运行,我必须通过 MApplication 类型访问应用程序模型——这是我的根元素应用模型。结合 EModelService 我可以访问我想要的所有 UI 元素并相应地操作它们。 注入任何 UI 元素,如 MPerspectiveStackMWindow 会导致跳过方法,因为这些方法由于尚未初始化而导致空值。