JUCE-7.0.12-0-g4f43011b96 JUCE-7.0.12-0-g4f43011b96
JUCE — C++ application framework with suport for VST, VST3, LV2 audio plug-ins

« « « Anklang Documentation
Loading...
Searching...
No Matches
juce_SidePanel.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
31 : titleLabel ("titleLabel", title),
32 isOnLeft (positionOnLeft),
33 panelWidth (width)
34{
35 lookAndFeelChanged();
36
37 addAndMakeVisible (titleLabel);
38
39 dismissButton.onClick = [this] { showOrHide (false); };
40 addAndMakeVisible (dismissButton);
41
43
44 desktop.addGlobalMouseListener (this);
45 desktop.getAnimator().addChangeListener (this);
46
47 if (contentToDisplay != nullptr)
49
50 setOpaque (false);
51 setVisible (false);
52 setAlwaysOnTop (true);
53}
54
56{
58
59 desktop.removeGlobalMouseListener (this);
60 desktop.getAnimator().removeChangeListener (this);
61
62 if (parent != nullptr)
63 parent->removeComponentListener (this);
64}
65
67{
68 if (contentComponent.get() != newContent)
69 {
71 contentComponent.setOwned (newContent);
72 else
73 contentComponent.setNonOwned (newContent);
74
75 addAndMakeVisible (contentComponent);
76
77 resized();
78 }
79}
80
84{
85 if (titleBarComponent.get() != titleBarComponentToUse)
86 {
88 titleBarComponent.setOwned (titleBarComponentToUse);
89 else
90 titleBarComponent.setNonOwned (titleBarComponentToUse);
91
92 addAndMakeVisible (titleBarComponent);
93
94 resized();
95 }
96
97 shouldShowDismissButton = keepDismissButton;
98}
99
100void SidePanel::showOrHide (bool show)
101{
102 if (parent != nullptr)
103 {
104 isShowing = show;
105
106 Desktop::getInstance().getAnimator().animateComponent (this, calculateBoundsInParent (*parent),
107 1.0f, 250, true, 1.0, 0.0);
108
109 if (isShowing && ! isVisible())
110 setVisible (true);
111 }
112}
113
115{
116 NullCheckedInvocation::invoke (onPanelMove);
117}
118
120{
121 auto bounds = getLocalBounds();
122
123 calculateAndRemoveShadowBounds (bounds);
124
125 auto titleBounds = bounds.removeFromTop (titleBarHeight);
126
127 if (titleBarComponent != nullptr)
128 {
129 if (shouldShowDismissButton)
130 dismissButton.setBounds (isOnLeft ? titleBounds.removeFromRight (30).withTrimmedRight (10)
131 : titleBounds.removeFromLeft (30).withTrimmedLeft (10));
132
133 titleBarComponent->setBounds (titleBounds);
134 }
135 else
136 {
137 dismissButton.setBounds (isOnLeft ? titleBounds.removeFromRight (30).withTrimmedRight (10)
138 : titleBounds.removeFromLeft (30).withTrimmedLeft (10));
139
140 titleLabel.setBounds (isOnLeft ? titleBounds.withTrimmedRight (40)
141 : titleBounds.withTrimmedLeft (40));
142 }
143
144 if (contentComponent != nullptr)
145 contentComponent->setBounds (bounds);
146}
147
149{
150 auto& lf = getLookAndFeel();
151
152 auto bgColour = lf.findColour (SidePanel::backgroundColour);
153 auto shadowColour = lf.findColour (SidePanel::shadowBaseColour);
154
155 g.setGradientFill (ColourGradient (shadowColour.withAlpha (0.7f), (isOnLeft ? shadowArea.getTopLeft()
156 : shadowArea.getTopRight()).toFloat(),
157 shadowColour.withAlpha (0.0f), (isOnLeft ? shadowArea.getTopRight()
158 : shadowArea.getTopLeft()).toFloat(), false));
159 g.fillRect (shadowArea);
160
162 .withX (isOnLeft ? 0 : shadowArea.getWidth()));
163 g.fillAll (bgColour);
164}
165
167{
169
170 if ((newParent != nullptr) && (parent != newParent))
171 {
172 if (parent != nullptr)
173 parent->removeComponentListener (this);
174
175 parent = newParent;
176 parent->addComponentListener (this);
177 }
178}
179
181{
182 if (shouldResize)
183 {
185
186 if (getParentComponent() == nullptr)
188 else
190
192
193 if (isOnLeft)
194 {
195 amountMoved = startingBounds.getRight() - currentMouseDragX;
196 setBounds (getBounds().withX (startingBounds.getX() - jmax (amountMoved, 0)));
197 }
198 else
199 {
200 amountMoved = currentMouseDragX - startingBounds.getX();
201 setBounds (getBounds().withX (startingBounds.getX() + jmax (amountMoved, 0)));
202 }
203 }
204 else if (isShowing)
205 {
208
211 {
212 shouldResize = true;
213 startingBounds = getBounds();
214 }
215 }
216}
217
219{
220 if (shouldResize)
221 {
222 showOrHide (amountMoved < (panelWidth / 2));
223
224 amountMoved = 0;
225 shouldResize = false;
226 }
227}
228
229//==============================================================================
230void SidePanel::lookAndFeelChanged()
231{
232 auto& lf = getLookAndFeel();
233
234 dismissButton.setShape (lf.getSidePanelDismissButtonShape (*this), false, true, false);
235
236 dismissButton.setColours (lf.findColour (SidePanel::dismissButtonNormalColour),
237 lf.findColour (SidePanel::dismissButtonOverColour),
238 lf.findColour (SidePanel::dismissButtonDownColour));
239
240 titleLabel.setFont (lf.getSidePanelTitleFont (*this));
241 titleLabel.setColour (Label::textColourId, findColour (SidePanel::titleTextColour));
242 titleLabel.setJustificationType (lf.getSidePanelTitleJustification (*this));
243}
244
245void SidePanel::componentMovedOrResized (Component& component, [[maybe_unused]] bool wasMoved, bool wasResized)
246{
247 if (wasResized && (&component == parent))
248 setBounds (calculateBoundsInParent (component));
249}
250
251void SidePanel::changeListenerCallback (ChangeBroadcaster*)
252{
253 if (! Desktop::getInstance().getAnimator().isAnimating (this))
254 {
255 NullCheckedInvocation::invoke (onPanelShowHide, isShowing);
256
257 if (isVisible() && ! isShowing)
258 setVisible (false);
259 }
260}
261
262Rectangle<int> SidePanel::calculateBoundsInParent (Component& parentComp) const
263{
264 auto parentBounds = parentComp.getLocalBounds();
265
266 if (isOnLeft)
267 {
268 return isShowing ? parentBounds.removeFromLeft (panelWidth)
269 : parentBounds.withX (parentBounds.getX() - panelWidth).withWidth (panelWidth);
270 }
271
272 return isShowing ? parentBounds.removeFromRight (panelWidth)
273 : parentBounds.withX (parentBounds.getRight()).withWidth (panelWidth);
274}
275
276void SidePanel::calculateAndRemoveShadowBounds (Rectangle<int>& bounds)
277{
278 shadowArea = isOnLeft ? bounds.removeFromRight (shadowWidth)
279 : bounds.removeFromLeft (shadowWidth);
280}
281
282bool SidePanel::isMouseEventInThisOrChildren (Component* eventComponent)
283{
284 if (eventComponent == this)
285 return true;
286
287 for (auto& child : getChildren())
288 if (eventComponent == child)
289 return true;
290
291 return false;
292}
293
294//==============================================================================
296{
297 return std::make_unique<AccessibilityHandler> (*this, AccessibilityRole::group);
298}
299
300} // namespace juce
std::function< void()> onClick
You can assign a lambda to this callback object to have it called when the button is clicked.
Describes the layout and colours that should be used to paint a colour gradient.
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.
The base class for all JUCE user-interface objects.
bool contains(Point< int > localPoint)
Returns true if a given point lies within this component or one of its children.
void removeComponentListener(ComponentListener *listenerToRemove)
Removes a component listener.
bool isVisible() const noexcept
Tests whether the component is visible or not.
Component * getParentComponent() const noexcept
Returns the component which this component is inside.
Point< int > getLocalPoint(const Component *sourceComponent, Point< int > pointRelativeToSourceComponent) const
Converts a point to be relative to this component's coordinate space.
void addComponentListener(ComponentListener *newListener)
Adds a listener to be told about changes to the component hierarchy or position.
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 setAlwaysOnTop(bool shouldStayOnTop)
Sets whether the component should always be kept at the front of its siblings.
void setOpaque(bool shouldBeOpaque)
Indicates whether any parts of the component might be transparent.
Rectangle< int > getBounds() const noexcept
Returns this component's bounding box.
void setBounds(int x, int y, int width, int height)
Changes the component's position and size.
void setColour(int colourID, Colour newColour)
Registers a colour to be used for a particular purpose.
Colour findColour(int colourID, bool inheritFromParent=false) const
Looks for a colour that has been registered with the given colour ID number.
Point< int > localPointToGlobal(Point< int > localPoint) const
Converts a point relative to this component's top-left into a screen coordinate.
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.
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 graphics context, used for drawing a component or image.
void setGradientFill(const ColourGradient &gradient)
Sets the context to use a gradient for its fill pattern.
void fillRect(Rectangle< int > rectangle) const
Fills a rectangle with the current colour or brush.
bool reduceClipRegion(int x, int y, int width, int height)
Intersects the current clipping region with another region.
void fillAll() const
Fills the context's entire clip region with the current colour or brush.
@ textColourId
The colour for the text.
Definition juce_Label.h:107
void setFont(const Font &newFont)
Changes the font to use to draw the text.
void setJustificationType(Justification justification)
Sets the style of justification to be used for positioning the text.
Contains position and status information about a mouse event.
Point< int > getPosition() const noexcept
The position of the mouse when the event occurred.
Point< int > getMouseDownPosition() const noexcept
Returns the coordinates of the last place that a mouse was pressed.
Component *const eventComponent
The component that this event applies to.
A pair of (x, y) coordinates.
Definition juce_Point.h:42
ValueType x
The point's X coordinate.
Definition juce_Point.h:251
ValueType getRight() const noexcept
Returns the x coordinate of the rectangle's right-hand-side.
ValueType getX() const noexcept
Returns the x coordinate of the rectangle's left-hand-side.
Point< ValueType > getTopLeft() const noexcept
Returns the rectangle's top-left position as a Point.
ValueType getWidth() const noexcept
Returns the width of the rectangle.
Point< ValueType > getTopRight() const noexcept
Returns the rectangle's top-right position as a Point.
Rectangle withTrimmedRight(ValueType amountToRemove) const noexcept
Returns a version of this rectangle with the given amount removed from its right-hand edge.
void setColours(Colour normalColour, Colour overColour, Colour downColour)
Set the colours to use for drawing the shape.
void setShape(const Path &newShape, bool resizeNowToFitThisShape, bool maintainShapeProportions, bool hasDropShadow)
Sets the shape to use.
void setTitleBarComponent(Component *titleBarComponentToUse, bool keepDismissButton, bool deleteComponentWhenNoLongerNeeded=true)
Sets a custom component to be used for the title bar of this SidePanel, replacing the default.
void showOrHide(bool show)
Shows or hides the SidePanel.
std::function< void()> onPanelMove
You can assign a lambda to this callback object and it will be called when the panel is moved.
void setContent(Component *newContentComponent, bool deleteComponentWhenNoLongerNeeded=true)
Sets the component that this SidePanel will contain.
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 parentHierarchyChanged() override
Called to indicate that the component's parents have changed.
void mouseUp(const MouseEvent &) override
Called when a mouse button is released.
void mouseDrag(const MouseEvent &) override
Called when the mouse is moved while a button is held down.
std::unique_ptr< AccessibilityHandler > createAccessibilityHandler() override
Override this method to return a custom AccessibilityHandler for this component.
~SidePanel() override
Destructor.
std::function< void(bool)> onPanelShowHide
You can assign a lambda to this callback object and it will be called when the panel is shown or hidd...
void moved() override
Called when this component's position has been changed.
SidePanel(StringRef title, int width, bool positionOnLeft, Component *contentComponent=nullptr, bool deleteComponentWhenNoLongerNeeded=true)
Creates a SidePanel component.
A simple class for holding temporary references to a string literal or String.
JUCE Namespace.
constexpr Type jmax(Type a, Type b)
Returns the larger of two values.
Type unalignedPointerCast(void *ptr) noexcept
Casts a pointer to another type via void*, which suppresses the cast-align warning which sometimes ar...
Definition juce_Memory.h:88