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_ComponentBuilder.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
29namespace ComponentBuilderHelpers
30{
31 static String getStateId (const ValueTree& state)
32 {
33 return state [ComponentBuilder::idProperty].toString();
34 }
35
36 static Component* removeComponentWithID (OwnedArray<Component>& components, const String& compId)
37 {
38 jassert (compId.isNotEmpty());
39
40 for (int i = components.size(); --i >= 0;)
41 {
42 Component* const c = components.getUnchecked (i);
43
44 if (c->getComponentID() == compId)
45 return components.removeAndReturn (i);
46 }
47
48 return nullptr;
49 }
50
51 static Component* findComponentWithID (Component& c, const String& compId)
52 {
53 jassert (compId.isNotEmpty());
54 if (c.getComponentID() == compId)
55 return &c;
56
57 for (auto* child : c.getChildren())
58 if (auto* found = findComponentWithID (*child, compId))
59 return found;
60
61 return nullptr;
62 }
63
64 static Component* createNewComponent (ComponentBuilder::TypeHandler& type,
65 const ValueTree& state, Component* parent)
66 {
67 Component* const c = type.addNewComponentFromState (state, parent);
68 jassert (c != nullptr && c->getParentComponent() == parent);
69 c->setComponentID (getStateId (state));
70 return c;
71 }
72
73 static void updateComponent (ComponentBuilder& builder, const ValueTree& state)
74 {
75 if (Component* topLevelComp = builder.getManagedComponent())
76 {
77 ComponentBuilder::TypeHandler* const type = builder.getHandlerForState (state);
78 const String uid (getStateId (state));
79
80 if (type == nullptr || uid.isEmpty())
81 {
82 // ..handle the case where a child of the actual state node has changed.
83 if (state.getParent().isValid())
84 updateComponent (builder, state.getParent());
85 }
86 else
87 {
88 if (Component* const changedComp = findComponentWithID (*topLevelComp, uid))
89 type->updateComponentFromState (changedComp, state);
90 }
91 }
92 }
93}
94
95//==============================================================================
96const Identifier ComponentBuilder::idProperty ("id");
97
99 : imageProvider (nullptr)
100{
101}
102
104 : state (state_), imageProvider (nullptr)
105{
106 state.addListener (this);
107}
108
110{
111 state.removeListener (this);
112
113 #if JUCE_DEBUG
114 // Don't delete the managed component!! The builder owns that component, and will delete
115 // it automatically when it gets deleted.
116 jassert (componentRef.get() == component.get());
117 #endif
118}
119
121{
122 if (component == nullptr)
123 {
124 component.reset (createComponent());
125
126 #if JUCE_DEBUG
127 componentRef = component.get();
128 #endif
129 }
130
131 return component.get();
132}
133
135{
136 jassert (types.size() > 0); // You need to register all the necessary types before you can load a component!
137
138 if (TypeHandler* const type = getHandlerForState (state))
139 return ComponentBuilderHelpers::createNewComponent (*type, state, nullptr);
140
141 jassertfalse; // trying to create a component from an unknown type of ValueTree
142 return nullptr;
143}
144
146{
147 jassert (type != nullptr);
148
149 // Don't try to move your types around! Once a type has been added to a builder, the
150 // builder owns it, and you should leave it alone!
151 jassert (type->builder == nullptr);
152
153 types.add (type);
154 type->builder = this;
155}
156
158{
159 const Identifier targetType (s.getType());
160
161 for (int i = 0; i < types.size(); ++i)
162 {
163 TypeHandler* const t = types.getUnchecked (i);
164
165 if (t->type == targetType)
166 return t;
167 }
168
169 return nullptr;
170}
171
173{
174 return types.size();
175}
176
178{
179 return types [index];
180}
181
185
190
192{
193 return imageProvider;
194}
195
196void ComponentBuilder::valueTreePropertyChanged (ValueTree& tree, const Identifier&)
197{
198 ComponentBuilderHelpers::updateComponent (*this, tree);
199}
200
201void ComponentBuilder::valueTreeChildAdded (ValueTree& tree, ValueTree&)
202{
203 ComponentBuilderHelpers::updateComponent (*this, tree);
204}
205
206void ComponentBuilder::valueTreeChildRemoved (ValueTree& tree, ValueTree&, int)
207{
208 ComponentBuilderHelpers::updateComponent (*this, tree);
209}
210
211void ComponentBuilder::valueTreeChildOrderChanged (ValueTree& tree, int, int)
212{
213 ComponentBuilderHelpers::updateComponent (*this, tree);
214}
215
216void ComponentBuilder::valueTreeParentChanged (ValueTree& tree)
217{
218 ComponentBuilderHelpers::updateComponent (*this, tree);
219}
220
221//==============================================================================
226
230
232{
233 // A type handler needs to be registered with a ComponentBuilder before using it!
234 jassert (builder != nullptr);
235 return builder;
236}
237
239{
240 using namespace ComponentBuilderHelpers;
241
243
246
247 {
250
251 for (int i = 0; i < numExistingChildComps; ++i)
252 existingComponents.add (parent.getChildComponent (i));
253
254 auto newNumChildren = children.getNumChildren();
255
256 for (int i = 0; i < newNumChildren; ++i)
257 {
258 auto childState = children.getChild (i);
259 auto* c = removeComponentWithID (existingComponents, getStateId (childState));
260
261 if (c == nullptr)
262 {
263 if (auto* type = getHandlerForState (childState))
264 c = ComponentBuilderHelpers::createNewComponent (*type, childState, &parent);
265 else
267 }
268
269 if (c != nullptr)
270 componentsInOrder.add (c);
271 }
272
273 // (remaining unused items in existingComponents get deleted here as it goes out of scope)
274 }
275
276 // Make sure the z-order is correct..
277 if (componentsInOrder.size() > 0)
278 {
279 componentsInOrder.getLast()->toFront (false);
280
281 for (int i = componentsInOrder.size() - 1; --i >= 0;)
282 componentsInOrder.getUnchecked (i)->toBehind (componentsInOrder.getUnchecked (i + 1));
283 }
284}
285
286} // namespace juce
Holds a resizable array of primitive or copy-by-value objects.
Definition juce_Array.h:56
void ensureStorageAllocated(int minNumElements)
Increases the array's internal storage to hold a minimum number of elements.
This class is used when references to images need to be stored in ValueTrees.
The class is a base class for objects that manage the loading of a type of component from a ValueTree...
const Identifier type
Returns the type of the ValueTrees that this handler can parse.
ComponentBuilder * getBuilder() const noexcept
Returns the builder that this type is registered with.
TypeHandler(const Identifier &valueTreeType)
Creates a TypeHandler.
Loads and maintains a tree of Components from a ValueTree that represents them.
int getNumHandlers() const noexcept
Returns the number of registered type handlers.
ComponentBuilder()
Creates a builder that doesn't have a state object.
ValueTree state
This is the ValueTree data object that the builder is working with.
void registerStandardComponentTypes()
Registers handlers for various standard juce components.
ImageProvider * getImageProvider() const noexcept
Returns the current image provider that this builder is using, or nullptr if none has been set.
void updateChildComponents(Component &parent, const ValueTree &children)
Updates the children of a parent component by updating them from the children of a given ValueTree.
void setImageProvider(ImageProvider *newImageProvider) noexcept
Gives the builder an ImageProvider object that the type handlers can use when loading images from sto...
TypeHandler * getHandler(int index) const noexcept
Returns one of the registered type handlers.
static const Identifier idProperty
An identifier for the property of the ValueTrees that is used to store a unique ID for that component...
~ComponentBuilder() override
Destructor.
TypeHandler * getHandlerForState(const ValueTree &state) const
Tries to find a registered type handler that can load a component from the given ValueTree.
Component * createComponent()
Creates and returns a new instance of the component that the ValueTree represents.
Component * getManagedComponent()
Returns the builder's component (creating it if necessary).
void registerTypeHandler(TypeHandler *type)
Adds a type handler that the builder can use when trying to load components.
The base class for all JUCE user-interface objects.
int getNumChildComponents() const noexcept
Returns the number of child components that this component contains.
Component * getChildComponent(int index) const noexcept
Returns one of this component's child components, by it index.
Represents a string identifier, designed for accessing properties by name.
An array designed for holding objects.
void ensureStorageAllocated(int minNumElements) noexcept
Increases the array's internal storage to hold a minimum number of elements.
A powerful tree structure that can be used to hold free-form data, and which can handle its own undo ...
ValueTree getChild(int index) const
Returns one of this tree's sub-trees.
int getNumChildren() const noexcept
Returns the number of child trees inside this one.
void addListener(Listener *listener)
Adds a listener to receive callbacks when this tree is changed in some way.
Identifier getType() const noexcept
Returns the type of this tree.
void removeListener(Listener *listener)
Removes a listener that was previously added with addListener().
#define jassert(expression)
Platform-independent assertion macro.
#define jassertfalse
This will always cause an assertion failure.
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