tracktion-engine 3.0-10-g034fdde4aa5
Tracktion Engine — High level data model for audio applications

« « « Anklang Documentation
Loading...
Searching...
No Matches
tracktion_Selectable.h
Go to the documentation of this file.
1
2/*
3 ,--. ,--. ,--. ,--.
4 ,-' '-.,--.--.,--,--.,---.| |,-.,-' '-.`--' ,---. ,--,--, Copyright 2024
5 '-. .-'| .--' ,-. | .--'| /'-. .-',--.| .-. || \ Tracktion Software
6 | | | | \ '-' \ `--.| \ \ | | | |' '-' '| || | Corporation
7 `---' `--' `--`--'`---'`--'`--' `---' `--' `---' `--''--' www.tracktion.com
8
9 Tracktion Engine uses a GPL/commercial licence - see LICENCE.md for details.
10*/
11
12namespace tracktion { inline namespace engine
13{
14
15class SelectableClass;
16class Selectable;
17class SelectionManager;
18
19//==============================================================================
20#if 0 // -> ./trkn/tracktion_decls.hh
21class SelectableListener
22{
23public:
24 virtual ~SelectableListener() {}
25
26 virtual void selectableObjectChanged (Selectable*) = 0;
27 virtual void selectableObjectAboutToBeDeleted (Selectable*) = 0;
28};
29#endif // -> ./trkn/tracktion_decls.hh
30
31//==============================================================================
38{
39public:
40 //==============================================================================
41 Selectable();
42 virtual ~Selectable();
43
44 static void initialise();
45
46 //==============================================================================
49
53 virtual void selectionStatusChanged (bool isNowSelected);
54
55 //==============================================================================
59 virtual void changed();
60
65
66 //==============================================================================
68 {
69 public:
71 ~Listener() override;
72
73 void selectableObjectChanged (Selectable*) override {}
74 void selectableObjectAboutToBeDeleted (Selectable*) override {}
75
76 private:
78 };
79
80 //==============================================================================
81 void addListener (SelectableListener*);
82 void removeListener (SelectableListener*);
83
84 void addSelectableListener (SelectableListener*);
85 void removeSelectableListener (SelectableListener*);
86
93 static bool isSelectableValid (const Selectable*) noexcept;
94
97
98 // deselects this from all selectionmanagers
99 void deselect();
100
101 // Tells any SelectableManagers to rebuild their property panels if this object is selected
102 void propertiesChanged();
103
104 // MUST be called by all subclasses of Selectable in their destructor!
105 void notifyListenersOfDeletion();
106
107 //==============================================================================
108 // This is deprecated: use SafeSelectable<Selectable> instead
110 WeakRef::Master masterReference;
111 [[ deprecated ("Use makeSafeRef() and SafeSelectable instead") ]] WeakRef getWeakRef() { return { this }; }
112
113private:
114 //==============================================================================
115 juce::ListenerList<SelectableListener> selectableListeners;
116
117 friend struct SelectableUpdateTimer;
118 bool needsAnUpdate = false, hasNotifiedListenersOfDeletion = false, isCallingListeners = false;
119
120 void sendChangeCallbackToListenersIfNeeded();
121
123};
124
125
126//==============================================================================
132{
133 SelectableList() = default;
134
136 {
137 items.addArray (initialItems);
138 }
139
140 template<typename SelectableType>
141 SelectableList (const juce::Array<SelectableType*>& initialItems)
142 {
143 items.addArray (initialItems);
144 }
145
146 template<typename SelectableType>
148 {
149 items.addArray (initialItems);
150 }
151
152 template<typename SelectableType>
153 SelectableList (const std::vector<SelectableType*>& initialItems)
154 {
155 items.addArray (initialItems.data(), static_cast<int> (initialItems.size()));
156 }
157
158 //==============================================================================
160 SelectableClass* getSelectableClass (int index) const;
161
166
167 //==============================================================================
168 template <typename SubclassType>
169 juce::Array<SubclassType*> getItemsOfType() const
170 {
172
173 for (auto s : items)
174 if (auto i = dynamic_cast<SubclassType*> (s))
175 results.add (i);
176
177 return results;
178 }
179
180 template <typename SubclassType>
181 SubclassType* getFirstOfType() const
182 {
183 return dynamic_cast<SubclassType*> (items.getFirst());
184 }
185
186 template <typename SubclassType>
187 bool containsType() const
188 {
189 for (auto s : items)
190 if (dynamic_cast<SubclassType*> (s) != nullptr)
191 return true;
192
193 return false;
194 }
195
196 //==============================================================================
197 int size() const { return items.size(); }
198 bool isEmpty() const { return items.isEmpty(); }
199 bool isNotEmpty() const { return ! isEmpty(); }
200
201 inline Selectable** begin() { return items.begin(); }
202 inline Selectable* const* begin() const { return items.begin(); }
203 inline Selectable** end() { return items.end(); }
204 inline Selectable* const* end() const { return items.end(); }
205 inline Selectable** data() { return begin(); }
206 inline Selectable* const* data() const { return begin(); }
207
208 Selectable* operator[] (int index) const { return items[index]; }
209 inline Selectable* getUnchecked (int index) const { return items.getUnchecked (index); }
210 inline Selectable* getFirst() const { return items.getFirst(); }
211 inline Selectable* getLast() const { return items.getLast(); }
212
213 template <class OtherArrayType>
214 inline void addArray (const OtherArrayType& arrayToAddFrom, int startIndex = 0, int numElementsToAdd = -1)
215 {
216 classes.clearQuick();
217 items.addArray (arrayToAddFrom, startIndex, numElementsToAdd);
218 }
219
220 template <class OtherArrayType>
221 inline void mergeArray (const OtherArrayType& arrayToMergeFrom)
222 {
223 classes.clearQuick();
224
225 for (auto& s : arrayToMergeFrom)
226 addIfNotAlreadyThere (s);
227 }
228
229 inline void add (Selectable* newElement) { items.add (newElement); }
230 inline bool addIfNotAlreadyThere (Selectable* newElement) { return items.addIfNotAlreadyThere (newElement); }
231
232 inline void clear() { classes.clear(); items.clear(); }
233 inline void remove (int indexToRemove) { classes.clearQuick(); return items.remove (indexToRemove); }
234 inline int removeAllInstancesOf (Selectable* s) { classes.clearQuick(); return items.removeAllInstancesOf (s); }
235 inline Selectable* removeAndReturn (int indexToRemove) { classes.clearQuick(); return items.removeAndReturn (indexToRemove); }
236 inline bool contains (Selectable* elementToLookFor) const { return items.contains (elementToLookFor); }
237 inline int indexOf (Selectable* elementToLookFor) const { return items.indexOf (elementToLookFor); }
238
239 template <class OtherArrayType>
240 inline bool operator== (const OtherArrayType& other) const { return items == other; }
241
242 template <class OtherArrayType>
243 inline bool operator!= (const OtherArrayType& other) const { return items != other; }
244
245 inline bool operator== (const SelectableList& other) const { return items == other.items; }
246 inline bool operator!= (const SelectableList& other) const { return items != other.items; }
247
248 using ScopedLockType = juce::Array<Selectable*>::ScopedLockType;
249 inline const juce::DummyCriticalSection& getLock() const noexcept { return items.getLock(); }
250
251private:
253 mutable juce::Array<SelectableClass*> classes;
254};
255
256
257//==============================================================================
263template<typename SelectableType>
265{
266public:
268 SafeSelectable() = default;
269
271 SafeSelectable (SelectableType& selectable) : weakRef (&selectable) {}
272
274 SafeSelectable (SelectableType* selectable) : weakRef (selectable) {}
275
277 SafeSelectable (const SafeSelectable& other) noexcept : weakRef (other.weakRef) {}
278
280 SafeSelectable& operator= (const SafeSelectable& other) { weakRef = other.weakRef; return *this; }
281
283 SafeSelectable& operator= (SelectableType* newSelectable) { weakRef = newSelectable; return *this; }
284
286 SelectableType* get() const noexcept { return dynamic_cast<SelectableType*> (weakRef.get()); }
287
289 operator SelectableType*() const noexcept { return get(); }
290
292 SelectableType* operator->() const noexcept { return get(); }
293
294 bool operator== (SelectableType* other) const noexcept { return weakRef.get() == other; }
295 bool operator!= (SelectableType* other) const noexcept { return weakRef.get() != other; }
296
297 bool operator== (const SafeSelectable& other) const noexcept { return weakRef.get() == other.weakRef.get(); }
298 bool operator!= (const SafeSelectable& other) const noexcept { return weakRef.get() != other.weakRef.get(); }
299
300 bool operator== (const SelectableType& other) const noexcept { return weakRef.get() == &other; }
301 bool operator!= (const SelectableType& other) const noexcept { return weakRef.get() != &other; }
302
303 bool operator== (decltype(nullptr)) const noexcept { return weakRef == nullptr; }
304 bool operator!= (decltype(nullptr)) const noexcept { return weakRef != nullptr; }
305
306private:
308};
309
311template<typename SelectableType>
312SafeSelectable<SelectableType> makeSafeRef (SelectableType& selectable)
313{
314 return SafeSelectable<SelectableType> (selectable);
315}
316
318template<typename Iterable>
319auto makeSafeVector (const Iterable& selectables) -> std::vector<SafeSelectable<typename std::remove_reference<decltype(*selectables[0])>::type>>
320{
321 using SelectableType = typename std::remove_reference<decltype(*selectables[0])>::type;
324 v.reserve (static_cast<size_t> (selectables.size()));
325
326 for (auto* s : selectables)
327 v.emplace_back (*s);
328
329 return v;
330}
331
332//==============================================================================
333//==============================================================================
339{
340public:
343
346 {
347 reset();
348 }
349
352 {
353 reset (&s);
354 }
355
357 void reset (Selectable* s = nullptr)
358 {
359 if (ref)
360 ref->removeSelectableListener (this);
361
362 ref = s;
363
364 if (ref)
365 ref->addSelectableListener (this);
366 }
367
368 std::function<void()> onSelectableChanged; /*<< Assignable callback for change events. */
369 std::function<void()> onSelectableAboutToBeDeleted; /*<< Assignable callback for deletion events. */
370
371private:
373
374 void selectableObjectChanged (Selectable*) override
375 {
376 if (onSelectableChanged)
377 onSelectableChanged();
378 }
379
380 void selectableObjectAboutToBeDeleted (Selectable*) override
381 {
382 if (onSelectableAboutToBeDeleted)
383 onSelectableAboutToBeDeleted();
384 }
385};
386
387
388}} // namespace tracktion { inline namespace engine
typename TypeOfCriticalSectionToUse::ScopedLockType ScopedLockType
void add(const ElementType &newElement)
A SelectableListener that safely handles listener to a Selectable and uses a lambda for its callback.
LambdaSelectableListener()=default
Constructs an empty listener.
LambdaSelectableListener(Selectable &s)
Constructs a listener for a Selectable.
void reset(Selectable *s=nullptr)
Resets the Selectable.
Holds a pointer to some type of Selectable, which automatically becomes null if the selectable is del...
SafeSelectable & operator=(const SafeSelectable &other)
Copies another pointer to this one.
SelectableType * get() const noexcept
Returns the selectable that this pointer refers to, or null if the selectable no longer exists.
SafeSelectable(SelectableType *selectable)
Creates a SafeSelectable that points at the given selectable.
SafeSelectable()=default
Creates a null SafeSelectable.
SafeSelectable(const SafeSelectable &other) noexcept
Creates a copy of another SafeSelectable.
SelectableType * operator->() const noexcept
Returns the selectable that this pointer refers to, or null if the selectable no longer exists.
SafeSelectable(SelectableType &selectable)
Creates a SafeSelectable that points at the given selectable.
Represents a type of object that can be selected.
Base class for things that can be selected, and whose properties can appear in the properties panel.
virtual void changed()
This should be called to send a change notification to any SelectableListeners that are registered wi...
virtual void selectionStatusChanged(bool isNowSelected)
Can be overridden to tell this object that it has just been selected or deselected.
static bool isSelectableValid(const Selectable *) noexcept
checks whether this object has been deleted.
virtual void selectableAboutToBeDeleted()
Called just before the selectable is about to be deleted so any subclasses should still be valid at t...
void cancelAnyPendingUpdates()
If changed() has been called, this will cancel any pending async change notificaions.
virtual juce::String getSelectableDescription()=0
Subclasses must return a description of what they are.
T data(T... args)
T is_pointer_v
#define JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(className)
auto makeSafeVector(const Iterable &selectables) -> std::vector< SafeSelectable< typename std::remove_reference< decltype(*selectables[0])>::type > >
Creates a std::vector<SafeSelectable<Something>> for a given juce::Array of selectable objects.
SafeSelectable< SelectableType > makeSafeRef(SelectableType &selectable)
Creates a SafeSelectable for a given selectable object.
T size(T... args)
A list of Selectables, similar to a juce::Array but contains a cached list of the SelectableClasses f...
std::pair< Selectable *, SelectableClass * > getSelectableAndClass(int index) const
Returns the selectable and it's associated class.
SelectableClass * getSelectableClass(int index) const
Returns the selectable class for a given Selectable in the list.