Как программно переключить перспективу после запуска приложения E4?

Сценарий

У меня есть чистое приложение E4, в котором я хочу выбрать начальную перспективу для пользователя в зависимости от ролей пользователя. Поэтому у меня есть перспектива для начала, которая содержит только одну часть. В этой части я использую @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));
  }
}

Эта проблема

Проблема довольно проста: при использовании вышеуказанного обработчика, запускаемого пунктом меню, он работает как положено и меняет перспективу. Но использование того же обработчика в моем первоначальном представлении (запуск его программно) не меняет перспективу. Я отладил код, чтобы проверить, получает ли обработчик одинаковую информацию в обоих случаях, и это так.

Может у меня приложение не до конца запустилось и поэтому обработчик не действует, но если проблема в этом, то как мне это проверить?

Любые идеи о том, что я, возможно, пропустил, приветствуются!


person TheGrav    schedule 06.07.2016    source источник
comment
Вы говорите, что pPartService.switchPerspective вызывается в обоих случаях?   -  person greg-449    schedule 06.07.2016
comment
Да, точно. Я зарегистрировал вышеуказанный обработчик с соответствующей командой в Application.e4xmi, которая будет выполняться для определенных пунктов меню с определенным идентификатором перспективы в качестве параметра команды. Для одного и того же идентификатора перспективы переключатель для каждого пункта меню работает нормально, но переключатель, управляемый программно, не работает.   -  person TheGrav    schedule 06.07.2016
comment
Я перепроверил это с помощью отладчика Eclipse IDE, и в обоих случаях я получил точно такой же экземпляр PerspectiveImpl.   -  person TheGrav    schedule 06.07.2016
comment
На всякий случай: сначала выполняется программный переключатель. Когда приложение запущено, я нажимаю пункт меню для переключения с элемента пользовательского интерфейса.   -  person TheGrav    schedule 06.07.2016
comment
Я не знаю, почему ваш подход не работает. Я бы предложил либо использовать надстройку для выбора первой перспективы, либо сделать это в LifeCycleHandler в @ProcessAdditions. Можно найти основной MPerspectiveStack, а затем использовать MPerspectiveStack.setSelectedItem для установки начальной перспективы. Таким образом, вам не нужно переключать его, и вам не нужна ваша фальшивая перспектива, потому что она уже установлена ​​​​правильно, когда модель приложения визуализируется.   -  person christoph.keimel    schedule 07.07.2016
comment
Звучит как хорошая идея. Я понял, как реализовать LifeCycleHandler, но не могу понять, как обратиться к моему MPerspectiveStack. Когда я пытаюсь получить это через DI для @ProcessAdditions-Method, вызов метода пропускается. Я пробовал простую инъекцию по типу, инъекцию по @@Named с идентификатором PerspectiveStack и с @@Active - ничего не сработало.   -  person TheGrav    schedule 07.07.2016


Ответы (1)


Основываясь на подсказке Кристофа Кеймеля, я мог создать рабочее решение (большое спасибо!). Вот код, решающий проблему:

@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, вы можете прочитать в учебнике Ларса Фогеля.

Моя основная проблема, связанная с поиском этого решения, заключалась в том, как получить доступ к стеку перспективы. Поскольку пользовательский интерфейс не работает, пока работает метод, аннотированный ProcessAdditions, мне нужно получить доступ к модели приложения через тип MApplication, который является корневым элементом моей модели приложения. Комбинируя EModelService, я могу получить доступ ко всем элементам пользовательского интерфейса, которые мне нужны, и управлять ими соответствующим образом. Внедрение любого элемента пользовательского интерфейса, такого как MPerspectiveStack или MWindow, приводит к пропущенному методу, поскольку они приводят к нулевым значениям из-за того, что они еще не инициализированы.

person TheGrav    schedule 11.07.2016