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_PropertyPanel.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{
33 bool sectionIsOpen,
34 int extraPadding)
36 isOpen (sectionIsOpen),
37 padding (extraPadding)
38 {
40
41 propertyComps.addArray (newProperties);
42
43 for (auto* propertyComponent : propertyComps)
44 {
46 propertyComponent->refresh();
47 }
48 }
49
50 ~SectionComponent() override
51 {
52 propertyComps.clear();
53 }
54
55 void paint (Graphics& g) override
56 {
57 if (titleHeight > 0)
58 getLookAndFeel().drawPropertyPanelSectionHeader (g, getName(), isOpen, getWidth(), titleHeight);
59 }
60
61 void resized() override
62 {
63 auto y = titleHeight;
64
65 for (auto* propertyComponent : propertyComps)
66 {
67 propertyComponent->setBounds (1, y, getWidth() - 2, propertyComponent->getPreferredHeight());
68 y = propertyComponent->getBottom() + padding;
69 }
70 }
71
72 void lookAndFeelChanged() override
73 {
74 titleHeight = getLookAndFeel().getPropertyPanelSectionHeaderHeight (getName());
75 resized();
76 repaint();
77 }
78
79 int getPreferredHeight() const
80 {
81 auto y = titleHeight;
82
83 auto numComponents = propertyComps.size();
84
85 if (numComponents > 0 && isOpen)
86 {
87 for (auto* propertyComponent : propertyComps)
88 y += propertyComponent->getPreferredHeight();
89
90 y += (numComponents - 1) * padding;
91 }
92
93 return y;
94 }
95
96 void setOpen (bool open)
97 {
98 if (isOpen != open)
99 {
100 isOpen = open;
101
102 for (auto* propertyComponent : propertyComps)
104
106 propertyPanel->resized();
107 }
108 }
109
110 void refreshAll() const
111 {
112 for (auto* propertyComponent : propertyComps)
113 propertyComponent->refresh();
114 }
115
116 void mouseUp (const MouseEvent& e) override
117 {
118 if (e.getMouseDownX() < titleHeight
119 && e.x < titleHeight
120 && e.getNumberOfClicks() != 2)
122 }
123
124 void mouseDoubleClick (const MouseEvent& e) override
125 {
126 if (e.y < titleHeight)
127 setOpen (! isOpen);
128 }
129
130 OwnedArray<PropertyComponent> propertyComps;
131 int titleHeight;
132 bool isOpen;
133 int padding;
134
136};
137
138//==============================================================================
140{
142
143 void paint (Graphics&) override {}
144
145 void updateLayout (int width)
146 {
147 auto y = 0;
148
149 for (auto* section : sections)
150 {
151 section->setBounds (0, y, width, section->getPreferredHeight());
152 y = section->getBottom();
153 }
154
155 setSize (width, y);
156 repaint();
157 }
158
159 void refreshAll() const
160 {
161 for (auto* section : sections)
162 section->refreshAll();
163 }
164
165 void insertSection (int indexToInsertAt, SectionComponent* newSection)
166 {
167 sections.insert (indexToInsertAt, newSection);
169 }
170
171 SectionComponent* getSectionWithNonEmptyName (int targetIndex) const noexcept
172 {
173 auto index = 0;
174 for (auto* section : sections)
175 {
176 if (section->getName().isNotEmpty())
177 if (index++ == targetIndex)
178 return section;
179 }
180
181 return nullptr;
182 }
183
185
186 JUCE_DECLARE_NON_COPYABLE (PropertyHolderComponent)
187};
188
189
190//==============================================================================
192{
193 init();
194}
195
197{
198 init();
199}
200
201void PropertyPanel::init()
202{
203 messageWhenEmpty = TRANS ("(nothing selected)");
204
205 addAndMakeVisible (viewport);
206 viewport.setViewedComponent (propertyHolderComponent = new PropertyHolderComponent());
208}
209
214
215//==============================================================================
217{
218 if (isEmpty())
219 {
220 g.setColour (Colours::black.withAlpha (0.5f));
221 g.setFont (14.0f);
222 g.drawText (messageWhenEmpty, getLocalBounds().withHeight (30),
224 }
225}
226
228{
229 viewport.setBounds (getLocalBounds());
230 updatePropHolderLayout();
231}
232
233//==============================================================================
235{
236 if (! isEmpty())
237 {
238 propertyHolderComponent->sections.clear();
239 updatePropHolderLayout();
240 }
241}
242
244{
245 return propertyHolderComponent->sections.size() == 0;
246}
247
249{
250 return propertyHolderComponent->getHeight();
251}
252
255{
256 if (isEmpty())
257 repaint();
258
259 propertyHolderComponent->insertSection (-1, new SectionComponent ({}, newProperties, true, extraPaddingBetweenComponents));
260 updatePropHolderLayout();
261}
262
265 bool shouldBeOpen,
266 int indexToInsertAt,
268{
269 jassert (sectionTitle.isNotEmpty());
270
271 if (isEmpty())
272 repaint();
273
274 propertyHolderComponent->insertSection (indexToInsertAt, new SectionComponent (sectionTitle,
278
279 updatePropHolderLayout();
280}
281
282void PropertyPanel::updatePropHolderLayout() const
283{
284 auto maxWidth = viewport.getMaximumVisibleWidth();
285 propertyHolderComponent->updateLayout (maxWidth);
286
287 auto newMaxWidth = viewport.getMaximumVisibleWidth();
288 if (maxWidth != newMaxWidth)
289 {
290 // need to do this twice because of scrollbars changing the size, etc.
291 propertyHolderComponent->updateLayout (newMaxWidth);
292 }
293}
294
296{
297 propertyHolderComponent->refreshAll();
298}
299
300//==============================================================================
302{
303 StringArray s;
304
305 for (auto* section : propertyHolderComponent->sections)
306 {
307 if (section->getName().isNotEmpty())
308 s.add (section->getName());
309 }
310
311 return s;
312}
313
314bool PropertyPanel::isSectionOpen (int sectionIndex) const
315{
316 if (auto* s = propertyHolderComponent->getSectionWithNonEmptyName (sectionIndex))
317 return s->isOpen;
318
319 return false;
320}
321
322void PropertyPanel::setSectionOpen (int sectionIndex, bool shouldBeOpen)
323{
324 if (auto* s = propertyHolderComponent->getSectionWithNonEmptyName (sectionIndex))
325 s->setOpen (shouldBeOpen);
326}
327
329{
330 if (auto* s = propertyHolderComponent->getSectionWithNonEmptyName (sectionIndex))
331 s->setEnabled (shouldBeEnabled);
332}
333
334void PropertyPanel::removeSection (int sectionIndex)
335{
336 if (auto* s = propertyHolderComponent->getSectionWithNonEmptyName (sectionIndex))
337 {
338 propertyHolderComponent->sections.removeObject (s);
339 updatePropHolderLayout();
340 }
341}
342
343//==============================================================================
345{
346 auto xml = std::make_unique<XmlElement> ("PROPERTYPANELSTATE");
347
348 xml->setAttribute ("scrollPos", viewport.getViewPositionY());
349
350 auto sections = getSectionNames();
351 for (auto s : sections)
352 {
353 if (s.isNotEmpty())
354 {
355 auto* e = xml->createNewChildElement ("SECTION");
356 e->setAttribute ("name", s);
357 e->setAttribute ("open", isSectionOpen (sections.indexOf (s)) ? 1 : 0);
358 }
359 }
360
361 return xml;
362}
363
365{
366 if (xml.hasTagName ("PROPERTYPANELSTATE"))
367 {
368 auto sections = getSectionNames();
369
370 for (auto* e : xml.getChildWithTagNameIterator ("SECTION"))
371 {
372 setSectionOpen (sections.indexOf (e->getStringAttribute ("name")),
373 e->getBoolAttribute ("open"));
374 }
375
376 viewport.setViewPosition (viewport.getViewPositionX(),
377 xml.getIntAttribute ("scrollPos", viewport.getViewPositionY()));
378 }
379}
380
381//==============================================================================
383{
384 if (messageWhenEmpty != newMessage)
385 {
386 messageWhenEmpty = newMessage;
387 repaint();
388 }
389}
390
392{
393 return messageWhenEmpty;
394}
395
396} // namespace juce
Holds a resizable array of primitive or copy-by-value objects.
Definition juce_Array.h:56
The base class for all JUCE user-interface objects.
void setFocusContainerType(FocusContainerType containerType) noexcept
Sets whether this component is a container for components that can have their focus traversed,...
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.
void repaint()
Marks the whole component as needing to be redrawn.
Component() noexcept
Creates a component.
@ keyboardFocusContainer
The component will act as a top-level component within which keyboard focus is passed around.
void setBounds(int x, int y, int width, int height)
Changes the component's position and size.
void setSize(int newWidth, int newHeight)
Changes the size of the 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.
virtual void setVisible(bool shouldBeVisible)
Makes the component visible or invisible.
String getName() const noexcept
Returns the name of this component.
A graphics context, used for drawing a component or image.
void drawText(const String &text, int x, int y, int width, int height, Justification justificationType, bool useEllipsesIfTooBig=true) const
Draws a line of text within a specified rectangle.
void setFont(const Font &newFont)
Changes the font to use for subsequent text-drawing functions.
void setColour(Colour newColour)
Changes the current drawing colour.
@ centred
Indicates that the item should be centred vertically and horizontally.
Contains position and status information about a mouse event.
int getMouseDownX() const noexcept
Returns the x coordinate of the last place that a mouse was pressed.
const int x
The x-position of the mouse when the event occurred.
const int y
The y-position of the mouse when the event occurred.
int getNumberOfClicks() const noexcept
For a click event, the number of times the mouse was clicked in succession.
An array designed for holding objects.
void paint(Graphics &) override
Components can override this method to draw their content.
StringArray getSectionNames() const
Returns a list of all the names of sections in the panel.
void setSectionEnabled(int sectionIndex, bool shouldBeEnabled)
Enables or disables one of the sections.
bool isEmpty() const
Returns true if the panel contains no properties.
std::unique_ptr< XmlElement > getOpennessState() const
Saves the current state of open/closed sections so it can be restored later.
int getTotalContentHeight() const
Returns the height that the panel needs in order to display all of its content without scrolling.
bool isSectionOpen(int sectionIndex) const
Returns true if the section at this index is currently open.
void setSectionOpen(int sectionIndex, bool shouldBeOpen)
Opens or closes one of the sections.
void removeSection(int sectionIndex)
Remove one of the sections using the section index.
void resized() override
Called when this component's size has been changed.
void addSection(const String &sectionTitle, const Array< PropertyComponent * > &newPropertyComponents, bool shouldSectionInitiallyBeOpen=true, int indexToInsertAt=-1, int extraPaddingBetweenComponents=0)
Adds a set of properties to the panel.
PropertyPanel()
Creates an empty property panel.
const String & getMessageWhenEmpty() const noexcept
Returns the message that is displayed when there are no properties.
~PropertyPanel() override
Destructor.
void setMessageWhenEmpty(const String &newMessage)
Sets a message to be displayed when there are no properties in the panel.
void clear()
Deletes all property components from the panel.
void refreshAll() const
Calls the refresh() method of all PropertyComponents in the panel.
void addProperties(const Array< PropertyComponent * > &newPropertyComponents, int extraPaddingBetweenComponents=0)
Adds a set of properties to the panel.
void restoreOpennessState(const XmlElement &newState)
Restores a previously saved arrangement of open/closed sections.
A special array for holding a list of strings.
void add(String stringToAdd)
Appends a string at the end of the array.
The JUCE String class!
Definition juce_String.h:53
int getViewPositionX() const noexcept
Returns the position within the child component of the top-left of its visible area.
void setViewPosition(int xPixelsOffset, int yPixelsOffset)
Changes the position of the viewed component.
int getViewPositionY() const noexcept
Returns the position within the child component of the top-left of its visible area.
int getMaximumVisibleWidth() const
Returns the width available within this component for the contents.
void setViewedComponent(Component *newViewedComponent, bool deleteComponentWhenNoLongerNeeded=true)
Sets the component that this viewport will contain and scroll around.
Used to build a tree of elements representing an XML document.
Iterator< GetNextElementWithTagName > getChildWithTagNameIterator(StringRef name) const
Allows iterating children of an XmlElement with a specific tag using range-for syntax.
bool hasTagName(StringRef possibleTagName) const noexcept
Tests whether this element has a particular tag name.
int getIntAttribute(StringRef attributeName, int defaultReturnValue=0) const
Returns the value of a named attribute as an integer.
#define TRANS(stringLiteral)
Uses the LocalisedStrings class to translate the given string literal.
#define jassert(expression)
Platform-independent assertion macro.
#define JUCE_DECLARE_NON_COPYABLE(className)
This is a shorthand macro for deleting a class's copy constructor and copy assignment operator.
JUCE Namespace.
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
open
void paint(Graphics &) override
Components can override this method to draw their content.
void resized() override
Called when this component's size has been changed.
void lookAndFeelChanged() override
Called to let the component react to a change in the look-and-feel setting.
void mouseDoubleClick(const MouseEvent &e) override
Called when a mouse button has been double-clicked on a component.
void mouseUp(const MouseEvent &e) override
Called when a mouse button is released.
void paint(Graphics &g) override
Components can override this method to draw their content.