private void selectViewableElement() {
   PsiDocumentManager.getInstance(myProject).commitAllDocuments();
   final Object currentEditorElement = myTreeModel.getCurrentEditorElement();
   if (currentEditorElement != null) {
     select(currentEditorElement, false);
   }
 }
  @Nullable
  public PsiElement getCurrentElement(@Nullable final PsiFile psiFile) {
    if (psiFile == null) return null;

    PsiDocumentManager.getInstance(myProject).commitAllDocuments();

    Object elementAtCursor = myTreeModel.getCurrentEditorElement();
    if (elementAtCursor instanceof PsiElement) {
      return (PsiElement) elementAtCursor;
    }

    return null;
  }
  protected ActionGroup createActionGroup() {
    DefaultActionGroup result = new DefaultActionGroup();
    Sorter[] sorters = myTreeModel.getSorters();
    for (final Sorter sorter : sorters) {
      if (sorter.isVisible()) {
        result.add(new TreeActionWrapper(sorter, this));
      }
    }
    if (sorters.length > 0) {
      result.addSeparator();
    }

    Grouper[] groupers = myTreeModel.getGroupers();
    for (Grouper grouper : groupers) {
      result.add(new TreeActionWrapper(grouper, this));
    }
    Filter[] filters = myTreeModel.getFilters();
    for (Filter filter : filters) {
      result.add(new TreeActionWrapper(filter, this));
    }
    if (myTreeModel instanceof ProvidingTreeModel) {
      final Collection<NodeProvider> providers =
          ((ProvidingTreeModel) myTreeModel).getNodeProviders();
      for (NodeProvider provider : providers) {
        result.add(new TreeActionWrapper(provider, this));
      }
    }

    result.add(new ExpandAllAction(getTree()));
    result.add(new CollapseAllAction(getTree()));
    if (showScrollToFromSourceActions()) {
      result.addSeparator();

      result.add(myAutoScrollToSourceHandler.createToggleAction());
      result.add(myAutoScrollFromSourceHandler.createToggleAction());
    }
    return result;
  }
  public JComponent createCenterPanel() {
    List<FileStructureFilter> fileStructureFilters = new ArrayList<FileStructureFilter>();
    List<FileStructureNodeProvider> fileStructureNodeProviders =
        new ArrayList<FileStructureNodeProvider>();
    if (myTreeActionsOwner != null) {
      for (Filter filter : myBaseTreeModel.getFilters()) {
        if (filter instanceof FileStructureFilter) {
          final FileStructureFilter fsFilter = (FileStructureFilter) filter;
          myTreeActionsOwner.setActionIncluded(fsFilter, true);
          fileStructureFilters.add(fsFilter);
        }
      }

      if (myBaseTreeModel instanceof ProvidingTreeModel) {
        for (NodeProvider provider : ((ProvidingTreeModel) myBaseTreeModel).getNodeProviders()) {
          if (provider instanceof FileStructureNodeProvider) {
            fileStructureNodeProviders.add((FileStructureNodeProvider) provider);
          }
        }
      }
    }
    final JPanel panel = new JPanel(new BorderLayout());
    JPanel comboPanel = new JPanel(new GridLayout(0, 2, 0, 0));

    final Shortcut[] F4 =
        ActionManager.getInstance()
            .getAction(IdeActions.ACTION_EDIT_SOURCE)
            .getShortcutSet()
            .getShortcuts();
    final Shortcut[] ENTER = CustomShortcutSet.fromString("ENTER").getShortcuts();
    final CustomShortcutSet shortcutSet = new CustomShortcutSet(ArrayUtil.mergeArrays(F4, ENTER));
    new AnAction() {
      public void actionPerformed(AnActionEvent e) {
        final boolean succeeded = navigateSelectedElement();
        if (succeeded) {
          unregisterCustomShortcutSet(panel);
        }
      }
    }.registerCustomShortcutSet(shortcutSet, panel);

    new AnAction() {
      public void actionPerformed(AnActionEvent e) {
        if (mySpeedSearch != null && mySpeedSearch.isPopupActive()) {
          mySpeedSearch.hidePopup();
        } else {
          myPopup.cancel();
        }
      }
    }.registerCustomShortcutSet(CustomShortcutSet.fromString("ESCAPE"), myTree);

    new ClickListener() {
      @Override
      public boolean onClick(MouseEvent e, int clickCount) {
        navigateSelectedElement();
        return true;
      }
    }.installOn(myTree);

    for (FileStructureFilter filter : fileStructureFilters) {
      addCheckbox(comboPanel, filter);
    }

    for (FileStructureNodeProvider provider : fileStructureNodeProviders) {
      addCheckbox(comboPanel, provider);
    }
    myPreferredWidth = Math.max(comboPanel.getPreferredSize().width, 350);
    panel.add(comboPanel, BorderLayout.NORTH);
    JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myAbstractTreeBuilder.getTree());
    scrollPane.setBorder(IdeBorderFactory.createBorder(SideBorder.TOP | SideBorder.BOTTOM));
    panel.add(scrollPane, BorderLayout.CENTER);
    panel.add(createSouthPanel(), BorderLayout.SOUTH);
    DataManager.registerDataProvider(
        panel,
        new DataProvider() {
          @Override
          public Object getData(@NonNls String dataId) {
            if (PlatformDataKeys.PROJECT.is(dataId)) {
              return myProject;
            }
            if (LangDataKeys.PSI_ELEMENT.is(dataId)) {
              final Object node =
                  ContainerUtil.getFirstItem(myAbstractTreeBuilder.getSelectedElements());
              if (!(node instanceof FilteringTreeStructure.FilteringNode)) return null;
              return getPsi((FilteringTreeStructure.FilteringNode) node);
            }
            if (LangDataKeys.POSITION_ADJUSTER_POPUP.is(dataId)) {
              return myPopup;
            }
            if (PlatformDataKeys.TREE_EXPANDER.is(dataId)) {
              return myTreeExpander;
            }
            return null;
          }
        });

    return panel;
  }
  @Override
  public void invoke(
      @NotNull final Project project, @NotNull final Editor editor, @NotNull PsiFile file) {
    PsiDocumentManager.getInstance(project).commitAllDocuments();

    PsiElement container = null;
    WeakReference<LightweightHint> ref = editor.getUserData(MY_LAST_HINT_KEY);
    if (ref != null) {
      LightweightHint hint = ref.get();
      if (hint != null && hint.isVisible()) {
        hint.hide();
        container = hint.getUserData(CONTAINER_KEY);
        if (container != null && !container.isValid()) {
          container = null;
        }
      }
    }

    StructureViewBuilder builder =
        LanguageStructureViewBuilder.INSTANCE.getStructureViewBuilder(file);
    if (builder instanceof TreeBasedStructureViewBuilder) {
      StructureViewModel model =
          ((TreeBasedStructureViewBuilder) builder).createStructureViewModel();
      boolean goOneLevelUp = true;
      if (container == null) {
        goOneLevelUp = false;
        Object element = model.getCurrentEditorElement();
        if (element instanceof PsiElement) {
          container = (PsiElement) element;
        }
      }
      while (true) {
        if (container == null || container instanceof PsiFile) {
          return;
        }
        if (goOneLevelUp) {
          goOneLevelUp = false;
        } else {
          if (!isDeclarationVisible(container, editor)) {
            break;
          }
        }

        container = container.getParent();
        while (container != null
            && DeclarationRangeUtil.getPossibleDeclarationAtRange(container) == null) {
          container = container.getParent();
          if (container instanceof PsiFile) return;
        }
      }
    }
    if (container == null) {
      return;
    }

    final TextRange range = DeclarationRangeUtil.getPossibleDeclarationAtRange(container);
    if (range == null) {
      return;
    }
    final PsiElement _container = container;
    ApplicationManager.getApplication()
        .invokeLater(
            new Runnable() {
              @Override
              public void run() {
                LightweightHint hint =
                    EditorFragmentComponent.showEditorFragmentHint(editor, range, true, true);
                if (hint != null) {
                  hint.putUserData(CONTAINER_KEY, _container);
                  editor.putUserData(MY_LAST_HINT_KEY, new WeakReference<LightweightHint>(hint));
                }
              }
            });
  }
 public boolean navigateToSelectedElement(boolean requestFocus) {
   return select(myTreeModel.getCurrentEditorElement(), requestFocus);
 }
 @Override
 @NotNull
 public Grouper[] getGroupers() {
   return myStructureViewModel.getGroupers();
 }
 @Override
 @NotNull
 public Filter[] getFilters() {
   return myStructureViewModel.getFilters();
 }
 @Override
 public void dispose() {
   myStructureViewModel.dispose();
 }
 @Override
 @NotNull
 public StructureViewTreeElement getRoot() {
   return new StructureViewElementWrapper<>(myStructureViewModel.getRoot(), myMainFile);
 }
 @Override
 public void removeModelListener(@NotNull final ModelListener modelListener) {
   myStructureViewModel.removeModelListener(modelListener);
 }
 @Override
 public void removeEditorPositionListener(@NotNull final FileEditorPositionListener listener) {
   myStructureViewModel.removeEditorPositionListener(listener);
 }
 @Override
 public Object getCurrentEditorElement() {
   return myStructureViewModel.getCurrentEditorElement();
 }