29const char*
const Toolbar::toolbarDragDescriptor =
"_toolbarItem_";
35 Spacer (
int itemID,
float sizeToUse,
bool shouldDrawBar)
37 fixedSize (sizeToUse),
38 drawBar (shouldDrawBar)
44 int& preferredSize,
int& minSize,
int& maxSize)
override
48 preferredSize = toolbarThickness * 2;
54 maxSize =
roundToInt ((
float) toolbarThickness * fixedSize);
55 minSize = drawBar ? maxSize :
jmin (4, maxSize);
56 preferredSize = maxSize;
59 preferredSize = maxSize = toolbarThickness / (drawBar ? 3 : 2);
73 int getResizeOrder() const noexcept
75 return fixedSize <= 0 ? 0 : 1;
87 auto thickness = 0.2f;
90 g.
fillRect ((
float) w * 0.1f, (
float) h * (0.5f - thickness * 0.5f), (
float) w * 0.8f, (
float) h * thickness);
92 g.
fillRect ((
float) w * (0.5f - thickness * 0.5f), (
float) h * 0.1f, (
float) w * thickness, (
float) h * 0.8f);
99 auto indentX =
jmin (2, (w - 3) / 2);
100 auto indentY =
jmin (2, (h - 3) / 2);
101 g.
drawRect (indentX, indentY, w - indentX * 2, h - indentY * 2, 1);
105 float x1,
y1, x2, y2, x3, y3, x4, y4, hw, hl;
109 x1 = (
float) w * 0.5f;
112 y2 = (
float) indentX * 2.0f;
115 y3 = (
float) h * 0.6f;
119 hw = (
float) w * 0.15f;
120 hl = (
float) w * 0.2f;
124 x1 = (
float) w * 0.4f;
126 x2 = (
float) indentX * 2.0f;
129 x3 = (
float) w * 0.6f;
134 hw = (
float) h * 0.15f;
135 hl = (
float) h * 0.2f;
139 p.
addArrow ({ x1,
y1, x2, y2 }, 1.5f, hw, hl);
140 p.
addArrow ({ x3, y3, x4, y4 }, 1.5f, hw, hl);
147 const float fixedSize;
162 for (
int i = bar.items.size(); --i >= 0;)
164 auto* tc = bar.items.getUnchecked (i);
166 if (tc !=
nullptr &&
dynamic_cast<Spacer*
> (tc) ==
nullptr && ! tc->
isVisible())
178 if (owner !=
nullptr)
186 owner->addChildComponent (tc, index);
195 void layout (
const int preferredWidth)
197 const int indent = 8;
206 int preferredSize = 1, minSize = 1, maxSize = 1;
208 if (tc->getToolbarItemSizes (height,
false, preferredSize, minSize, maxSize))
210 if (x + preferredSize > preferredWidth && x > indent)
216 tc->setBounds (x, y, preferredSize, height);
219 maxX =
jmax (maxX, x);
224 setSize (maxX + 8, y + height + 8);
246 initMissingItemButton();
256 if (vertical != shouldBeVertical)
258 vertical = shouldBeVertical;
278void Toolbar::addItemInternal (ToolbarItemFactory& factory,
280 const int insertIndex)
285 if (
auto* tc = createItem (factory, itemId))
288 Array<int> allowedIds;
289 factory.getAllToolbarItemIds (allowedIds);
293 jassert (allowedIds.contains (itemId));
296 items.insert (insertIndex, tc);
303 addItemInternal (factory, itemId, insertIndex);
315 addItemInternal (factoryToUse, i, -1);
322 items.remove (itemIndex);
328 if (
auto* tc = items.removeAndReturn (itemIndex))
345 if (
auto* tc = getItemComponent (itemIndex))
346 return tc->getItemId();
353 return items[itemIndex];
376 if (toolbarStyle != newStyle)
378 toolbarStyle = newStyle;
379 updateAllItemPositions (
false);
394 const String& savedVersion)
404 for (
auto& t : tokens)
405 addItemInternal (factoryToUse, t.getIntValue(), -1);
428 if (isEditingActive != active)
430 isEditingActive = active;
431 updateAllItemPositions (
false);
438 updateAllItemPositions (
false);
441void Toolbar::updateAllItemPositions (
bool animate)
447 for (
auto* tc : items)
452 tc->setStyle (toolbarStyle);
454 auto* spacer =
dynamic_cast<Spacer*
> (tc);
456 int preferredSize = 1, minSize = 1, maxSize = 1;
459 preferredSize, minSize, maxSize))
462 resizer.
addItem (preferredSize, minSize, maxSize,
463 spacer !=
nullptr ? spacer->getResizeOrder() : 2);
467 tc->isActive =
false;
468 tc->setVisible (
false);
479 const bool itemsOffTheEnd = totalLength >
getLength();
482 missingItemsButton->setSize (extrasButtonSize, extrasButtonSize);
483 missingItemsButton->setVisible (itemsOffTheEnd);
484 missingItemsButton->setEnabled (! isEditingActive);
487 missingItemsButton->setCentrePosition (
getWidth() / 2,
490 missingItemsButton->setCentrePosition (
getWidth() - 4 - extrasButtonSize / 2,
493 auto maxLength = itemsOffTheEnd ? (vertical ? missingItemsButton->getY()
494 : missingItemsButton->getX()) - 4
497 int pos = 0, activeIndex = 0;
499 for (
auto* tc : items)
505 Rectangle<int> newBounds;
510 newBounds.setBounds (pos, 0, size,
getHeight());
520 animator.cancelAnimation (tc,
false);
521 tc->setBounds (newBounds);
525 tc->setVisible (pos <= maxLength
526 && ((! tc->isBeingDragged)
534void Toolbar::initMissingItemButton()
536 if (missingItemsButton ==
nullptr)
540 missingItemsButton->setAlwaysOnTop (
true);
541 missingItemsButton->onClick = [
this] { showMissingItems(); };
544void Toolbar::showMissingItems()
546 jassert (missingItemsButton->isShowing());
548 if (missingItemsButton->isShowing())
552 m.addCustomItem (1, std::move (comp),
nullptr,
TRANS (
"Additional Items"));
553 m.showMenuAsync (PopupMenu::Options().withTargetComponent (missingItemsButton.get()));
560 return dragSourceDetails.
description == toolbarDragDescriptor && isEditingActive;
567 if (! items.contains (tc))
572 palette->replaceComponent (*tc);
581 updateAllItemPositions (
true);
588 auto currentIndex = items.indexOf (tc);
589 auto newIndex = currentIndex;
591 auto dragObjectLeft = vertical ? (dragSourceDetails.
localPosition.
getY() - tc->dragOffsetY)
593 auto dragObjectRight = dragObjectLeft + (vertical ? tc->getHeight() : tc->getWidth());
597 if (
auto* prev = getNextActiveComponent (newIndex, -1))
599 auto previousPos = animator.getComponentDestination (prev);
601 if (std::abs (dragObjectLeft - (vertical ? previousPos.getY() : previousPos.getX()))
602 < std::abs (dragObjectRight - (vertical ? current.getBottom() : current.getRight())))
608 if (
auto* next = getNextActiveComponent (newIndex, 1))
610 auto nextPos = animator.getComponentDestination (next);
612 if (std::abs (dragObjectLeft - (vertical ? current.getY() : current.getX()))
613 > std::abs (dragObjectRight - (vertical ? nextPos.getBottom() : nextPos.getRight())))
619 if (newIndex == currentIndex)
622 items.removeObject (tc,
false);
625 items.insert (newIndex, tc);
626 updateAllItemPositions (
true);
637 items.removeObject (tc,
false);
639 updateAllItemPositions (
true);
647 tc->setState (Button::buttonNormal);
652 missingItemsButton.reset (
getLookAndFeel().createToolbarMissingItemsButton (*
this));
653 initMissingItemButton();
669 setContentOwned (
new CustomiserPanel (factory, toolbar, optionFlags),
true);
691 void positionNearBar()
699 if (pos.x > screenSize.getCentreX())
708 if (pos.y > screenSize.getCentreY())
723 CustomiserPanel (ToolbarItemFactory& tbf,
Toolbar& bar,
int optionFlags)
724 : factory (tbf), toolbar (bar), palette (tbf, bar),
725 instructions ({},
TRANS (
"You can drag the items above and drop them onto a toolbar to add them.")
727 +
TRANS (
"Items on the toolbar can also be dragged around to change their order, or dragged off the edge to delete them.")),
728 defaultButton (
TRANS (
"Restore to default set of items"))
737 styleBox.setEditableText (
false);
743 int selectedStyle = 0;
752 styleBox.setSelectedId (selectedStyle);
754 styleBox.onChange = [
this] { updateStyle(); };
760 defaultButton.onClick = [
this] { toolbar.addDefaultItems (factory); };
764 instructions.setFont (Font (13.0f));
771 switch (styleBox.getSelectedId())
782 void paint (Graphics& g)
override
786 if (
auto* dw = findParentComponentOfClass<DialogWindow>())
787 background = dw->getBackgroundColour();
789 g.setColour (background.contrasting().withAlpha (0.3f));
790 g.fillRect (palette.getX(), palette.getBottom() - 1, palette.getWidth(), 1);
793 void resized()
override
796 styleBox.setBounds (10,
getHeight() - 110, 200, 22);
798 defaultButton.changeWidthToFitText (22);
799 defaultButton.setTopLeftPosition (240,
getHeight() - 110);
805 ToolbarItemFactory& factory;
808 ToolbarItemPalette palette;
811 TextButton defaultButton;
Holds a resizable array of primitive or copy-by-value objects.
void insert(int indexToInsertAt, ParameterType newElement)
Inserts a new element into the array at a given position.
ElementType removeAndReturn(int indexToRemove)
Removes an element from the array.
void animateComponent(Component *component, const Rectangle< int > &finalBounds, float finalAlpha, int animationDurationMilliseconds, bool useProxyComponent, double startSpeed, double endSpeed)
Starts a component moving from its current position to a specified position.
Holds a pointer to some type of Component, which automatically becomes null if the component is delet...
The base class for all JUCE user-interface objects.
bool isVisible() const noexcept
Tests whether the component is visible or not.
int getNumChildComponents() const noexcept
Returns the number of child components that this component contains.
int getIndexOfChildComponent(const Component *child) const noexcept
Returns the index of this component in the list of child components.
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.
Component() noexcept
Creates a component.
void removeChildComponent(Component *childToRemove)
Removes one of this component's child-components.
Component * getChildComponent(int index) const noexcept
Returns one of this component's child components, by it index.
bool isParentOf(const Component *possibleChild) const noexcept
Checks whether a component is anywhere inside this component or its children.
void setSize(int newWidth, int newHeight)
Changes the size of the component.
void enterModalState(bool takeKeyboardFocus=true, ModalComponentManager::Callback *callback=nullptr, bool deleteWhenDismissed=false)
Puts the component into a modal state.
void setWantsKeyboardFocus(bool wantsFocus) noexcept
Sets a flag to indicate whether this component wants keyboard focus or not.
Colour findColour(int colourID, bool inheritFromParent=false) const
Looks for a colour that has been registered with the given colour ID number.
Rectangle< int > getParentMonitorArea() const
Returns the screen coordinates of the monitor that contains this component.
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.
Point< int > getScreenPosition() const
Returns the position of this component's top-left corner relative to the screen's top-left.
void setTopLeftPosition(int x, int y)
Moves the component to a new position.
void addChildComponent(Component *child, int zOrder=-1)
Adds a child component to this one.
const Array< Component * > & getChildren() const noexcept
Provides access to the underlying array of child components.
virtual void setVisible(bool shouldBeVisible)
Makes the component visible or invisible.
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 dialog-box style window.
Contains details about the source of a drag-and-drop operation.
Point< int > localPosition
The local position of the mouse, relative to the target component.
WeakReference< Component > sourceComponent
The component from the drag operation was started.
var description
A descriptor for the drag - this is set DragAndDropContainer::startDragging().
A graphics context, used for drawing a component or image.
void drawRect(int x, int y, int width, int height, int lineThickness=1) const
Draws a rectangular outline, using the current colour or brush.
void fillRect(Rectangle< int > rectangle) const
Fills a rectangle with the current colour or brush.
void fillPath(const Path &path) const
Fills a path using the currently selected colour or brush.
void setColour(Colour newColour)
Changes the current drawing colour.
Contains position and status information about a mouse event.
A path is a sequence of lines and curves that may either form a closed shape or be open-ended.
void addArrow(Line< float > line, float lineThickness, float arrowheadWidth, float arrowheadLength)
Adds a line with an arrowhead on the end.
constexpr ValueType getY() const noexcept
Returns the point's y coordinate.
constexpr ValueType getX() const noexcept
Returns the point's x coordinate.
ValueType x
The point's X coordinate.
Manages a rectangle and allows geometric operations to be performed on it.
void setResizable(bool shouldBeResizable, bool useBottomRightCornerResizer)
Make the window resizable or fixed.
void setResizeLimits(int newMinimumWidth, int newMinimumHeight, int newMaximumWidth, int newMaximumHeight) noexcept
This sets the maximum and minimum sizes for the window.
void setContentOwned(Component *newContentComponent, bool resizeToFitWhenContentChangesSize)
Changes the current content component.
A utility class for fitting a set of objects whose sizes can vary between a minimum and maximum size,...
void addItem(double currentSize, double minSize, double maxSize, int order=0)
Adds an item to the list.
double getItemSize(int index) const noexcept
Returns the size of one of the items.
int getNumItems() const noexcept
Returns the number of items that have been added.
void resizeToFit(double targetSize)
Resizes all the items to fit this amount of space.
A special array for holding a list of strings.
int addTokens(StringRef stringToTokenise, bool preserveQuotedStrings)
Breaks up a string into tokens and adds them to this array.
bool startsWith(StringRef text) const noexcept
Tests whether the string begins with another string.
String trimEnd() const
Returns a copy of this string with any whitespace characters removed from the end.
String substring(int startIndex, int endIndex) const
Returns a subsection of the string.
#define TRANS(stringLiteral)
Uses the LocalisedStrings class to translate the given string literal.
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.
int roundToInt(const FloatType value) noexcept
Fast floating-point-to-integer conversion.