1 /*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2020 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 By using JUCE, you agree to the terms of both the JUCE 6 End-User License
11 Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
12
13 End User License Agreement: www.juce.com/juce-6-licence
14 Privacy Policy: www.juce.com/juce-privacy-policy
15
16 Or: You may also use this code under the terms of the GPL v3 (see
17 www.gnu.org/licenses).
18
19 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21 DISCLAIMED.
22
23 ==============================================================================
24 */
25
26 namespace juce
27 {
28
ToolbarItemFactory()29 ToolbarItemFactory::ToolbarItemFactory() {}
~ToolbarItemFactory()30 ToolbarItemFactory::~ToolbarItemFactory() {}
31
32 //==============================================================================
33 class ToolbarItemComponent::ItemDragAndDropOverlayComponent : public Component
34 {
35 public:
ItemDragAndDropOverlayComponent()36 ItemDragAndDropOverlayComponent()
37 : isDragging (false)
38 {
39 setAlwaysOnTop (true);
40 setRepaintsOnMouseActivity (true);
41 setMouseCursor (MouseCursor::DraggingHandCursor);
42 }
43
paint(Graphics & g)44 void paint (Graphics& g) override
45 {
46 if (ToolbarItemComponent* const tc = getToolbarItemComponent())
47 {
48 if (isMouseOverOrDragging()
49 && tc->getEditingMode() == ToolbarItemComponent::editableOnToolbar)
50 {
51 g.setColour (findColour (Toolbar::editingModeOutlineColourId, true));
52 g.drawRect (getLocalBounds(), jmin (2, (getWidth() - 1) / 2,
53 (getHeight() - 1) / 2));
54 }
55 }
56 }
57
mouseDown(const MouseEvent & e)58 void mouseDown (const MouseEvent& e) override
59 {
60 isDragging = false;
61
62 if (ToolbarItemComponent* const tc = getToolbarItemComponent())
63 {
64 tc->dragOffsetX = e.x;
65 tc->dragOffsetY = e.y;
66 }
67 }
68
mouseDrag(const MouseEvent & e)69 void mouseDrag (const MouseEvent& e) override
70 {
71 if (e.mouseWasDraggedSinceMouseDown() && ! isDragging)
72 {
73 isDragging = true;
74
75 if (DragAndDropContainer* const dnd = DragAndDropContainer::findParentDragContainerFor (this))
76 {
77 dnd->startDragging (Toolbar::toolbarDragDescriptor, getParentComponent(), Image(), true, nullptr, &e.source);
78
79 if (ToolbarItemComponent* const tc = getToolbarItemComponent())
80 {
81 tc->isBeingDragged = true;
82
83 if (tc->getEditingMode() == ToolbarItemComponent::editableOnToolbar)
84 tc->setVisible (false);
85 }
86 }
87 }
88 }
89
mouseUp(const MouseEvent &)90 void mouseUp (const MouseEvent&) override
91 {
92 isDragging = false;
93
94 if (ToolbarItemComponent* const tc = getToolbarItemComponent())
95 {
96 tc->isBeingDragged = false;
97
98 if (Toolbar* const tb = tc->getToolbar())
99 tb->updateAllItemPositions (true);
100 else if (tc->getEditingMode() == ToolbarItemComponent::editableOnToolbar)
101 delete tc;
102 }
103 }
104
parentSizeChanged()105 void parentSizeChanged() override
106 {
107 setBounds (0, 0, getParentWidth(), getParentHeight());
108 }
109
110 private:
111 //==============================================================================
112 bool isDragging;
113
getToolbarItemComponent() const114 ToolbarItemComponent* getToolbarItemComponent() const noexcept
115 {
116 return dynamic_cast<ToolbarItemComponent*> (getParentComponent());
117 }
118
119 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ItemDragAndDropOverlayComponent)
120 };
121
122
123 //==============================================================================
ToolbarItemComponent(const int itemId_,const String & labelText,const bool isBeingUsedAsAButton_)124 ToolbarItemComponent::ToolbarItemComponent (const int itemId_,
125 const String& labelText,
126 const bool isBeingUsedAsAButton_)
127 : Button (labelText),
128 itemId (itemId_),
129 mode (normalMode),
130 toolbarStyle (Toolbar::iconsOnly),
131 dragOffsetX (0),
132 dragOffsetY (0),
133 isActive (true),
134 isBeingDragged (false),
135 isBeingUsedAsAButton (isBeingUsedAsAButton_)
136 {
137 // Your item ID can't be 0!
138 jassert (itemId_ != 0);
139 }
140
~ToolbarItemComponent()141 ToolbarItemComponent::~ToolbarItemComponent()
142 {
143 overlayComp.reset();
144 }
145
getToolbar() const146 Toolbar* ToolbarItemComponent::getToolbar() const
147 {
148 return dynamic_cast<Toolbar*> (getParentComponent());
149 }
150
isToolbarVertical() const151 bool ToolbarItemComponent::isToolbarVertical() const
152 {
153 const Toolbar* const t = getToolbar();
154 return t != nullptr && t->isVertical();
155 }
156
setStyle(const Toolbar::ToolbarItemStyle & newStyle)157 void ToolbarItemComponent::setStyle (const Toolbar::ToolbarItemStyle& newStyle)
158 {
159 if (toolbarStyle != newStyle)
160 {
161 toolbarStyle = newStyle;
162 repaint();
163 resized();
164 }
165 }
166
paintButton(Graphics & g,const bool over,const bool down)167 void ToolbarItemComponent::paintButton (Graphics& g, const bool over, const bool down)
168 {
169 if (isBeingUsedAsAButton)
170 getLookAndFeel().paintToolbarButtonBackground (g, getWidth(), getHeight(),
171 over, down, *this);
172
173 if (toolbarStyle != Toolbar::iconsOnly)
174 {
175 auto indent = contentArea.getX();
176 auto y = indent;
177 auto h = getHeight() - indent * 2;
178
179 if (toolbarStyle == Toolbar::iconsWithText)
180 {
181 y = contentArea.getBottom() + indent / 2;
182 h -= contentArea.getHeight();
183 }
184
185 getLookAndFeel().paintToolbarButtonLabel (g, indent, y, getWidth() - indent * 2, h,
186 getButtonText(), *this);
187 }
188
189 if (! contentArea.isEmpty())
190 {
191 Graphics::ScopedSaveState ss (g);
192
193 g.reduceClipRegion (contentArea);
194 g.setOrigin (contentArea.getPosition());
195
196 paintButtonArea (g, contentArea.getWidth(), contentArea.getHeight(), over, down);
197 }
198 }
199
resized()200 void ToolbarItemComponent::resized()
201 {
202 if (toolbarStyle != Toolbar::textOnly)
203 {
204 const int indent = jmin (proportionOfWidth (0.08f),
205 proportionOfHeight (0.08f));
206
207 contentArea = Rectangle<int> (indent, indent,
208 getWidth() - indent * 2,
209 toolbarStyle == Toolbar::iconsWithText ? proportionOfHeight (0.55f)
210 : (getHeight() - indent * 2));
211 }
212 else
213 {
214 contentArea = {};
215 }
216
217 contentAreaChanged (contentArea);
218 }
219
setEditingMode(const ToolbarEditingMode newMode)220 void ToolbarItemComponent::setEditingMode (const ToolbarEditingMode newMode)
221 {
222 if (mode != newMode)
223 {
224 mode = newMode;
225 repaint();
226
227 if (mode == normalMode)
228 {
229 overlayComp.reset();
230 }
231 else if (overlayComp == nullptr)
232 {
233 overlayComp.reset (new ItemDragAndDropOverlayComponent());
234 addAndMakeVisible (overlayComp.get());
235 overlayComp->parentSizeChanged();
236 }
237
238 resized();
239 }
240 }
241
242 } // namespace juce
243