LMMS
Loading...
Searching...
No Matches
juce_ConcertinaPanel.cpp
Go to the documentation of this file.
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - 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 7 End-User License
11 Agreement and JUCE Privacy Policy.
12
13 End User License Agreement: www.juce.com/juce-7-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
26namespace juce
27{
28
30{
31 struct Panel
32 {
33 Panel() = default;
34
35 Panel (int sz, int mn, int mx) noexcept
36 : size (sz), minSize (mn), maxSize (mx) {}
37
38 int setSize (int newSize) noexcept
39 {
41 auto oldSize = size;
42 size = jlimit (minSize, maxSize, newSize);
43 return size - oldSize;
44 }
45
46 int expand (int amount) noexcept
47 {
48 amount = jmin (amount, maxSize - size);
49 size += amount;
50 return amount;
51 }
52
53 int reduce (int amount) noexcept
54 {
55 amount = jmin (amount, size - minSize);
56 size -= amount;
57 return amount;
58 }
59
60 bool canExpand() const noexcept { return size < maxSize; }
61 bool isMinimised() const noexcept { return size <= minSize; }
62
64 };
65
67
68 Panel& get (int index) noexcept { return sizes.getReference (index); }
69 const Panel& get (int index) const noexcept { return sizes.getReference (index); }
70
71 PanelSizes withMovedPanel (int index, int targetPosition, int totalSpace) const
72 {
73 auto num = sizes.size();
74 totalSpace = jmax (totalSpace, getMinimumSize (0, num));
75 targetPosition = jmax (targetPosition, totalSpace - getMaximumSize (index, num));
76
77 PanelSizes newSizes (*this);
78 newSizes.stretchRange (0, index, targetPosition - newSizes.getTotalSize (0, index), stretchLast);
79 newSizes.stretchRange (index, num, totalSpace - newSizes.getTotalSize (0, index) - newSizes.getTotalSize (index, num), stretchFirst);
80 return newSizes;
81 }
82
83 PanelSizes fittedInto (int totalSpace) const
84 {
85 auto newSizes (*this);
86 auto num = newSizes.sizes.size();
87 totalSpace = jmax (totalSpace, getMinimumSize (0, num));
88 newSizes.stretchRange (0, num, totalSpace - newSizes.getTotalSize (0, num), stretchAll);
89 return newSizes;
90 }
91
92 PanelSizes withResizedPanel (int index, int panelHeight, int totalSpace) const
93 {
94 PanelSizes newSizes (*this);
95
96 if (totalSpace <= 0)
97 {
98 newSizes.get(index).size = panelHeight;
99 }
100 else
101 {
102 auto num = sizes.size();
103 auto minSize = getMinimumSize (0, num);
104 totalSpace = jmax (totalSpace, minSize);
105
106 newSizes.get(index).setSize (panelHeight);
107 newSizes.stretchRange (0, index, totalSpace - newSizes.getTotalSize (0, num), stretchLast);
108 newSizes.stretchRange (index, num, totalSpace - newSizes.getTotalSize (0, num), stretchLast);
109 newSizes = newSizes.fittedInto (totalSpace);
110 }
111
112 return newSizes;
113 }
114
115private:
122
123 void growRangeFirst (int start, int end, int spaceDiff) noexcept
124 {
125 for (int attempts = 4; --attempts >= 0 && spaceDiff > 0;)
126 for (int i = start; i < end && spaceDiff > 0; ++i)
127 spaceDiff -= get (i).expand (spaceDiff);
128 }
129
130 void growRangeLast (int start, int end, int spaceDiff) noexcept
131 {
132 for (int attempts = 4; --attempts >= 0 && spaceDiff > 0;)
133 for (int i = end; --i >= start && spaceDiff > 0;)
134 spaceDiff -= get (i).expand (spaceDiff);
135 }
136
137 void growRangeAll (int start, int end, int spaceDiff) noexcept
138 {
139 Array<Panel*> expandableItems;
140
141 for (int i = start; i < end; ++i)
142 if (get(i).canExpand() && ! get(i).isMinimised())
143 expandableItems.add (& get(i));
144
145 for (int attempts = 4; --attempts >= 0 && spaceDiff > 0;)
146 for (int i = expandableItems.size(); --i >= 0 && spaceDiff > 0;)
147 spaceDiff -= expandableItems.getUnchecked(i)->expand (spaceDiff / (i + 1));
148
149 growRangeLast (start, end, spaceDiff);
150 }
151
152 void shrinkRangeFirst (int start, int end, int spaceDiff) noexcept
153 {
154 for (int i = start; i < end && spaceDiff > 0; ++i)
155 spaceDiff -= get(i).reduce (spaceDiff);
156 }
157
158 void shrinkRangeLast (int start, int end, int spaceDiff) noexcept
159 {
160 for (int i = end; --i >= start && spaceDiff > 0;)
161 spaceDiff -= get(i).reduce (spaceDiff);
162 }
163
164 void stretchRange (int start, int end, int amountToAdd, ExpandMode expandMode) noexcept
165 {
166 if (end > start)
167 {
168 if (amountToAdd > 0)
169 {
170 if (expandMode == stretchAll) growRangeAll (start, end, amountToAdd);
171 else if (expandMode == stretchFirst) growRangeFirst (start, end, amountToAdd);
172 else if (expandMode == stretchLast) growRangeLast (start, end, amountToAdd);
173 }
174 else
175 {
176 if (expandMode == stretchFirst) shrinkRangeFirst (start, end, -amountToAdd);
177 else shrinkRangeLast (start, end, -amountToAdd);
178 }
179 }
180 }
181
182 int getTotalSize (int start, int end) const noexcept
183 {
184 int tot = 0;
185 while (start < end) tot += get (start++).size;
186 return tot;
187 }
188
189 int getMinimumSize (int start, int end) const noexcept
190 {
191 int tot = 0;
192 while (start < end) tot += get (start++).minSize;
193 return tot;
194 }
195
196 int getMaximumSize (int start, int end) const noexcept
197 {
198 int tot = 0;
199
200 while (start < end)
201 {
202 auto mx = get (start++).maxSize;
203
204 if (mx > 0x100000)
205 return mx;
206
207 tot += mx;
208 }
209
210 return tot;
211 }
212};
213
214//==============================================================================
216{
217public:
218 PanelHolder (Component* comp, bool takeOwnership)
219 : component (comp, takeOwnership)
220 {
222 setWantsKeyboardFocus (false);
224 }
225
226 void paint (Graphics& g) override
227 {
228 if (customHeaderComponent == nullptr)
229 {
230 const Rectangle<int> area (getWidth(), getHeaderSize());
231 g.reduceClipRegion (area);
232
233 getLookAndFeel().drawConcertinaPanelHeader (g, area, isMouseOver(), isMouseButtonDown(),
234 getPanel(), *component);
235 }
236 }
237
238 void resized() override
239 {
240 auto bounds = getLocalBounds();
241 auto headerBounds = bounds.removeFromTop (getHeaderSize());
242
243 if (customHeaderComponent != nullptr)
244 customHeaderComponent->setBounds (headerBounds);
245
246 component->setBounds (bounds);
247 }
248
249 void mouseDown (const MouseEvent&) override
250 {
251 mouseDownY = getY();
252 dragStartSizes = getPanel().getFittedSizes();
253 }
254
255 void mouseDrag (const MouseEvent& e) override
256 {
257 if (e.mouseWasDraggedSinceMouseDown())
258 {
259 auto& panel = getPanel();
260 panel.setLayout (dragStartSizes.withMovedPanel (panel.holders.indexOf (this),
261 mouseDownY + e.getDistanceFromDragStartY(),
262 panel.getHeight()), false);
263 }
264 }
265
266 void mouseDoubleClick (const MouseEvent&) override
267 {
268 getPanel().panelHeaderDoubleClicked (component);
269 }
270
271 void setCustomHeaderComponent (Component* headerComponent, bool shouldTakeOwnership)
272 {
273 customHeaderComponent.set (headerComponent, shouldTakeOwnership);
274
275 if (headerComponent != nullptr)
276 {
278 customHeaderComponent->addMouseListener (this, false);
279 }
280 }
281
283
284private:
288
290 {
291 ConcertinaPanel& panel = getPanel();
292 auto ourIndex = panel.holders.indexOf (this);
293 return panel.currentSizes->get(ourIndex).minSize;
294 }
295
297 {
298 auto panel = dynamic_cast<ConcertinaPanel*> (getParentComponent());
299 jassert (panel != nullptr);
300 return *panel;
301 }
302
304};
305
306//==============================================================================
312
314
316{
317 return holders.size();
318}
319
320Component* ConcertinaPanel::getPanel (int index) const noexcept
321{
322 if (PanelHolder* h = holders[index])
323 return h->component;
324
325 return nullptr;
326}
327
328void ConcertinaPanel::addPanel (int insertIndex, Component* component, bool takeOwnership)
329{
330 jassert (component != nullptr); // can't use a null pointer here!
331 jassert (indexOfComp (component) < 0); // You can't add the same component more than once!
332
333 auto holder = new PanelHolder (component, takeOwnership);
334 holders.insert (insertIndex, holder);
335 currentSizes->sizes.insert (insertIndex, PanelSizes::Panel (headerHeight, headerHeight, std::numeric_limits<int>::max()));
336 addAndMakeVisible (holder);
337 resized();
338}
339
341{
342 auto index = indexOfComp (component);
343
344 if (index >= 0)
345 {
346 currentSizes->sizes.remove (index);
347 holders.remove (index);
348 resized();
349 }
350}
351
352bool ConcertinaPanel::setPanelSize (Component* panelComponent, int height, bool animate)
353{
354 auto index = indexOfComp (panelComponent);
355 jassert (index >= 0); // The specified component doesn't seem to have been added!
356
357 height += currentSizes->get(index).minSize;
358 auto oldSize = currentSizes->get(index).size;
359 setLayout (currentSizes->withResizedPanel (index, height, getHeight()), animate);
360 return oldSize != currentSizes->get(index).size;
361}
362
363bool ConcertinaPanel::expandPanelFully (Component* component, bool animate)
364{
365 return setPanelSize (component, getHeight(), animate);
366}
367
368void ConcertinaPanel::setMaximumPanelSize (Component* component, int maximumSize)
369{
370 auto index = indexOfComp (component);
371 jassert (index >= 0); // The specified component doesn't seem to have been added!
372
373 if (index >= 0)
374 {
375 currentSizes->get(index).maxSize = currentSizes->get(index).minSize + maximumSize;
376 resized();
377 }
378}
379
380void ConcertinaPanel::setPanelHeaderSize (Component* component, int headerSize)
381{
382 auto index = indexOfComp (component);
383 jassert (index >= 0); // The specified component doesn't seem to have been added!
384
385 if (index >= 0)
386 {
387 auto oldMin = currentSizes->get (index).minSize;
388
389 currentSizes->get (index).minSize = headerSize;
390 currentSizes->get (index).size += headerSize - oldMin;
391 resized();
392 }
393}
394
395void ConcertinaPanel::setCustomPanelHeader (Component* component, Component* customComponent, bool takeOwnership)
396{
397 OptionalScopedPointer<Component> optional (customComponent, takeOwnership);
398
399 auto index = indexOfComp (component);
400 jassert (index >= 0); // The specified component doesn't seem to have been added!
401
402 if (index >= 0)
403 holders.getUnchecked (index)->setCustomHeaderComponent (optional.release(), takeOwnership);
404}
405
407{
408 applyLayout (getFittedSizes(), false);
409}
410
412{
413 for (int i = 0; i < holders.size(); ++i)
414 if (holders.getUnchecked(i)->component == comp)
415 return i;
416
417 return -1;
418}
419
424
426{
427 if (! animate)
428 animator.cancelAllAnimations (false);
429
430 const int animationDuration = 150;
431 auto w = getWidth();
432 int y = 0;
433
434 for (int i = 0; i < holders.size(); ++i)
435 {
436 PanelHolder& p = *holders.getUnchecked (i);
437
438 auto h = sizes.get (i).size;
439 const Rectangle<int> pos (0, y, w, h);
440
441 if (animate)
442 animator.animateComponent (&p, pos, 1.0f, animationDuration, false, 1.0, 1.0);
443 else
444 p.setBounds (pos);
445
446 y += h;
447 }
448}
449
450void ConcertinaPanel::setLayout (const PanelSizes& sizes, bool animate)
451{
453 applyLayout (getFittedSizes(), animate);
454}
455
457{
458 if (! expandPanelFully (component, true))
459 setPanelSize (component, 0, true);
460}
461
462//==============================================================================
463std::unique_ptr<AccessibilityHandler> ConcertinaPanel::createAccessibilityHandler()
464{
465 return std::make_unique<AccessibilityHandler> (*this, AccessibilityRole::group);
466}
467
468} // namespace juce
Type jmin(const Type a, const Type b)
Definition MathsFunctions.h:60
Type jmax(const Type a, const Type b)
Definition MathsFunctions.h:48
#define noexcept
Definition DistrhoDefines.h:72
Definition juce_Array.h:56
ElementType getUnchecked(int index) const
Definition juce_Array.h:252
int size() const noexcept
Definition juce_Array.h:215
void add(const ElementType &newElement)
Definition juce_Array.h:418
bool isMouseButtonDown(bool includeChildren=false) const
Definition juce_Component.cpp:3177
void setRepaintsOnMouseActivity(bool shouldRepaint) noexcept
Definition juce_Component.cpp:1881
Component * getParentComponent() const noexcept
Definition juce_Component.h:804
int getHeight() const noexcept
Definition juce_Component.h:274
void addAndMakeVisible(Component *child, int zOrder=-1)
Definition juce_Component.cpp:1554
Component() noexcept
Definition juce_Component.cpp:517
int getY() const noexcept
Definition juce_Component.h:268
void setWantsKeyboardFocus(bool wantsFocus) noexcept
Definition juce_Component.cpp:2842
bool isMouseOver(bool includeChildren=false) const
Definition juce_Component.cpp:3159
int getWidth() const noexcept
Definition juce_Component.h:271
LookAndFeel & getLookAndFeel() const noexcept
Definition juce_Component.cpp:2173
Rectangle< int > getLocalBounds() const noexcept
Definition juce_Component.cpp:2283
Definition juce_ConcertinaPanel.cpp:216
void mouseDown(const MouseEvent &) override
Definition juce_ConcertinaPanel.cpp:249
void resized() override
Definition juce_ConcertinaPanel.cpp:238
void setCustomHeaderComponent(Component *headerComponent, bool shouldTakeOwnership)
Definition juce_ConcertinaPanel.cpp:271
int mouseDownY
Definition juce_ConcertinaPanel.cpp:286
void paint(Graphics &g) override
Definition juce_ConcertinaPanel.cpp:226
void mouseDrag(const MouseEvent &e) override
Definition juce_ConcertinaPanel.cpp:255
int getHeaderSize() const noexcept
Definition juce_ConcertinaPanel.cpp:289
PanelHolder(Component *comp, bool takeOwnership)
Definition juce_ConcertinaPanel.cpp:218
ConcertinaPanel & getPanel() const
Definition juce_ConcertinaPanel.cpp:296
void mouseDoubleClick(const MouseEvent &) override
Definition juce_ConcertinaPanel.cpp:266
OptionalScopedPointer< Component > customHeaderComponent
Definition juce_ConcertinaPanel.cpp:287
PanelSizes dragStartSizes
Definition juce_ConcertinaPanel.cpp:285
OptionalScopedPointer< Component > component
Definition juce_ConcertinaPanel.cpp:282
void setMaximumPanelSize(Component *panelComponent, int maximumSize)
Definition juce_ConcertinaPanel.cpp:368
void panelHeaderDoubleClicked(Component *)
Definition juce_ConcertinaPanel.cpp:456
int getNumPanels() const noexcept
Definition juce_ConcertinaPanel.cpp:315
void setCustomPanelHeader(Component *panelComponent, Component *customHeaderComponent, bool takeOwnership)
Definition juce_ConcertinaPanel.cpp:395
int headerHeight
Definition juce_ConcertinaPanel.h:131
std::unique_ptr< PanelSizes > currentSizes
Definition juce_ConcertinaPanel.h:128
void setPanelHeaderSize(Component *panelComponent, int headerSize)
Definition juce_ConcertinaPanel.cpp:380
void addPanel(int insertIndex, Component *component, bool takeOwnership)
Definition juce_ConcertinaPanel.cpp:328
PanelSizes getFittedSizes() const
Definition juce_ConcertinaPanel.cpp:420
ComponentAnimator animator
Definition juce_ConcertinaPanel.h:130
void setLayout(const PanelSizes &, bool animate)
Definition juce_ConcertinaPanel.cpp:450
Component * getPanel(int index) const noexcept
Definition juce_ConcertinaPanel.cpp:320
bool expandPanelFully(Component *panelComponent, bool animate)
Definition juce_ConcertinaPanel.cpp:363
bool setPanelSize(Component *panelComponent, int newHeight, bool animate)
Definition juce_ConcertinaPanel.cpp:352
~ConcertinaPanel() override
Definition juce_ConcertinaPanel.cpp:313
ConcertinaPanel()
Definition juce_ConcertinaPanel.cpp:307
void applyLayout(const PanelSizes &, bool animate)
Definition juce_ConcertinaPanel.cpp:425
int indexOfComp(Component *) const noexcept
Definition juce_ConcertinaPanel.cpp:411
void resized() override
Definition juce_ConcertinaPanel.cpp:406
std::unique_ptr< AccessibilityHandler > createAccessibilityHandler() override
Definition juce_ConcertinaPanel.cpp:463
OwnedArray< PanelHolder > holders
Definition juce_ConcertinaPanel.h:129
void removePanel(Component *panelComponent)
Definition juce_ConcertinaPanel.cpp:340
Definition juce_GraphicsContext.h:45
Definition juce_MouseEvent.h:39
Definition juce_OptionalScopedPointer.h:38
ObjectType * release() noexcept
Definition juce_OptionalScopedPointer.h:124
Definition juce_Rectangle.h:67
* e
Definition inflate.c:1404
UINT_D64 w
Definition inflate.c:942
int y
Definition inflate.c:1588
int g
Definition inflate.c:1573
register unsigned i
Definition inflate.c:1575
static int int height
Definition pugl.h:1594
virtual ASIOError start()=0
#define jassert(expression)
#define JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(className)
static const unsigned sizes[]
Definition hash.c:27
static int JUCE_CDECL comp(const void *a, const void *b)
Definition lsp.c:298
Definition carla_juce.cpp:31
RangedDirectoryIterator end(const RangedDirectoryIterator &)
Definition juce_RangedDirectoryIterator.h:184
Type jlimit(Type lowerLimit, Type upperLimit, Type valueToConstrain) noexcept
Definition juce_MathsFunctions.h:262
@ group
Definition juce_AccessibilityRole.h:61
Definition juce_ConcertinaPanel.cpp:32
int minSize
Definition juce_ConcertinaPanel.cpp:63
int size
Definition juce_ConcertinaPanel.cpp:63
int setSize(int newSize) noexcept
Definition juce_ConcertinaPanel.cpp:38
bool isMinimised() const noexcept
Definition juce_ConcertinaPanel.cpp:61
int reduce(int amount) noexcept
Definition juce_ConcertinaPanel.cpp:53
int maxSize
Definition juce_ConcertinaPanel.cpp:63
Panel(int sz, int mn, int mx) noexcept
Definition juce_ConcertinaPanel.cpp:35
int expand(int amount) noexcept
Definition juce_ConcertinaPanel.cpp:46
bool canExpand() const noexcept
Definition juce_ConcertinaPanel.cpp:60
Definition juce_ConcertinaPanel.cpp:30
PanelSizes withResizedPanel(int index, int panelHeight, int totalSpace) const
Definition juce_ConcertinaPanel.cpp:92
int getTotalSize(int start, int end) const noexcept
Definition juce_ConcertinaPanel.cpp:182
void stretchRange(int start, int end, int amountToAdd, ExpandMode expandMode) noexcept
Definition juce_ConcertinaPanel.cpp:164
const Panel & get(int index) const noexcept
Definition juce_ConcertinaPanel.cpp:69
Panel & get(int index) noexcept
Definition juce_ConcertinaPanel.cpp:68
PanelSizes withMovedPanel(int index, int targetPosition, int totalSpace) const
Definition juce_ConcertinaPanel.cpp:71
Array< Panel > sizes
Definition juce_ConcertinaPanel.cpp:66
void growRangeFirst(int start, int end, int spaceDiff) noexcept
Definition juce_ConcertinaPanel.cpp:123
void growRangeLast(int start, int end, int spaceDiff) noexcept
Definition juce_ConcertinaPanel.cpp:130
void shrinkRangeLast(int start, int end, int spaceDiff) noexcept
Definition juce_ConcertinaPanel.cpp:158
void shrinkRangeFirst(int start, int end, int spaceDiff) noexcept
Definition juce_ConcertinaPanel.cpp:152
ExpandMode
Definition juce_ConcertinaPanel.cpp:117
@ stretchAll
Definition juce_ConcertinaPanel.cpp:118
@ stretchLast
Definition juce_ConcertinaPanel.cpp:120
@ stretchFirst
Definition juce_ConcertinaPanel.cpp:119
int getMinimumSize(int start, int end) const noexcept
Definition juce_ConcertinaPanel.cpp:189
int getMaximumSize(int start, int end) const noexcept
Definition juce_ConcertinaPanel.cpp:196
PanelSizes fittedInto(int totalSpace) const
Definition juce_ConcertinaPanel.cpp:83
void growRangeAll(int start, int end, int spaceDiff) noexcept
Definition juce_ConcertinaPanel.cpp:137
uch * p
Definition crypt.c:594
uch h[RAND_HEAD_LEN]
Definition crypt.c:459
ulg size
Definition extract.c:2350
#define const
Definition zconf.h:137