TablePassInfo (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, 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.myVisibleInfos) { 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 eachInfo : data.myVisibleInfos) { final TabLabel eachLabel = myTabs.getTabLabel(eachInfo); if (eachY == -1 || eachY != eachLabel.getY()) { if (eachY != -1) { eachTableRow = new TableRow(data); } eachY = eachLabel.getY(); data.table.add(eachTableRow); } eachTableRow.add(eachInfo, eachLabel.getWidth()); } doScrollToSelectedTab(data); clampScrollOffsetToBounds(data); return data; }