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_RelativeCoordinatePositioner.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 MarkerListScope (Component& comp) : component (comp) {}
32
33 Expression getSymbolValue (const String& symbol) const override
34 {
35 auto type = RelativeCoordinate::StandardStrings::getTypeOf (symbol);
36
37 if (type == RelativeCoordinate::StandardStrings::width) return Expression ((double) component.getWidth());
38 if (type == RelativeCoordinate::StandardStrings::height) return Expression ((double) component.getHeight());
39
40 MarkerList* list;
41
42 if (auto* marker = findMarker (component, symbol, list))
43 return Expression (marker->position.getExpression().evaluate (*this));
44
46 }
47
48 void visitRelativeScope (const String& scopeName, Visitor& visitor) const override
49 {
51 {
52 if (auto* parent = component.getParentComponent())
53 {
54 visitor.visit (MarkerListScope (*parent));
55 return;
56 }
57 }
58
60 }
61
62 String getScopeUID() const override
63 {
64 return String::toHexString ((pointer_sized_int) (void*) &component) + "m";
65 }
66
67 static const MarkerList::Marker* findMarker (Component& component, const String& name, MarkerList*& list)
68 {
69 const MarkerList::Marker* marker = nullptr;
70
71 auto* mlh = dynamic_cast<MarkerList::MarkerListHolder*> (&component);
72
73 if (mlh != nullptr)
74 {
75 list = mlh->getMarkers (true);
76
77 if (list != nullptr)
78 marker = list->getMarker (name);
79 }
80
81 if (marker == nullptr)
82 {
83 if (mlh != nullptr)
84 {
85 list = mlh->getMarkers (false);
86
87 if (list != nullptr)
88 marker = list->getMarker (name);
89 }
90 }
91
92 return marker;
93 }
94
95 Component& component;
96};
97
98//==============================================================================
99RelativeCoordinatePositionerBase::ComponentScope::ComponentScope (Component& comp)
100 : component (comp)
101{
102}
103
105{
106 switch (RelativeCoordinate::StandardStrings::getTypeOf (symbol))
107 {
108 case RelativeCoordinate::StandardStrings::x:
109 case RelativeCoordinate::StandardStrings::left: return Expression ((double) component.getX());
110 case RelativeCoordinate::StandardStrings::y:
111 case RelativeCoordinate::StandardStrings::top: return Expression ((double) component.getY());
112 case RelativeCoordinate::StandardStrings::width: return Expression ((double) component.getWidth());
113 case RelativeCoordinate::StandardStrings::height: return Expression ((double) component.getHeight());
114 case RelativeCoordinate::StandardStrings::right: return Expression ((double) component.getRight());
115 case RelativeCoordinate::StandardStrings::bottom: return Expression ((double) component.getBottom());
116 case RelativeCoordinate::StandardStrings::parent:
117 case RelativeCoordinate::StandardStrings::unknown:
118 default: break;
119 }
120
121 if (Component* const parent = component.getParentComponent())
122 {
123 MarkerList* list;
124
125 if (auto* marker = MarkerListScope::findMarker (*parent, symbol, list))
126 {
127 MarkerListScope scope (*parent);
128 return Expression (marker->position.getExpression().evaluate (scope));
129 }
130 }
131
132 return Expression::Scope::getSymbolValue (symbol);
133}
134
136{
137 if (auto* targetComp = (scopeName == RelativeCoordinate::Strings::parent)
138 ? component.getParentComponent()
139 : findSiblingComponent (scopeName))
140 visitor.visit (ComponentScope (*targetComp));
141 else
143}
144
149
150Component* RelativeCoordinatePositionerBase::ComponentScope::findSiblingComponent (const String& componentID) const
151{
152 if (Component* const parent = component.getParentComponent())
153 return parent->findChildWithID (componentID);
154
155 return nullptr;
156}
157
158//==============================================================================
160{
161public:
163 : ComponentScope (comp), positioner (p), ok (result)
164 {
165 }
166
167 Expression getSymbolValue (const String& symbol) const override
168 {
169 switch (RelativeCoordinate::StandardStrings::getTypeOf (symbol))
170 {
171 case RelativeCoordinate::StandardStrings::x:
172 case RelativeCoordinate::StandardStrings::left:
173 case RelativeCoordinate::StandardStrings::y:
174 case RelativeCoordinate::StandardStrings::top:
175 case RelativeCoordinate::StandardStrings::width:
176 case RelativeCoordinate::StandardStrings::height:
177 case RelativeCoordinate::StandardStrings::right:
178 case RelativeCoordinate::StandardStrings::bottom:
179 positioner.registerComponentListener (component);
180 break;
181
182 case RelativeCoordinate::StandardStrings::parent:
183 case RelativeCoordinate::StandardStrings::unknown:
184 default:
185 if (auto* parent = component.getParentComponent())
186 {
187 MarkerList* list;
188
189 if (MarkerListScope::findMarker (*parent, symbol, list) != nullptr)
190 {
191 positioner.registerMarkerListListener (list);
192 }
193 else
194 {
195 // The marker we want doesn't exist, so watch all lists in case they change and the marker appears later..
196 if (auto* mlh = dynamic_cast<MarkerList::MarkerListHolder*> (parent))
197 {
198 positioner.registerMarkerListListener (mlh->getMarkers (true));
199 positioner.registerMarkerListListener (mlh->getMarkers (false));
200 }
201
202 ok = false;
203 }
204 }
205 break;
206 }
207
208 return ComponentScope::getSymbolValue (symbol);
209 }
210
211 void visitRelativeScope (const String& scopeName, Visitor& visitor) const override
212 {
213 if (Component* const targetComp = (scopeName == RelativeCoordinate::Strings::parent)
214 ? component.getParentComponent()
215 : findSiblingComponent (scopeName))
216 {
217 visitor.visit (DependencyFinderScope (*targetComp, positioner, ok));
218 }
219 else
220 {
221 // The named component doesn't exist, so we'll watch the parent for changes in case it appears later..
222 if (Component* const parent = component.getParentComponent())
223 positioner.registerComponentListener (*parent);
224
225 positioner.registerComponentListener (component);
226 ok = false;
227 }
228 }
229
230private:
232 bool& ok;
233};
234
235//==============================================================================
236RelativeCoordinatePositionerBase::RelativeCoordinatePositionerBase (Component& comp)
237 : Component::Positioner (comp), registeredOk (false)
238{
239}
240
241RelativeCoordinatePositionerBase::~RelativeCoordinatePositionerBase()
242{
243 unregisterListeners();
244}
245
246void RelativeCoordinatePositionerBase::componentMovedOrResized (Component&, bool /*wasMoved*/, bool /*wasResized*/)
247{
248 apply();
249}
250
255
257{
258 if (getComponent().getParentComponent() == &changed && ! registeredOk)
259 apply();
260}
261
263{
264 jassert (sourceComponents.contains (&comp));
265 sourceComponents.removeFirstMatchingValue (&comp);
266 registeredOk = false;
267}
268
273
275{
276 jassert (sourceMarkerLists.contains (markerList));
277 sourceMarkerLists.removeFirstMatchingValue (markerList);
278}
279
280void RelativeCoordinatePositionerBase::apply()
281{
282 if (! registeredOk)
283 {
284 unregisterListeners();
285 registeredOk = registerCoordinates();
286 }
287
288 applyToComponentBounds();
289}
290
291bool RelativeCoordinatePositionerBase::addCoordinate (const RelativeCoordinate& coord)
292{
293 bool ok = true;
294 DependencyFinderScope finderScope (getComponent(), *this, ok);
295 coord.getExpression().evaluate (finderScope);
296 return ok;
297}
298
299bool RelativeCoordinatePositionerBase::addPoint (const RelativePoint& point)
300{
301 const bool ok = addCoordinate (point.x);
302 return addCoordinate (point.y) && ok;
303}
304
305void RelativeCoordinatePositionerBase::registerComponentListener (Component& comp)
306{
307 if (! sourceComponents.contains (&comp))
308 {
309 comp.addComponentListener (this);
310 sourceComponents.add (&comp);
311 }
312}
313
314void RelativeCoordinatePositionerBase::registerMarkerListListener (MarkerList* const list)
315{
316 if (list != nullptr && ! sourceMarkerLists.contains (list))
317 {
318 list->addListener (this);
319 sourceMarkerLists.add (list);
320 }
321}
322
323void RelativeCoordinatePositionerBase::unregisterListeners()
324{
325 for (int i = sourceComponents.size(); --i >= 0;)
326 sourceComponents.getUnchecked (i)->removeComponentListener (this);
327
328 for (int i = sourceMarkerLists.size(); --i >= 0;)
329 sourceMarkerLists.getUnchecked (i)->removeListener (this);
330
331 sourceComponents.clear();
332 sourceMarkerLists.clear();
333}
334
335} // namespace juce
Positioner(Component &component) noexcept
Creates a Positioner which can control the specified component.
Component & getComponent() const noexcept
Returns the component that this positioner controls.
The base class for all JUCE user-interface objects.
Component * findChildWithID(StringRef componentID) const noexcept
Looks for a child component with the specified ID.
Component * getParentComponent() const noexcept
Returns the component which this component is inside.
int getBottom() const noexcept
Returns the y coordinate of the bottom edge of this component.
int getHeight() const noexcept
Returns the component's height in pixels.
int getX() const noexcept
Returns the x coordinate of the component's left edge.
int getY() const noexcept
Returns the y coordinate of the top of this component.
int getWidth() const noexcept
Returns the component's width in pixels.
int getRight() const noexcept
Returns the x coordinate of the component's right-hand edge.
Used as a callback by the Scope::visitRelativeScope() method.
When evaluating an Expression object, this class is used to resolve symbols and perform functions tha...
virtual Expression getSymbolValue(const String &symbol) const
Returns the value of a symbol.
virtual void visitRelativeScope(const String &scopeName, Visitor &visitor) const
Creates a Scope object for a named scope, and then calls a visitor to do some kind of processing with...
A class for dynamically evaluating simple numeric expressions.
double evaluate() const
Evaluates this expression, without using a Scope.
Represents a marker in a MarkerList.
RelativeCoordinate position
The marker's position.
Holds a set of named marker points along a one-dimensional axis.
Used for resolving a RelativeCoordinate expression in the context of a component.
String getScopeUID() const override
Returns some kind of globally unique ID that identifies this scope.
void visitRelativeScope(const String &scopeName, Visitor &) const override
Creates a Scope object for a named scope, and then calls a visitor to do some kind of processing with...
Expression getSymbolValue(const String &symbol) const override
Returns the value of a symbol.
Expression getSymbolValue(const String &symbol) const override
Returns the value of a symbol.
void visitRelativeScope(const String &scopeName, Visitor &visitor) const override
Creates a Scope object for a named scope, and then calls a visitor to do some kind of processing with...
Base class for Component::Positioners that are based upon relative coordinates.
void componentBeingDeleted(Component &) override
Called when the component is in the process of being deleted.
void componentChildrenChanged(Component &) override
Called when the component has children added or removed, or their z-order changes.
void markersChanged(MarkerList *) override
Called when something in the given marker list changes.
void componentParentHierarchyChanged(Component &) override
Called to indicate that the component's parents have changed.
void componentMovedOrResized(Component &, bool, bool) override
Called when the component's position or size changes.
void markerListBeingDeleted(MarkerList *) override
Called when the given marker list is being deleted.
const Expression & getExpression() const
Returns the expression that defines this coordinate.
The JUCE String class!
Definition juce_String.h:53
static String toHexString(IntegerType number)
Returns a string representing this numeric value in hexadecimal.
#define jassert(expression)
Platform-independent assertion macro.
JUCE Namespace.
int pointer_sized_int
A signed integer type that's guaranteed to be large enough to hold a pointer without truncating it.
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
Expression getSymbolValue(const String &symbol) const override
Returns the value of a symbol.
void visitRelativeScope(const String &scopeName, Visitor &visitor) const override
Creates a Scope object for a named scope, and then calls a visitor to do some kind of processing with...
String getScopeUID() const override
Returns some kind of globally unique ID that identifies this scope.
A base class for objects that want to provide a MarkerList.