TGUI  0.8.0
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 
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  using Delegate##TypeName = std::function<void(Type)>; \
212  using Delegate##TypeName##Ex = std::function<void(std::shared_ptr<Widget>, const std::string&, Type)>; \
213  using Signal::connect; \
214  \
215  /************************************************************************************************************************ \
216  * @brief Constructor
217  ************************************************************************************************************************/ \
218  Signal##TypeName(std::string&& name) : \
219  Signal{std::move(name), 1} \
220  { \
221  } \
222  \
223  /************************************************************************************************************************ \
224  * @brief Connects a signal handler that will be called when this signal is emitted
225  *
226  * @param handler Callback function that is given a Vector2f as argument
227  *
228  * @return Unique id of the connection
229  ************************************************************************************************************************/ \
230  unsigned int connect(const Delegate##TypeName& handler); \
231  \
232  /************************************************************************************************************************ \
233  * @brief Connects a signal handler that will be called when this signal is emitted
234  *
235  * @param handler Callback function that is given a pointer to the widget, the name of the signal and a Vector2f as arguments
236  *
237  * @return Unique id of the connection
238  ************************************************************************************************************************/ \
239  unsigned int connect(const Delegate##TypeName##Ex& handler); \
240  \
241  /************************************************************************************************************************ \
242  * @internal
243  * @brief Call all connected signal handlers
244  ************************************************************************************************************************/ \
245  bool emit(const Widget* widget, Type strParam) \
246  { \
247  if (m_handlers.empty()) \
248  return false; \
249  \
250  internal_signal::parameters[1] = static_cast<const void*>(&strParam); \
251  return Signal::emit(widget); \
252  } \
253  \
254  /************************************************************************************************************************ \
255  * @internal
256  * @brief Checks whether the unbound parameters match with this signal
257  * @return The index in the parameters list where the parameters will be stored
258  ************************************************************************************************************************/ \
259  unsigned int validateTypes(std::initializer_list<std::type_index> unboundParameters) const override; \
260  };
261 
262 
263  TGUI_SIGNAL_VALUE_DECLARATION(Int, int)
264  TGUI_SIGNAL_VALUE_DECLARATION(UInt, unsigned int)
265  TGUI_SIGNAL_VALUE_DECLARATION(Bool, bool)
266  TGUI_SIGNAL_VALUE_DECLARATION(Float, float)
267  TGUI_SIGNAL_VALUE_DECLARATION(String, const sf::String&)
268  TGUI_SIGNAL_VALUE_DECLARATION(Vector2f, Vector2f)
269 
270 
271 
272  class TGUI_API SignalRange : public Signal
275  {
276  public:
277 
278  using DelegateRange = std::function<void(float, float)>;
279  using DelegateRangeEx = std::function<void(std::shared_ptr<Widget>, const std::string&, float, float)>;
280 
281  using Signal::connect;
282 
283 
287  SignalRange(std::string&& name) :
288  Signal{std::move(name), 2}
289  {
290  }
291 
292 
300  unsigned int connect(const DelegateRange& handler);
301 
302 
310  unsigned int connect(const DelegateRangeEx& handler);
311 
312 
317  bool emit(const Widget* widget, float value1, float value2);
318 
319 
325  unsigned int validateTypes(std::initializer_list<std::type_index> unboundParameters) const override;
326 
327 
329  };
330 
331 
335  class TGUI_API SignalChildWindow : public Signal
336  {
337  public:
338 
339  using DelegateChildWindow = std::function<void(std::shared_ptr<ChildWindow>)>;
340  using DelegateChildWindowEx = std::function<void(std::shared_ptr<Widget>, const std::string&, std::shared_ptr<ChildWindow>)>;
341 
342  using Signal::connect;
343 
344 
348  SignalChildWindow(std::string&& name) :
349  Signal{std::move(name), 1}
350  {
351  }
352 
353 
361  unsigned int connect(const DelegateChildWindow& handler);
362 
363 
371  unsigned int connect(const DelegateChildWindowEx& handler);
372 
373 
378  bool emit(const ChildWindow* param);
379 
380 
386  unsigned int validateTypes(std::initializer_list<std::type_index> unboundParameters) const override;
387 
388 
390  };
391 
392 
396  class TGUI_API SignalItem : public Signal
397  {
398  public:
399 
400  using DelegateItem = std::function<void(const sf::String&)>;
401  using DelegateItemAndId = std::function<void(const sf::String&, const sf::String&)>;
402  using DelegateItemEx = std::function<void(std::shared_ptr<Widget>, const std::string&, const sf::String&)>;
403  using DelegateItemAndIdEx = std::function<void(std::shared_ptr<Widget>, const std::string&, const sf::String&, const sf::String&)>;
404 
405  using Signal::connect;
406 
407 
411  SignalItem(std::string&& name) :
412  Signal{std::move(name), 2}
413  {
414  }
415 
416 
424  unsigned int connect(const DelegateItem& handler);
425 
426 
434  unsigned int connect(const DelegateItemEx& handler);
435 
436 
444  unsigned int connect(const DelegateItemAndId& handler);
445 
446 
454  unsigned int connect(const DelegateItemAndIdEx& handler);
455 
456 
461  bool emit(const Widget* widget, const sf::String& item, const sf::String& id)
462  {
463  if (m_handlers.empty())
464  return false;
465 
466  internal_signal::parameters[1] = static_cast<const void*>(&item);
467  internal_signal::parameters[2] = static_cast<const void*>(&id);
468  return Signal::emit(widget);
469  }
470 
471 
477  unsigned int validateTypes(std::initializer_list<std::type_index> unboundParameters) const override;
478 
479 
481  };
482 
483 
492  class TGUI_API SignalAnimation : public Signal
493  {
494  public:
495 
499  SignalAnimation(std::string&& name) :
500  Signal{std::move(name), 2}
501  {
502  }
503 
508  bool emit(const Widget* widget, ShowAnimationType type, bool visible)
509  {
510  if (m_handlers.empty())
511  return false;
512 
513  internal_signal::parameters[1] = static_cast<const void*>(&type);
514  internal_signal::parameters[2] = static_cast<const void*>(&visible);
515  return Signal::emit(widget);
516  }
517 
518 
524  unsigned int validateTypes(std::initializer_list<std::type_index> unboundParameters) const override;
525 
526 
528  };
529 
530 
534  class TGUI_API SignalMenuItem : public Signal
535  {
536  public:
537 
538  using DelegateMenuItem = std::function<void(const sf::String&)>;
539  using DelegateMenuItemFull = std::function<void(const std::vector<sf::String>&)>;
540  using DelegateMenuItemEx = std::function<void(std::shared_ptr<Widget>, const std::string&, const sf::String&)>;
541  using DelegateMenuItemFullEx = std::function<void(std::shared_ptr<Widget>, const std::string&, const std::vector<sf::String>&)>;
542 
543  using Signal::connect;
544 
545 
549  SignalMenuItem(std::string&& name) :
550  Signal{std::move(name), 2}
551  {
552  }
553 
554 
562  unsigned int connect(const DelegateMenuItem& handler);
563 
564 
572  unsigned int connect(const DelegateMenuItemEx& handler);
573 
574 
582  unsigned int connect(const DelegateMenuItemFull& handler);
583 
584 
592  unsigned int connect(const DelegateMenuItemFullEx& handler);
593 
594 
599  bool emit(const Widget* widget, const sf::String& item, const std::vector<sf::String>& fullItem)
600  {
601  if (m_handlers.empty())
602  return false;
603 
604  internal_signal::parameters[1] = static_cast<const void*>(&item);
605  internal_signal::parameters[2] = static_cast<const void*>(&fullItem);
606  return Signal::emit(widget);
607  }
608 
609 
615  unsigned int validateTypes(std::initializer_list<std::type_index> unboundParameters) const override;
616 
617 
619  };
620 
621 
625  class TGUI_API SignalWidgetBase
626  {
627  public:
628 
629  virtual ~SignalWidgetBase() = default;
630 
631 #ifdef TGUI_USE_CPP17
632  template <typename Func, typename... BoundArgs>
642  unsigned int connect(std::string signalName, Func&& handler, const BoundArgs&... args);
643 
644 #else
645  template <typename Func, typename... Args, typename std::enable_if<std::is_convertible<Func, std::function<void(const Args&...)>>::value>::type* = nullptr>
655  unsigned int connect(std::string signalName, Func&& handler, const Args&... args);
656 
657 
668  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>
669  unsigned int connect(std::string signalName, Func&& handler, BoundArgs&&... args);
670 
671 
681  template <typename Func, typename... BoundArgs, typename std::enable_if<!std::is_convertible<Func, std::function<void(const BoundArgs&...)>>::value
682  && !std::is_convertible<Func, std::function<void(const BoundArgs&..., std::shared_ptr<Widget>, const std::string&)>>::value>::type* = nullptr>
683  unsigned int connect(std::string signalName, Func&& handler, BoundArgs&&... args);
684 #endif
685 
695  template <typename Func, typename... BoundArgs>
696  unsigned int connect(std::initializer_list<std::string> signalNames, Func&& handler, BoundArgs&&... args);
697 
698 
706  bool disconnect(unsigned int id);
707 
708 
714  void disconnectAll(std::string signalName);
715 
716 
720  void disconnectAll();
721 
722 
724  protected:
725 
729  virtual Signal& getSignal(std::string signalName) = 0;
730 
731 
733  private:
734 
735  std::map<unsigned int, std::string> m_connectedSignals;
736 
737 
739  };
740 
742 }
743 
745 
746 #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:348
Base class for Widget which provides functionality to connect signals based on their name...
Definition: Signal.hpp:625
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:534
Signal to which the user can subscribe to get callbacks from.
Definition: Signal.hpp:396
SignalRange(std::string &&name)
Constructor.
Definition: Signal.hpp:287
SignalAnimation(std::string &&name)
Constructor.
Definition: Signal.hpp:499
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:335
SignalMenuItem(std::string &&name)
Constructor.
Definition: Signal.hpp:549
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:411
Signal(std::string &&name, std::size_t extraParameters=0)
Constructor.
Definition: Signal.hpp:76
Signal to which the user can subscribe to get callbacks from.
Definition: Signal.hpp:492