OpenShot Audio Library | OpenShotAudio  0.3.2
juce_ListenerList.h
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2017 - ROLI Ltd.
6 
7  JUCE is an open source library subject to commercial or open-source
8  licensing.
9 
10  The code included in this file is provided under the terms of the ISC license
11  http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12  To use, copy, modify, and/or distribute this software for any purpose with or
13  without fee is hereby granted provided that the above copyright notice and
14  this permission notice appear in all copies.
15 
16  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18  DISCLAIMED.
19 
20  ==============================================================================
21 */
22 
23 namespace juce
24 {
25 
26 //==============================================================================
66 template <class ListenerClass,
67  class ArrayType = Array<ListenerClass*>>
69 {
70 public:
71  //==============================================================================
73  ListenerList() = default;
74 
76  ~ListenerList() = default;
77 
78  //==============================================================================
84  void add (ListenerClass* listenerToAdd)
85  {
86  if (listenerToAdd != nullptr)
87  listeners.addIfNotAlreadyThere (listenerToAdd);
88  else
89  jassertfalse; // Listeners can't be null pointers!
90  }
91 
95  void remove (ListenerClass* listenerToRemove)
96  {
97  jassert (listenerToRemove != nullptr); // Listeners can't be null pointers!
98  listeners.removeFirstMatchingValue (listenerToRemove);
99  }
100 
102  int size() const noexcept { return listeners.size(); }
103 
105  bool isEmpty() const noexcept { return listeners.isEmpty(); }
106 
108  void clear() { listeners.clear(); }
109 
111  bool contains (ListenerClass* listener) const noexcept { return listeners.contains (listener); }
112 
114  const ArrayType& getListeners() const noexcept { return listeners; }
115 
116  //==============================================================================
118  template <typename Callback>
119  void call (Callback&& callback)
120  {
121  typename ArrayType::ScopedLockType lock (listeners.getLock());
122 
123  for (Iterator<DummyBailOutChecker, ThisType> iter (*this); iter.next();)
124  callback (*iter.getListener());
125  }
126 
130  template <typename Callback>
131  void callExcluding (ListenerClass* listenerToExclude, Callback&& callback)
132  {
133  typename ArrayType::ScopedLockType lock (listeners.getLock());
134 
135  for (Iterator<DummyBailOutChecker, ThisType> iter (*this); iter.next();)
136  {
137  auto* l = iter.getListener();
138 
139  if (l != listenerToExclude)
140  callback (*l);
141  }
142  }
143 
147  template <typename Callback, typename BailOutCheckerType>
148  void callChecked (const BailOutCheckerType& bailOutChecker, Callback&& callback)
149  {
150  typename ArrayType::ScopedLockType lock (listeners.getLock());
151 
152  for (Iterator<BailOutCheckerType, ThisType> iter (*this); iter.next (bailOutChecker);)
153  callback (*iter.getListener());
154  }
155 
160  template <typename Callback, typename BailOutCheckerType>
161  void callCheckedExcluding (ListenerClass* listenerToExclude,
162  const BailOutCheckerType& bailOutChecker,
163  Callback&& callback)
164  {
165  typename ArrayType::ScopedLockType lock (listeners.getLock());
166 
167  for (Iterator<BailOutCheckerType, ThisType> iter (*this); iter.next (bailOutChecker);)
168  {
169  auto* l = iter.getListener();
170 
171  if (l != listenerToExclude)
172  callback (*l);
173  }
174  }
175 
176  //==============================================================================
181  {
182  bool shouldBailOut() const noexcept { return false; }
183  };
184 
186  using ListenerType = ListenerClass;
187 
188  //==============================================================================
190  template <class BailOutCheckerType, class ListType>
191  struct Iterator
192  {
193  Iterator (const ListType& listToIterate) noexcept
194  : list (listToIterate), index (listToIterate.size())
195  {}
196 
197  ~Iterator() = default;
198 
199  //==============================================================================
200  bool next() noexcept
201  {
202  if (index <= 0)
203  return false;
204 
205  auto listSize = list.size();
206 
207  if (--index < listSize)
208  return true;
209 
210  index = listSize - 1;
211  return index >= 0;
212  }
213 
214  bool next (const BailOutCheckerType& bailOutChecker) noexcept
215  {
216  return (! bailOutChecker.shouldBailOut()) && next();
217  }
218 
219  typename ListType::ListenerType* getListener() const noexcept
220  {
221  return list.getListeners().getUnchecked (index);
222  }
223 
224  //==============================================================================
225  private:
226  const ListType& list;
227  int index;
228 
229  JUCE_DECLARE_NON_COPYABLE (Iterator)
230  };
231 
232  //==============================================================================
233  #ifndef DOXYGEN
234  // There are now lambda-based call functions that can be used to replace these old method-based versions.
235  // We'll eventually deprecate these old ones, so please begin moving your code to use lambdas!
236  void call (void (ListenerClass::*callbackFunction) ())
237  {
238  call ([=] (ListenerClass& l) { (l.*callbackFunction)(); });
239  }
240 
241  void callExcluding (ListenerClass* listenerToExclude, void (ListenerClass::*callbackFunction) ())
242  {
243  callExcluding (listenerToExclude, [=] (ListenerClass& l) { (l.*callbackFunction)(); });
244  }
245 
246  template <class BailOutCheckerType>
247  void callChecked (const BailOutCheckerType& bailOutChecker, void (ListenerClass::*callbackFunction) ())
248  {
249  callChecked (bailOutChecker, [=] (ListenerClass& l) { (l.*callbackFunction)(); });
250  }
251 
252  template <class BailOutCheckerType>
253  void callCheckedExcluding (ListenerClass* listenerToExclude,
254  const BailOutCheckerType& bailOutChecker,
255  void (ListenerClass::*callbackFunction) ())
256  {
257  callCheckedExcluding (listenerToExclude, bailOutChecker, [=] (ListenerClass& l) { (l.*callbackFunction)(); });
258  }
259 
260  template <typename... MethodArgs, typename... Args>
261  void call (void (ListenerClass::*callbackFunction) (MethodArgs...), Args&&... args)
262  {
263  typename ArrayType::ScopedLockType lock (listeners.getLock());
264 
265  for (Iterator<DummyBailOutChecker, ThisType> iter (*this); iter.next();)
266  (iter.getListener()->*callbackFunction) (static_cast<typename TypeHelpers::ParameterType<Args>::type> (args)...);
267  }
268 
269  template <typename... MethodArgs, typename... Args>
270  void callExcluding (ListenerClass* listenerToExclude,
271  void (ListenerClass::*callbackFunction) (MethodArgs...),
272  Args&&... args)
273  {
274  typename ArrayType::ScopedLockType lock (listeners.getLock());
275 
276  for (Iterator<DummyBailOutChecker, ThisType> iter (*this); iter.next();)
277  if (iter.getListener() != listenerToExclude)
278  (iter.getListener()->*callbackFunction) (static_cast<typename TypeHelpers::ParameterType<Args>::type> (args)...);
279  }
280 
281  template <typename BailOutCheckerType, typename... MethodArgs, typename... Args>
282  void callChecked (const BailOutCheckerType& bailOutChecker,
283  void (ListenerClass::*callbackFunction) (MethodArgs...),
284  Args&&... args)
285  {
286  typename ArrayType::ScopedLockType lock (listeners.getLock());
287 
288  for (Iterator<BailOutCheckerType, ThisType> iter (*this); iter.next (bailOutChecker);)
289  (iter.getListener()->*callbackFunction) (static_cast<typename TypeHelpers::ParameterType<Args>::type> (args)...);
290  }
291 
292  template <typename BailOutCheckerType, typename... MethodArgs, typename... Args>
293  void callCheckedExcluding (ListenerClass* listenerToExclude,
294  const BailOutCheckerType& bailOutChecker,
295  void (ListenerClass::*callbackFunction) (MethodArgs...),
296  Args&&... args)
297  {
298  typename ArrayType::ScopedLockType lock (listeners.getLock());
299 
300  for (Iterator<BailOutCheckerType, ThisType> iter (*this); iter.next (bailOutChecker);)
301  if (iter.getListener() != listenerToExclude)
302  (iter.getListener()->*callbackFunction) (static_cast<typename TypeHelpers::ParameterType<Args>::type> (args)...);
303  }
304  #endif
305 
306 private:
307  //==============================================================================
308  ArrayType listeners;
309 
310  JUCE_DECLARE_NON_COPYABLE (ListenerList)
311 };
312 
313 } // namespace juce
~ListenerList()=default
void callChecked(const BailOutCheckerType &bailOutChecker, Callback &&callback)
const ArrayType & getListeners() const noexcept
bool isEmpty() const noexcept
void callCheckedExcluding(ListenerClass *listenerToExclude, const BailOutCheckerType &bailOutChecker, Callback &&callback)
void call(Callback &&callback)
void callExcluding(ListenerClass *listenerToExclude, Callback &&callback)
void add(ListenerClass *listenerToAdd)
void remove(ListenerClass *listenerToRemove)
bool contains(ListenerClass *listener) const noexcept
int size() const noexcept
ListenerList()=default