LMMS
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{
31 SectionComponent (const String& sectionTitle,
32 const Array<PropertyComponent*>& newProperties,
33 bool sectionIsOpen,
34 int extraPadding)
35 : Component (sectionTitle),
36 isOpen (sectionIsOpen),
37 padding (extraPadding)
38 {
40
41 propertyComps.addArray (newProperties);
42
43 for (auto* propertyComponent : propertyComps)
44 {
45 addAndMakeVisible (propertyComponent);
46 propertyComponent->refresh();
47 }
48 }
49
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
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)
103 propertyComponent->setVisible (open);
104
105 if (auto* propertyPanel = findParentComponentOfClass<PropertyPanel>())
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
132 bool isOpen;
134
136};
137
138//==============================================================================
140{
142
143 void paint (Graphics&) override {}
144
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);
168 addAndMakeVisible (newSection, 0);
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
187};
188
189
190//==============================================================================
195
200
202{
203 messageWhenEmpty = TRANS("(nothing selected)");
204
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());
231}
232
233//==============================================================================
235{
236 if (! isEmpty())
237 {
238 propertyHolderComponent->sections.clear();
240 }
241}
242
244{
245 return propertyHolderComponent->sections.size() == 0;
246}
247
249{
250 return propertyHolderComponent->getHeight();
251}
252
254 int extraPaddingBetweenComponents)
255{
256 if (isEmpty())
257 repaint();
258
259 propertyHolderComponent->insertSection (-1, new SectionComponent ({}, newProperties, true, extraPaddingBetweenComponents));
261}
262
263void PropertyPanel::addSection (const String& sectionTitle,
264 const Array<PropertyComponent*>& newProperties,
265 bool shouldBeOpen,
266 int indexToInsertAt,
267 int extraPaddingBetweenComponents)
268{
269 jassert (sectionTitle.isNotEmpty());
270
271 if (isEmpty())
272 repaint();
273
274 propertyHolderComponent->insertSection (indexToInsertAt, new SectionComponent (sectionTitle,
275 newProperties,
276 shouldBeOpen,
277 extraPaddingBetweenComponents));
278
280}
281
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{
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
328void PropertyPanel::setSectionEnabled (int sectionIndex, bool shouldBeEnabled)
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);
340 }
341}
342
343//==============================================================================
344std::unique_ptr<XmlElement> PropertyPanel::getOpennessState() const
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
395
396} // namespace juce
#define noexcept
Definition DistrhoDefines.h:72
Definition juce_Array.h:56
void addAndMakeVisible(Component *child, int zOrder=-1)
Definition juce_Component.cpp:1554
void repaint()
Definition juce_Component.cpp:1917
Component() noexcept
Definition juce_Component.cpp:517
@ keyboardFocusContainer
Definition juce_Component.h:1307
void setSize(int newWidth, int newHeight)
Definition juce_Component.cpp:1262
TargetClass * findParentComponentOfClass() const
Definition juce_Component.h:813
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
String getName() const noexcept
Definition juce_Component.h:76
Definition juce_GraphicsContext.h:45
@ centred
Definition juce_Justification.h:138
Definition juce_MouseEvent.h:39
Definition juce_OwnedArray.h:51
void paint(Graphics &) override
Definition juce_PropertyPanel.cpp:216
StringArray getSectionNames() const
Definition juce_PropertyPanel.cpp:301
void setSectionEnabled(int sectionIndex, bool shouldBeEnabled)
Definition juce_PropertyPanel.cpp:328
bool isEmpty() const
Definition juce_PropertyPanel.cpp:243
std::unique_ptr< XmlElement > getOpennessState() const
Definition juce_PropertyPanel.cpp:344
int getTotalContentHeight() const
Definition juce_PropertyPanel.cpp:248
void updatePropHolderLayout() const
Definition juce_PropertyPanel.cpp:282
bool isSectionOpen(int sectionIndex) const
Definition juce_PropertyPanel.cpp:314
void setSectionOpen(int sectionIndex, bool shouldBeOpen)
Definition juce_PropertyPanel.cpp:322
Viewport viewport
Definition juce_PropertyPanel.h:164
void removeSection(int sectionIndex)
Definition juce_PropertyPanel.cpp:334
void resized() override
Definition juce_PropertyPanel.cpp:227
void addSection(const String &sectionTitle, const Array< PropertyComponent * > &newPropertyComponents, bool shouldSectionInitiallyBeOpen=true, int indexToInsertAt=-1, int extraPaddingBetweenComponents=0)
Definition juce_PropertyPanel.cpp:263
void init()
Definition juce_PropertyPanel.cpp:201
PropertyHolderComponent * propertyHolderComponent
Definition juce_PropertyPanel.h:167
PropertyPanel()
Definition juce_PropertyPanel.cpp:191
const String & getMessageWhenEmpty() const noexcept
Definition juce_PropertyPanel.cpp:391
~PropertyPanel() override
Definition juce_PropertyPanel.cpp:210
void setMessageWhenEmpty(const String &newMessage)
Definition juce_PropertyPanel.cpp:382
void clear()
Definition juce_PropertyPanel.cpp:234
String messageWhenEmpty
Definition juce_PropertyPanel.h:168
void refreshAll() const
Definition juce_PropertyPanel.cpp:295
void addProperties(const Array< PropertyComponent * > &newPropertyComponents, int extraPaddingBetweenComponents=0)
Definition juce_PropertyPanel.cpp:253
void restoreOpennessState(const XmlElement &newState)
Definition juce_PropertyPanel.cpp:364
Definition juce_StringArray.h:35
Definition juce_String.h:53
bool isNotEmpty() const noexcept
Definition juce_String.h:316
Definition juce_XmlElement.h:83
Iterator< GetNextElementWithTagName > getChildWithTagNameIterator(StringRef name) const
Definition juce_XmlElement.h:730
bool hasTagName(StringRef possibleTagName) const noexcept
Definition juce_XmlElement.cpp:470
int getIntAttribute(StringRef attributeName, int defaultReturnValue=0) const
Definition juce_XmlElement.cpp:571
* e
Definition inflate.c:1404
int y
Definition inflate.c:1588
int g
Definition inflate.c:1573
unsigned s
Definition inflate.c:1555
static const char * name
Definition pugl.h:1582
static int width
Definition pugl.h:1593
#define TRANS(stringLiteral)
Definition juce_LocalisedStrings.h:208
#define jassert(expression)
#define JUCE_DECLARE_NON_COPYABLE(className)
const Colour black
Definition juce_Colours.h:50
Definition carla_juce.cpp:31
Definition juce_PropertyPanel.cpp:140
void paint(Graphics &) override
Definition juce_PropertyPanel.cpp:143
void updateLayout(int width)
Definition juce_PropertyPanel.cpp:145
void refreshAll() const
Definition juce_PropertyPanel.cpp:159
SectionComponent * getSectionWithNonEmptyName(int targetIndex) const noexcept
Definition juce_PropertyPanel.cpp:171
void insertSection(int indexToInsertAt, SectionComponent *newSection)
Definition juce_PropertyPanel.cpp:165
OwnedArray< SectionComponent > sections
Definition juce_PropertyPanel.cpp:184
PropertyHolderComponent()
Definition juce_PropertyPanel.cpp:141
Definition juce_PropertyPanel.cpp:30
void resized() override
Definition juce_PropertyPanel.cpp:61
int titleHeight
Definition juce_PropertyPanel.cpp:131
void lookAndFeelChanged() override
Definition juce_PropertyPanel.cpp:72
bool isOpen
Definition juce_PropertyPanel.cpp:132
void refreshAll() const
Definition juce_PropertyPanel.cpp:110
void mouseDoubleClick(const MouseEvent &e) override
Definition juce_PropertyPanel.cpp:124
~SectionComponent() override
Definition juce_PropertyPanel.cpp:50
SectionComponent(const String &sectionTitle, const Array< PropertyComponent * > &newProperties, bool sectionIsOpen, int extraPadding)
Definition juce_PropertyPanel.cpp:31
OwnedArray< PropertyComponent > propertyComps
Definition juce_PropertyPanel.cpp:130
int getPreferredHeight() const
Definition juce_PropertyPanel.cpp:79
void setOpen(bool open)
Definition juce_PropertyPanel.cpp:96
void mouseUp(const MouseEvent &e) override
Definition juce_PropertyPanel.cpp:116
int padding
Definition juce_PropertyPanel.cpp:133
void paint(Graphics &g) override
Definition juce_PropertyPanel.cpp:55
ZCONST uch * init
Definition extract.c:2392
#define const
Definition zconf.h:137