private boolean handleNextStep(final PopupStep nextStep, Object parentValue, InputEvent e) {
    if (nextStep != PopupStep.FINAL_CHOICE) {
      final Point point = myList.indexToLocation(myList.getSelectedIndex());
      SwingUtilities.convertPointToScreen(point, myList);
      myChild = createPopup(this, nextStep, parentValue);
      if (myChild instanceof ListPopupImpl) {
        for (ListSelectionListener listener : myList.getListSelectionListeners()) {
          ((ListPopupImpl) myChild).addListSelectionListener(listener);
        }
      }
      final JComponent container = getContent();
      assert container != null : "container == null";

      int y = point.y;
      if (parentValue != null && getListModel().isSeparatorAboveOf(parentValue)) {
        SeparatorWithText swt = new SeparatorWithText();
        swt.setCaption(getListModel().getCaptionAboveOf(parentValue));
        y += swt.getPreferredSize().height - 1;
      }

      myChild.show(container, point.x + container.getWidth() - STEP_X_PADDING, y, true);
      setIndexForShowingChild(myList.getSelectedIndex());
      return false;
    } else {
      setOk(true);
      setFinalRunnable(myStep.getFinalRunnable());
      disposeAllParents(e);
      setIndexForShowingChild(-1);
      return true;
    }
  }
 @Override
 public void dispose() {
   if (myDisposeCallback != null) {
     myDisposeCallback.run();
   }
   ActionMenu.showDescriptionInStatusBar(true, myComponent, null);
   super.dispose();
 }
  private void chooseAndImport(Editor editor, final Project project) {
    if (ApplicationManager.getApplication().isUnitTestMode()) {
      doImport(candidates.get(0));
      return;
    }
    final BaseListPopupStep<PsiMethod> step =
        new BaseListPopupStep<PsiMethod>(
            QuickFixBundle.message("class.to.import.chooser.title"), candidates) {

          @Override
          public PopupStep onChosen(PsiMethod selectedValue, boolean finalChoice) {
            if (selectedValue == null) {
              return FINAL_CHOICE;
            }

            if (finalChoice) {
              PsiDocumentManager.getInstance(project).commitAllDocuments();
              LOG.assertTrue(selectedValue.isValid());
              doImport(selectedValue);
              return FINAL_CHOICE;
            }

            String qname = getMemberQualifiedName(selectedValue);
            if (qname == null) return FINAL_CHOICE;
            List<String> excludableStrings = AddImportAction.getAllExcludableStrings(qname);
            return new BaseListPopupStep<String>(null, excludableStrings) {
              @NotNull
              @Override
              public String getTextFor(String value) {
                return "Exclude '" + value + "' from auto-import";
              }

              @Override
              public PopupStep onChosen(String selectedValue, boolean finalChoice) {
                if (finalChoice) {
                  AddImportAction.excludeFromImport(project, selectedValue);
                }

                return super.onChosen(selectedValue, finalChoice);
              }
            };
          }

          @Override
          public boolean hasSubstep(PsiMethod selectedValue) {
            return true;
          }

          @NotNull
          @Override
          public String getTextFor(PsiMethod value) {
            return ObjectUtils.assertNotNull(value.getName());
          }

          @Override
          public Icon getIconFor(PsiMethod aValue) {
            return aValue.getIcon(0);
          }
        };

    final ListPopupImpl popup =
        new ListPopupImpl(step) {
          final PopupListElementRenderer rightArrow = new PopupListElementRenderer(this);

          @Override
          protected ListCellRenderer getListElementRenderer() {
            return new MethodCellRenderer(true, PsiFormatUtilBase.SHOW_NAME) {
              @Override
              protected DefaultListCellRenderer getRightCellRenderer() {
                final DefaultListCellRenderer moduleRenderer = super.getRightCellRenderer();
                return new DefaultListCellRenderer() {
                  @Override
                  public Component getListCellRendererComponent(
                      JList list,
                      Object value,
                      int index,
                      boolean isSelected,
                      boolean cellHasFocus) {
                    JPanel panel = new JPanel(new BorderLayout());
                    if (moduleRenderer != null) {
                      Component moduleComponent =
                          moduleRenderer.getListCellRendererComponent(
                              list, value, index, isSelected, cellHasFocus);
                      panel.add(moduleComponent, BorderLayout.CENTER);
                    }
                    rightArrow.getListCellRendererComponent(
                        list, value, index, isSelected, cellHasFocus);
                    Component rightArrowComponent = rightArrow.getNextStepLabel();
                    panel.add(rightArrowComponent, BorderLayout.EAST);
                    return panel;
                  }
                };
              }
            };
          }
        };
    popup.showInBestPositionFor(editor);
  }
  private static JBPopup getPsiElementPopup(
      final Object[] elements,
      final Map<PsiElement, GotoRelatedItem> itemsMap,
      final String title,
      final Processor<Object> processor) {

    final Ref<Boolean> hasMnemonic = Ref.create(false);
    final DefaultPsiElementCellRenderer renderer =
        new DefaultPsiElementCellRenderer() {
          {
            setFocusBorderEnabled(false);
          }

          @Override
          public String getElementText(PsiElement element) {
            String customName = itemsMap.get(element).getCustomName();
            return (customName != null ? customName : super.getElementText(element));
          }

          @Override
          protected Icon getIcon(PsiElement element) {
            Icon customIcon = itemsMap.get(element).getCustomIcon();
            return customIcon != null ? customIcon : super.getIcon(element);
          }

          @Override
          public String getContainerText(PsiElement element, String name) {
            PsiFile file = element.getContainingFile();
            return file != null && !getElementText(element).equals(file.getName())
                ? "(" + file.getName() + ")"
                : null;
          }

          @Override
          protected DefaultListCellRenderer getRightCellRenderer() {
            return null;
          }

          @Override
          protected boolean customizeNonPsiElementLeftRenderer(
              ColoredListCellRenderer renderer,
              JList list,
              Object value,
              int index,
              boolean selected,
              boolean hasFocus) {
            final GotoRelatedItem item = (GotoRelatedItem) value;
            Color color = list.getForeground();
            final SimpleTextAttributes nameAttributes = new SimpleTextAttributes(Font.PLAIN, color);
            final String name = item.getCustomName();
            if (name == null) return false;
            renderer.append(name, nameAttributes);
            renderer.setIcon(item.getCustomIcon());
            return true;
          }

          @Override
          public Component getListCellRendererComponent(
              JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            final JPanel component =
                (JPanel)
                    super.getListCellRendererComponent(
                        list, value, index, isSelected, cellHasFocus);
            if (!hasMnemonic.get()) return component;

            final JPanel panelWithMnemonic = new JPanel(new BorderLayout());
            final int mnemonic = getMnemonic(value, itemsMap);
            final JLabel label = new JLabel("");
            if (mnemonic != -1) {
              label.setText(mnemonic + ".");
              label.setDisplayedMnemonicIndex(0);
            }
            label.setPreferredSize(new JLabel("8.").getPreferredSize());

            final JComponent leftRenderer = (JComponent) component.getComponents()[0];
            component.remove(leftRenderer);
            panelWithMnemonic.setBackground(leftRenderer.getBackground());
            label.setBackground(leftRenderer.getBackground());
            panelWithMnemonic.add(label, BorderLayout.WEST);
            panelWithMnemonic.add(leftRenderer, BorderLayout.CENTER);
            component.add(panelWithMnemonic);
            return component;
          }
        };
    final ListPopupImpl popup =
        new ListPopupImpl(
            new BaseListPopupStep<Object>(title, Arrays.asList(elements)) {
              @Override
              public boolean isSpeedSearchEnabled() {
                return true;
              }

              @Override
              public PopupStep onChosen(Object selectedValue, boolean finalChoice) {
                processor.process(selectedValue);
                return super.onChosen(selectedValue, finalChoice);
              }
            }) {
          @Override
          protected ListCellRenderer getListElementRenderer() {
            return renderer;
          }
        };
    popup.setMinimumSize(new Dimension(200, -1));
    for (Object item : elements) {
      final int mnemonic = getMnemonic(item, itemsMap);
      if (mnemonic != -1) {
        final Action action = createNumberAction(mnemonic, popup, itemsMap, processor);
        popup.registerAction(
            mnemonic + "Action", KeyStroke.getKeyStroke(String.valueOf(mnemonic)), action);
        hasMnemonic.set(true);
      }
    }
    return popup;
  }
  private static JBPopup getPsiElementPopup(
      final Object[] elements,
      final Map<PsiElement, GotoRelatedItem> itemsMap,
      final String title,
      final boolean showContainingModules,
      final Processor<Object> processor) {

    final Ref<Boolean> hasMnemonic = Ref.create(false);
    final DefaultPsiElementCellRenderer renderer =
        new DefaultPsiElementCellRenderer() {
          {
            setFocusBorderEnabled(false);
          }

          @Override
          public String getElementText(PsiElement element) {
            String customName = itemsMap.get(element).getCustomName();
            return (customName != null ? customName : super.getElementText(element));
          }

          @Override
          protected Icon getIcon(PsiElement element) {
            Icon customIcon = itemsMap.get(element).getCustomIcon();
            return customIcon != null ? customIcon : super.getIcon(element);
          }

          @Override
          public String getContainerText(PsiElement element, String name) {
            String customContainerName = itemsMap.get(element).getCustomContainerName();

            if (customContainerName != null) {
              return customContainerName;
            }
            PsiFile file = element.getContainingFile();
            return file != null && !getElementText(element).equals(file.getName())
                ? "(" + file.getName() + ")"
                : null;
          }

          @Override
          protected DefaultListCellRenderer getRightCellRenderer(Object value) {
            return showContainingModules ? super.getRightCellRenderer(value) : null;
          }

          @Override
          protected boolean customizeNonPsiElementLeftRenderer(
              ColoredListCellRenderer renderer,
              JList list,
              Object value,
              int index,
              boolean selected,
              boolean hasFocus) {
            final GotoRelatedItem item = (GotoRelatedItem) value;
            Color color = list.getForeground();
            final SimpleTextAttributes nameAttributes =
                new SimpleTextAttributes(SimpleTextAttributes.STYLE_PLAIN, color);
            final String name = item.getCustomName();
            if (name == null) return false;
            renderer.append(name, nameAttributes);
            renderer.setIcon(item.getCustomIcon());
            return true;
          }

          @Override
          public Component getListCellRendererComponent(
              JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            final JPanel component =
                (JPanel)
                    super.getListCellRendererComponent(
                        list, value, index, isSelected, cellHasFocus);
            if (!hasMnemonic.get()) return component;

            final JPanel panelWithMnemonic = new JPanel(new BorderLayout());
            final int mnemonic = getMnemonic(value, itemsMap);
            final JLabel label = new JLabel("");
            if (mnemonic != -1) {
              label.setText(mnemonic + ".");
              label.setDisplayedMnemonicIndex(0);
            }
            label.setPreferredSize(new JLabel("8.").getPreferredSize());

            final JComponent leftRenderer = (JComponent) component.getComponents()[0];
            component.remove(leftRenderer);
            panelWithMnemonic.setBorder(BorderFactory.createEmptyBorder(0, 7, 0, 0));
            panelWithMnemonic.setBackground(leftRenderer.getBackground());
            label.setBackground(leftRenderer.getBackground());
            panelWithMnemonic.add(label, BorderLayout.WEST);
            panelWithMnemonic.add(leftRenderer, BorderLayout.CENTER);
            component.add(panelWithMnemonic);
            return component;
          }
        };
    final ListPopupImpl popup =
        new ListPopupImpl(
            new BaseListPopupStep<Object>(title, Arrays.asList(elements)) {
              @Override
              public boolean isSpeedSearchEnabled() {
                return true;
              }

              @Override
              public String getIndexedString(Object value) {
                if (value instanceof GotoRelatedItem) {
                  //noinspection ConstantConditions
                  return ((GotoRelatedItem) value).getCustomName();
                }
                PsiElement element = (PsiElement) value;
                if (!element.isValid()) return "INVALID";
                return renderer.getElementText(element)
                    + " "
                    + renderer.getContainerText(element, null);
              }

              @Override
              public PopupStep onChosen(Object selectedValue, boolean finalChoice) {
                processor.process(selectedValue);
                return super.onChosen(selectedValue, finalChoice);
              }
            }) {};
    popup
        .getList()
        .setCellRenderer(
            new PopupListElementRenderer(popup) {
              Map<Object, String> separators = new HashMap<Object, String>();

              {
                final ListModel model = popup.getList().getModel();
                String current = null;
                boolean hasTitle = false;
                for (int i = 0; i < model.getSize(); i++) {
                  final Object element = model.getElementAt(i);
                  final GotoRelatedItem item = itemsMap.get(element);
                  if (item != null && !StringUtil.equals(current, item.getGroup())) {
                    current = item.getGroup();
                    separators.put(element, current);
                    if (!hasTitle && !StringUtil.isEmpty(current)) {
                      hasTitle = true;
                    }
                  }
                }

                if (!hasTitle) {
                  separators.remove(model.getElementAt(0));
                }
              }

              @Override
              public Component getListCellRendererComponent(
                  JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
                final Component component =
                    renderer.getListCellRendererComponent(
                        list, value, index, isSelected, cellHasFocus);
                final String separator = separators.get(value);

                if (separator != null) {
                  JPanel panel = new JPanel(new BorderLayout());
                  panel.add(component, BorderLayout.CENTER);
                  final SeparatorWithText sep =
                      new SeparatorWithText() {
                        @Override
                        protected void paintComponent(Graphics g) {
                          g.setColor(new JBColor(Color.WHITE, UIUtil.getSeparatorColor()));
                          g.fillRect(0, 0, getWidth(), getHeight());
                          super.paintComponent(g);
                        }
                      };
                  sep.setCaption(separator);
                  panel.add(sep, BorderLayout.NORTH);
                  return panel;
                }
                return component;
              }
            });

    popup.setMinimumSize(new Dimension(200, -1));

    for (Object item : elements) {
      final int mnemonic = getMnemonic(item, itemsMap);
      if (mnemonic != -1) {
        final Action action = createNumberAction(mnemonic, popup, itemsMap, processor);
        popup.registerAction(
            mnemonic + "Action", KeyStroke.getKeyStroke(String.valueOf(mnemonic)), action);
        popup.registerAction(
            mnemonic + "Action",
            KeyStroke.getKeyStroke("NUMPAD" + String.valueOf(mnemonic)),
            action);
        hasMnemonic.set(true);
      }
    }
    return popup;
  }