TGUI  0.8-dev
Signal.hpp
1 //
3 // TGUI - Texus' Graphical User Interface
4 // Copyright (C) 2012-2017 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 <SFML/System/String.hpp>
33 #include <SFML/System/Vector2.hpp>
34 #include <functional>
35 #include <typeindex>
36 #include <cstddef>
37 #include <memory>
38 #include <vector>
39 #include <deque>
40 #include <map>
41 
43 
44 namespace tgui
45 {
46  class Widget;
47  class ChildWindow;
48  class SignalWidgetBase;
49 
50  namespace internal_signal
51  {
52  extern TGUI_API std::deque<const void*> parameters;
53  }
54 
55 
59  class TGUI_API Signal
60  {
61  public:
62 
63  using Delegate = std::function<void()>;
64  using DelegateEx = std::function<void(std::shared_ptr<Widget>, const std::string&)>;
65 
66 
67  virtual ~Signal() = default;
68 
69 
76  Signal(std::string&& name, std::size_t extraParameters = 0) :
77  m_name{std::move(name)}
78  {
79  if (1 + extraParameters > internal_signal::parameters.size())
80  internal_signal::parameters.resize(1 + extraParameters);
81  }
82 
83 
87  Signal(const Signal& other);
88 
89 
93  Signal(Signal&& other) = default;
94 
95 
99  Signal& operator=(const Signal& other);
100 
101 
105  Signal& operator=(Signal&& other) = default;
106 
107 
115  unsigned int connect(const Delegate& handler);
116 
117 
125  unsigned int connect(const DelegateEx& handler);
126 
127 
135  bool disconnect(unsigned int id);
136 
137 
141  void disconnectAll();
142 
143 
151  bool emit(const Widget* widget)
152  {
153  if (m_handlers.empty())
154  return false;
155 
156  internal_signal::parameters[0] = static_cast<const void*>(&widget);
157 
158  for (auto& handler : m_handlers)
159  handler.second();
160 
161  return true;
162  }
163 
164 
170  std::string getName() const
171  {
172  return m_name;
173  }
174 
175 
181  virtual unsigned int validateTypes(std::initializer_list<std::type_index> unboundParameters);
182 
183 
185  protected:
186 
191  static std::shared_ptr<Widget> getWidget();
192 
193 
195  protected:
196 
197  std::string m_name;
198  std::map<unsigned int, std::function<void()>> m_handlers;
199  };
200 
201 
202  #define TGUI_SIGNAL_VALUE_DECLARATION(TypeName, Type) \
203  /**************************************************************************************************************************** \
204  * @brief Signal to which the user can subscribe to get callbacks from
205  ****************************************************************************************************************************/ \
206  class TGUI_API Signal##TypeName : public Signal \
207  { \
208  public: \
209  using Delegate##TypeName = std::function<void(Type)>; \
210  using Delegate##TypeName##Ex = std::function<void(std::shared_ptr<Widget>, const std::string&, Type)>; \
211  using Signal::connect; \
212  \
213  /************************************************************************************************************************ \
214  * @brief Constructor
215  ************************************************************************************************************************/ \
216  Signal##TypeName(std::string&& name) : \
217  Signal{std::move(name), 1} \
218  { \
219  } \
220  \
221  /************************************************************************************************************************ \
222  * @brief Connects a signal handler that will be called when this signal is emitted
223  *
224  * @param handler Callback function that is given a Vector2f as argument
225  *
226  * @return Unique id of the connection
227  ************************************************************************************************************************/ \
228  unsigned int connect(const Delegate##TypeName& handler); \
229  \
230  /************************************************************************************************************************ \
231  * @brief Connects a signal handler that will be called when this signal is emitted
232  *
233  * @param handler Callback function that is given a pointer to the widget, the name of the signal and a Vector2f as arguments
234  *
235  * @return Unique id of the connection
236  ************************************************************************************************************************/ \
237  unsigned int connect(const Delegate##TypeName##Ex& handler); \
238  \
239  /************************************************************************************************************************ \
240  * @internal
241  * @brief Call all connected signal handlers
242  ************************************************************************************************************************/ \
243  bool emit(const Widget* widget, Type strParam) \
244  { \
245  if (m_handlers.empty()) \
246  return false; \
247  \
248  internal_signal::parameters[1] = static_cast<const void*>(&strParam); \
249  return Signal::emit(widget); \
250  } \
251  \
252  /************************************************************************************************************************ \
253  * @internal
254  * @brief Checks whether the unbound parameters match with this signal
255  * @return The index in the parameters list where the parameters will be stored
256  ************************************************************************************************************************/ \
257  unsigned int validateTypes(std::initializer_list<std::type_index> unboundParameters) override; \
258  };
259 
260 
261  TGUI_SIGNAL_VALUE_DECLARATION(Int, int)
262  TGUI_SIGNAL_VALUE_DECLARATION(UInt, unsigned int)
263  TGUI_SIGNAL_VALUE_DECLARATION(Bool, bool)
264  TGUI_SIGNAL_VALUE_DECLARATION(Float, float)
265  TGUI_SIGNAL_VALUE_DECLARATION(String, const sf::String&)
266  TGUI_SIGNAL_VALUE_DECLARATION(Vector2f, sf::Vector2f)
267 
268 
269 
270  class TGUI_API SignalRange : public Signal
273  {
274  public:
275 
276  using DelegateRange = std::function<void(int, int)>;
277  using DelegateRangeEx = std::function<void(std::shared_ptr<Widget>, const std::string&, int, int)>;
278 
279  using Signal::connect;
280 
281 
285  SignalRange(std::string&& name) :
286  Signal{std::move(name), 2}
287  {
288  }
289 
290 
298  unsigned int connect(const DelegateRange& handler);
299 
300 
308  unsigned int connect(const DelegateRangeEx& handler);
309 
310 
315  bool emit(const Widget* widget, int value1, int value2);
316 
317 
323  unsigned int validateTypes(std::initializer_list<std::type_index> unboundParameters) override;
324 
325 
327  };
328 
329 
333  class TGUI_API SignalChildWindow : public Signal
334  {
335  public:
336 
337  using DelegateChildWindow = std::function<void(std::shared_ptr<ChildWindow>)>;
338  using DelegateChildWindowEx = std::function<void(std::shared_ptr<Widget>, const std::string&, std::shared_ptr<ChildWindow>)>;
339 
340  using Signal::connect;
341 
342 
346  SignalChildWindow(std::string&& name) :
347  Signal{std::move(name), 1}
348  {
349  }
350 
351 
359  unsigned int connect(const DelegateChildWindow& handler);
360 
361 
369  unsigned int connect(const DelegateChildWindowEx& handler);
370 
371 
376  bool emit(const ChildWindow* param);
377 
378 
384  unsigned int validateTypes(std::initializer_list<std::type_index> unboundParameters) override;
385 
386 
388  };
389 
390 
394  class TGUI_API SignalItem : public Signal
395  {
396  public:
397 
398  using DelegateItem = std::function<void(const sf::String&)>;
399  using DelegateItemAndId = std::function<void(const sf::String&, const sf::String&)>;
400  using DelegateItemEx = std::function<void(std::shared_ptr<Widget>, const std::string&, const sf::String&)>;
401  using DelegateItemAndIdEx = std::function<void(std::shared_ptr<Widget>, const std::string&, const sf::String&, const sf::String&)>;
402 
403  using Signal::connect;
404 
405 
409  SignalItem(std::string&& name) :
410  Signal{std::move(name), 2}
411  {
412  }
413 
414 
422  unsigned int connect(const DelegateItem& handler);
423 
424 
432  unsigned int connect(const DelegateItemEx& handler);
433 
434 
442  unsigned int connect(const DelegateItemAndId& handler);
443 
444 
452  unsigned int connect(const DelegateItemAndIdEx& handler);
453 
454 
459  bool emit(const Widget* widget, const sf::String& item, const sf::String& id)
460  {
461  if (m_handlers.empty())
462  return false;
463 
464  internal_signal::parameters[1] = static_cast<const void*>(&item);
465  internal_signal::parameters[2] = static_cast<const void*>(&id);
466  return Signal::emit(widget);
467  }
468 
469 
475  unsigned int validateTypes(std::initializer_list<std::type_index> unboundParameters) override;
476 
477 
479  };
480 
481 
485  class TGUI_API SignalMenuItem : public Signal
486  {
487  public:
488 
489  using DelegateMenuItem = std::function<void(const sf::String&)>;
490  using DelegateMenuItemFull = std::function<void(const std::vector<sf::String>&)>;
491  using DelegateMenuItemEx = std::function<void(std::shared_ptr<Widget>, const std::string&, const sf::String&)>;
492  using DelegateMenuItemFullEx = std::function<void(std::shared_ptr<Widget>, const std::string&, const std::vector<sf::String>&)>;
493 
494  using Signal::connect;
495 
496 
500  SignalMenuItem(std::string&& name) :
501  Signal{std::move(name), 2}
502  {
503  }
504 
505 
513  unsigned int connect(const DelegateMenuItem& handler);
514 
515 
523  unsigned int connect(const DelegateMenuItemEx& handler);
524 
525 
533  unsigned int connect(const DelegateMenuItemFull& handler);
534 
535 
543  unsigned int connect(const DelegateMenuItemFullEx& handler);
544 
545 
550  bool emit(const Widget* widget, const sf::String& item, const std::vector<sf::String>& fullItem)
551  {
552  if (m_handlers.empty())
553  return false;
554 
555  internal_signal::parameters[1] = static_cast<const void*>(&item);
556  internal_signal::parameters[2] = static_cast<const void*>(&fullItem);
557  return Signal::emit(widget);
558  }
559 
560 
566  unsigned int validateTypes(std::initializer_list<std::type_index> unboundParameters) override;
567 
568 
570  };
571 
572 
573  namespace internal_signal
574  {
575  // make_integer_sequence implementation taken from https://gist.github.com/jappa/62f30b6da5adea60bad3
576  #ifdef TGUI_NO_CPP14
577  template <class Type, Type... Indices>
578  struct integer_sequence
579  {
580  typedef Type value_type;
581  static std::size_t size()
582  {
583  return sizeof...(Indices);
584  }
585  };
586 
587  template<std::size_t... Ints>
588  using index_sequence = integer_sequence<std::size_t, Ints...>;
589 
590  namespace integer_sequence_detail
591  {
592  template <typename T, std::size_t ..._Extra>
593  struct repeat;
594 
595  template <typename T, T ...N, std::size_t ..._Extra>
596  struct repeat<integer_sequence<T, N...>, _Extra...>
597  {
598  typedef integer_sequence<T, N...,
599  1 * sizeof...(N) + N...,
600  2 * sizeof...(N) + N...,
601  3 * sizeof...(N) + N...,
602  4 * sizeof...(N) + N...,
603  5 * sizeof...(N) + N...,
604  6 * sizeof...(N) + N...,
605  7 * sizeof...(N) + N...,
606  _Extra...> type;
607  };
608 
609  template <std::size_t N> struct parity;
610  template <std::size_t N> struct make:parity<N % 8>::template pmake<N> {};
611 
612  template <> struct make<0> { typedef integer_sequence<std::size_t> type; };
613  template <> struct make<1> { typedef integer_sequence<std::size_t, 0> type; };
614  template <> struct make<2> { typedef integer_sequence<std::size_t, 0, 1> type; };
615  template <> struct make<3> { typedef integer_sequence<std::size_t, 0, 1, 2> type; };
616  template <> struct make<4> { typedef integer_sequence<std::size_t, 0, 1, 2, 3> type; };
617  template <> struct make<5> { typedef integer_sequence<std::size_t, 0, 1, 2, 3, 4> type; };
618  template <> struct make<6> { typedef integer_sequence<std::size_t, 0, 1, 2, 3, 4, 5> type; };
619  template <> struct make<7> { typedef integer_sequence<std::size_t, 0, 1, 2, 3, 4, 5, 6> type; };
620 
621  template <> struct parity<0> { template <std::size_t N> struct pmake:repeat<typename make<N / 8>::type> {}; };
622  template <> struct parity<1> { template <std::size_t N> struct pmake:repeat<typename make<N / 8>::type, N - 1> {}; };
623  template <> struct parity<2> { template <std::size_t N> struct pmake:repeat<typename make<N / 8>::type, N - 2, N - 1> {}; };
624  template <> struct parity<3> { template <std::size_t N> struct pmake:repeat<typename make<N / 8>::type, N - 3, N - 2, N - 1> {}; };
625  template <> struct parity<4> { template <std::size_t N> struct pmake:repeat<typename make<N / 8>::type, N - 4, N - 3, N - 2, N - 1> {}; };
626  template <> struct parity<5> { template <std::size_t N> struct pmake:repeat<typename make<N / 8>::type, N - 5, N - 4, N - 3, N - 2, N - 1> {}; };
627  template <> struct parity<6> { template <std::size_t N> struct pmake:repeat<typename make<N / 8>::type, N - 6, N - 5, N - 4, N - 3, N - 2, N - 1> {}; };
628  template <> struct parity<7> { template <std::size_t N> struct pmake:repeat<typename make<N / 8>::type, N - 7, N - 6, N - 5, N - 4, N - 3, N - 2, N - 1> {}; };
629 
630  template <typename T, typename U>
631  struct convert
632  {
633  template <typename>
634  struct result;
635 
636  template <T ...N>
637  struct result<integer_sequence<T, N...> >
638  {
639  typedef integer_sequence<U, N...> type;
640  };
641  };
642 
643  template <typename T>
644  struct convert<T, T>
645  {
646  template <typename U>
647  struct result
648  {
649  typedef U type;
650  };
651  };
652 
653  template <typename T, T N>
654  using make_integer_sequence_unchecked = typename convert<std::size_t, T>::template result<typename make<N>::type>::type;
655 
656  template <typename T, T N>
657  struct make_integer_sequence
658  {
659  static_assert(std::is_integral<T>::value,
660  "std::make_integer_sequence can only be instantiated with an integral type");
661  static_assert(0 <= N,"std::make_integer_sequence input shall not be negative");
662 
663  typedef make_integer_sequence_unchecked<T, N> type;
664  };
665  }
666 
667  template <typename T, T N>
668  using make_integer_sequence = typename integer_sequence_detail::make_integer_sequence<T, N>::type;
669 
670  template<std::size_t N>
671  using make_index_sequence = make_integer_sequence<std::size_t, N>;
672 
673  template<class... T>
674  using index_sequence_for = make_index_sequence<sizeof...(T)>;
675  #else
676  using std::index_sequence;
677  using std::index_sequence_for;
678  #endif
679 
680  // void_t only exists in c++17 so we use our own implementation to support c++14 compilers
681  template<typename...>
682  using void_t = void;
683 
684  // Type to pass a list of template types
685  template <typename...>
686  struct TypeSet;
687 
688  // Used for static_assert errors inside template functions
689  template <typename...>
690  struct always_false : std::false_type {};
691 
692  // The dereference function turns the void* elements in the parameters list back into its original type right before calling the signal handler
693  template <typename Type, typename std::enable_if<std::is_same<Type, std::string>::value>::type* = nullptr>
694  #ifdef TGUI_NO_CPP14
695  std::string dereference(const void* obj)
696  #else
697  decltype(auto) dereference(const void* obj)
698  #endif
699  {
700  // Signal handlers are allowed to have std::string parameters while the signal sends sf::String
701  return static_cast<std::string>(*static_cast<const sf::String*>(obj));
702  }
703 
704  template <typename Type, typename std::enable_if<!std::is_same<Type, std::string>::value>::type* = nullptr>
705  #ifdef TGUI_NO_CPP14
706  const Type& dereference(const void* obj)
707  #else
708  decltype(auto) dereference(const void* obj)
709  #endif
710  {
711  return *static_cast<const typename std::decay<Type>::type*>(obj);
712  }
713 
714  // std::invoke only exists in c++17 so we use our own implementation to support c++14 compilers
715  // Visual Studio compiler did not like it when the function was called "invoke"
716  template <typename Func, typename... Args, typename std::enable_if<std::is_member_pointer<typename std::decay<Func>::type>::value>::type* = nullptr>
717  void invokeFunc(Func&& func, Args&&... args)
718  {
719  std::mem_fn(func)(std::forward<Args>(args)...);
720  }
721 
722  template <typename Func, typename... Args, typename std::enable_if<!std::is_member_pointer<typename std::decay<Func>::type>::value>::type* = nullptr>
723  void invokeFunc(Func&& func, Args&&... args)
724  {
725  std::forward<Func>(func)(std::forward<Args>(args)...);
726  }
727 
728  // The binder will figure out the unbound parameters and bind them if they correspond to what the signal sends
729  template <typename... Args>
730  struct binder;
731 
732  template <typename Arg, typename... AllArgs, typename BoundArg, typename... BoundArgs>
733  struct binder<TypeSet<Arg, AllArgs...>, TypeSet<BoundArg, BoundArgs...>>
734  : binder<TypeSet<AllArgs...>, TypeSet<BoundArgs...>>
735  {
736  };
737 
738  template <typename... UnboundArgs>
739  struct binder<TypeSet<std::shared_ptr<Widget>, std::string, UnboundArgs...>, TypeSet<>>
740  {
741  template <typename Func, typename... BoundArgs>
742  #ifdef TGUI_NO_CPP14
743  static std::function<void(const std::shared_ptr<Widget>& widget, const std::string& signalName)> bind(Signal& signal, Func&& func, BoundArgs&&... args)
744  #else
745  static decltype(auto) bind(Signal& signal, Func&& func, BoundArgs&&... args)
746  #endif
747  {
748  return bindImpl(index_sequence_for<UnboundArgs...>{}, signal, std::forward<Func>(func), std::forward<BoundArgs>(args)...);
749  }
750 
751  private:
752 
753  template <typename Func, typename... BoundArgs, std::size_t... Indices>
754  #ifdef TGUI_NO_CPP14
755  static std::function<void(const std::shared_ptr<Widget>& widget, const std::string& signalName)> bindImpl(index_sequence<Indices...>, Signal& signal, Func&& func, BoundArgs&&... args)
756  #else
757  static decltype(auto) bindImpl(index_sequence<Indices...>, Signal& signal, Func&& func, BoundArgs&&... args)
758  #endif
759  {
760  const std::size_t offset = (sizeof...(UnboundArgs) > 0) ? signal.validateTypes({typeid(UnboundArgs)...}) : 0;
761  #ifdef TGUI_NO_CPP14
762  return [=](const std::shared_ptr<Widget>& widget, const std::string& signalName) {
763  auto f = func;
764  #else
765  return [=, f=func](const std::shared_ptr<Widget>& widget, const std::string& signalName) { // f=func is needed to decay free functions
766  #endif
767  invokeFunc(f,
768  args...,
769  widget,
770  signalName,
771  internal_signal::dereference<UnboundArgs>(internal_signal::parameters[offset + Indices])...);
772  };
773  }
774  };
775 
776  template <typename... UnboundArgs>
777  struct binder<TypeSet<UnboundArgs...>, TypeSet<>>
778  {
779  template <typename Func, typename... BoundArgs>
780  #ifdef TGUI_NO_CPP14
781  static std::function<void()> bind(Signal& signal, Func&& func, BoundArgs&&... args)
782  #else
783  static decltype(auto) bind(Signal& signal, Func&& func, BoundArgs&&... args)
784  #endif
785  {
786  return bindImpl(index_sequence_for<UnboundArgs...>{}, signal, std::forward<Func>(func), std::forward<BoundArgs>(args)...);
787  }
788 
789  private:
790 
791  template <typename Func, typename... BoundArgs, std::size_t... Indices>
792  #ifdef TGUI_NO_CPP14
793  static std::function<void()> bindImpl(index_sequence<Indices...>, Signal& signal, Func&& func, BoundArgs&&... args)
794  #else
795  static decltype(auto) bindImpl(index_sequence<Indices...>, Signal& signal, Func&& func, BoundArgs&&... args)
796  #endif
797  {
798  const std::size_t offset = (sizeof...(UnboundArgs) > 0) ? signal.validateTypes({typeid(UnboundArgs)...}) : 0;
799  #ifdef TGUI_NO_CPP14
800  return [=]() {
801  auto f = func;
802  #else
803  return [=, f=func]() { // f=func is needed to decay free functions
804  #endif
805  invokeFunc(f,
806  args...,
807  internal_signal::dereference<UnboundArgs>(internal_signal::parameters[offset + Indices])...);
808  };
809  }
810  };
811 
812 
813  // Error case (function signature did not match anything)
814  template <typename Enable, typename Func, typename... BoundArgs>
815  struct func_traits;
816 
817  // Normal function or lambda
818  template <typename Func, typename... BoundArgs>
819  struct func_traits<void_t<decltype(&Func::operator())>, Func, BoundArgs...>
820  : public func_traits<void, decltype(&Func::operator()), Func*, BoundArgs...>
821  {
822  };
823 
824  // Non-const member function
825  template <typename Class, typename... Args, typename... BoundArgs>
826  struct func_traits<void, void(Class::*)(Args...), BoundArgs...>
827  : binder<TypeSet<Class*, typename std::decay<Args>::type...>, TypeSet<BoundArgs...>>
828  {
829  };
830 
831  // Const member function
832  template <typename Class, typename... Args, typename... BoundArgs>
833  struct func_traits<void, void(Class::*)(Args...) const, BoundArgs...>
834  : binder<TypeSet<const Class*, typename std::decay<Args>::type...>, TypeSet<BoundArgs...>>
835  {
836  };
837 
838  // Free function
839  template <typename... Args, typename... BoundArgs>
840  struct func_traits<void, void(*)(Args...), BoundArgs...>
841  : binder<TypeSet<typename std::decay<Args>::type...>, TypeSet<BoundArgs...>>
842  {
843  };
844  }
845 
846 
850  class TGUI_API SignalWidgetBase
851  {
852  public:
853 
854  virtual ~SignalWidgetBase() = default;
855 
856 
866  template <typename Func, typename... Args, typename std::enable_if<std::is_convertible<Func, std::function<void(const Args&...)>>::value>::type* = nullptr>
867  unsigned int connect(std::string signalName, Func&& handler, const Args&... args)
868  {
869  #ifdef TGUI_NO_CPP14
870  const unsigned int id = getSignal(toLower(signalName)).connect([=](){ (std::function<void(const Args&...)>(handler))(args...); });
871  #else
872  const unsigned int id = getSignal(toLower(signalName)).connect([f=std::function<void(const Args&...)>(handler),args...](){ f(args...); });
873  #endif
874  m_connectedSignals[id] = toLower(signalName);
875  return id;
876  }
877 
878 
889  template <typename Func, typename... BoundArgs, typename std::enable_if<std::is_convertible<Func, std::function<void(const BoundArgs&..., std::shared_ptr<Widget>, const std::string&)>>::value>::type* = nullptr>
890  unsigned int connect(std::string signalName, Func&& handler, BoundArgs&&... args)
891  {
892  #ifdef TGUI_NO_CPP14
893  const unsigned int id = getSignal(toLower(signalName)).connect(
894  [=](const std::shared_ptr<Widget>& w, const std::string& s) {
895  (std::function<void(const BoundArgs&..., const std::shared_ptr<Widget>&, const std::string&)>(handler))(args..., w, s);
896  }
897  );
898  #else
899  const unsigned int id = getSignal(toLower(signalName)).connect(
900  [f=std::function<void(const BoundArgs&..., const std::shared_ptr<Widget>&, const std::string&)>(handler), args...]
901  (const std::shared_ptr<Widget>& w, const std::string& s)
902  { f(args..., w, s); }
903  );
904  #endif
905 
906  m_connectedSignals[id] = toLower(signalName);
907  return id;
908  }
909 
910 
920  template <typename Func, typename... BoundArgs, typename std::enable_if<!std::is_convertible<Func, std::function<void(const BoundArgs&...)>>::value
921  && !std::is_convertible<Func, std::function<void(const BoundArgs&..., std::shared_ptr<Widget>, const std::string&)>>::value>::type* = nullptr>
922  unsigned int connect(std::string signalName, Func&& handler, BoundArgs&&... args)
923  {
924  Signal& signal = getSignal(toLower(signalName));
925  using binder = internal_signal::func_traits<void, typename std::decay<Func>::type, BoundArgs...>;
926  const unsigned int id = signal.connect(binder::bind(signal, std::forward<Func>(handler), std::forward<BoundArgs>(args)...));
927  m_connectedSignals[id] = toLower(signalName);
928  return id;
929  }
930 
931 
941  template <typename Func, typename... BoundArgs>
942  unsigned int connect(std::initializer_list<std::string> signalNames, Func&& handler, BoundArgs&&... args)
943  {
944  unsigned int lastId = 0;
945  for (auto& signalName : signalNames)
946  lastId = connect(std::move(signalName), handler, args...);
947 
948  return lastId;
949  }
950 
951 
959  bool disconnect(unsigned int id);
960 
961 
967  void disconnectAll(std::string signalName);
968 
969 
973  void disconnectAll();
974 
975 
977  protected:
978 
982  virtual Signal& getSignal(std::string signalName) = 0;
983 
984 
986  private:
987 
988  std::map<unsigned int, std::string> m_connectedSignals;
989 
990 
992  };
993 
995 }
996 
998 
999 #endif // TGUI_SIGNAL_HPP
Namespace that contains all TGUI functions and classes.
Definition: AbsoluteOrRelativeValue.hpp:36
Child window widget.
Definition: ChildWindow.hpp:42
The parent class for every widget.
Definition: Widget.hpp:62
SignalChildWindow(std::string &&name)
Constructor.
Definition: Signal.hpp:346
Base class for Widget which provides functionality to connect signals based on their name...
Definition: Signal.hpp:850
unsigned int connect(std::string signalName, Func &&handler, BoundArgs &&... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:890
unsigned int connect(std::string signalName, Func &&handler, const Args &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:867
bool emit(const Widget *widget)
Call all connected signal handlers.
Definition: Signal.hpp:151
unsigned int connect(std::initializer_list< std::string > signalNames, Func &&handler, BoundArgs &&... args)
Connect a signal handler to multiple signals.
Definition: Signal.hpp:942
std::string getName() const
Returns the name given to the signal.
Definition: Signal.hpp:170
Signal to which the user can subscribe to get callbacks from.
Definition: Signal.hpp:485
Signal to which the user can subscribe to get callbacks from.
Definition: Signal.hpp:394
SignalRange(std::string &&name)
Constructor.
Definition: Signal.hpp:285
Signal to which the user can subscribe to get callbacks from.
Definition: Signal.hpp:59
Signal to which the user can subscribe to get callbacks from.
Definition: Signal.hpp:333
SignalMenuItem(std::string &&name)
Constructor.
Definition: Signal.hpp:500
unsigned int connect(const Delegate &handler)
Connects a signal handler that will be called when this signal is emitted.
SignalItem(std::string &&name)
Constructor.
Definition: Signal.hpp:409
Signal(std::string &&name, std::size_t extraParameters=0)
Constructor.
Definition: Signal.hpp:76