| @@ -74,50 +74,27 @@ bool TabBarButton::hitTest (int mx, int my) | |||||
| int TabBarButton::getBestTabLength (const int depth) | int TabBarButton::getBestTabLength (const int depth) | ||||
| { | { | ||||
| int textWidth = getLookAndFeel().getTabButtonBestWidth (*this, depth); | |||||
| int extraCompSize = extraComponent != nullptr ? (owner.isVertical() ? extraComponent->getHeight() | |||||
| : extraComponent->getWidth()) : 0; | |||||
| return jlimit (depth * 2, depth * 8, textWidth + extraCompSize); | |||||
| return getLookAndFeel().getTabButtonBestWidth (*this, depth); | |||||
| } | } | ||||
| void TabBarButton::calcAreas (Rectangle<int>& extraComp, Rectangle<int>& text) const | void TabBarButton::calcAreas (Rectangle<int>& extraComp, Rectangle<int>& text) const | ||||
| { | { | ||||
| LookAndFeel& lf = getLookAndFeel(); | |||||
| text = getActiveArea(); | text = getActiveArea(); | ||||
| const int depth = owner.isVertical() ? text.getWidth() : text.getHeight(); | const int depth = owner.isVertical() ? text.getWidth() : text.getHeight(); | ||||
| const int indent = getLookAndFeel().getTabButtonOverlap (depth); | |||||
| if (owner.isVertical()) | |||||
| text.reduce (0, indent); | |||||
| else | |||||
| text.reduce (indent, 0); | |||||
| const int overlap = lf.getTabButtonOverlap (depth); | |||||
| if (extraComponent != nullptr) | |||||
| if (overlap > 0) | |||||
| { | { | ||||
| if (extraCompPlacement == beforeText) | |||||
| { | |||||
| switch (owner.getOrientation()) | |||||
| { | |||||
| case TabbedButtonBar::TabsAtLeft: extraComp = text.removeFromBottom (extraComponent->getHeight()); break; | |||||
| case TabbedButtonBar::TabsAtRight: extraComp = text.removeFromTop (extraComponent->getHeight()); break; | |||||
| case TabbedButtonBar::TabsAtBottom: | |||||
| case TabbedButtonBar::TabsAtTop: extraComp = text.removeFromLeft (extraComponent->getWidth()); break; | |||||
| default: jassertfalse; break; | |||||
| } | |||||
| } | |||||
| if (owner.isVertical()) | |||||
| text.reduce (0, overlap); | |||||
| else | else | ||||
| { | |||||
| switch (owner.getOrientation()) | |||||
| { | |||||
| case TabbedButtonBar::TabsAtLeft: extraComp = text.removeFromTop (extraComponent->getHeight()); break; | |||||
| case TabbedButtonBar::TabsAtRight: extraComp = text.removeFromBottom (extraComponent->getHeight()); break; | |||||
| case TabbedButtonBar::TabsAtBottom: | |||||
| case TabbedButtonBar::TabsAtTop: extraComp = text.removeFromRight (extraComponent->getWidth()); break; | |||||
| default: jassertfalse; break; | |||||
| } | |||||
| } | |||||
| text.reduce (overlap, 0); | |||||
| } | } | ||||
| if (extraComponent != nullptr) | |||||
| extraComp = lf.getTabButtonExtraComponentBounds (*this, text, *extraComponent); | |||||
| } | } | ||||
| Rectangle<int> TabBarButton::getTextArea() const | Rectangle<int> TabBarButton::getTextArea() const | ||||
| @@ -389,7 +366,7 @@ void TabbedButtonBar::resized() | |||||
| const int overlap = lf.getTabButtonOverlap (depth) + lf.getTabButtonSpaceAroundImage() * 2; | const int overlap = lf.getTabButtonOverlap (depth) + lf.getTabButtonSpaceAroundImage() * 2; | ||||
| int totalLength = overlap; | |||||
| int totalLength = jmax (0, overlap); | |||||
| int numVisibleButtons = tabs.size(); | int numVisibleButtons = tabs.size(); | ||||
| for (int i = 0; i < tabs.size(); ++i) | for (int i = 0; i < tabs.size(); ++i) | ||||
| @@ -397,7 +374,7 @@ void TabbedButtonBar::resized() | |||||
| TabBarButton* const tb = tabs.getUnchecked(i)->button; | TabBarButton* const tb = tabs.getUnchecked(i)->button; | ||||
| totalLength += tb->getBestTabLength (depth) - overlap; | totalLength += tb->getBestTabLength (depth) - overlap; | ||||
| tb->overlapPixels = overlap / 2; | |||||
| tb->overlapPixels = jmax (0, overlap / 2); | |||||
| } | } | ||||
| double scale = 1.0; | double scale = 1.0; | ||||
| @@ -405,7 +382,7 @@ void TabbedButtonBar::resized() | |||||
| if (totalLength > length) | if (totalLength > length) | ||||
| scale = jmax (minimumScale, length / (double) totalLength); | scale = jmax (minimumScale, length / (double) totalLength); | ||||
| const bool isTooBig = totalLength * scale > length; | |||||
| const bool isTooBig = (int) (totalLength * scale) > length; | |||||
| int tabsButtonPos = 0; | int tabsButtonPos = 0; | ||||
| if (isTooBig) | if (isTooBig) | ||||
| @@ -71,6 +71,12 @@ public: | |||||
| void setExtraComponent (Component* extraTabComponent, | void setExtraComponent (Component* extraTabComponent, | ||||
| ExtraComponentPlacement extraComponentPlacement); | ExtraComponentPlacement extraComponentPlacement); | ||||
| /** Returns the custom component, if there is one. */ | |||||
| Component* getExtraComponent() const noexcept { return extraComponent; } | |||||
| /** Returns the placement of the custom component, if there is one. */ | |||||
| ExtraComponentPlacement getExtraComponentPlacement() const noexcept { return extraCompPlacement; } | |||||
| /** Returns an area of the component that's safe to draw in. | /** Returns an area of the component that's safe to draw in. | ||||
| This deals with the orientation of the tabs, which affects which side is | This deals with the orientation of the tabs, which affects which side is | ||||
| @@ -2076,8 +2076,48 @@ int LookAndFeel::getTabButtonSpaceAroundImage() | |||||
| int LookAndFeel::getTabButtonBestWidth (TabBarButton& button, int tabDepth) | int LookAndFeel::getTabButtonBestWidth (TabBarButton& button, int tabDepth) | ||||
| { | { | ||||
| return Font (tabDepth * 0.6f).getStringWidth (button.getButtonText().trim()) | |||||
| + getTabButtonOverlap (tabDepth) * 2; | |||||
| int width = Font (tabDepth * 0.6f).getStringWidth (button.getButtonText().trim()) | |||||
| + getTabButtonOverlap (tabDepth) * 2; | |||||
| Component* const extraComponent = button.getExtraComponent(); | |||||
| if (extraComponent != nullptr) | |||||
| width += button.getTabbedButtonBar().isVertical() ? extraComponent->getHeight() | |||||
| : extraComponent->getWidth(); | |||||
| return jlimit (tabDepth * 2, tabDepth * 8, width); | |||||
| } | |||||
| Rectangle<int> LookAndFeel::getTabButtonExtraComponentBounds (const TabBarButton& button, Rectangle<int>& textArea, Component& comp) | |||||
| { | |||||
| Rectangle<int> extraComp; | |||||
| const TabbedButtonBar::Orientation orientation = button.getTabbedButtonBar().getOrientation(); | |||||
| if (button.getExtraComponentPlacement() == TabBarButton::beforeText) | |||||
| { | |||||
| switch (orientation) | |||||
| { | |||||
| case TabbedButtonBar::TabsAtBottom: | |||||
| case TabbedButtonBar::TabsAtTop: extraComp = textArea.removeFromLeft (comp.getWidth()); break; | |||||
| case TabbedButtonBar::TabsAtLeft: extraComp = textArea.removeFromBottom (comp.getHeight()); break; | |||||
| case TabbedButtonBar::TabsAtRight: extraComp = textArea.removeFromTop (comp.getHeight()); break; | |||||
| default: jassertfalse; break; | |||||
| } | |||||
| } | |||||
| else | |||||
| { | |||||
| switch (orientation) | |||||
| { | |||||
| case TabbedButtonBar::TabsAtBottom: | |||||
| case TabbedButtonBar::TabsAtTop: extraComp = textArea.removeFromRight (comp.getWidth()); break; | |||||
| case TabbedButtonBar::TabsAtLeft: extraComp = textArea.removeFromTop (comp.getHeight()); break; | |||||
| case TabbedButtonBar::TabsAtRight: extraComp = textArea.removeFromBottom (comp.getHeight()); break; | |||||
| default: jassertfalse; break; | |||||
| } | |||||
| } | |||||
| return extraComp; | |||||
| } | } | ||||
| void LookAndFeel::createTabButtonShape (TabBarButton& button, Path& p, bool /*isMouseOver*/, bool /*isMouseDown*/) | void LookAndFeel::createTabButtonShape (TabBarButton& button, Path& p, bool /*isMouseOver*/, bool /*isMouseDown*/) | ||||
| @@ -516,6 +516,7 @@ public: | |||||
| virtual int getTabButtonSpaceAroundImage(); | virtual int getTabButtonSpaceAroundImage(); | ||||
| virtual int getTabButtonOverlap (int tabDepth); | virtual int getTabButtonOverlap (int tabDepth); | ||||
| virtual int getTabButtonBestWidth (TabBarButton&, int tabDepth); | virtual int getTabButtonBestWidth (TabBarButton&, int tabDepth); | ||||
| virtual Rectangle<int> getTabButtonExtraComponentBounds (const TabBarButton&, Rectangle<int>& textArea, Component& extraComp); | |||||
| virtual void drawTabButton (TabBarButton&, Graphics& g, bool isMouseOver, bool isMouseDown); | virtual void drawTabButton (TabBarButton&, Graphics& g, bool isMouseOver, bool isMouseDown); | ||||
| virtual void drawTabButtonText (TabBarButton&, Graphics& g, bool isMouseOver, bool isMouseDown); | virtual void drawTabButtonText (TabBarButton&, Graphics& g, bool isMouseOver, bool isMouseDown); | ||||