1 /*
2   ==============================================================================
3 
4    This file is part of the JUCE library.
5    Copyright (c) 2020 - 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 6 End-User License
11    Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
12 
13    End User License Agreement: www.juce.com/juce-6-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 
26 namespace juce
27 {
28 
29 //==============================================================================
30 /**
31     A panel that holds a list of PropertyComponent objects.
32 
33     This panel displays a list of PropertyComponents, and allows them to be organised
34     into collapsible sections.
35 
36     To use, simply create one of these and add your properties to it with addProperties()
37     or addSection().
38 
39     @see PropertyComponent
40 
41     @tags{GUI}
42 */
43 class JUCE_API  PropertyPanel  : public Component
44 {
45 public:
46     //==============================================================================
47     /** Creates an empty property panel. */
48     PropertyPanel();
49 
50     /** Creates an empty property panel. */
51     PropertyPanel (const String& name);
52 
53     /** Destructor. */
54     ~PropertyPanel() override;
55 
56     //==============================================================================
57     /** Deletes all property components from the panel. */
58     void clear();
59 
60     /** Adds a set of properties to the panel.
61 
62         The components in the list will be owned by this object and will be automatically
63         deleted later on when no longer needed.
64 
65         These properties are added without them being inside a named section. If you
66         want them to be kept together in a collapsible section, use addSection() instead.
67     */
68     void addProperties (const Array<PropertyComponent*>& newPropertyComponents);
69 
70     /** Adds a set of properties to the panel.
71 
72         These properties are added under a section heading with a plus/minus button that
73         allows it to be opened and closed. If indexToInsertAt is < 0 then it will be added
74         at the end of the list, or before the given index if the index is non-zero.
75 
76         The components in the list will be owned by this object and will be automatically
77         deleted later on when no longer needed.
78 
79         To add properties without them being in a section, use addProperties().
80     */
81     void addSection (const String& sectionTitle,
82                      const Array<PropertyComponent*>& newPropertyComponents,
83                      bool shouldSectionInitiallyBeOpen = true,
84                      int indexToInsertAt = -1);
85 
86     /** Calls the refresh() method of all PropertyComponents in the panel */
87     void refreshAll() const;
88 
89     /** Returns true if the panel contains no properties. */
90     bool isEmpty() const;
91 
92     /** Returns the height that the panel needs in order to display all of its content
93         without scrolling.
94     */
95     int getTotalContentHeight() const;
96 
97     //==============================================================================
98     /** Returns a list of all the names of sections in the panel.
99         These are the sections that have been added with addSection().
100     */
101     StringArray getSectionNames() const;
102 
103     /** Returns true if the section at this index is currently open.
104         The index is from 0 up to the number of items returned by getSectionNames().
105     */
106     bool isSectionOpen (int sectionIndex) const;
107 
108     /** Opens or closes one of the sections.
109         The index is from 0 up to the number of items returned by getSectionNames().
110     */
111     void setSectionOpen (int sectionIndex, bool shouldBeOpen);
112 
113     /** Enables or disables one of the sections.
114         The index is from 0 up to the number of items returned by getSectionNames().
115     */
116     void setSectionEnabled (int sectionIndex, bool shouldBeEnabled);
117 
118     /** Remove one of the sections using the section index.
119         The index is from 0 up to the number of items returned by getSectionNames().
120     */
121     void removeSection (int sectionIndex);
122 
123     //==============================================================================
124     /** Saves the current state of open/closed sections so it can be restored later.
125         To restore this state, use restoreOpennessState().
126         @see restoreOpennessState
127     */
128     std::unique_ptr<XmlElement> getOpennessState() const;
129 
130     /** Restores a previously saved arrangement of open/closed sections.
131 
132         This will try to restore a snapshot of the panel's state that was created by
133         the getOpennessState() method. If any of the sections named in the original
134         XML aren't present, they will be ignored.
135 
136         @see getOpennessState
137     */
138     void restoreOpennessState (const XmlElement& newState);
139 
140     //==============================================================================
141     /** Sets a message to be displayed when there are no properties in the panel.
142         The default message is "nothing selected".
143     */
144     void setMessageWhenEmpty (const String& newMessage);
145 
146     /** Returns the message that is displayed when there are no properties.
147         @see setMessageWhenEmpty
148     */
149     const String& getMessageWhenEmpty() const noexcept;
150 
151     //==============================================================================
152     /** Returns the PropertyPanel's internal Viewport. */
getViewport()153     Viewport& getViewport() noexcept        { return viewport; }
154 
155     //==============================================================================
156     /** @internal */
157     void paint (Graphics&) override;
158     /** @internal */
159     void resized() override;
160 
161 private:
162     Viewport viewport;
163     struct SectionComponent;
164     struct PropertyHolderComponent;
165     PropertyHolderComponent* propertyHolderComponent;
166     String messageWhenEmpty;
167 
168     void init();
169     void updatePropHolderLayout() const;
170     void updatePropHolderLayout (int width) const;
171 
172     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PropertyPanel)
173 };
174 
175 } // namespace juce
176