@Override
  public void layout() {
    Rectangle bounds = ui.getTabComponent().getBounds();
    ContentManager manager = ui.getContentManager();
    LayoutData data = new LayoutData(ui);

    data.toolbarWidth = getTabToolbarPreferredWidth();
    data.eachX = getTabLayoutStart();
    data.eachY = 0;

    if (isIdVisible()) {
      idLabel.setBounds(data.eachX, data.eachY, idLabel.getPreferredSize().width, bounds.height);
      data.eachX += idLabel.getPreferredSize().width;
    }
    else {
      idLabel.setBounds(data.eachX, data.eachY, 0, 0);
    }
    int tabsStart = data.eachX;

    boolean toolbarUpdateNeeded = false;
    if (manager.getContentCount() != 0) {
      Content selected = manager.getSelectedContent();
      if (selected == null) {
        selected = manager.getContents()[0];
      }

      if (lastLayout != null &&
          (idLabel == null || idLabel.isValid()) &&
          lastLayout.layoutSize.equals(bounds.getSize()) &&
          lastLayout.contentCount == manager.getContentCount() &&
          lastLayout.toolbarWidth == data.toolbarWidth &&
          ContainerUtil.all(tabs, Component::isValid)) {
        for (ContentTabLabel each : tabs) {
          if (each.getContent() == selected && each.getBounds().width != 0) {
            return; // keep last layout
          }
        }
      }

      ArrayList<JLabel> toLayout = new ArrayList<>();
      Collection<JLabel> toDrop = new HashSet<>();

      for (JLabel eachTab : tabs) {
        final Dimension eachSize = eachTab.getPreferredSize();
        data.requiredWidth += eachSize.width;
        toLayout.add(eachTab);
      }

      if (ui.dropOverIndex != -1 && !isSingleContentView) {
        data.requiredWidth += ui.dropOverWidth;
        int index = Math.min(toLayout.size(), Math.max(0, ui.dropOverIndex - 1));
        toLayout.add(index, dropOverPlaceholder);
      }

      data.toFitWidth = bounds.getSize().width - data.toolbarWidth - data.eachX;

      final ContentTabLabel selectedTab = contentToTabs.get(selected);
      while (true) {
        if (data.requiredWidth <= data.toFitWidth) break;
        if (toLayout.size() <= 1) break;

        JLabel firstLabel = toLayout.get(0);
        JLabel lastLabel = toLayout.get(toLayout.size() - 1);
        JLabel labelToDrop;
        if (firstLabel != selectedTab && firstLabel != dropOverPlaceholder) {
          labelToDrop = firstLabel;
        }
        else if (lastLabel != selectedTab && lastLabel != dropOverPlaceholder) {
          labelToDrop = lastLabel;
        }
        else {
          break;
        }
        data.requiredWidth -= (labelToDrop.getPreferredSize().width + 1);
        toDrop.add(labelToDrop);
        toLayout.remove(labelToDrop);
      }

      boolean reachedBounds = false;
      TabsDrawMode toDrawTabs = isToDrawTabs();
      for (JLabel each : toLayout) {
        if (toDrawTabs == TabsDrawMode.HIDE) {
          each.setBounds(0, 0, 0, 0);
          continue;
        }
        data.eachY = 0;
        final Dimension eachSize = each.getPreferredSize();
        if (data.eachX + eachSize.width < data.toFitWidth + tabsStart) {
          each.setBounds(data.eachX, data.eachY, eachSize.width, bounds.height - data.eachY);
          data.eachX += eachSize.width;
        }
        else {
          if (!reachedBounds) {
            final int width = bounds.width - data.eachX - data.toolbarWidth;
            each.setBounds(data.eachX, data.eachY, width, bounds.height - data.eachY);
            data.eachX += width;
          }
          else {
            each.setBounds(0, 0, 0, 0);
          }
          reachedBounds = true;
        }
      }

      for (JLabel each : toDrop) {
        each.setBounds(0, 0, 0, 0);
      }

      if (toDrop.isEmpty()) {
        toolbarUpdateNeeded = lastLayout != null && lastLayout.morePopupOffset != null;
        data.morePopupOffset = null;
      }
      else {
        toolbarUpdateNeeded = lastLayout != null && lastLayout.morePopupOffset == null;
        data.morePopupOffset = new Point(data.eachX + data.toolbarWidth + MORE_ICON_BORDER, bounds.height);
      }
    }

    // Tab toolbar is positioned at the end.
    ActionToolbar tabToolbar = ui.getTabToolbar();
    if (tabToolbar != null) {
      JComponent component = tabToolbar.getComponent();
      Dimension size = component.getPreferredSize();
      component.setBounds(data.eachX, data.eachY + (bounds.height - size.height) / 2, size.width, size.height);
      data.eachX += component.getWidth();
    }

    lastLayout = data;

    if (toolbarUpdateNeeded) {
      ActivityTracker.getInstance().inc();
    }
  }
@Override
  public void layout()