void TabbedButtonBar::resized() { int depth = getWidth(); int length = getHeight(); if (orientation == TabsAtTop || orientation == TabsAtBottom) std::swap (depth, length); const int overlap = getLookAndFeel().getTabButtonOverlap (depth) + getLookAndFeel().getTabButtonSpaceAroundImage() * 2; int i, totalLength = overlap; int numVisibleButtons = tabs.size(); for (i = 0; i < tabs.size(); ++i) { TabBarButton* const tb = tabs.getUnchecked(i)->component; totalLength += tb->getBestTabLength (depth) - overlap; tb->overlapPixels = overlap / 2; } double scale = 1.0; if (totalLength > length) scale = jmax (minimumScale, length / (double) totalLength); const bool isTooBig = totalLength * scale > length; int tabsButtonPos = 0; if (isTooBig) { if (extraTabsButton == nullptr) { addAndMakeVisible (extraTabsButton = getLookAndFeel().createTabBarExtrasButton()); extraTabsButton->addListener (behindFrontTab); extraTabsButton->setAlwaysOnTop (true); extraTabsButton->setTriggeredOnMouseDown (true); } const int buttonSize = jmin (proportionOfWidth (0.7f), proportionOfHeight (0.7f)); extraTabsButton->setSize (buttonSize, buttonSize); if (orientation == TabsAtTop || orientation == TabsAtBottom) { tabsButtonPos = getWidth() - buttonSize / 2 - 1; extraTabsButton->setCentrePosition (tabsButtonPos, getHeight() / 2); } else { tabsButtonPos = getHeight() - buttonSize / 2 - 1; extraTabsButton->setCentrePosition (getWidth() / 2, tabsButtonPos); } totalLength = 0; for (i = 0; i < tabs.size(); ++i) { TabBarButton* const tb = tabs.getUnchecked(i)->component; const int newLength = totalLength + tb->getBestTabLength (depth); if (i > 0 && newLength * minimumScale > tabsButtonPos) { totalLength += overlap; break; } numVisibleButtons = i + 1; totalLength = newLength - overlap; } scale = jmax (minimumScale, tabsButtonPos / (double) totalLength); } else { extraTabsButton = nullptr; } int pos = 0; TabBarButton* frontTab = nullptr; for (i = 0; i < tabs.size(); ++i) { TabBarButton* const tb = getTabButton (i); if (tb != nullptr) { const int bestLength = roundToInt (scale * tb->getBestTabLength (depth)); if (i < numVisibleButtons) { if (orientation == TabsAtTop || orientation == TabsAtBottom) tb->setBounds (pos, 0, bestLength, getHeight()); else tb->setBounds (0, pos, getWidth(), bestLength); tb->toBack(); if (i == currentTabIndex) frontTab = tb; tb->setVisible (true); } else { tb->setVisible (false); } pos += bestLength - overlap; } } behindFrontTab->setBounds (getLocalBounds()); if (frontTab != nullptr) { frontTab->toFront (false); behindFrontTab->toBehind (frontTab); } }
//============================================================================== void TabbedButtonBar::updateTabPositions (bool animate) { LookAndFeel& lf = getLookAndFeel(); int depth = getWidth(); int length = getHeight(); if (! isVertical()) std::swap (depth, length); const int overlap = lf.getTabButtonOverlap (depth) + lf.getTabButtonSpaceAroundImage() * 2; int totalLength = jmax (0, overlap); int numVisibleButtons = tabs.size(); for (int i = 0; i < tabs.size(); ++i) { TabBarButton* const tb = tabs.getUnchecked(i)->button; totalLength += tb->getBestTabLength (depth) - overlap; tb->overlapPixels = jmax (0, overlap / 2); } double scale = 1.0; if (totalLength > length) scale = jmax (minimumScale, length / (double) totalLength); const bool isTooBig = (int) (totalLength * scale) > length; int tabsButtonPos = 0; if (isTooBig) { if (extraTabsButton == nullptr) { addAndMakeVisible (extraTabsButton = lf.createTabBarExtrasButton()); extraTabsButton->addListener (behindFrontTab); extraTabsButton->setAlwaysOnTop (true); extraTabsButton->setTriggeredOnMouseDown (true); } const int buttonSize = jmin (proportionOfWidth (0.7f), proportionOfHeight (0.7f)); extraTabsButton->setSize (buttonSize, buttonSize); if (isVertical()) { tabsButtonPos = getHeight() - buttonSize / 2 - 1; extraTabsButton->setCentrePosition (getWidth() / 2, tabsButtonPos); } else { tabsButtonPos = getWidth() - buttonSize / 2 - 1; extraTabsButton->setCentrePosition (tabsButtonPos, getHeight() / 2); } totalLength = 0; for (int i = 0; i < tabs.size(); ++i) { TabBarButton* const tb = tabs.getUnchecked(i)->button; const int newLength = totalLength + tb->getBestTabLength (depth); if (i > 0 && newLength * minimumScale > tabsButtonPos) { totalLength += overlap; break; } numVisibleButtons = i + 1; totalLength = newLength - overlap; } scale = jmax (minimumScale, tabsButtonPos / (double) totalLength); } else { extraTabsButton = nullptr; } int pos = 0; TabBarButton* frontTab = nullptr; ComponentAnimator& animator = Desktop::getInstance().getAnimator(); for (int i = 0; i < tabs.size(); ++i) { if (TabBarButton* const tb = getTabButton (i)) { const int bestLength = roundToInt (scale * tb->getBestTabLength (depth)); if (i < numVisibleButtons) { const Rectangle<int> newBounds (isVertical() ? Rectangle<int> (0, pos, getWidth(), bestLength) : Rectangle<int> (pos, 0, bestLength, getHeight())); if (animate) { animator.animateComponent (tb, newBounds, 1.0f, 200, false, 3.0, 0.0); } else { animator.cancelAnimation (tb, false); tb->setBounds (newBounds); } tb->toBack(); if (i == currentTabIndex) frontTab = tb; tb->setVisible (true); } else { tb->setVisible (false); } pos += bestLength - overlap; } } behindFrontTab->setBounds (getLocalBounds()); if (frontTab != nullptr) { frontTab->toFront (false); behindFrontTab->toBehind (frontTab); } }