TGUI  0.8.2
Signal.hpp
1 //
3 // TGUI - Texus' Graphical User Interface
4 // Copyright (C) 2012-2018 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())
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 
183  virtual unsigned int validateTypes(std::initializer_list<std::type_index> unboundParameters) const;
184 
185 
187  protected:
188 
193  static std::shared_ptr<Widget> getWidget();
194 
195 
197  protected:
198 
199  std::string m_name;
200  std::map<unsigned int, std::function<void()>> m_handlers;
201  };
202 
203 #ifdef TGUI_REMOVE_DEPRECATED_CODE
204  #define TGUI_SIGNAL_VALUE_DECLARATION(TypeName, Type) \
205  /**************************************************************************************************************************** \
206  * @brief Signal to which the user can subscribe to get callbacks from
207  ****************************************************************************************************************************/ \
208  class TGUI_API Signal##TypeName : public Signal \
209  { \
210  public: \
211  /************************************************************************************************************************ \
212  * @brief Constructor
213  ************************************************************************************************************************/ \
214  Signal##TypeName(std::string&& name) : \
215  Signal{std::move(name), 1} \
216  { \
217  } \
218  \
219  /************************************************************************************************************************ \
220  * @internal
221  * @brief Call all connected signal handlers
222  ************************************************************************************************************************/ \
223  bool emit(const Widget* widget, Type param) \
224  { \
225  if (m_handlers.empty()) \
226  return false; \
227  \
228  internal_signal::parameters[1] = static_cast<const void*>(&param); \
229  return Signal::emit(widget); \
230  } \
231  \
232  private: \
233  /************************************************************************************************************************ \
234  * @internal
235  * @brief Checks whether the unbound parameters match with this signal
236  * @return The index in the parameters list where the parameters will be stored
237  ************************************************************************************************************************/ \
238  unsigned int validateTypes(std::initializer_list<std::type_index> unboundParameters) const override; \
239  };
240 #else
241  #define TGUI_SIGNAL_VALUE_DECLARATION(TypeName, Type) \
242  /**************************************************************************************************************************** \
243  * @brief Signal to which the user can subscribe to get callbacks from
244  ****************************************************************************************************************************/ \
245  class TGUI_API Signal##TypeName : public Signal \
246  { \
247  public: \
248  using Delegate##TypeName = std::function<void(Type)>; \
249  using Delegate##TypeName##Ex = std::function<void(std::shared_ptr<Widget>, const std::string&, Type)>; \
250  using Signal::connect; \
251  \
252  /************************************************************************************************************************ \
253  * @brief Constructor
254  ************************************************************************************************************************/ \
255  Signal##TypeName(std::string&& name) : \
256  Signal{std::move(name), 1} \
257  { \
258  } \
259  \
260  /************************************************************************************************************************ \
261  * @brief Connects a signal handler that will be called when this signal is emitted
262  *
263  * @param handler Callback function that is given a Vector2f as argument
264  *
265  * @return Unique id of the connection
266  ************************************************************************************************************************/ \
267  TGUI_DEPRECATED("Use connect function from widget instead") unsigned int connect(const Delegate##TypeName& handler); \
268  \
269  /************************************************************************************************************************ \
270  * @brief Connects a signal handler that will be called when this signal is emitted
271  *
272  * @param handler Callback function that is given a pointer to the widget, the name of the signal and a Vector2f as arguments
273  *
274  * @return Unique id of the connection
275  ************************************************************************************************************************/ \
276  TGUI_DEPRECATED("Use connect function from widget instead") unsigned int connect(const Delegate##TypeName##Ex& handler); \
277  \
278  /************************************************************************************************************************ \
279  * @internal
280  * @brief Call all connected signal handlers
281  ************************************************************************************************************************/ \
282  bool emit(const Widget* widget, Type param) \
283  { \
284  if (m_handlers.empty()) \
285  return false; \
286  \
287  internal_signal::parameters[1] = static_cast<const void*>(&param); \
288  return Signal::emit(widget); \
289  } \
290  \
291  private: \
292  /************************************************************************************************************************ \
293  * @internal
294  * @brief Checks whether the unbound parameters match with this signal
295  * @return The index in the parameters list where the parameters will be stored
296  ************************************************************************************************************************/ \
297  unsigned int validateTypes(std::initializer_list<std::type_index> unboundParameters) const override; \
298  };
299 #endif
300 
301  TGUI_SIGNAL_VALUE_DECLARATION(Int, int)
302  TGUI_SIGNAL_VALUE_DECLARATION(UInt, unsigned int)
303  TGUI_SIGNAL_VALUE_DECLARATION(Bool, bool)
304  TGUI_SIGNAL_VALUE_DECLARATION(Float, float)
305  TGUI_SIGNAL_VALUE_DECLARATION(String, const sf::String&)
306  TGUI_SIGNAL_VALUE_DECLARATION(Vector2f, Vector2f)
307 
308 
309 
310  class TGUI_API SignalRange : public Signal
313  {
314  public:
315 
316  #ifndef TGUI_REMOVE_DEPRECATED_CODE
317  using DelegateRange = std::function<void(float, float)>;
318  using DelegateRangeEx = std::function<void(std::shared_ptr<Widget>, const std::string&, float, float)>;
319  using Signal::connect;
320  #endif
321 
325  SignalRange(std::string&& name) :
326  Signal{std::move(name), 2}
327  {
328  }
329 
330  #ifndef TGUI_REMOVE_DEPRECATED_CODE
331  TGUI_DEPRECATED("Use connect function from widget instead") unsigned int connect(const DelegateRange& handler);
339 
340 
348  TGUI_DEPRECATED("Use connect function from widget instead") unsigned int connect(const DelegateRangeEx& handler);
349  #endif
350 
355  bool emit(const Widget* widget, float value1, float value2);
356 
357 
358  private:
359 
365  unsigned int validateTypes(std::initializer_list<std::type_index> unboundParameters) const override;
366 
367 
369  };
370 
371 
375  class TGUI_API SignalChildWindow : public Signal
376  {
377  public:
378 
379  #ifndef TGUI_REMOVE_DEPRECATED_CODE
380  using DelegateChildWindow = std::function<void(std::shared_ptr<ChildWindow>)>;
381  using DelegateChildWindowEx = std::function<void(std::shared_ptr<Widget>, const std::string&, std::shared_ptr<ChildWindow>)>;
382  using Signal::connect;
383  #endif
384 
388  SignalChildWindow(std::string&& name) :
389  Signal{std::move(name), 1}
390  {
391  }
392 
393  #ifndef TGUI_REMOVE_DEPRECATED_CODE
394  TGUI_DEPRECATED("Use connect function from widget instead") unsigned int connect(const DelegateChildWindow& handler);
402 
403 
411  TGUI_DEPRECATED("Use connect function from widget instead") unsigned int connect(const DelegateChildWindowEx& handler);
412  #endif
413 
418  bool emit(ChildWindow* param);
419 
420 
421  private:
422 
428  unsigned int validateTypes(std::initializer_list<std::type_index> unboundParameters) const override;
429 
430 
432  };
433 
434 
438  class TGUI_API SignalItem : public Signal
439  {
440  public:
441 
442  #ifndef TGUI_REMOVE_DEPRECATED_CODE
443  using DelegateItem = std::function<void(const sf::String&)>;
444  using DelegateItemAndId = std::function<void(const sf::String&, const sf::String&)>;
445  using DelegateItemEx = std::function<void(std::shared_ptr<Widget>, const std::string&, const sf::String&)>;
446  using DelegateItemAndIdEx = std::function<void(std::shared_ptr<Widget>, const std::string&, const sf::String&, const sf::String&)>;
447  using Signal::connect;
448  #endif
449 
453  SignalItem(std::string&& name) :
454  Signal{std::move(name), 2}
455  {
456  }
457 
458  #ifndef TGUI_REMOVE_DEPRECATED_CODE
459  TGUI_DEPRECATED("Use connect function from widget instead") unsigned int connect(const DelegateItem& handler);
467 
468 
476  TGUI_DEPRECATED("Use connect function from widget instead") unsigned int connect(const DelegateItemEx& handler);
477 
478 
486  TGUI_DEPRECATED("Use connect function from widget instead") unsigned int connect(const DelegateItemAndId& handler);
487 
488 
496  TGUI_DEPRECATED("Use connect function from widget instead") unsigned int connect(const DelegateItemAndIdEx& handler);
497  #endif
498 
503  bool emit(const Widget* widget, const sf::String& item, const sf::String& id)
504  {
505  if (m_handlers.empty())
506  return false;
507 
508  internal_signal::parameters[1] = static_cast<const void*>(&item);
509  internal_signal::parameters[2] = static_cast<const void*>(&id);
510  return Signal::emit(widget);
511  }
512 
513 
514  private:
515 
521  unsigned int validateTypes(std::initializer_list<std::type_index> unboundParameters) const override;
522 
523 
525  };
526 
527 
536  class TGUI_API SignalAnimation : public Signal
537  {
538  public:
539 
543  SignalAnimation(std::string&& name) :
544  Signal{std::move(name), 2}
545  {
546  }
547 
552  bool emit(const Widget* widget, ShowAnimationType type, bool visible)
553  {
554  if (m_handlers.empty())
555  return false;
556 
557  internal_signal::parameters[1] = static_cast<const void*>(&type);
558  internal_signal::parameters[2] = static_cast<const void*>(&visible);
559  return Signal::emit(widget);
560  }
561 
562 
563  private:
564 
570  unsigned int validateTypes(std::initializer_list<std::type_index> unboundParameters) const override;
571 
572 
574  };
575 
576 
580  class TGUI_API SignalItemHierarchy : public Signal
581  {
582  public:
583 
584  #ifndef TGUI_REMOVE_DEPRECATED_CODE
585  using DelegateMenuItem = std::function<void(const sf::String&)>;
586  using DelegateMenuItemFull = std::function<void(const std::vector<sf::String>&)>;
587  using DelegateMenuItemEx = std::function<void(std::shared_ptr<Widget>, const std::string&, const sf::String&)>;
588  using DelegateMenuItemFullEx = std::function<void(std::shared_ptr<Widget>, const std::string&, const std::vector<sf::String>&)>;
589  using Signal::connect;
590  #endif
591 
595  SignalItemHierarchy(std::string&& name) :
596  Signal{std::move(name), 2}
597  {
598  }
599 
600  #ifndef TGUI_REMOVE_DEPRECATED_CODE
601  TGUI_DEPRECATED("Use connect function from widget instead") unsigned int connect(const DelegateMenuItem& handler);
609 
610 
618  TGUI_DEPRECATED("Use connect function from widget instead") unsigned int connect(const DelegateMenuItemEx& handler);
619 
620 
628  TGUI_DEPRECATED("Use connect function from widget instead") unsigned int connect(const DelegateMenuItemFull& handler);
629 
630 
638  TGUI_DEPRECATED("Use connect function from widget instead") unsigned int connect(const DelegateMenuItemFullEx& handler);
639  #endif
640 
645  bool emit(const Widget* widget, const sf::String& item, const std::vector<sf::String>& fullItem)
646  {
647  if (m_handlers.empty())
648  return false;
649 
650  internal_signal::parameters[1] = static_cast<const void*>(&item);
651  internal_signal::parameters[2] = static_cast<const void*>(&fullItem);
652  return Signal::emit(widget);
653  }
654 
655 
656  private:
657 
663  unsigned int validateTypes(std::initializer_list<std::type_index> unboundParameters) const override;
664 
665 
667  };
668 
669 #ifndef TGUI_REMOVE_DEPRECATED_CODE
670  using SignalMenuItem = SignalItemHierarchy;
671 #endif
672 
673 
677  class TGUI_API SignalWidgetBase
678  {
679  public:
680 
681  virtual ~SignalWidgetBase() = default;
682 
683 #ifdef TGUI_USE_CPP17
684  template <typename Func, typename... BoundArgs>
694  unsigned int connect(std::string signalName, Func&& handler, const BoundArgs&... args);
695 
696 #else
697  template <typename Func, typename... Args, typename std::enable_if<std::is_convertible<Func, std::function<void(const Args&...)>>::value>::type* = nullptr>
707  unsigned int connect(std::string signalName, Func&& handler, const Args&... args);
708 
709 
720  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>
721  unsigned int connect(std::string signalName, Func&& handler, BoundArgs&&... args);
722 
723 
733  template <typename Func, typename... BoundArgs, typename std::enable_if<!std::is_convertible<Func, std::function<void(const BoundArgs&...)>>::value
734  && !std::is_convertible<Func, std::function<void(const BoundArgs&..., std::shared_ptr<Widget>, const std::string&)>>::value>::type* = nullptr>
735  unsigned int connect(std::string signalName, Func&& handler, BoundArgs&&... args);
736 #endif
737 
747  template <typename Func, typename... BoundArgs>
748  unsigned int connect(std::initializer_list<std::string> signalNames, Func&& handler, BoundArgs&&... args);
749 
750 
758  bool disconnect(unsigned int id);
759 
760 
766  void disconnectAll(std::string signalName);
767 
768 
772  void disconnectAll();
773 
774 
776  protected:
777 
781  virtual Signal& getSignal(std::string signalName) = 0;
782 
783 
785  private:
786 
787  std::map<unsigned int, std::string> m_connectedSignals;
788 
789 
791  };
792 
794 }
795 
797 
798 #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:388
Base class for Widget which provides functionality to connect signals based on their name...
Definition: Signal.hpp:677
Signal to which the user can subscribe to get callbacks from.
Definition: Signal.hpp:580
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:438
SignalRange(std::string &&name)
Constructor.
Definition: Signal.hpp:325
SignalAnimation(std::string &&name)
Constructor.
Definition: Signal.hpp:543
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:375
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:453
Signal(std::string &&name, std::size_t extraParameters=0)
Constructor.
Definition: Signal.hpp:76
SignalItemHierarchy(std::string &&name)
Constructor.
Definition: Signal.hpp:595
Signal to which the user can subscribe to get callbacks from.
Definition: Signal.hpp:536