private Insets getCalculatedInsets(
      PanePainter pane, int index, boolean selected, Direction direction) {
    Rectangle b = pane.getBoundsAt(index);
    final int sizer = b.height + b.width;

    Icon icon = pane.getIconAt(index);

    pane.setIconAt(index, new SizeIcon(sizer, sizer));

    if (selected) pane.setSelectedIndex(index);

    Rectangle bounds = pane.getBoundsAt(index);

    pane.setIconAt(index, icon);
    pane.setSelectedIndex(DEFAULT_SELECTED_INDEX);

    int height = bounds.height - sizer - getHeightCompensate(direction);
    int width = bounds.width - sizer - getWidthCompensate(direction);
    int top = height / 2;
    int left = width / 2 + width % 2;
    int bottom = height / 2 + height % 2;
    int right = width / 2;

    return new Insets(top, left, bottom, right);
  }
  private void applyFocusAndHover(PanePainter pane, boolean active) {
    if (active) {
      for (int i = 0; i < tabData.getTabCount(); i++) {
        Tab tab = (Tab) tabData.getTabList().get(i);

        if (tab.getFocusableComponent() != null && tab.getFocusableComponent().hasFocus()) {
          pane.setMouseEntered(true);
          pane.setFocusActive(true);
          break;
        }
      }

      if (hoveredTab != null) {
        for (int i = 0; i < tabData.getTabCount(); i++) {
          Tab tab = (Tab) tabData.getTabList().get(i);

          if (tab == hoveredTab) {
            pane.setMouseEntered(true);
            pane.setHoveredTab(i);
            break;
          }
        }
      }
    } else {
      pane.setFocusActive(false);
      pane.setMouseEntered(false);
    }
  }
  private void estimateSwappedTabDirection(PanePainter pane, int index) {
    reset(pane);

    SizeIcon icon = new SizeIcon(80, 80);
    SizeIcon icon2 = new SizeIcon(160, 80);

    pane.addTab(EMPTY_STRING, icon, getComponent());
    pane.doValidation();

    Rectangle bounds = pane.getBoundsAt(0);
    pane.setIconAt(0, icon2);
    pane.doValidation();
    Rectangle bounds2 = pane.getBoundsAt(0);

    swapWidthHeights[index] = bounds2.height > 1.5 * bounds.height;
  }
  private void initPaintableTabLocations(PanePainter pane) {
    reset(pane);
    if (tabData.getPreTab() != null) {
      tabData.getTabList().add(0, tabData.getPreTab());
      tabData.getVisibleTabRects().add(0, new Rectangle(0, 0, 0, 0));
    }

    if (tabData.getPostTab() != null) {
      tabData.getTabList().add(tabData.getPostTab());
      tabData.getVisibleTabRects().add(new Rectangle(0, 0, 0, 0));
    }

    setSize(0);
    int selectedIndex = -1;

    for (int i = 0; i < tabData.getTabCount(); i++) {
      final Tab tab = (Tab) tabData.getTabList().get(i);

      SizeIcon icon =
          new SizeIcon(
              getInternalTabWidth(tab) - getWidthCompensate(tabData.getAreaOrientation()),
              getInternalTabHeight(tab) - getHeightCompensate(tabData.getAreaOrientation()),
              isSwapWidthHeight(tabData.getAreaOrientation()));

      pane.addTab(EMPTY_STRING, icon, getComponent());

      if (tab.isHighlighted()) selectedIndex = pane.getTabCount() - 1;

      if (!tab.isEnabled()) {
        pane.setEnabledAt(i, false);
        pane.setDisabledIconAt(i, icon);
      }

      setSize(getSize() + (tabData.isHorizontalLayout() ? tab.getWidth() : tab.getHeight()));
    }

    pane.setSelectedIndex(selectedIndex);
    pane.doValidation();
  }
 private void reset(PanePainter pane) {
   pane.removeAllTabs();
   componentCache.reset();
 }
  public void paintContentArea(
      TabbedPanelContentPanel p, Graphics g, int x, int y, int width, int height) {
    if (enabled && PAINT_CONTENT_AREA) {
      tabData.initialize(p.getTabbedPanel());
      PanePainter pane = paneHandler.getPainter(tabData.getAreaOrientation());

      initTabLocations(pane);

      int tx = 0;
      int ty = 0;

      if (tabData.getTabbedPanel().hasContentArea()) {
        Point l = getLocationInTabbedPanel(p, tabData.getTabbedPanel());

        int yComp = 0;
        int xComp = 0;

        if (pane.getTabCount() == 0 && tabData.getTabCount() > 0) {
          if (tabData.getAreaOrientation() == Direction.UP) {
            yComp = tabData.getTabAreaHeight();
          } else if (tabData.getAreaOrientation() == Direction.DOWN) {
            yComp = -tabData.getTabAreaHeight();
          } else if (tabData.getAreaOrientation() == Direction.LEFT) {
            xComp = tabData.getTabAreaWidth();
          } else {
            xComp = -tabData.getTabAreaWidth();
          }
        }

        tx = -l.x + (xComp > 0 ? xComp : 0);
        ty = -l.y + (yComp > 0 ? yComp : 0);

        int extraWidth = 0;
        int extraHeight = 0;

        if (tabAreaNotVisibleFix && !tabData.getTabbedPanel().isTabAreaVisible()) {
          extraWidth =
              !tabData.isHorizontalLayout()
                  ? tabMinimumSizes[getDirectionIndex(tabData.getAreaOrientation())].width
                      - raiseds[getDirectionIndex(tabData.getAreaOrientation())]
                      + (tabData.getAreaOrientation() == Direction.LEFT
                          ? areaInsets[getDirectionIndex(Direction.LEFT)].left
                          : areaInsets[getDirectionIndex(Direction.RIGHT)].right)
                  : 0;
          extraHeight =
              tabData.isHorizontalLayout()
                  ? tabMinimumSizes[getDirectionIndex(tabData.getAreaOrientation())].height
                      - raiseds[getDirectionIndex(tabData.getAreaOrientation())]
                      + (tabData.getAreaOrientation() == Direction.UP
                          ? areaInsets[getDirectionIndex(Direction.UP)].top
                          : areaInsets[getDirectionIndex(Direction.DOWN)].bottom)
                  : 0;
        }

        tx -= tabData.getAreaOrientation() == Direction.LEFT ? extraWidth : 0;
        ty -= tabData.getAreaOrientation() == Direction.UP ? extraHeight : 0;

        pane.setSize(
            tabData.getTabbedPanelSize().width - Math.abs(xComp) + extraWidth,
            tabData.getTabbedPanelSize().height - Math.abs(yComp) + extraHeight);

        pane.doValidation();
      } else {
        if (tabData.isHorizontalLayout()) {
          pane.setSize(p.getWidth(), p.getHeight() + tabData.getTabAreaHeight());
        } else {
          pane.setSize(p.getWidth() + tabData.getTabAreaWidth(), p.getHeight());
        }

        pane.doValidation();

        if (tabData.getAreaOrientation() == Direction.UP) ty -= tabData.getTabAreaHeight();
        else if (tabData.getAreaOrientation() == Direction.LEFT) tx -= tabData.getTabAreaWidth();
      }

      pane.paint(g, tx, ty);

      tabData.reset();

      reset(pane);
    }
  }
  private void paintTabs(
      PanePainter pane, TabData tabData, Graphics g, int x, int y, int width, int height) {
    if (enabled && PAINT_TAB) {
      Tab lastTab = (Tab) tabData.getTabList().get(tabData.getTabList().size() - 1);
      Rectangle lastVisibleRect =
          (Rectangle) tabData.getVisibleTabRects().get(tabData.getTabCount() - 1);

      // Fix post/pre tabs
      initPaintableTabLocations(pane);

      Insets aInsets = getTabAreaInsets(tabData.getAreaOrientation());

      Point l = getLocationInTabbedPanel(lastTab, tabData.getTabbedPanel());

      if (tabData.isHorizontalLayout()) {
        int w =
            aInsets.left
                + aInsets.right
                + Math.max(0, tabData.getTabAreaWidth() - l.x - lastVisibleRect.width)
                + EXTRA_SIZE;

        for (int i = 0; i < tabData.getTabList().size(); i++)
          w += ((Tab) tabData.getTabList().get(i)).getWidth();

        pane.setSize(w, getTabbedPanelExtraSize());
      } else {
        int h =
            aInsets.top
                + aInsets.bottom
                + Math.max(0, tabData.getTabAreaHeight() - l.y - lastVisibleRect.height)
                + EXTRA_SIZE;

        for (int i = 0; i < tabData.getTabList().size(); i++)
          h += ((Tab) tabData.getTabList().get(i)).getHeight();

        pane.setSize(getTabbedPanelExtraSize(), h);
      }

      pane.doValidation();

      int index = tabData.getPreTab() == null ? 0 : tabData.getTabCount() > 1 ? 1 : 0;

      Shape originalClip = g.getClip();

      int tx =
          -x
              - (tabData.getAreaOrientation() == Direction.RIGHT
                  ? -tabData.getTabbedPanelWidth() + getTabbedPanelExtraSize()
                  : 0);
      int ty =
          -y
              - (tabData.getAreaOrientation() == Direction.DOWN
                  ? -tabData.getTabbedPanelHeight() + getTabbedPanelExtraSize()
                  : 0);

      Rectangle visibleRect = (Rectangle) tabData.getVisibleTabRects().get(index);
      Tab tab = (Tab) tabData.getTabList().get(index);

      if (tabData.isHorizontalLayout()) {
        tx -=
            (tabData.getPreTab() != null
                ? tab.getX() - tabData.getPreTab().getX() + visibleRect.x
                : visibleRect.x);
        g.clipRect(aInsets.left, 0, tabData.getTabAreaWidth(), height);
      } else {
        ty -=
            (tabData.getPreTab() != null
                ? tab.getY() - tabData.getPreTab().getY() + visibleRect.y
                : visibleRect.y);
        g.clipRect(0, aInsets.top, width, tabData.getTabAreaHeight());
      }

      applyFocusAndHover(pane, true);
      pane.paint(g, tx, ty);
      applyFocusAndHover(pane, false);

      g.setClip(originalClip);
    }
  }
  public void paintTabArea(TabbedPanel tp, Graphics g, int x, int y, int width, int height) {
    int heightTemp = height;
    int widthTemp = width;
    int xTemp = x;
    int yTemp = y;
    if (enabled && tp.isTabAreaVisible()) {

      tabData.initialize(tp);

      PanePainter pane = paneHandler.getPainter(tabData.getAreaOrientation());

      initTabLocations(pane);
      Insets aInsets = getTabAreaInsets(tabData.getAreaOrientation());

      if (tp.getTabCount() > 0) {
        // Adjust x, y
        if (tabData.getAreaOrientation() == Direction.DOWN) {
          yTemp += tabData.getTabbedPanelHeight() - heightTemp;
        } else if (tabData.getAreaOrientation() == Direction.RIGHT) {
          xTemp += tabData.getTabbedPanelWidth() - widthTemp;
        }

        widthTemp = xTemp < 0 ? widthTemp + xTemp : widthTemp;
        heightTemp = yTemp < 0 ? heightTemp + yTemp : heightTemp;

        xTemp = Math.max(0, xTemp);
        yTemp = Math.max(0, yTemp);

        if (tabData.isHorizontalLayout())
          pane.setSize(tabData.getTabbedPanelSize().width, getTabbedPanelExtraSize());
        else pane.setSize(getTabbedPanelExtraSize(), tabData.getTabbedPanelHeight());

        if (PAINT_TAB_AREA && !(pane.getTabCount() == 0 && tabData.getTabCount() > 0)) {
          Shape originalClip = g.getClip();

          int tx =
              -xTemp
                  - (tabData.getAreaOrientation() == Direction.RIGHT
                      ? -tabData.getTabbedPanelWidth() + getTabbedPanelExtraSize()
                      : 0);
          int ty =
              -yTemp
                  - (tabData.getAreaOrientation() == Direction.DOWN
                      ? -tabData.getTabbedPanelHeight() + getTabbedPanelExtraSize()
                      : 0);

          Rectangle firstVisibleRect = (Rectangle) tabData.getVisibleTabRects().get(0);
          Rectangle lastVisibleRect =
              (Rectangle) tabData.getVisibleTabRects().get(tabData.getTabCount() - 1);
          Tab lastTab = (Tab) tabData.getTabList().get(tabData.getTabCount() - 1);

          if (tabData.isHorizontalLayout()) {
            int extraWidth =
                lastTab.getWidth() == lastVisibleRect.width
                    ? 0
                    : 2 * tabData.getTabbedPanelSize().width - tabData.getTabAreaWidth();
            pane.setSize(pane.getWidth() + extraWidth, pane.getHeight());

            pane.doValidation();

            // Before tabs
            g.clipRect(
                0,
                0,
                aInsets.left + (firstVisibleRect.width > 0 && firstVisibleRect.x == 0 ? 1 : 0),
                heightTemp);
            pane.paint(g, tx, ty);
            g.setClip(originalClip);

            // After tabs
            tx -= extraWidth;

            int clipExtraWidth = extraWidth == 0 ? 1 : 0;
            g.clipRect(
                aInsets.left + tabData.getTabAreaWidth() - clipExtraWidth,
                0,
                widthTemp - aInsets.left - tabData.getTabAreaWidth() + clipExtraWidth,
                heightTemp);
            pane.paint(g, tx, ty);
            g.setClip(originalClip);
          } else {
            int extraHeight =
                lastTab.getHeight() == lastVisibleRect.height
                    ? 0
                    : 2 * tabData.getTabbedPanelSize().height - tabData.getTabAreaHeight();
            pane.setSize(pane.getWidth(), pane.getHeight() + extraHeight);

            pane.doValidation();

            // Before tabs
            g.clipRect(
                0,
                0,
                widthTemp,
                aInsets.top + (firstVisibleRect.height > 0 && firstVisibleRect.y == 0 ? 1 : 0));
            pane.paint(g, tx, ty);
            g.setClip(originalClip);

            // After tabs
            ty -= extraHeight;

            int clipExtraHeight = extraHeight == 0 ? 1 : 0;
            g.clipRect(
                0,
                aInsets.top + tabData.getTabAreaHeight() - clipExtraHeight,
                widthTemp,
                heightTemp - aInsets.top - tabData.getTabAreaHeight() + clipExtraHeight);
            pane.paint(g, tx, ty);
            g.setClip(originalClip);
          }
        }

        // First and last tab
        paintTabs(pane, tabData, g, xTemp, yTemp, widthTemp, heightTemp);

        tabData.reset();

        reset(pane);
      }
    }
  }
  private void estimateContentTabAreaBorderColor(
      PanePainter pane, int index, final Direction direction) {
    Dimension preSize = pane.getSize();

    reset(pane);

    pane.addTab(EMPTY_STRING, SizeIcon.EMPTY, getComponent());

    pane.setSelectedIndex(-1);

    Dimension paneSize = pane.getMinimumSize();

    if (direction.isHorizontal()) pane.setSize(paneSize.width, paneSize.height * 2);
    else pane.setSize(paneSize.width * 2, paneSize.height);

    pane.doValidation();

    Rectangle tabBounds = pane.getBoundsAt(0);

    BufferedImage img =
        new BufferedImage(pane.getWidth(), pane.getHeight(), BufferedImage.TYPE_INT_ARGB);

    int x = 0;
    int y = 0;

    if (direction == Direction.UP) {
      x = tabBounds.x + (tabBounds.width / 2);
      y = pane.getHeight() - contentInsets[index].top - contentInsets[index].bottom - 1;
    } else if (direction == Direction.DOWN) {
      x = tabBounds.x + (tabBounds.width / 2);
      y = contentInsets[index].top + contentInsets[index].bottom;
    } else if (direction == Direction.LEFT) {
      x = pane.getWidth() - contentInsets[index].left - contentInsets[index].right - 1;
      y = tabBounds.y + (tabBounds.height / 2);
    } else {
      x += contentInsets[index].left + contentInsets[index].right;
      y = tabBounds.y + (tabBounds.height / 2);
    }

    final int px = x;
    final int py = y;

    RGBImageFilter colorFilter =
        new RGBImageFilter() {
          @Override
          public int filterRGB(int x, int y, int rgb) {
            if (px == x && py == y) {
              int r = (rgb >> 16) & 0xff;
              int g = (rgb >> 8) & 0xff;
              int b = (rgb) & 0xff;
              int a = (rgb >> 24) & 0xff;
              contentTabAreaBorderColors[getDirectionIndex(direction.getOpposite())] =
                  new Color(r, g, b, a);
            }

            return rgb;
          }
        };

    FilteredImageSource source = new FilteredImageSource(img.getSource(), colorFilter);
    pane.paint(img.getGraphics());

    BufferedImage img2 =
        new BufferedImage(pane.getWidth(), pane.getHeight(), BufferedImage.TYPE_INT_ARGB);
    img2.getGraphics().drawImage(Toolkit.getDefaultToolkit().createImage(source), 0, 0, null);

    pane.setSize(preSize);

    pane.doValidation();
  }
  private void calculateAreaInsets(PanePainter pane, int index, Direction direction) {

    // Area insets
    pane.setSelectedIndex(0);
    Rectangle selectedBounds = pane.getBoundsAt(0);
    pane.setSelectedIndex(DEFAULT_SELECTED_INDEX);

    Rectangle normalBounds = pane.getBoundsAt(0);
    int left = 0;
    int top = 0;
    int bottom = 0;
    int right = 0;

    if (direction == Direction.UP) {
      left = Math.min(selectedBounds.x, normalBounds.x);
      top = Math.min(selectedBounds.y, normalBounds.y);
      bottom = 0;
    } else if (direction == Direction.DOWN) {
      left = Math.min(selectedBounds.x, normalBounds.x);
      top = 0;
      bottom =
          pane.getHeight()
              - Math.max(
                  selectedBounds.y + selectedBounds.height, normalBounds.y + normalBounds.height);
    } else if (direction == Direction.LEFT) {
      top = Math.min(selectedBounds.y, normalBounds.y);
      left = Math.min(selectedBounds.x, normalBounds.x);
      right = 0;
    } else {
      top = Math.min(selectedBounds.y, normalBounds.y);
      left = 0;
      right =
          pane.getWidth()
              - Math.max(
                  selectedBounds.x + selectedBounds.width, normalBounds.x + normalBounds.width);
    }

    Dimension sizeTemp = pane.getSize();

    reset(pane);

    for (int i = 0; i < 4; i++) pane.addTab(EMPTY_STRING, SizeIcon.EMPTY, getComponent());

    pane.setSelectedIndex(-1);

    pane.setSize(pane.getMinimumSize());
    pane.doValidation();

    if (!direction.isHorizontal()) {
      int width = pane.getWidth() - 1;

      boolean found = false;

      while (!found) {
        width++;
        pane.setSize(width, pane.getHeight());

        pane.doValidation();
        found = pane.getBoundsAt(0).y == pane.getBoundsAt(3).y;
      }

      Rectangle endBounds = pane.getBoundsAt(3);
      right = pane.getWidth() - endBounds.x - endBounds.width - spacings[index];
    } else {
      int height = pane.getHeight() - 1;

      boolean found = false;

      while (!found) {
        height++;
        pane.setSize(pane.getWidth(), height);

        pane.doValidation();
        found = pane.getBoundsAt(0).x == pane.getBoundsAt(3).x;
      }

      Rectangle endBounds = pane.getBoundsAt(3);
      bottom = pane.getHeight() - endBounds.y - endBounds.height - spacings[index];
    }

    areaInsets[index] = new Insets(top, left, bottom, right);

    pane.setSize(sizeTemp);

    pane.doValidation();
  }
  private void initValues(PanePainter pane, int index, Direction direction) {
    estimateSwappedTabDirection(pane, index);

    reset(pane);

    pane.setSize(1000, 1000);

    boolean upDown = !direction.isHorizontal();

    for (int i = 0; i < DEFAULT_TAB_COUNT; i++) {
      pane.addTab(EMPTY_STRING, getComponent());
    }

    pane.setSelectedIndex(DEFAULT_SELECTED_INDEX);

    pane.doValidation();

    // Tab insets if any from UImanager
    Insets insets = UIManager.getInsets("TabbedPane.tabInsets");
    if (insets == null) insets = new Insets(0, 0, 0, 0);

    if (!upDown) tabInsets[index] = new Insets(0, insets.left, 0, insets.right);
    else tabInsets[index] = InsetsUtil.EMPTY_INSETS;

    // Raised
    Rectangle bounds = pane.getBoundsAt(0);
    Rectangle bounds2 = pane.getBoundsAt(pane.getSelectedIndex());

    if (direction == Direction.UP) raiseds[index] = Math.max(0, bounds.y - bounds2.y);
    else if (direction == Direction.LEFT) raiseds[index] = Math.max(0, bounds.x - bounds2.x);
    else if (direction == Direction.DOWN) raiseds[index] = raiseds[getDirectionIndex(Direction.UP)];
    else raiseds[index] = raiseds[getDirectionIndex(Direction.LEFT)];

    // Spacing
    Insets normal = getCalculatedInsets(pane, 0, false, direction);
    Insets selected = getCalculatedInsets(pane, 0, true, direction);

    if (upDown) spacings[index] = normal.left + normal.right - selected.left - selected.right;
    else spacings[index] = normal.top + normal.bottom - selected.top - selected.bottom;

    // Normal insets
    normalInsets[index] = getCalculatedInsets(pane, 0, false, direction);

    // Selected insets
    Insets insetsTemp = getCalculatedInsets(pane, 0, true, direction);
    int spacing = spacings[index];
    int spaceFirst = spacing / 2;
    int spaceAfter = spacing / 2 + spacing % 2;

    if (direction == Direction.UP) {
      insetsTemp.bottom = normalInsets[index].bottom;
      insetsTemp.top = normalInsets[index].top;
      insetsTemp.left += spaceFirst;
      insetsTemp.right += spaceAfter;
    } else if (direction == Direction.LEFT) {
      insetsTemp.right = normalInsets[index].right;
      insetsTemp.left = normalInsets[index].left;
      insetsTemp.top += spaceFirst;
      insetsTemp.bottom += spaceAfter;
    } else if (direction == Direction.RIGHT) {
      insetsTemp.right = normalInsets[index].right;
      insetsTemp.left = normalInsets[index].left;
      insetsTemp.top += spaceFirst;
      insetsTemp.bottom += spaceAfter;
    } else {
      insetsTemp.bottom = normalInsets[index].bottom;
      insetsTemp.top = normalInsets[index].top;
      insetsTemp.left += spaceFirst;
      insetsTemp.right += spaceAfter;
    }

    selectedInsets[index] = insetsTemp;

    // Content insets
    JPanel c = new JPanel();
    pane.addTab(EMPTY_STRING, c);
    pane.setSelectedIndex(pane.getTabCount() - 1);
    pane.doValidation();

    Point l = SwingUtilities.convertPoint(c.getParent(), c.getLocation(), pane);

    Rectangle boundsTemp = pane.getBoundsAt(0);
    int top = 0;
    int left = 0;
    int bottom = 0;
    int right = 0;

    if (direction == Direction.UP) {
      top = l.y - boundsTemp.height - boundsTemp.y;
      left = l.x;
      bottom = pane.getHeight() - l.y - c.getHeight();
      right = pane.getWidth() - l.x - c.getWidth();
    } else if (direction == Direction.DOWN) {
      top = l.y;
      left = l.x;
      bottom = pane.getHeight() - c.getHeight() - l.y - (pane.getHeight() - boundsTemp.y);
      right = pane.getWidth() - l.x - c.getWidth();
    } else if (direction == Direction.LEFT) {
      top = l.y;
      left = l.x - boundsTemp.width - boundsTemp.x;
      bottom = pane.getHeight() - l.y - c.getHeight();
      right = pane.getWidth() - l.x - c.getWidth();
    } else {
      top = l.y;
      left = l.x;
      bottom = pane.getHeight() - l.y - c.getHeight();
      right = pane.getWidth() - c.getWidth() - l.x - (pane.getWidth() - boundsTemp.x);
    }

    contentInsets[index] = new Insets(top, left, bottom, right);

    Insets i = contentInsets[0];
    Insets i2 = InsetsUtil.rotate(direction.getNextCW(), i);
    Insets adjustedInsets = InsetsUtil.max(i, i2);
    adjustedContentInsets[index] = adjustedInsets;
    adjustedContentInsetsTabAreaHidden[index] =
        new Insets(
            direction == Direction.UP ? adjustedInsets.left : adjustedInsets.top,
            direction == Direction.LEFT ? adjustedInsets.top : adjustedInsets.left,
            direction == Direction.DOWN ? adjustedInsets.right : adjustedInsets.bottom,
            direction == Direction.RIGHT ? adjustedInsets.bottom : adjustedInsets.right);

    pane.removeTabAt(pane.getTabCount() - 1);
    pane.setSelectedIndex(DEFAULT_SELECTED_INDEX);

    pane.doValidation();

    // Minimum sizes
    Rectangle rectangleBounds = pane.getBoundsAt(DEFAULT_SELECTED_INDEX);
    tabMinimumSizes[index] = new Dimension(rectangleBounds.width, rectangleBounds.height);
    minimumSizes[index] =
        new Dimension(
            rectangleBounds.width - tabInsets[index].left - tabInsets[index].right,
            rectangleBounds.height - tabInsets[index].top - tabInsets[index].bottom);

    calculateAreaInsets(pane, index, direction);

    estimateContentTabAreaBorderColor(pane, index, direction);
  }
  private void initTabLocations(PanePainter pane) {
    findPaintableTabs();

    Dimension minSize = getTabExternalMinSize(tabData.getAreaOrientation());
    Insets aInsets = getTabAreaInsets(tabData.getAreaOrientation());

    int selectedIndex = -1;

    if (tabData.getTabbedPanel().isTabAreaVisible()) {
      for (int i = 0; i < tabData.getTabCount(); i++) {
        final Tab tab = (Tab) tabData.getTabList().get(i);
        final Rectangle visibleRect = (Rectangle) tabData.getVisibleTabRects().get(i);
        Insets insets = getTabInsets(tabData.getAreaOrientation());

        int iconWidth =
            Math.max(
                -insets.left - insets.right,
                getInternalTabWidth(tab) - (tab.getWidth() - visibleRect.width));

        int iconHeight =
            Math.max(
                -insets.top - insets.bottom,
                getInternalTabHeight(tab) - (tab.getHeight() - visibleRect.height));

        Point l = getLocationInTabbedPanel(tab, tabData.getTabbedPanel());

        if ((tabData.isHorizontalLayout()
                && (visibleRect.width >= minSize.width
                    || minSize.width < tabData.getTabbedPanelWidth() - l.x - aInsets.right))
            || (!tabData.isHorizontalLayout()
                && (visibleRect.height >= minSize.height
                    || minSize.height < tabData.getTabbedPanelHeight() - l.y - aInsets.bottom))) {
          final int iWidth = iconWidth;
          final int iHeight = iconHeight;

          SizeIcon icon =
              new SizeIcon(
                  iWidth - getWidthCompensate(tabData.getAreaOrientation()),
                  iHeight - getHeightCompensate(tabData.getAreaOrientation()),
                  isSwapWidthHeight(tabData.getAreaOrientation()));

          int j = pane.getTabCount();
          pane.addTab(EMPTY_STRING, icon, getComponent());

          if (i == tabData.getSelectedTabPainterIndex()) {
            selectedIndex = j;
          }

          if (!tab.isEnabled()) {
            pane.setEnabledAt(j, false);
            pane.setDisabledIconAt(j, icon);
          }
        }
      }
    } else if (tabAreaNotVisibleFix) {
      pane.addTab(EMPTY_STRING, componentCache.getComponent());
    }

    if (pane.getTabCount() > 0) pane.setSelectedIndex(selectedIndex);

    pane.doValidation();
  }