30 :
Button (name), owner (bar)
43 getLookAndFeel().drawTabButton (*
this, g, shouldDrawButtonAsHighlighted, shouldDrawButtonAsDown);
61 && my >= area.getY() + overlapPixels && my < area.getBottom() - overlapPixels)
67 && mx >= area.getX() + overlapPixels && mx < area.getRight() - overlapPixels)
74 return p.
contains ((
float) (mx - area.getX()),
75 (
float) (my - area.getY()));
89 auto overlap = lf.getTabButtonOverlap (depth);
94 textArea.
reduce (0, overlap);
96 textArea.
reduce (overlap, 0);
99 if (extraComponent !=
nullptr)
101 extraComp = lf.getTabButtonExtraComponentBounds (*
this, textArea, *extraComponent);
105 if (orientation == TabbedButtonBar::TabsAtLeft || orientation == TabbedButtonBar::TabsAtRight)
125 calcAreas (extraComp, textArea);
132 auto spaceAroundImage =
getLookAndFeel().getTabButtonSpaceAroundImage();
135 if (orientation != TabbedButtonBar::TabsAtLeft) r.removeFromRight (spaceAroundImage);
136 if (orientation != TabbedButtonBar::TabsAtRight) r.removeFromLeft (spaceAroundImage);
137 if (orientation != TabbedButtonBar::TabsAtBottom) r.removeFromTop (spaceAroundImage);
138 if (orientation != TabbedButtonBar::TabsAtTop) r.removeFromBottom (spaceAroundImage);
145 jassert (extraCompPlacement == beforeText || extraCompPlacement == afterText);
146 extraCompPlacement = placement;
147 extraComponent.reset (comp);
154 if (c == extraComponent.get())
163 if (extraComponent !=
nullptr)
166 calcAreas (extraComp, textArea);
169 extraComponent->setBounds (extraComp);
200 : orientation (orientationToUse)
211 extraTabsButton.reset();
217 orientation = newOrientation;
232 minimumScale = newMinimumScale;
240 extraTabsButton.reset();
245 Colour tabBackgroundColour,
253 insertIndex = tabs.
size();
255 auto* currentTab = tabs[currentTabIndex];
257 auto* newTab =
new TabInfo();
258 newTab->name = tabName;
259 newTab->colour = tabBackgroundColour;
261 jassert (newTab->button !=
nullptr);
263 tabs.
insert (insertIndex, newTab);
264 currentTabIndex = tabs.
indexOf (currentTab);
269 if (currentTabIndex < 0)
276 if (
auto* tab = tabs[tabIndex])
278 if (tab->name != newName)
281 tab->button->setButtonText (newName);
291 auto oldSelectedIndex = currentTabIndex;
293 if (indexToRemove == currentTabIndex)
294 oldSelectedIndex = -1;
295 else if (indexToRemove < oldSelectedIndex)
298 tabs.
remove (indexToRemove);
301 updateTabPositions (animate);
307 auto* currentTab = tabs[currentTabIndex];
308 tabs.
move (currentIndex, newIndex);
309 currentTabIndex = tabs.
indexOf (currentTab);
310 updateTabPositions (animate);
320 if (
auto* tab = tabs [currentTabIndex])
338 if (currentTabIndex != newIndex)
343 currentTabIndex = newIndex;
345 for (
int i = 0; i < tabs.
size(); ++i)
350 if (shouldSendChangeMessage)
359 if (
auto* tab = tabs[index])
367 for (
int i = tabs.
size(); --i >= 0;)
381 return animator.
isAnimating (button) ? animator.getComponentDestination (button)
382 : button->getBounds();
387 extraTabsButton.reset();
398 updateTabPositions (
false);
402void TabbedButtonBar::updateTabPositions (
bool animate)
412 auto overlap = lf.getTabButtonOverlap (depth) + lf.getTabButtonSpaceAroundImage() * 2;
414 auto totalLength =
jmax (0, overlap);
415 auto numVisibleButtons = tabs.
size();
417 for (
int i = 0; i < tabs.
size(); ++i)
421 totalLength += tb->getBestTabLength (depth) - overlap;
422 tb->overlapPixels =
jmax (0, overlap / 2);
427 if (totalLength > length)
428 scale =
jmax (minimumScale, length / (
double) totalLength);
430 const bool isTooBig = (
int) (totalLength * scale) > length;
431 int tabsButtonPos = 0;
435 if (extraTabsButton ==
nullptr)
437 extraTabsButton.reset (lf.createTabBarExtrasButton());
439 extraTabsButton->setAlwaysOnTop (
true);
440 extraTabsButton->setTriggeredOnMouseDown (
true);
441 extraTabsButton->onClick = [
this] { showExtraItemsMenu(); };
445 extraTabsButton->setSize (buttonSize, buttonSize);
449 tabsButtonPos =
getHeight() - buttonSize / 2 - 1;
450 extraTabsButton->setCentrePosition (
getWidth() / 2, tabsButtonPos);
454 tabsButtonPos =
getWidth() - buttonSize / 2 - 1;
455 extraTabsButton->setCentrePosition (tabsButtonPos,
getHeight() / 2);
460 for (
int i = 0; i < tabs.
size(); ++i)
463 auto newLength = totalLength + tb->getBestTabLength (depth);
465 if (i > 0 && newLength * minimumScale > tabsButtonPos)
467 totalLength += overlap;
471 numVisibleButtons = i + 1;
472 totalLength = newLength - overlap;
475 scale =
jmax (minimumScale, tabsButtonPos / (
double) totalLength);
479 extraTabsButton.reset();
484 TabBarButton* frontTab =
nullptr;
487 for (
int i = 0; i < tabs.
size(); ++i)
491 auto bestLength =
roundToInt (scale * tb->getBestTabLength (depth));
493 if (i < numVisibleButtons)
500 animator.animateComponent (tb, newBounds, 1.0f, 200,
false, 3.0, 0.0);
504 animator.cancelAnimation (tb,
false);
505 tb->setBounds (newBounds);
510 if (i == currentTabIndex)
513 tb->setVisible (
true);
517 tb->setVisible (
false);
520 pos += bestLength - overlap;
526 if (frontTab !=
nullptr)
528 frontTab->toFront (
false);
529 behindFrontTab->toBehind (frontTab);
536 if (
auto* tab = tabs[tabIndex])
539 return Colours::transparentBlack;
544 if (
auto* tab = tabs [tabIndex])
546 if (tab->colour != newColour)
548 tab->colour = newColour;
554void TabbedButtonBar::showExtraItemsMenu()
558 for (
int i = 0; i < tabs.
size(); ++i)
562 if (! tab->button->isVisible())
565 .
setAction ([
this, i] { setCurrentTabIndex (i); }));
569 .withDeletionCheck (*
this)
570 .withTargetComponent (extraTabsButton.get()));
void sendChangeMessage()
Causes an asynchronous change message to be sent to all the registered listeners.
Represents a colour, also including a transparency value.
bool isAnimating(Component *component) const noexcept
Returns true if the specified component is currently being animated.
The base class for all JUCE user-interface objects.
int proportionOfWidth(float proportion) const noexcept
Returns a proportion of the component's width.
void setInterceptsMouseClicks(bool allowClicksOnThisComponent, bool allowClicksOnChildComponents) noexcept
Changes the default return value for the hitTest() method.
int proportionOfHeight(float proportion) const noexcept
Returns a proportion of the component's height.
void setFocusContainerType(FocusContainerType containerType) noexcept
Sets whether this component is a container for components that can have their focus traversed,...
int getHeight() const noexcept
Returns the component's height in pixels.
void addAndMakeVisible(Component *child, int zOrder=-1)
Adds a child component to this one, and also makes the child visible if it isn't already.
void repaint()
Marks the whole component as needing to be redrawn.
@ keyboardFocusContainer
The component will act as a top-level component within which keyboard focus is passed around.
void setWantsKeyboardFocus(bool wantsFocus) noexcept
Sets a flag to indicate whether this component wants keyboard focus or not.
int getWidth() const noexcept
Returns the component's width in pixels.
LookAndFeel & getLookAndFeel() const noexcept
Finds the appropriate look-and-feel to use for this component.
Rectangle< int > getLocalBounds() const noexcept
Returns the component's bounds, relative to its own origin.
const Array< Component * > & getChildren() const noexcept
Provides access to the underlying array of child components.
ComponentAnimator & getAnimator() noexcept
The Desktop object has a ComponentAnimator instance which can be used for performing your animations.
static Desktop &JUCE_CALLTYPE getInstance()
There's only one desktop object, and this method will return it.
A graphics context, used for drawing a component or image.
Represents the state of the mouse buttons and modifier keys.
bool isPopupMenu() const noexcept
Checks whether the user is trying to launch a pop-up menu.
int size() const noexcept
Returns the number of items currently in the array.
ObjectClass * getUnchecked(int index) const noexcept
Returns a pointer to the object at this index in the array, without checking whether the index is in-...
void remove(int indexToRemove, bool deleteObject=true)
Removes an object from the array.
void clear(bool deleteObjects=true)
Clears the array, optionally deleting the objects inside it first.
int indexOf(const ObjectClass *objectToLookFor) const noexcept
Finds the index of an object which might be in the array.
void move(int currentIndex, int newIndex) noexcept
Moves one of the objects to a different position.
ObjectClass * insert(int indexToInsertAt, ObjectClass *newObject)
Inserts a new object into the array at the given index.
A path is a sequence of lines and curves that may either form a closed shape or be open-ended.
bool contains(float x, float y, float tolerance=defaultToleranceForTesting) const
Checks whether a point lies within the path.
Manages a rectangle and allows geometric operations to be performed on it.
ValueType getRight() const noexcept
Returns the x coordinate of the rectangle's right-hand-side.
void setLeft(ValueType newLeft) noexcept
Moves the x position, adjusting the width so that the right-hand edge remains in the same place.
ValueType getX() const noexcept
Returns the x coordinate of the rectangle's left-hand-side.
ValueType getCentreX() const noexcept
Returns the x coordinate of the rectangle's centre.
void setRight(ValueType newRight) noexcept
Adjusts the width so that the right-hand edge of the rectangle has this new value.
void setBottom(ValueType newBottom) noexcept
Adjusts the height so that the bottom edge of the rectangle has this new value.
ValueType getCentreY() const noexcept
Returns the y coordinate of the rectangle's centre.
ValueType getBottom() const noexcept
Returns the y coordinate of the rectangle's bottom edge.
ValueType getWidth() const noexcept
Returns the width of the rectangle.
void setTop(ValueType newTop) noexcept
Moves the y position, adjusting the height so that the bottom edge remains in the same place.
ValueType getY() const noexcept
Returns the y coordinate of the rectangle's top edge.
bool isEmpty() const noexcept
Returns true if the rectangle's width or height are zero or less.
void reduce(ValueType deltaX, ValueType deltaY) noexcept
Shrinks the rectangle by a given amount.
ValueType getHeight() const noexcept
Returns the height of the rectangle.
A special array for holding a list of strings.
void add(String stringToAdd)
Appends a string at the end of the array.
bool isNotEmpty() const noexcept
Returns true if the string contains at least one character.
constexpr Type jmin(Type a, Type b)
Returns the smaller of two values.
constexpr Type jmax(Type a, Type b)
Returns the larger of two values.
@ dontSendNotification
No notification message should be sent.
bool isPositiveAndBelow(Type1 valueToTest, Type2 upperLimit) noexcept
Returns true if a value is at least zero, and also below a specified upper limit.
int roundToInt(const FloatType value) noexcept
Fast floating-point-to-integer conversion.