private void rebuildPopup(
      @NotNull final UsageViewImpl usageView,
      @NotNull final List<Usage> usages,
      @NotNull List<UsageNode> nodes,
      @NotNull final JTable table,
      @NotNull final JBPopup popup,
      @NotNull final UsageViewPresentation presentation,
      @NotNull final RelativePoint popupPosition,
      boolean findUsagesInProgress) {
    ApplicationManager.getApplication().assertIsDispatchThread();

    boolean shouldShowMoreSeparator = usages.contains(MORE_USAGES_SEPARATOR);
    if (shouldShowMoreSeparator) {
      nodes.add(MORE_USAGES_SEPARATOR_NODE);
    }

    String title = presentation.getTabText();
    String fullTitle =
        getFullTitle(
            usages,
            title,
            shouldShowMoreSeparator,
            nodes.size() - (shouldShowMoreSeparator ? 1 : 0),
            findUsagesInProgress);

    ((AbstractPopup) popup).setCaption(fullTitle);

    List<UsageNode> data = collectData(usages, nodes, usageView, presentation);
    MyModel tableModel = setTableModel(table, usageView, data);
    List<UsageNode> existingData = tableModel.getItems();

    int row = table.getSelectedRow();

    int newSelection = updateModel(tableModel, existingData, data, row == -1 ? 0 : row);
    if (newSelection < 0 || newSelection >= tableModel.getRowCount()) {
      TableScrollingUtil.ensureSelectionExists(table);
      newSelection = table.getSelectedRow();
    } else {
      table.getSelectionModel().setSelectionInterval(newSelection, newSelection);
    }
    TableScrollingUtil.ensureIndexIsVisible(table, newSelection, 0);

    setSizeAndDimensions(table, popup, popupPosition, data);
  }
  @NotNull
  @Override
  public RelativePoint guessBestPopupLocation(@NotNull final JComponent component) {
    Point popupMenuPoint = null;
    final Rectangle visibleRect = component.getVisibleRect();
    if (component instanceof JList) { // JList
      JList list = (JList) component;
      int firstVisibleIndex = list.getFirstVisibleIndex();
      int lastVisibleIndex = list.getLastVisibleIndex();
      int[] selectedIndices = list.getSelectedIndices();
      for (int index : selectedIndices) {
        if (firstVisibleIndex <= index && index <= lastVisibleIndex) {
          Rectangle cellBounds = list.getCellBounds(index, index);
          popupMenuPoint =
              new Point(visibleRect.x + visibleRect.width / 4, cellBounds.y + cellBounds.height);
          break;
        }
      }
    } else if (component instanceof JTree) { // JTree
      JTree tree = (JTree) component;
      int[] selectionRows = tree.getSelectionRows();
      if (selectionRows != null) {
        Arrays.sort(selectionRows);
        for (int i = 0; i < selectionRows.length; i++) {
          int row = selectionRows[i];
          Rectangle rowBounds = tree.getRowBounds(row);
          if (visibleRect.contains(rowBounds)) {
            popupMenuPoint = new Point(rowBounds.x + 2, rowBounds.y + rowBounds.height - 1);
            break;
          }
        }
        if (popupMenuPoint == null) { // All selected rows are out of visible rect
          Point visibleCenter =
              new Point(
                  visibleRect.x + visibleRect.width / 2, visibleRect.y + visibleRect.height / 2);
          double minDistance = Double.POSITIVE_INFINITY;
          int bestRow = -1;
          Point rowCenter;
          double distance;
          for (int i = 0; i < selectionRows.length; i++) {
            int row = selectionRows[i];
            Rectangle rowBounds = tree.getRowBounds(row);
            rowCenter =
                new Point(rowBounds.x + rowBounds.width / 2, rowBounds.y + rowBounds.height / 2);
            distance = visibleCenter.distance(rowCenter);
            if (minDistance > distance) {
              minDistance = distance;
              bestRow = row;
            }
          }

          if (bestRow != -1) {
            Rectangle rowBounds = tree.getRowBounds(bestRow);
            tree.scrollRectToVisible(
                new Rectangle(
                    rowBounds.x,
                    rowBounds.y,
                    Math.min(visibleRect.width, rowBounds.width),
                    rowBounds.height));
            popupMenuPoint = new Point(rowBounds.x + 2, rowBounds.y + rowBounds.height - 1);
          }
        }
      }
    } else if (component instanceof JTable) {
      JTable table = (JTable) component;
      int column = table.getColumnModel().getSelectionModel().getLeadSelectionIndex();
      int row =
          Math.max(
              table.getSelectionModel().getLeadSelectionIndex(),
              table.getSelectionModel().getAnchorSelectionIndex());
      Rectangle rect = table.getCellRect(row, column, false);
      if (!visibleRect.intersects(rect)) {
        table.scrollRectToVisible(rect);
      }
      popupMenuPoint = new Point(rect.x, rect.y + rect.height);
    } else if (component instanceof PopupOwner) {
      popupMenuPoint = ((PopupOwner) component).getBestPopupPosition();
    }
    if (popupMenuPoint == null) {
      popupMenuPoint =
          new Point(visibleRect.x + visibleRect.width / 2, visibleRect.y + visibleRect.height / 2);
    }

    return new RelativePoint(component, popupMenuPoint);
  }