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
113 Ase::VirtualBase *ase_obj_ = nullptr;
114
115private:
116 //==============================================================================
117 juce::ListenerList<SelectableListener> selectableListeners;
118
119 friend struct SelectableUpdateTimer;
120 bool needsAnUpdate = false, hasNotifiedListenersOfDeletion = false, isCallingListeners = false;
121
122 void sendChangeCallbackToListenersIfNeeded();
123
125};
126
127
128//==============================================================================
134{
135 SelectableList() = default;
136
138 {
139 items.addArray (initialItems);
140 }
141
142 template<typename SelectableType>
143 SelectableList (const juce::Array<SelectableType*>& initialItems)
144 {
145 items.addArray (initialItems);
146 }
147
148 template<typename SelectableType>
150 {
151 items.addArray (initialItems);
152 }
153
154 template<typename SelectableType>
155 SelectableList (const std::vector<SelectableType*>& initialItems)
156 {
157 items.addArray (initialItems.data(), static_cast<int> (initialItems.size()));
158 }
159
160 //==============================================================================
162 SelectableClass* getSelectableClass (int index) const;
163
168
169 //==============================================================================
170 template <typename SubclassType>
171 juce::Array<SubclassType*> getItemsOfType() const
172 {
174
175 for (auto s : items)
176 if (auto i = dynamic_cast<SubclassType*> (s))
177 results.add (i);
178
179 return results;
180 }
181
182 template <typename SubclassType>
183 SubclassType* getFirstOfType() const
184 {
185 return dynamic_cast<SubclassType*> (items.getFirst());
186 }
187
188 template <typename SubclassType>
189 bool containsType() const
190 {
191 for (auto s : items)
192 if (dynamic_cast<SubclassType*> (s) != nullptr)
193 return true;
194
195 return false;
196 }
197
198 //==============================================================================
199 int size() const { return items.size(); }
200 bool isEmpty() const { return items.isEmpty(); }
201 bool isNotEmpty() const { return ! isEmpty(); }
202
203 inline Selectable** begin() { return items.begin(); }
204 inline Selectable* const* begin() const { return items.begin(); }
205 inline Selectable** end() { return items.end(); }
206 inline Selectable* const* end() const { return items.end(); }
207 inline Selectable** data() { return begin(); }
208 inline Selectable* const* data() const { return begin(); }
209
210 Selectable* operator[] (int index) const { return items[index]; }
211 inline Selectable* getUnchecked (int index) const { return items.getUnchecked (index); }
212 inline Selectable* getFirst() const { return items.getFirst(); }
213 inline Selectable* getLast() const { return items.getLast(); }
214
215 template <class OtherArrayType>
216 inline void addArray (const OtherArrayType& arrayToAddFrom, int startIndex = 0, int numElementsToAdd = -1)
217 {
218 classes.clearQuick();
219 items.addArray (arrayToAddFrom, startIndex, numElementsToAdd);
220 }
221
222 template <class OtherArrayType>
223 inline void mergeArray (const OtherArrayType& arrayToMergeFrom)
224 {
225 classes.clearQuick();
226
227 for (auto& s : arrayToMergeFrom)
228 addIfNotAlreadyThere (s);
229 }
230
231 inline void add (Selectable* newElement) { items.add (newElement); }
232 inline bool addIfNotAlreadyThere (Selectable* newElement) { return items.addIfNotAlreadyThere (newElement); }
233
234 inline void clear() { classes.clear(); items.clear(); }
235 inline void remove (int indexToRemove) { classes.clearQuick(); return items.remove (indexToRemove); }
236 inline int removeAllInstancesOf (Selectable* s) { classes.clearQuick(); return items.removeAllInstancesOf (s); }
237 inline Selectable* removeAndReturn (int indexToRemove) { classes.clearQuick(); return items.removeAndReturn (indexToRemove); }
238 inline bool contains (Selectable* elementToLookFor) const { return items.contains (elementToLookFor); }
239 inline int indexOf (Selectable* elementToLookFor) const { return items.indexOf (elementToLookFor); }
240
241 template <class OtherArrayType>
242 inline bool operator== (const OtherArrayType& other) const { return items == other; }
243
244 template <class OtherArrayType>
245 inline bool operator!= (const OtherArrayType& other) const { return items != other; }
246
247 inline bool operator== (const SelectableList& other) const { return items == other.items; }
248 inline bool operator!= (const SelectableList& other) const { return items != other.items; }
249
250 using ScopedLockType = juce::Array<Selectable*>::ScopedLockType;
251 inline const juce::DummyCriticalSection& getLock() const noexcept { return items.getLock(); }
252
253private:
255 mutable juce::Array<SelectableClass*> classes;
256};
257
258
259//==============================================================================
265template<typename SelectableType>
267{
268public:
270 SafeSelectable() = default;
271
273 SafeSelectable (SelectableType& selectable) : weakRef (&selectable) {}
274
276 SafeSelectable (SelectableType* selectable) : weakRef (selectable) {}
277
279 SafeSelectable (const SafeSelectable& other) noexcept : weakRef (other.weakRef) {}
280
282 SafeSelectable& operator= (const SafeSelectable& other) { weakRef = other.weakRef; return *this; }
283
285 SafeSelectable& operator= (SelectableType* newSelectable) { weakRef = newSelectable; return *this; }
286
288 SelectableType* get() const noexcept { return dynamic_cast<SelectableType*> (weakRef.get()); }
289
291 operator SelectableType*() const noexcept { return get(); }
292
294 SelectableType* operator->() const noexcept { return get(); }
295
296 bool operator== (SelectableType* other) const noexcept { return weakRef.get() == other; }
297 bool operator!= (SelectableType* other) const noexcept { return weakRef.get() != other; }
298
299 bool operator== (const SafeSelectable& other) const noexcept { return weakRef.get() == other.weakRef.get(); }
300 bool operator!= (const SafeSelectable& other) const noexcept { return weakRef.get() != other.weakRef.get(); }
301
302 bool operator== (const SelectableType& other) const noexcept { return weakRef.get() == &other; }
303 bool operator!= (const SelectableType& other) const noexcept { return weakRef.get() != &other; }
304
305 bool operator== (decltype(nullptr)) const noexcept { return weakRef == nullptr; }
306 bool operator!= (decltype(nullptr)) const noexcept { return weakRef != nullptr; }
307
308private:
310};
311
313template<typename SelectableType>
314SafeSelectable<SelectableType> makeSafeRef (SelectableType& selectable)
315{
316 return SafeSelectable<SelectableType> (selectable);
317}
318
320template<typename Iterable>
321auto makeSafeVector (const Iterable& selectables) -> std::vector<SafeSelectable<typename std::remove_reference<decltype(*selectables[0])>::type>>
322{
323 using SelectableType = typename std::remove_reference<decltype(*selectables[0])>::type;
326 v.reserve (static_cast<size_t> (selectables.size()));
327
328 for (auto* s : selectables)
329 v.emplace_back (*s);
330
331 return v;
332}
333
334//==============================================================================
335//==============================================================================
341{
342public:
345
348 {
349 reset();
350 }
351
354 {
355 reset (&s);
356 }
357
359 void reset (Selectable* s = nullptr)
360 {
361 if (ref)
362 ref->removeSelectableListener (this);
363
364 ref = s;
365
366 if (ref)
367 ref->addSelectableListener (this);
368 }
369
370 std::function<void()> onSelectableChanged; /*<< Assignable callback for change events. */
371 std::function<void()> onSelectableAboutToBeDeleted; /*<< Assignable callback for deletion events. */
372
373private:
375
376 void selectableObjectChanged (Selectable*) override
377 {
378 if (onSelectableChanged)
379 onSelectableChanged();
380 }
381
382 void selectableObjectAboutToBeDeleted (Selectable*) override
383 {
384 if (onSelectableAboutToBeDeleted)
385 onSelectableAboutToBeDeleted();
386 }
387};
388
389
390}} // 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.