FINAL CUT
fcallback.h
1 /***********************************************************************
2 * fcallback.h - Implements the callback functionality *
3 * *
4 * This file is part of the FINAL CUT widget toolkit *
5 * *
6 * Copyright 2020-2022 Markus Gans *
7 * *
8 * FINAL CUT is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU Lesser General Public License as *
10 * published by the Free Software Foundation; either version 3 of *
11 * the License, or (at your option) any later version. *
12 * *
13 * FINAL CUT is distributed in the hope that it will be useful, but *
14 * WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU Lesser General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU Lesser General Public *
19 * License along with this program. If not, see *
20 * <http://www.gnu.org/licenses/>. *
21 ***********************************************************************/
22 
23 /* Standalone class
24  * ════════════════
25  *
26  * ▕▔▔▔▔▔▔▔▔▔▔▔▏1 *▕▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▏
27  * ▕ FCallback ▏- - - -▕ FCallbackData ▏
28  * ▕▁▁▁▁▁▁▁▁▁▁▁▏ ▕▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▏
29  */
30 
31 #ifndef FCALLBACK_H
32 #define FCALLBACK_H
33 
34 #if !defined (USE_FINAL_H) && !defined (COMPILE_FINAL_CUT)
35  #error "Only <final/final.h> can be included directly."
36 #endif
37 
38 #include <utility>
39 #include <vector>
40 
41 #include "final/ftypes.h"
42 #include "final/util/fstring.h"
43 
44 namespace finalcut
45 {
46 
47 // class forward declaration
48 class FWidget;
49 
50 //----------------------------------------------------------------------
51 // struct FCallbackData
52 //----------------------------------------------------------------------
53 
55 {
56  // Constructor
57  FCallbackData() = default;
58 
59  template <typename FuncPtr>
60  FCallbackData (FString&& s, FWidget* i, FuncPtr m, FCall&& c)
61  : cb_signal(std::move(s))
62  , cb_instance(i)
63  , cb_function_ptr(m)
64  , cb_function(std::move(c))
65  { }
66 
67  FCallbackData (const FCallbackData&) = default;
68  FCallbackData (FCallbackData&&) noexcept = default;
69 
70  auto operator = (const FCallbackData&) -> FCallbackData& = default;
71  auto operator = (FCallbackData&&) noexcept -> FCallbackData& = default;
72 
73  // Data members
74  FString cb_signal{};
75  FWidget* cb_instance{};
76  void* cb_function_ptr{};
77  FCall cb_function{};
78 };
79 
80 
81 //----------------------------------------------------------------------
82 // class FCallback
83 //----------------------------------------------------------------------
84 
85 class FCallback
86 {
87  public:
88  // Using-declaration
89  template <typename T>
90  using enable_if_ObjectPointer_t =
91  std::enable_if_t< ! std::is_member_function_pointer<T>::value
92  && ! std::is_function<std::remove_pointer_t<T>>::value
93  && ! std::is_function<T>::value
94  && std::is_pointer<T>::value
95  && std::is_object<T>::value
96  && ! std::is_class<T>::value
97  , std::nullptr_t >;
98  template <typename T>
99  using enable_if_ClassObject_t =
100  std::enable_if_t< ! std::is_member_function_pointer<T>::value
101  && ! std::is_function<std::remove_pointer_t<T>>::value
102  && ! std::is_function<T>::value
103  && ! std::is_pointer<T>::value
104  && std::is_object<T>::value
105  && std::is_class<T>::value
106  , std::nullptr_t >;
107  template <typename T>
108  using enable_if_MemberFunctionPointer_t =
109  std::enable_if_t< std::is_member_function_pointer<T>::value
110  && ! std::is_function<std::remove_pointer_t<T>>::value
111  && ! std::is_function<T>::value
112  && ! std::is_pointer<T>::value
113  && std::is_object<T>::value
114  && ! std::is_class<T>::value
115  , std::nullptr_t >;
116  template <typename T>
117  using enable_if_FunctionPointer_t =
118  std::enable_if_t< ! std::is_member_function_pointer<T>::value
119  && std::is_function<std::remove_pointer_t<T>>::value
120  && ! std::is_function<T>::value
121  && std::is_pointer<T>::value
122  && std::is_object<T>::value
123  && ! std::is_class<T>::value
124  , std::nullptr_t >;
125  template <typename T>
126  using enable_if_FunctionReference_t =
127  std::enable_if_t< ! std::is_member_function_pointer<T>::value
128  && std::is_function<std::remove_pointer_t<T>>::value
129  && std::is_function<T>::value
130  && ! std::is_pointer<T>::value
131  && ! std::is_object<T>::value
132  && ! std::is_class<T>::value
133  , std::nullptr_t >;
134 
135  // Constructors
136  FCallback() = default;
137 
138  // Disable copy constructor
139  FCallback (const FCallback&) = delete;
140 
141  // Destructor
142  ~FCallback() noexcept = default;
143 
144  // Disable copy assignment operator (=)
145  auto operator = (const FCallback&) -> FCallback& = delete;
146 
147  // Accessors
148  auto getClassName() const -> FString;
149  auto getCallbackCount() const -> std::size_t;
150 
151  // Methods
152  template <typename Object
153  , typename Function
154  , enable_if_ObjectPointer_t<Object> = nullptr
155  , enable_if_MemberFunctionPointer_t<Function> = nullptr
156  , typename... Args>
157  void addCallback ( FString&& cb_signal
158  , Object&& cb_instance
159  , Function&& cb_member
160  , Args&&... args) noexcept;
161  template <typename Object
162  , typename Function
163  , enable_if_ObjectPointer_t<Object> = nullptr
164  , enable_if_ClassObject_t<Function> = nullptr
165  , typename... Args>
166  void addCallback ( FString&& cb_signal
167  , Object&& cb_instance
168  , Function&& cb_function
169  , Args&&... args) noexcept;
170  template < typename Function
171  , enable_if_ClassObject_t<Function> = nullptr
172  , typename... Args>
173  void addCallback ( FString&& cb_signal
174  , Function&& cb_function
175  , Args&&... args) noexcept;
176  template <typename Function
177  , enable_if_ClassObject_t<Function> = nullptr
178  , typename... Args>
179  void addCallback ( FString&& cb_signal
180  , Function& cb_function
181  , Args&&... args) noexcept;
182  template <typename Function
183  , enable_if_FunctionReference_t<Function> = nullptr
184  , typename... Args>
185  void addCallback ( FString&& cb_signal
186  , Function& cb_function
187  , Args&&... args) noexcept;
188  template <typename Function
189  , enable_if_FunctionPointer_t<Function> = nullptr
190  , typename... Args>
191  void addCallback ( FString&& cb_signal
192  , Function&& cb_function
193  , Args&&... args) noexcept;
194  template <typename Object
195  , enable_if_ObjectPointer_t<Object> = nullptr>
196  void delCallback (Object&& cb_instance) noexcept;
197  void delCallback (const FString& cb_signal);
198  template <typename Object
199  , enable_if_ObjectPointer_t<Object> = nullptr>
200  void delCallback ( const FString& cb_signal
201  , Object&& cb_instance ) noexcept;
202  template <typename FunctionPtr
203  , enable_if_FunctionPointer_t<FunctionPtr> = nullptr>
204  void delCallback (FunctionPtr&& cb_func_ptr) noexcept;
205  template <typename Function
206  , enable_if_FunctionReference_t<Function> = nullptr>
207  void delCallback (const Function& cb_function);
208  void delCallback();
209  void emitCallback (const FString& emit_signal) const;
210 
211  private:
212  // Using-declaration
213  using FCallbackObjects = std::vector<FCallbackData>;
214 
215  // Data members
216  FCallbackObjects callback_objects{};
217 };
218 
219 // FCallback inline functions
220 //----------------------------------------------------------------------
221 inline auto FCallback::getClassName() const -> FString
222 { return "FCallback"; }
223 
224 //----------------------------------------------------------------------
225 inline auto FCallback::getCallbackCount() const -> std::size_t
226 { return callback_objects.size(); }
227 
228 //----------------------------------------------------------------------
229 template <typename Object
230  , typename Function
231  , FCallback::enable_if_ObjectPointer_t<Object>
232  , FCallback::enable_if_MemberFunctionPointer_t<Function>
233  , typename... Args>
234 inline void FCallback::addCallback ( FString&& cb_signal
235  , Object&& cb_instance
236  , Function&& cb_member
237  , Args&&... args) noexcept
238 {
239  // Add a member function pointer as callback
240 
241  Object instance = cb_instance;
242  auto fn = std::bind ( std::forward<Function>(cb_member)
243  , std::forward<Object>(cb_instance)
244  , std::forward<Args>(args)... );
245  callback_objects.emplace_back (std::move(cb_signal), instance, nullptr, fn);
246 }
247 
248 //----------------------------------------------------------------------
249 template <typename Object
250  , typename Function
251  , FCallback::enable_if_ObjectPointer_t<Object>
252  , FCallback::enable_if_ClassObject_t<Function>
253  , typename... Args>
254 inline void FCallback::addCallback ( FString&& cb_signal
255  , Object&& cb_instance
256  , Function&& cb_function
257  , Args&&... args) noexcept
258 {
259  // Add a function object to an instance as callback
260 
261  auto fn = std::bind (std::forward<Function>(cb_function), std::forward<Args>(args)...);
262  callback_objects.emplace_back (std::move(cb_signal), cb_instance, nullptr, fn);
263 }
264 
265 //----------------------------------------------------------------------
266 template <typename Function
267  , FCallback::enable_if_ClassObject_t<Function>
268  , typename... Args>
269 inline void FCallback::addCallback ( FString&& cb_signal
270  , Function&& cb_function
271  , Args&&... args) noexcept
272 {
273  // Add a function object as callback
274 
275  auto fn = std::bind ( std::forward<Function>(cb_function)
276  , std::forward<Args>(args)... );
277  callback_objects.emplace_back (std::move(cb_signal), nullptr, nullptr, fn);
278 }
279 
280 //----------------------------------------------------------------------
281 template <typename Function
282  , FCallback::enable_if_ClassObject_t<Function>
283  , typename... Args>
284 inline void FCallback::addCallback ( FString&& cb_signal
285  , Function& cb_function
286  , Args&&... args) noexcept
287 {
288  // Add a function object reference as callback
289 
290  auto fn = std::bind (cb_function, std::forward<Args>(args)...);
291  callback_objects.emplace_back (std::move(cb_signal), nullptr, nullptr, fn);
292 }
293 
294 //----------------------------------------------------------------------
295 template <typename Function
296  , FCallback::enable_if_FunctionReference_t<Function>
297  , typename... Args>
298 inline void FCallback::addCallback ( FString&& cb_signal
299  , Function& cb_function
300  , Args&&... args) noexcept
301 {
302  // Add a function reference as callback
303 
304  auto ptr = reinterpret_cast<void*>(&cb_function);
305  auto fn = std::bind (cb_function, std::forward<Args>(args)...);
306  callback_objects.emplace_back (std::move(cb_signal), nullptr, ptr, fn);
307 }
308 
309 //----------------------------------------------------------------------
310 template <typename Function
311  , FCallback::enable_if_FunctionPointer_t<Function>
312  , typename... Args>
313 inline void FCallback::addCallback ( FString&& cb_signal
314  , Function&& cb_function
315  , Args&&... args) noexcept
316 {
317  // Add a function pointer as callback
318 
319  auto ptr = reinterpret_cast<void*>(cb_function);
320  auto fn = std::bind ( std::forward<Function>(cb_function)
321  , std::forward<Args>(args)... );
322  callback_objects.emplace_back(std::move(cb_signal), nullptr, ptr, fn);
323 }
324 
325 //----------------------------------------------------------------------
326 template <typename Object
327  , FCallback::enable_if_ObjectPointer_t<Object>>
328 inline void FCallback::delCallback (Object&& cb_instance) noexcept
329 {
330  // Deletes entries with the given instance from the callback list
331 
332  if ( callback_objects.empty() )
333  return;
334 
335  auto iter = callback_objects.cbegin();
336 
337  while ( iter != callback_objects.cend() )
338  {
339  if ( iter->cb_instance == cb_instance )
340  iter = callback_objects.erase(iter);
341  else
342  ++iter;
343  }
344 }
345 
346 //----------------------------------------------------------------------
347 template <typename Object
348  , FCallback::enable_if_ObjectPointer_t<Object>>
349 inline void FCallback::delCallback ( const FString& cb_signal
350  , Object&& cb_instance ) noexcept
351 {
352  // Deletes entries with the given signal and instance
353  // from the callback list
354 
355  if ( callback_objects.empty() )
356  return;
357 
358  auto iter = callback_objects.cbegin();
359 
360  while ( iter != callback_objects.cend() )
361  {
362  if ( iter->cb_signal == cb_signal
363  && iter->cb_instance == cb_instance )
364  iter = callback_objects.erase(iter);
365  else
366  ++iter;
367  }
368 }
369 
370 //----------------------------------------------------------------------
371 template <typename FunctionPtr
372  , FCallback::enable_if_FunctionPointer_t<FunctionPtr>>
373 inline void FCallback::delCallback (FunctionPtr&& cb_func_ptr) noexcept
374 {
375  // Deletes entries with the given function pointer
376  // from the callback list
377 
378  if ( callback_objects.empty() )
379  return;
380 
381  auto ptr = reinterpret_cast<void*>(cb_func_ptr);
382  auto iter = callback_objects.cbegin();
383 
384  while ( iter != callback_objects.cend() )
385  {
386  if ( iter->cb_function_ptr == ptr )
387  iter = callback_objects.erase(iter);
388  else
389  ++iter;
390  }
391 }
392 
393 //----------------------------------------------------------------------
394 template <typename Function
395  , FCallback::enable_if_FunctionReference_t<Function>>
396 inline void FCallback::delCallback (const Function& cb_function)
397 {
398  // Deletes entries with the given function reference
399  // from the callback list
400 
401  if ( callback_objects.empty() )
402  return;
403 
404  auto ptr = reinterpret_cast<void*>(&cb_function);
405  auto iter = callback_objects.cbegin();
406 
407  while ( iter != callback_objects.cend() )
408  {
409  if ( iter->cb_function_ptr == ptr )
410  iter = callback_objects.erase(iter);
411  else
412  ++iter;
413  }
414 }
415 
416 } // namespace finalcut
417 
418 #endif // FCALLBACK_H
Definition: fcallback.h:54
Definition: fcallback.h:85
Definition: class_template.cpp:25
Definition: fstring.h:79
Definition: fwidget.h:129