TGUI  0.8.5
Signal.hpp
1 //
3 // TGUI - Texus' Graphical User Interface
4 // Copyright (C) 2012-2019 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/Vector2f.hpp>
33 #include <TGUI/Animation.hpp>
34 #include <SFML/System/String.hpp>
35 #include <functional>
36 #include <typeindex>
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() || !m_enabled)
154  return false;
155 
156  internal_signal::parameters[0] = static_cast<const void*>(&widget);
157 
158  // Copy the handlers before calling them in case the widget (and this signal) gets destroyed during the handler
159  auto handlers = m_handlers;
160  for (auto& handler : handlers)
161  handler.second();
162 
163  return true;
164  }
165 
166 
172  std::string getName() const
173  {
174  return m_name;
175  }
176 
177 
186  void setEnabled(bool enabled)
187  {
188  m_enabled = enabled;
189  }
190 
191 
200  bool isEnabled() const
201  {
202  return m_enabled;
203  }
204 
205 
211  virtual unsigned int validateTypes(std::initializer_list<std::type_index> unboundParameters) const;
212 
213 
215  protected:
216 
221  static std::shared_ptr<Widget> getWidget();
222 
223 
225  protected:
226 
227  bool m_enabled = true;
228  std::string m_name;
229  std::map<unsigned int, std::function<void()>> m_handlers;
230  };
231 
232 #ifdef TGUI_REMOVE_DEPRECATED_CODE
233  #define TGUI_SIGNAL_VALUE_DECLARATION(TypeName, Type) \
234  /**************************************************************************************************************************** \
235  * @brief Signal to which the user can subscribe to get callbacks from
236  ****************************************************************************************************************************/ \
237  class TGUI_API Signal##TypeName : public Signal \
238  { \
239  public: \
240  /************************************************************************************************************************ \
241  * @brief Constructor
242  ************************************************************************************************************************/ \
243  Signal##TypeName(std::string&& name) : \
244  Signal{std::move(name), 1} \
245  { \
246  } \
247  \
248  /************************************************************************************************************************ \
249  * @internal
250  * @brief Call all connected signal handlers
251  ************************************************************************************************************************/ \
252  bool emit(const Widget* widget, Type param) \
253  { \
254  if (m_handlers.empty()) \
255  return false; \
256  \
257  internal_signal::parameters[1] = static_cast<const void*>(&param); \
258  return Signal::emit(widget); \
259  } \
260  \
261  private: \
262  /************************************************************************************************************************ \
263  * @internal
264  * @brief Checks whether the unbound parameters match with this signal
265  * @return The index in the parameters list where the parameters will be stored
266  ************************************************************************************************************************/ \
267  unsigned int validateTypes(std::initializer_list<std::type_index> unboundParameters) const override; \
268  };
269 #else
270  #define TGUI_SIGNAL_VALUE_DECLARATION(TypeName, Type) \
271  /**************************************************************************************************************************** \
272  * @brief Signal to which the user can subscribe to get callbacks from
273  ****************************************************************************************************************************/ \
274  class TGUI_API Signal##TypeName : public Signal \
275  { \
276  public: \
277  using Delegate##TypeName = std::function<void(Type)>; \
278  using Delegate##TypeName##Ex = std::function<void(std::shared_ptr<Widget>, const std::string&, Type)>; \
279  using Signal::connect; \
280  \
281  /************************************************************************************************************************ \
282  * @brief Constructor
283  ************************************************************************************************************************/ \
284  Signal##TypeName(std::string&& name) : \
285  Signal{std::move(name), 1} \
286  { \
287  } \
288  \
289  /************************************************************************************************************************ \
290  * @brief Connects a signal handler that will be called when this signal is emitted
291  *
292  * @param handler Callback function that is given a Vector2f as argument
293  *
294  * @return Unique id of the connection
295  ************************************************************************************************************************/ \
296  TGUI_DEPRECATED("Use connect function from widget instead") unsigned int connect(const Delegate##TypeName& handler); \
297  \
298  /************************************************************************************************************************ \
299  * @brief Connects a signal handler that will be called when this signal is emitted
300  *
301  * @param handler Callback function that is given a pointer to the widget, the name of the signal and a Vector2f as arguments
302  *
303  * @return Unique id of the connection
304  ************************************************************************************************************************/ \
305  TGUI_DEPRECATED("Use connect function from widget instead") unsigned int connect(const Delegate##TypeName##Ex& handler); \
306  \
307  /************************************************************************************************************************ \
308  * @internal
309  * @brief Call all connected signal handlers
310  ************************************************************************************************************************/ \
311  bool emit(const Widget* widget, Type param) \
312  { \
313  if (m_handlers.empty()) \
314  return false; \
315  \
316  internal_signal::parameters[1] = static_cast<const void*>(&param); \
317  return Signal::emit(widget); \
318  } \
319  \
320  private: \
321  /************************************************************************************************************************ \
322  * @internal
323  * @brief Checks whether the unbound parameters match with this signal
324  * @return The index in the parameters list where the parameters will be stored
325  ************************************************************************************************************************/ \
326  unsigned int validateTypes(std::initializer_list<std::type_index> unboundParameters) const override; \
327  };
328 #endif
329 
330  TGUI_SIGNAL_VALUE_DECLARATION(Int, int)
331  TGUI_SIGNAL_VALUE_DECLARATION(UInt, unsigned int)
332  TGUI_SIGNAL_VALUE_DECLARATION(Bool, bool)
333  TGUI_SIGNAL_VALUE_DECLARATION(Float, float)
334  TGUI_SIGNAL_VALUE_DECLARATION(String, const sf::String&)
335  TGUI_SIGNAL_VALUE_DECLARATION(Vector2f, Vector2f)
336 
337 
338 
339  class TGUI_API SignalRange : public Signal
342  {
343  public:
344 
345  #ifndef TGUI_REMOVE_DEPRECATED_CODE
346  using DelegateRange = std::function<void(float, float)>;
347  using DelegateRangeEx = std::function<void(std::shared_ptr<Widget>, const std::string&, float, float)>;
348  using Signal::connect;
349  #endif
350 
354  SignalRange(std::string&& name) :
355  Signal{std::move(name), 2}
356  {
357  }
358 
359  #ifndef TGUI_REMOVE_DEPRECATED_CODE
360  TGUI_DEPRECATED("Use connect function from widget instead") unsigned int connect(const DelegateRange& handler);
368 
369 
377  TGUI_DEPRECATED("Use connect function from widget instead") unsigned int connect(const DelegateRangeEx& handler);
378  #endif
379 
384  bool emit(const Widget* widget, float value1, float value2);
385 
386 
387  private:
388 
394  unsigned int validateTypes(std::initializer_list<std::type_index> unboundParameters) const override;
395 
396 
398  };
399 
400 
404  class TGUI_API SignalChildWindow : public Signal
405  {
406  public:
407 
408  #ifndef TGUI_REMOVE_DEPRECATED_CODE
409  using DelegateChildWindow = std::function<void(std::shared_ptr<ChildWindow>)>;
410  using DelegateChildWindowEx = std::function<void(std::shared_ptr<Widget>, const std::string&, std::shared_ptr<ChildWindow>)>;
411  using Signal::connect;
412  #endif
413 
417  SignalChildWindow(std::string&& name) :
418  Signal{std::move(name), 1}
419  {
420  }
421 
422  #ifndef TGUI_REMOVE_DEPRECATED_CODE
423  TGUI_DEPRECATED("Use connect function from widget instead") unsigned int connect(const DelegateChildWindow& handler);
431 
432 
440  TGUI_DEPRECATED("Use connect function from widget instead") unsigned int connect(const DelegateChildWindowEx& handler);
441  #endif
442 
447  bool emit(ChildWindow* param);
448 
449 
450  private:
451 
457  unsigned int validateTypes(std::initializer_list<std::type_index> unboundParameters) const override;
458 
459 
461  };
462 
463 
467  class TGUI_API SignalItem : public Signal
468  {
469  public:
470 
471  #ifndef TGUI_REMOVE_DEPRECATED_CODE
472  using DelegateItem = std::function<void(const sf::String&)>;
473  using DelegateItemAndId = std::function<void(const sf::String&, const sf::String&)>;
474  using DelegateItemEx = std::function<void(std::shared_ptr<Widget>, const std::string&, const sf::String&)>;
475  using DelegateItemAndIdEx = std::function<void(std::shared_ptr<Widget>, const std::string&, const sf::String&, const sf::String&)>;
476  using Signal::connect;
477  #endif
478 
482  SignalItem(std::string&& name) :
483  Signal{std::move(name), 2}
484  {
485  }
486 
487  #ifndef TGUI_REMOVE_DEPRECATED_CODE
488  TGUI_DEPRECATED("Use connect function from widget instead") unsigned int connect(const DelegateItem& handler);
496 
497 
505  TGUI_DEPRECATED("Use connect function from widget instead") unsigned int connect(const DelegateItemEx& handler);
506 
507 
515  TGUI_DEPRECATED("Use connect function from widget instead") unsigned int connect(const DelegateItemAndId& handler);
516 
517 
525  TGUI_DEPRECATED("Use connect function from widget instead") unsigned int connect(const DelegateItemAndIdEx& handler);
526  #endif
527 
532  bool emit(const Widget* widget, const sf::String& item, const sf::String& id)
533  {
534  if (m_handlers.empty())
535  return false;
536 
537  internal_signal::parameters[1] = static_cast<const void*>(&item);
538  internal_signal::parameters[2] = static_cast<const void*>(&id);
539  return Signal::emit(widget);
540  }
541 
542 
543  private:
544 
550  unsigned int validateTypes(std::initializer_list<std::type_index> unboundParameters) const override;
551 
552 
554  };
555 
556 
565  class TGUI_API SignalAnimation : public Signal
566  {
567  public:
568 
572  SignalAnimation(std::string&& name) :
573  Signal{std::move(name), 2}
574  {
575  }
576 
581  bool emit(const Widget* widget, ShowAnimationType type, bool visible)
582  {
583  if (m_handlers.empty())
584  return false;
585 
586  internal_signal::parameters[1] = static_cast<const void*>(&type);
587  internal_signal::parameters[2] = static_cast<const void*>(&visible);
588  return Signal::emit(widget);
589  }
590 
591 
592  private:
593 
599  unsigned int validateTypes(std::initializer_list<std::type_index> unboundParameters) const override;
600 
601 
603  };
604 
605 
609  class TGUI_API SignalItemHierarchy : public Signal
610  {
611  public:
612 
613  #ifndef TGUI_REMOVE_DEPRECATED_CODE
614  using DelegateMenuItem = std::function<void(const sf::String&)>;
615  using DelegateMenuItemFull = std::function<void(const std::vector<sf::String>&)>;
616  using DelegateMenuItemEx = std::function<void(std::shared_ptr<Widget>, const std::string&, const sf::String&)>;
617  using DelegateMenuItemFullEx = std::function<void(std::shared_ptr<Widget>, const std::string&, const std::vector<sf::String>&)>;
618  using Signal::connect;
619  #endif
620 
624  SignalItemHierarchy(std::string&& name) :
625  Signal{std::move(name), 2}
626  {
627  }
628 
629  #ifndef TGUI_REMOVE_DEPRECATED_CODE
630  TGUI_DEPRECATED("Use connect function from widget instead") unsigned int connect(const DelegateMenuItem& handler);
638 
639 
647  TGUI_DEPRECATED("Use connect function from widget instead") unsigned int connect(const DelegateMenuItemEx& handler);
648 
649 
657  TGUI_DEPRECATED("Use connect function from widget instead") unsigned int connect(const DelegateMenuItemFull& handler);
658 
659 
667  TGUI_DEPRECATED("Use connect function from widget instead") unsigned int connect(const DelegateMenuItemFullEx& handler);
668  #endif
669 
674  bool emit(const Widget* widget, const sf::String& item, const std::vector<sf::String>& fullItem)
675  {
676  if (m_handlers.empty())
677  return false;
678 
679  internal_signal::parameters[1] = static_cast<const void*>(&item);
680  internal_signal::parameters[2] = static_cast<const void*>(&fullItem);
681  return Signal::emit(widget);
682  }
683 
684 
685  private:
686 
692  unsigned int validateTypes(std::initializer_list<std::type_index> unboundParameters) const override;
693 
694 
696  };
697 
698 #ifndef TGUI_REMOVE_DEPRECATED_CODE
699  using SignalMenuItem = SignalItemHierarchy;
700 #endif
701 
702 
706  class TGUI_API SignalWidgetBase
707  {
708  public:
709 
710  virtual ~SignalWidgetBase() = default;
711 
712 #ifdef TGUI_USE_CPP17
713  template <typename Func, typename... BoundArgs>
723  unsigned int connect(std::string signalName, Func&& handler, const BoundArgs&... args);
724 
725 #else
726  template <typename Func, typename... Args, typename std::enable_if<std::is_convertible<Func, std::function<void(const Args&...)>>::value>::type* = nullptr>
736  unsigned int connect(std::string signalName, Func&& handler, const Args&... args);
737 
738 
749  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>
750  unsigned int connect(std::string signalName, Func&& handler, BoundArgs&&... args);
751 
752 
762  template <typename Func, typename... BoundArgs, typename std::enable_if<!std::is_convertible<Func, std::function<void(const BoundArgs&...)>>::value
763  && !std::is_convertible<Func, std::function<void(const BoundArgs&..., std::shared_ptr<Widget>, const std::string&)>>::value>::type* = nullptr>
764  unsigned int connect(std::string signalName, Func&& handler, BoundArgs&&... args);
765 #endif
766 
776  template <typename Func, typename... BoundArgs>
777  unsigned int connect(std::initializer_list<std::string> signalNames, Func&& handler, BoundArgs&&... args);
778 
779 
787  bool disconnect(unsigned int id);
788 
789 
795  void disconnectAll(std::string signalName);
796 
797 
801  void disconnectAll();
802 
803 
805  protected:
806 
810  virtual Signal& getSignal(std::string signalName) = 0;
811 
812 
814  private:
815 
816  std::map<unsigned int, std::string> m_connectedSignals;
817 
818 
820  };
821 
823 }
824 
826 
827 #endif // TGUI_SIGNAL_HPP
Namespace that contains all TGUI functions and classes.
Definition: AbsoluteOrRelativeValue.hpp:36
The parent class for every widget.
Definition: Widget.hpp:72
SignalChildWindow(std::string &&name)
Constructor.
Definition: Signal.hpp:417
Base class for Widget which provides functionality to connect signals based on their name.
Definition: Signal.hpp:706
Signal to which the user can subscribe to get callbacks from.
Definition: Signal.hpp:609
bool emit(const Widget *widget)
Call all connected signal handlers.
Definition: Signal.hpp:151
ShowAnimationType
Type of animation to show/hide widget.
Definition: Animation.hpp:43
std::string getName() const
Returns the name given to the signal.
Definition: Signal.hpp:172
Signal to which the user can subscribe to get callbacks from.
Definition: Signal.hpp:467
SignalRange(std::string &&name)
Constructor.
Definition: Signal.hpp:354
SignalAnimation(std::string &&name)
Constructor.
Definition: Signal.hpp:572
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:404
unsigned int connect(const Delegate &handler)
Connects a signal handler that will be called when this signal is emitted.
bool isEnabled() const
Returns whether this signal calls the connected functions when triggered.
Definition: Signal.hpp:200
SignalItem(std::string &&name)
Constructor.
Definition: Signal.hpp:482
Signal(std::string &&name, std::size_t extraParameters=0)
Constructor.
Definition: Signal.hpp:76
SignalItemHierarchy(std::string &&name)
Constructor.
Definition: Signal.hpp:624
Signal to which the user can subscribe to get callbacks from.
Definition: Signal.hpp:565
void setEnabled(bool enabled)
Changes whether this signal calls the connected functions when triggered.
Definition: Signal.hpp:186