35 Panel (
int sz,
int mn,
int mx) noexcept
36 : size (sz), minSize (mn), maxSize (mx) {}
38 int setSize (
int newSize)
noexcept
42 size =
jlimit (minSize, maxSize, newSize);
43 return size - oldSize;
46 int expand (
int amount)
noexcept
48 amount =
jmin (amount, maxSize - size);
53 int reduce (
int amount)
noexcept
55 amount =
jmin (amount, size - minSize);
60 bool canExpand()
const noexcept {
return size < maxSize; }
61 bool isMinimised()
const noexcept {
return size <= minSize; }
63 int size, minSize, maxSize;
69 const Panel& get (
int index)
const noexcept {
return sizes.
getReference (index); }
71 PanelSizes withMovedPanel (
int index,
int targetPosition,
int totalSpace)
const
73 auto num = sizes.
size();
74 totalSpace =
jmax (totalSpace, getMinimumSize (0, num));
75 targetPosition =
jmax (targetPosition, totalSpace - getMaximumSize (index, num));
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);
83 PanelSizes fittedInto (
int totalSpace)
const
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);
92 PanelSizes withResizedPanel (
int index,
int panelHeight,
int totalSpace)
const
94 PanelSizes newSizes (*
this);
98 newSizes.get (index).size = panelHeight;
102 auto num = sizes.
size();
103 auto minSize = getMinimumSize (0, num);
104 totalSpace =
jmax (totalSpace, minSize);
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);
123 void growRangeFirst (
int start,
int end,
int spaceDiff)
noexcept
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);
130 void growRangeLast (
int start,
int end,
int spaceDiff)
noexcept
132 for (
int attempts = 4; --attempts >= 0 && spaceDiff > 0;)
133 for (
int i =
end; --i >= start && spaceDiff > 0;)
134 spaceDiff -= get (i).expand (spaceDiff);
137 void growRangeAll (
int start,
int end,
int spaceDiff)
noexcept
139 Array<Panel*> expandableItems;
141 for (
int i = start; i <
end; ++i)
142 if (get (i).canExpand() && ! get (i).isMinimised())
143 expandableItems.add (& get (i));
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));
149 growRangeLast (start,
end, spaceDiff);
152 void shrinkRangeFirst (
int start,
int end,
int spaceDiff)
noexcept
154 for (
int i = start; i < end && spaceDiff > 0; ++i)
155 spaceDiff -= get (i).reduce (spaceDiff);
158 void shrinkRangeLast (
int start,
int end,
int spaceDiff)
noexcept
160 for (
int i =
end; --i >= start && spaceDiff > 0;)
161 spaceDiff -= get (i).reduce (spaceDiff);
164 void stretchRange (
int start,
int end,
int amountToAdd, ExpandMode expandMode)
noexcept
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);
176 if (expandMode == stretchFirst) shrinkRangeFirst (start,
end, -amountToAdd);
177 else shrinkRangeLast (start,
end, -amountToAdd);
182 int getTotalSize (
int start,
int end)
const noexcept
185 while (start <
end) tot += get (start++).size;
189 int getMinimumSize (
int start,
int end)
const noexcept
192 while (start <
end) tot += get (start++).minSize;
196 int getMaximumSize (
int start,
int end)
const noexcept
202 auto mx = get (start++).maxSize;
219 : component (comp, takeOwnership)
228 if (customHeader.get() !=
nullptr)
235 getPanel(), *component);
241 auto headerBounds = bounds.removeFromTop (getHeaderSize());
243 if (customHeader.get() !=
nullptr)
244 customHeader.get()->setBounds (headerBounds);
246 component->setBounds (bounds);
252 dragStartSizes = getPanel().getFittedSizes();
259 auto& panel = getPanel();
260 panel.setLayout (dragStartSizes.withMovedPanel (panel.holders.indexOf (
this),
262 panel.getHeight()),
false);
268 getPanel().panelHeaderDoubleClicked (component);
271 void setCustomHeaderComponent (
Component* headerComponent,
bool shouldTakeOwnership)
280 PanelSizes dragStartSizes;
285 CustomHeader() =
default;
289 customHeaderComponent (
std::move (c))
291 if (customHeaderComponent !=
nullptr)
292 customHeaderComponent->addMouseListener (listener,
false);
295 CustomHeader (CustomHeader&& other) noexcept
297 customHeaderComponent (
std::exchange (other.customHeaderComponent, {})) {}
299 CustomHeader& operator= (CustomHeader&& other)
noexcept
302 std::swap (other.customHeaderComponent, customHeaderComponent);
306 CustomHeader (
const CustomHeader& other) =
delete;
307 CustomHeader& operator= (
const CustomHeader& other) =
delete;
309 ~CustomHeader() noexcept
311 if (customHeaderComponent !=
nullptr)
312 customHeaderComponent->removeMouseListener (listener);
315 Component*
get()
const {
return customHeaderComponent.get(); }
318 MouseListener* listener =
nullptr;
319 OptionalScopedPointer<Component> customHeaderComponent;
322 CustomHeader customHeader;
324 int getHeaderSize() const noexcept
327 auto ourIndex = panel.holders.indexOf (
this);
328 return panel.currentSizes->get (ourIndex).minSize;
352 return holders.size();
365 jassert (component !=
nullptr);
366 jassert (indexOfComp (component) < 0);
368 auto holder =
new PanelHolder (component, takeOwnership);
369 holders.insert (insertIndex, holder);
377 auto index = indexOfComp (component);
381 currentSizes->sizes.remove (index);
382 holders.remove (index);
389 auto index = indexOfComp (panelComponent);
392 height += currentSizes->get (index).minSize;
393 auto oldSize = currentSizes->get (index).size;
394 setLayout (currentSizes->withResizedPanel (index, height,
getHeight()), animate);
395 return oldSize != currentSizes->get (index).size;
405 auto index = indexOfComp (component);
410 currentSizes->get (index).maxSize = currentSizes->get (index).minSize + maximumSize;
417 auto index = indexOfComp (component);
422 auto oldMin = currentSizes->get (index).minSize;
424 currentSizes->get (index).minSize = headerSize;
425 currentSizes->get (index).size += headerSize - oldMin;
434 auto index = indexOfComp (component);
438 holders.getUnchecked (index)->setCustomHeaderComponent (optional.
release(), takeOwnership);
441void ConcertinaPanel::resized()
443 applyLayout (getFittedSizes(),
false);
446int ConcertinaPanel::indexOfComp (Component* comp)
const noexcept
448 for (
int i = 0; i < holders.size(); ++i)
449 if (holders.getUnchecked (i)->component == comp)
455ConcertinaPanel::PanelSizes ConcertinaPanel::getFittedSizes()
const
457 return currentSizes->fittedInto (
getHeight());
460void ConcertinaPanel::applyLayout (
const PanelSizes& sizes,
bool animate)
465 const int animationDuration = 150;
469 for (
int i = 0; i < holders.size(); ++i)
471 PanelHolder& p = *holders.getUnchecked (i);
473 auto h = sizes.get (i).size;
474 const Rectangle<int> pos (0, y, w, h);
477 animator.
animateComponent (&p, pos, 1.0f, animationDuration,
false, 1.0, 1.0);
485void ConcertinaPanel::setLayout (
const PanelSizes& sizes,
bool animate)
487 *currentSizes = sizes;
488 applyLayout (getFittedSizes(), animate);
491void ConcertinaPanel::panelHeaderDoubleClicked (Component* component)
Holds a resizable array of primitive or copy-by-value objects.
int size() const noexcept
Returns the current number of elements in the array.
ElementType & getReference(int index) noexcept
Returns a direct reference to one of the elements in the array, without checking the index passed in.
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.
void cancelAllAnimations(bool moveComponentsToTheirFinalPositions)
Clears all of the active animations.
The base class for all JUCE user-interface objects.
bool isMouseButtonDown(bool includeChildren=false) const
Returns true if the mouse button is currently held down in this component.
void setRepaintsOnMouseActivity(bool shouldRepaint) noexcept
Causes automatic repaints when the mouse enters or exits this component.
Component * getParentComponent() const noexcept
Returns the component which this component is inside.
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.
int getY() const noexcept
Returns the y coordinate of the top of this component.
void setWantsKeyboardFocus(bool wantsFocus) noexcept
Sets a flag to indicate whether this component wants keyboard focus or not.
bool isMouseOver(bool includeChildren=false) const
Returns true if the mouse is currently over 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.
Rectangle< int > getLocalBounds() const noexcept
Returns the component's bounds, relative to its own origin.
void mouseDown(const MouseEvent &) override
Called when a mouse button is pressed.
void resized() override
Called when this component's size has been changed.
void paint(Graphics &g) override
Components can override this method to draw their content.
void mouseDrag(const MouseEvent &e) override
Called when the mouse is moved while a button is held down.
void mouseDoubleClick(const MouseEvent &) override
Called when a mouse button has been double-clicked on a component.
void setMaximumPanelSize(Component *panelComponent, int maximumSize)
Sets a maximum size for one of the panels.
int getNumPanels() const noexcept
Returns the number of panels.
void setCustomPanelHeader(Component *panelComponent, Component *customHeaderComponent, bool takeOwnership)
Sets a custom header Component for one of the panels.
void setPanelHeaderSize(Component *panelComponent, int headerSize)
Sets the height of the header section for one of the panels.
void addPanel(int insertIndex, Component *component, bool takeOwnership)
Adds a component to the panel.
Component * getPanel(int index) const noexcept
Returns one of the panels.
bool expandPanelFully(Component *panelComponent, bool animate)
Attempts to make one of the panels full-height.
bool setPanelSize(Component *panelComponent, int newHeight, bool animate)
Resizes one of the panels.
~ConcertinaPanel() override
Destructor.
ConcertinaPanel()
Creates an empty concertina panel.
std::unique_ptr< AccessibilityHandler > createAccessibilityHandler() override
Override this method to return a custom AccessibilityHandler for this component.
void removePanel(Component *panelComponent)
Removes one of the panels.
A graphics context, used for drawing a component or image.
bool reduceClipRegion(int x, int y, int width, int height)
Intersects the current clipping region with another region.
Contains position and status information about a mouse event.
bool mouseWasDraggedSinceMouseDown() const noexcept
Returns true if the user seems to be performing a drag gesture.
int getDistanceFromDragStartY() const noexcept
Returns the difference between the mouse's current y position and where it was when the button was la...
A MouseListener can be registered with a component to receive callbacks about mouse events that happe...
Holds a pointer to an object which can optionally be deleted when this pointer goes out of scope.
ObjectType * release() noexcept
Removes the current object from this OptionalScopedPointer without deleting it.
Manages a rectangle and allows geometric operations to be performed on it.
auto & get(ProcessorChain< Processors... > &chain) noexcept
Non-member equivalent of ProcessorChain::get which avoids awkward member template syntax.
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.
RangedDirectoryIterator end(const RangedDirectoryIterator &)
Returns a default-constructed sentinel value.
Type jlimit(Type lowerLimit, Type upperLimit, Type valueToConstrain) noexcept
Constrains a value to keep it within a given range.