public void focusLost(final FocusEvent e) {
    if (myPanel.getProject().isDisposed()) {
      myPanel.setContextComponent(null);
      myPanel.hideHint();
      return;
    }
    final DialogWrapper dialog = DialogWrapper.findInstance(e.getOppositeComponent());
    shouldFocusEditor = dialog != null;
    if (dialog != null) {
      Disposer.register(
          dialog.getDisposable(),
          new Disposable() {
            @Override
            public void dispose() {
              if (dialog.getExitCode() == DialogWrapper.CANCEL_EXIT_CODE) {
                shouldFocusEditor = false;
              }
            }
          });
    }

    // required invokeLater since in current call sequence KeyboardFocusManager is not initialized
    // yet
    // but future focused component
    //noinspection SSBasedInspection
    SwingUtilities.invokeLater(
        new Runnable() {
          public void run() {
            processFocusLost(e);
          }
        });
  }
  @Override
  public void keyPressed(final KeyEvent e) {
    if (!(e.isAltDown() || e.isMetaDown() || e.isControlDown() || myPanel.isNodePopupActive())) {
      if (!Character.isLetter(e.getKeyChar())) {
        return;
      }

      final IdeFocusManager focusManager = IdeFocusManager.getInstance(myPanel.getProject());
      final ActionCallback firstCharTyped = new ActionCallback();
      focusManager.typeAheadUntil(firstCharTyped);
      myPanel.moveDown();
      //noinspection SSBasedInspection
      SwingUtilities.invokeLater(
          new Runnable() {
            public void run() {
              try {
                final Robot robot = new Robot();
                final boolean shiftOn = e.isShiftDown();
                final int code = e.getKeyCode();
                if (shiftOn) {
                  robot.keyPress(KeyEvent.VK_SHIFT);
                }
                robot.keyPress(code);
                robot.keyRelease(code);

                // don't release Shift
                firstCharTyped.setDone();
              } catch (AWTException ignored) {
              }
            }
          });
    }
  }
 @Override
 public void propertyChange(PropertyChangeEvent evt) {
   if (myPanel.isShowing()) {
     final String name = evt.getPropertyName();
     if ("focusOwner".equals(name) || "permanentFocusOwner".equals(name)) {
       myPanel.getUpdateQueue().restartRebuild();
     }
   }
 }
  @Override
  public void afterActionPerformed(AnAction action, DataContext dataContext, AnActionEvent event) {
    if (shouldSkipAction(action)) return;

    if (myPanel.isInFloatingMode()) {
      myPanel.hideHint();
    } else {
      myPanel.cancelPopup();
    }
  }
 @Override
 public void actionPerformed(ActionEvent e) {
   final NavBarKeyboardCommand cmd = NavBarKeyboardCommand.fromString(e.getActionCommand());
   if (cmd != null) {
     switch (cmd) {
       case LEFT:
         myPanel.moveLeft();
         break;
       case RIGHT:
         myPanel.moveRight();
         break;
       case HOME:
         myPanel.moveHome();
         break;
       case END:
         myPanel.moveEnd();
         break;
       case DOWN:
         myPanel.moveDown();
         break;
       case UP:
         myPanel.moveDown();
         break;
       case ENTER:
         myPanel.enter();
         break;
       case ESCAPE:
         myPanel.escape();
         break;
       case NAVIGATE:
         myPanel.navigate();
         break;
     }
   }
 }
 NavBarListener(NavBarPanel panel) {
   myPanel = panel;
   for (NavBarKeyboardCommand command : NavBarKeyboardCommand.values()) {
     registerKey(command);
   }
   myPanel.addFocusListener(this);
 }
 static void unsubscribeFrom(NavBarPanel panel) {
   final NavBarListener listener = (NavBarListener) panel.getClientProperty(LISTENER);
   panel.putClientProperty(LISTENER, null);
   if (listener != null) {
     final Project project = panel.getProject();
     KeyboardFocusManager.getCurrentKeyboardFocusManager().removePropertyChangeListener(listener);
     FileStatusManager.getInstance(project).removeFileStatusListener(listener);
     PsiManager.getInstance(project).removePsiTreeChangeListener(listener);
     WolfTheProblemSolver.getInstance(project).removeProblemListener(listener);
     ActionManager.getInstance().removeAnActionListener(listener);
     final MessageBusConnection connection = (MessageBusConnection) panel.getClientProperty(BUS);
     panel.putClientProperty(BUS, null);
     if (connection != null) {
       connection.disconnect();
     }
   }
 }
  static void subscribeTo(NavBarPanel panel) {
    if (panel.getClientProperty(LISTENER) != null) {
      unsubscribeFrom(panel);
    }

    final NavBarListener listener = new NavBarListener(panel);
    final Project project = panel.getProject();
    panel.putClientProperty(LISTENER, listener);
    KeyboardFocusManager.getCurrentKeyboardFocusManager().addPropertyChangeListener(listener);
    FileStatusManager.getInstance(project).addFileStatusListener(listener);
    PsiManager.getInstance(project).addPsiTreeChangeListener(listener);
    WolfTheProblemSolver.getInstance(project).addProblemListener(listener);
    ActionManager.getInstance().addAnActionListener(listener);

    final MessageBusConnection connection = project.getMessageBus().connect();
    connection.subscribe(ProjectTopics.PROJECT_ROOTS, listener);
    connection.subscribe(NavBarModelListener.NAV_BAR, listener);
    connection.subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, listener);
    panel.putClientProperty(BUS, connection);
    panel.addKeyListener(listener);

    if (panel.isInFloatingMode()) {
      final Window window = SwingUtilities.windowForComponent(panel);
      if (window != null) {
        window.addWindowFocusListener(listener);
      }
    }
  }
 public void focusGained(final FocusEvent e) {
   if (e.getOppositeComponent() == null && shouldFocusEditor) {
     shouldFocusEditor = false;
     ToolWindowManager.getInstance(myPanel.getProject()).activateEditorComponent();
     return;
   }
   myPanel.updateItems();
   final List<NavBarItem> items = myPanel.getItems();
   if (!myPanel.isInFloatingMode() && items.size() > 0) {
     myPanel.setContextComponent(items.get(items.size() - 1));
   } else {
     myPanel.setContextComponent(null);
   }
 }
  private void processFocusLost(FocusEvent e) {
    final Component opposite = e.getOppositeComponent();

    if (myPanel.isInFloatingMode()
        && opposite != null
        && DialogWrapper.findInstance(opposite) != null) {
      myPanel.hideHint();
      return;
    }

    final boolean nodePopupInactive = !myPanel.isNodePopupActive();
    boolean childPopupInactive = !JBPopupFactory.getInstance().isChildPopupFocused(myPanel);
    if (nodePopupInactive && childPopupInactive) {
      if (opposite != null
          && opposite != myPanel
          && !myPanel.isAncestorOf(opposite)
          && !e.isTemporary()) {
        myPanel.setContextComponent(null);
        myPanel.hideHint();
      }
    }

    myPanel.updateItems();
  }
 @Override
 public void selectionChanged() {
   myPanel.updateItems();
   myPanel.scrollSelectionToVisible();
 }
 private void updateModel() {
   if (myPanel.isShowing()) {
     myPanel.getModel().setChanged(true);
     myPanel.getUpdateQueue().queueModelUpdateFromFocus();
   }
 }
 private void rebuildUI() {
   if (myPanel.isShowing()) {
     myPanel.getUpdateQueue().queueRebuildUi();
   }
 }
 private void registerKey(NavBarKeyboardCommand cmd) {
   myPanel.registerKeyboardAction(this, cmd.name(), cmd.getKeyStroke(), JComponent.WHEN_FOCUSED);
 }