TGUI  0.9.1
Signal.hpp
1 //
3 // TGUI - Texus' Graphical User Interface
4 // Copyright (C) 2012-2021 Bruno Van de Velde (vdv_b@tgui.eu)
5 //
6 // This software is provided 'as-is', without any express or implied warranty.
7 // In no event will the authors be held liable for any damages arising from the use of this software.
8 //
9 // Permission is granted to anyone to use this software for any purpose,
10 // including commercial applications, and to alter it and redistribute it freely,
11 // subject to the following restrictions:
12 //
13 // 1. The origin of this software must not be misrepresented;
14 // you must not claim that you wrote the original software.
15 // If you use this software in a product, an acknowledgment
16 // in the product documentation would be appreciated but is not required.
17 //
18 // 2. Altered source versions must be plainly marked as such,
19 // and must not be misrepresented as being the original software.
20 //
21 // 3. This notice may not be removed or altered from any source distribution.
22 //
24 
25 
26 #ifndef TGUI_SIGNAL_HPP
27 #define TGUI_SIGNAL_HPP
28 
30 
31 #include <TGUI/Global.hpp>
32 #include <TGUI/String.hpp>
33 #include <TGUI/Color.hpp>
34 #include <TGUI/Vector2.hpp>
35 #include <TGUI/Animation.hpp>
36 #include <TGUI/Filesystem.hpp>
37 #include <type_traits>
38 #include <functional>
39 #include <typeindex>
40 #include <memory>
41 #include <vector>
42 #include <deque>
43 #include <map>
44 
45 #undef MessageBox // windows.h defines MessageBox when NOMB isn't defined before including windows.h
46 
48 
49 namespace tgui
50 {
51  class Widget;
52  class ChildWindow;
53 
57  class TGUI_API Signal
58  {
59  public:
60 
64  virtual ~Signal() = default;
65 
66 
73  Signal(String&& name, std::size_t extraParameters = 0) :
74  m_name{std::move(name)}
75  {
76  if (1 + extraParameters > m_parameters.size())
77  m_parameters.resize(1 + extraParameters);
78  }
79 
80 
84  Signal(const Signal& other);
85 
86 
90  Signal(Signal&& other) noexcept = default;
91 
92 
96  Signal& operator=(const Signal& other);
97 
98 
102  Signal& operator=(Signal&& other) noexcept = default;
103 
104 
113  template <typename Func, typename... BoundArgs>
114  unsigned int operator()(const Func& func, const BoundArgs&... args)
115  {
116  return connect(func, args...);
117  }
118 
119 
128  template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&...)>>::value>* = nullptr>
129  unsigned int connect(const Func& func, const BoundArgs&... args)
130  {
131  const auto id = ++m_lastSignalId;
132 #if defined(__cpp_if_constexpr) && (__cpp_if_constexpr >= 201606L)
133  if constexpr(sizeof...(BoundArgs) == 0)
134  m_handlers[id] = func;
135  else
136 #endif
137  {
138  m_handlers[id] = [=]{ invokeFunc(func, args...); };
139  }
140 
141  return id;
142  }
143 
144 
153  template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&..., std::shared_ptr<Widget>, const String&)>>::value>* = nullptr>
154  unsigned int connectEx(const Func& func, const BoundArgs&... args)
155  {
156  // The name is copied so that the lambda does not depend on the 'this' pointer
157  return connect([func, name=m_name, args...](){ invokeFunc(func, args..., getWidget(), name); });
158  }
159 
160 
168  bool disconnect(unsigned int id);
169 
170 
175 
176 
184  bool emit(const Widget* widget);
185 
186 
192  String getName() const
193  {
194  return m_name;
195  }
196 
197 
206  void setEnabled(bool enabled)
207  {
208  m_enabled = enabled;
209  }
210 
211 
220  bool isEnabled() const
221  {
222  return m_enabled;
223  }
224 
225 
227  protected:
228 
232  static std::shared_ptr<Widget> getWidget();
233 
234 
238  template <typename Type>
239  static const std::decay_t<Type>& dereferenceParam(std::size_t paramIndex)
240  {
241  return *static_cast<const std::decay_t<Type>*>(m_parameters[paramIndex]);
242  }
243 
244 
245 #if defined(__cpp_lib_invoke) && (__cpp_lib_invoke >= 201411L)
246  template <typename Func, typename... Args>
247  static void invokeFunc(Func&& func, Args&&... args)
248  {
249  std::invoke(std::forward<Func>(func), std::forward<Args>(args)...);
250  }
251 #else
252  // std::invoke only exists in c++17 so we use our own implementation to support c++14 compilers
253  template <typename Func, typename... Args, typename std::enable_if<std::is_member_pointer<typename std::decay<Func>::type>::value>::type* = nullptr>
254  static void invokeFunc(Func&& func, Args&&... args)
255  {
256  std::mem_fn(func)(std::forward<Args>(args)...);
257  }
258 
259  template <typename Func, typename... Args, typename std::enable_if<!std::is_member_pointer<typename std::decay<Func>::type>::value>::type* = nullptr>
260  static void invokeFunc(Func&& func, Args&&... args)
261  {
262  std::forward<Func>(func)(std::forward<Args>(args)...);
263  }
264 #endif
265 
266 
268  protected:
269 
270  bool m_enabled = true;
271  String m_name;
272  std::map<unsigned int, std::function<void()>> m_handlers;
273 
274  static unsigned int m_lastSignalId;
275  static std::deque<const void*> m_parameters;
276  };
277 
278 
285  template <typename T>
286  class SignalTyped : public Signal
287  {
288  public:
289 
293  SignalTyped(String&& name) :
294  Signal{std::move(name), 1}
295  {
296  }
297 
298 
307  template <typename Func, typename... BoundArgs>
308  unsigned int operator()(const Func& func, const BoundArgs&... args)
309  {
310  return connect(func, args...);
311  }
312 
313 
322  template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&...)>>::value>* = nullptr>
323  unsigned int connect(const Func& func, const BoundArgs&... args)
324  {
325  return Signal::connect(func, args...);
326  }
327 
328 
337  template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&..., T)>>::value>* = nullptr>
338  unsigned int connect(const Func& func, const BoundArgs&... args)
339  {
340  return Signal::connect([=]{ invokeFunc(func, args..., dereferenceParam<T>(1)); });
341  }
342 
343 
352  bool emit(const Widget* widget, T param)
353  {
354  if (m_handlers.empty())
355  return false;
356 
357  m_parameters[1] = static_cast<const void*>(&param);
358  return Signal::emit(widget);
359  }
360  };
361 
362 
369  template <typename T1, typename T2>
370  class SignalTyped2 : public Signal
371  {
372  public:
373 
378  Signal{std::move(name), 2}
379  {
380  }
381 
382 
391  template <typename Func, typename... BoundArgs>
392  unsigned int operator()(const Func& func, const BoundArgs&... args)
393  {
394  return connect(func, args...);
395  }
396 
397 
406  template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&...)>>::value>* = nullptr>
407  unsigned int connect(const Func& func, const BoundArgs&... args)
408  {
409  return Signal::connect(func, args...);
410  }
411 
412 
421  template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&..., T1, T2)>>::value>* = nullptr>
422  unsigned int connect(const Func& func, const BoundArgs&... args)
423  {
424  return Signal::connect([=]{ invokeFunc(func, args..., dereferenceParam<T1>(1), dereferenceParam<T2>(2)); });
425  }
426 
427 
437  bool emit(const Widget* widget, T1 param1, T2 param2)
438  {
439  if (m_handlers.empty())
440  return false;
441 
442  m_parameters[1] = static_cast<const void*>(&param1);
443  m_parameters[2] = static_cast<const void*>(&param2);
444  return Signal::emit(widget);
445  }
446  };
447 
458 
459 
466  class TGUI_API SignalChildWindow : public Signal
467  {
468  public:
469 
474  Signal{std::move(name), 1}
475  {
476  }
477 
478 
487  template <typename Func, typename... BoundArgs>
488  unsigned int operator()(const Func& func, const BoundArgs&... args)
489  {
490  return connect(func, args...);
491  }
492 
493 
502  template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&...)>>::value>* = nullptr>
503  unsigned int connect(const Func& func, const BoundArgs&... args)
504  {
505  return Signal::connect(func, args...);
506  }
507 
508 
517  template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&..., const std::shared_ptr<ChildWindow>&)>>::value>* = nullptr>
518  unsigned int connect(const Func& func, const BoundArgs&... args)
519  {
520  return Signal::connect([=]{ invokeFunc(func, args..., dereferenceChildWindow()); });
521  }
522 
523 
531  bool emit(ChildWindow* param);
532 
533 
535  private:
536 
540  static std::shared_ptr<ChildWindow> dereferenceChildWindow();
541 
542 
544  };
545 
546 
555  class TGUI_API SignalItem : public Signal
556  {
557  public:
558 
562  SignalItem(String&& name) :
563  Signal{std::move(name), 3}
564  {
565  }
566 
567 
576  template <typename Func, typename... BoundArgs>
577  unsigned int operator()(const Func& func, const BoundArgs&... args)
578  {
579  return connect(func, args...);
580  }
581 
582 
591  template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&...)>>::value>* = nullptr>
592  unsigned int connect(const Func& func, const BoundArgs&... args)
593  {
594  return Signal::connect(func, args...);
595  }
596 
597 
606  template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&..., int)>>::value>* = nullptr>
607  unsigned int connect(const Func& func, const BoundArgs&... args)
608  {
609  return Signal::connect([=]{ invokeFunc(func, args..., dereferenceParam<int>(1)); });
610  }
611 
612 
621  template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&..., const String&)>>::value>* = nullptr>
622  unsigned int connect(const Func& func, const BoundArgs&... args)
623  {
624  return Signal::connect([=]{ invokeFunc(func, args..., dereferenceParam<String>(2)); });
625  }
626 
627 
636  template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&..., const String&, const String&)>>::value>* = nullptr>
637  unsigned int connect(const Func& func, const BoundArgs&... args)
638  {
639  return Signal::connect([=]{ invokeFunc(func, args..., dereferenceParam<String>(2), dereferenceParam<String>(3)); });
640  }
641 
642 
653  bool emit(const Widget* widget, int index, const String& item, const String& id);
654 
655 
657  };
658 
659 
668  class TGUI_API SignalAnimation : public Signal
669  {
670  public:
671 
676  Signal{std::move(name), 2}
677  {
678  }
679 
680 
689  template <typename Func, typename... BoundArgs>
690  unsigned int operator()(const Func& func, const BoundArgs&... args)
691  {
692  return connect(func, args...);
693  }
694 
695 
704  template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&...)>>::value>* = nullptr>
705  unsigned int connect(const Func& func, const BoundArgs&... args)
706  {
707  return Signal::connect(func, args...);
708  }
709 
710 
719  template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&..., ShowAnimationType)>>::value>* = nullptr>
720  unsigned int connect(const Func& func, const BoundArgs&... args)
721  {
722  return Signal::connect([=]{ invokeFunc(func, args..., dereferenceParam<ShowAnimationType>(1)); });
723  }
724 
725 
734  template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&..., bool)>>::value>* = nullptr>
735  unsigned int connect(const Func& func, const BoundArgs&... args)
736  {
737  return Signal::connect([=]{ invokeFunc(func, args..., dereferenceParam<bool>(2)); });
738  }
739 
740 
749  template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&..., ShowAnimationType, bool)>>::value>* = nullptr>
750  unsigned int connect(const Func& func, const BoundArgs&... args)
751  {
752  return Signal::connect([=]{ invokeFunc(func, args..., dereferenceParam<ShowAnimationType>(1), dereferenceParam<bool>(2)); });
753  }
754 
755 
765  bool emit(const Widget* widget, ShowAnimationType type, bool visible);
766 
767 
769  };
770 
771 
779  class TGUI_API SignalItemHierarchy : public Signal
780  {
781  public:
782 
787  Signal{std::move(name), 2}
788  {
789  }
790 
791 
800  template <typename Func, typename... BoundArgs>
801  unsigned int operator()(const Func& func, const BoundArgs&... args)
802  {
803  return connect(func, args...);
804  }
805 
806 
815  template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&...)>>::value>* = nullptr>
816  unsigned int connect(const Func& func, const BoundArgs&... args)
817  {
818  return Signal::connect(func, args...);
819  }
820 
821 
830  template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&..., const String&)>>::value>* = nullptr>
831  unsigned int connect(const Func& func, const BoundArgs&... args)
832  {
833  return Signal::connect([=]{ invokeFunc(func, args..., dereferenceParam<String>(1)); });
834  }
835 
836 
845  template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&..., const std::vector<String>&)>>::value>* = nullptr>
846  unsigned int connect(const Func& func, const BoundArgs&... args)
847  {
848  return Signal::connect([=]{ invokeFunc(func, args..., dereferenceParam<std::vector<String>>(2)); });
849  }
850 
851 
861  bool emit(const Widget* widget, const String& item, const std::vector<String>& fullItem);
862 
863 
865  };
866 
868 }
869 
871 
872 #endif // TGUI_SIGNAL_HPP
Child window widget.
Definition: ChildWindow.hpp:44
Signal to which the user can subscribe to get callbacks from.
Definition: Signal.hpp:669
SignalAnimation(String &&name)
Constructor.
Definition: Signal.hpp:675
unsigned int operator()(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:690
unsigned int connect(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:705
bool emit(const Widget *widget, ShowAnimationType type, bool visible)
Call all connected signal handlers.
Signal to which the user can subscribe to get callbacks from.
Definition: Signal.hpp:467
SignalChildWindow(String &&name)
Constructor.
Definition: Signal.hpp:473
bool emit(ChildWindow *param)
Call all connected signal handlers.
unsigned int connect(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:518
unsigned int operator()(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:488
unsigned int connect(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:503
Signal to which the user can subscribe to get callbacks from.
Definition: Signal.hpp:780
unsigned int connect(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:846
unsigned int connect(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:816
SignalItemHierarchy(String &&name)
Constructor.
Definition: Signal.hpp:786
bool emit(const Widget *widget, const String &item, const std::vector< String > &fullItem)
Call all connected signal handlers.
unsigned int operator()(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:801
Signal to which the user can subscribe to get callbacks from.
Definition: Signal.hpp:556
bool emit(const Widget *widget, int index, const String &item, const String &id)
Call all connected signal handlers.
unsigned int operator()(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:577
SignalItem(String &&name)
Constructor.
Definition: Signal.hpp:562
unsigned int connect(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:592
Signal to which the user can subscribe to get callbacks from.
Definition: Signal.hpp:371
bool emit(const Widget *widget, T1 param1, T2 param2)
Call all connected signal handlers.
Definition: Signal.hpp:437
unsigned int connect(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:407
SignalTyped2(String &&name)
Constructor.
Definition: Signal.hpp:377
unsigned int operator()(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:392
Signal to which the user can subscribe to get callbacks from.
Definition: Signal.hpp:287
SignalTyped(String &&name)
Constructor.
Definition: Signal.hpp:293
unsigned int operator()(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:308
bool emit(const Widget *widget, T param)
Call all connected signal handlers.
Definition: Signal.hpp:352
unsigned int connect(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:323
Signal to which the user can subscribe to get callbacks from.
Definition: Signal.hpp:58
bool emit(const Widget *widget)
Call all connected signal handlers.
Signal & operator=(const Signal &other)
Copy assignment operator which will not copy the signal handlers.
Signal & operator=(Signal &&other) noexcept=default
Default move assignment operator.
Signal(const Signal &other)
Copy constructor which will not copy the signal handlers.
static std::shared_ptr< Widget > getWidget()
Extracts the widget stored in the first parameter.
unsigned int operator()(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:114
bool isEnabled() const
Returns whether this signal calls the connected functions when triggered.
Definition: Signal.hpp:220
void disconnectAll()
Disconnect all signal handler from this signal.
void setEnabled(bool enabled)
Changes whether this signal calls the connected functions when triggered.
Definition: Signal.hpp:206
bool disconnect(unsigned int id)
Disconnect a signal handler from this signal.
String getName() const
Returns the name given to the signal.
Definition: Signal.hpp:192
unsigned int connect(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:129
virtual ~Signal()=default
Default destructor.
Signal(String &&name, std::size_t extraParameters=0)
Constructor.
Definition: Signal.hpp:73
static const std::decay_t< Type > & dereferenceParam(std::size_t paramIndex)
Turns the void* parameters back into its original type right before calling the callback function.
Definition: Signal.hpp:239
Signal(Signal &&other) noexcept=default
Default move constructor.
unsigned int connectEx(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:154
Wrapper class to store strings.
Definition: String.hpp:74
The parent class for every widget.
Definition: Widget.hpp:70
Namespace that contains all TGUI functions and classes.
Definition: AbsoluteOrRelativeValue.hpp:36
ShowAnimationType
Type of animation to show/hide widget.
Definition: Animation.hpp:44