private TablePassInfo computeLayoutTable(List<TabInfo> visibleInfos) {
    final TablePassInfo data = new TablePassInfo(this, visibleInfos);
    if (myTabs.isHideTabs()) {
      return data;
    }
    doScrollToSelectedTab(lastTableLayout);

    boolean singleRow = myTabs.isSingleRow();
    boolean showPinnedTabsSeparately = showPinnedTabsSeparately();
    boolean scrollable = UISettings.getInstance().getHideTabsIfNeeded() && singleRow;
    int titleWidth = myTabs.getTitleWrapper().getPreferredSize().width;

    data.titleRect.setBounds(data.toFitRec.x, data.toFitRec.y, titleWidth, Objects.requireNonNull(myTabs.getHeaderFitSize()).height);
    data.entryPointRect.setBounds(data.toFitRec.x + data.toFitRec.width - myTabs.getEntryPointPreferredSize().width - myTabs.getActionsInsets().right,
                                  data.toFitRec.y,
                                  myTabs.getEntryPointPreferredSize().width,
                                  myTabs.getHeaderFitSize().height);
    data.moreRect.setBounds(data.toFitRec.x + data.toFitRec.width - myTabs.getEntryPointPreferredSize().width - myTabs.getActionsInsets().right,
                            data.toFitRec.y, 0, myTabs.getHeaderFitSize().height);
    calculateLengths(data);

    int eachX = data.titleRect.x + data.titleRect.width;
    Insets insets = myTabs.getLayoutInsets();
    int eachY = insets.top;
    int requiredRowsPinned = 0;
    int requiredRowsUnpinned = 0;

    int maxX = data.moreRect.x - (singleRow ? myTabs.getActionsInsets().left : 0);
    if (!singleRow && showPinnedTabsSeparately && ContainerUtil.all(visibleInfos, info -> !info.isPinned())) {
      maxX += myTabs.getEntryPointPreferredSize().width;
    }

    int hGap = myTabs.getTabHGap();
    int entryPointMargin = scrollable ? 0 : myTabs.getEntryPointPreferredSize().width;
    for (TabInfo eachInfo : data.visibleInfos) {
      TabLabel eachLabel = myTabs.getTabLabel(eachInfo);
      boolean pinned = eachLabel.isPinned();
      int width = data.lengths.get(eachInfo);
      if (!pinned || !showPinnedTabsSeparately) {
        data.requiredLength += width;
      }
      if (pinned && showPinnedTabsSeparately) {
        if (requiredRowsPinned == 0) {
          requiredRowsPinned = 1;
        }
        myTabs.layout(eachLabel, eachX, eachY, width, myTabs.getHeaderFitSize().height);
        data.bounds.put(eachInfo, eachLabel.getBounds());
      }
      else {
        if ((!scrollable && eachX + width + hGap > maxX - entryPointMargin && !singleRow) || (showPinnedTabsSeparately && eachLabel.isNextToLastPinned())) {
          requiredRowsUnpinned++;
          eachY += myTabs.getHeaderFitSize().height;
          eachX = data.toFitRec.x;
        }
        else if (requiredRowsUnpinned == 0) {
          requiredRowsUnpinned = 1;
        }
        if (scrollable) {
          if (eachX - getScrollOffset() + width + hGap > maxX - entryPointMargin) {
            width = Math.max(0, maxX - eachX + getScrollOffset());
            data.invisible.add(eachInfo);
          }
        }

        myTabs.layout(eachLabel, eachX - getScrollOffset(), eachY, width == 1 ? 0 : width, myTabs.getHeaderFitSize().height);
        Rectangle rectangle = new Rectangle(myTabs.getHeaderFitSize());
        data.bounds.put(eachInfo, eachLabel.getBounds());
        int intersection = eachLabel.getBounds().intersection(rectangle).width;
        if (scrollable && intersection < eachLabel.getBounds().width) {
          data.invisible.add(eachInfo);
        }
      }
      eachX += width + hGap;
      if (requiredRowsPinned + requiredRowsUnpinned > 1) {
        entryPointMargin = singleRow ? 0 : - data.moreRect.width;
      }
    }
    if (requiredRowsPinned > 0 && requiredRowsUnpinned > 0) data.moreRect.y += myTabs.getHeaderFitSize().height /*+ myTabs.getSeparatorWidth()*/;

    if (data.invisible.isEmpty()) {
      data.moreRect.setBounds(0, 0, 0, 0);
    }

    eachY = -1;
    TableRow eachTableRow = new TableRow(data);

    for (TabInfo info : data.visibleInfos) {
      final TabLabel tabLabel = myTabs.getTabLabel(info);
      if (eachY == -1 || eachY != Objects.requireNonNull(tabLabel).getY()) {
        if (eachY != -1) {
          eachTableRow = new TableRow(data);
        }
        eachY = tabLabel.getY();
        data.table.add(eachTableRow);
      }
      eachTableRow.add(info, tabLabel.getWidth());
    }

    doScrollToSelectedTab(data);
    clampScrollOffsetToBounds(data);
    return data;
  }
private TablePassInfo computeLayoutTable(List<TabInfo> visibleInfos)