TGUI  0.9-dev
SignalManager.hpp
1 //
3 // TGUI - Texus' Graphical User Interface
4 // Copyright (C) 2012-2020 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_MANAGER_HPP
27 #define TGUI_SIGNAL_MANAGER_HPP
28 
29 
30 #include <TGUI/Widget.hpp>
31 #include <memory>
32 
33 
35 
36 namespace tgui
37 {
39 
40  class TGUI_API SignalManager
41  {
42  public:
43 
44  typedef std::shared_ptr<SignalManager> Ptr;
45  typedef std::shared_ptr<const SignalManager> ConstPtr;
46 
47  using Delegate = std::function<void()>;
48  using DelegateEx = std::function<void(std::shared_ptr<Widget>, const String&)>;
49 
50  typedef std::weak_ptr<Widget> Weak;
51  typedef unsigned int SignalID;
52 
53  struct SignalTuple
54  {
55  String widgetName;
56  String signalName;
57  std::pair<Delegate, DelegateEx> func;
58  };
59 
61  {
62  SignalID signalId;
63  Weak widget;
64  unsigned int signalWidgetID;
65  };
66 
70  SignalManager();
71 
75  virtual ~SignalManager();
76 
82  static void setDefaultSignalManager(const SignalManager::Ptr& manager);
83 
89  static SignalManager::Ptr getSignalManager();
90 
91 #if defined(__cpp_if_constexpr) && (__cpp_if_constexpr >= 201606L)
92  template <typename Func, typename... BoundArgs>
103  unsigned int connect(String widgetName, String signalName, Func&& handler, const BoundArgs&... args);
104 
105 #else
106  template <typename Func, typename... Args, typename std::enable_if<std::is_convertible<Func, std::function<void(const Args&...)>>::value>::type* = nullptr>
117  unsigned int connect(String widgetName, String signalName, Func&& handler, const Args&... args);
118 
119 
131  template <typename Func, typename... BoundArgs, typename std::enable_if<!std::is_convertible<Func, std::function<void(const BoundArgs&...)>>::value // Ambigious otherwise when passing bind expression
132  && std::is_convertible<Func, std::function<void(const BoundArgs&..., std::shared_ptr<Widget>, const String&)>>::value>::type* = nullptr>
133  unsigned int connect(String widgetName, String signalName, Func&& handler, BoundArgs&&... args);
134 #endif
135 
143  virtual bool disconnect(unsigned int id);
144 
145 
149  virtual void disconnectAll();
150 
151 
155  virtual void add(const Widget::Ptr& widgetPtr);
156 
157 
161  virtual void remove(Widget* widget);
162 
164  private:
168  unsigned int generateUniqueId();
169 
170  unsigned int m_lastId;
171 
172 
174  protected:
175 
179  std::pair<Delegate, DelegateEx> makeSignal(const Delegate&);
180 
181 
185  std::pair<Delegate, DelegateEx> makeSignalEx(const DelegateEx&);
186 
187 
195  virtual void connect(SignalID id);
196 
197 
199 
200  static SignalManager::Ptr m_manager;
201 
202  std::vector<Weak> m_widgets;
203  std::map<SignalID, SignalTuple> m_signals;
204  std::vector<ConnectedSignalTuple> m_connectedSignals;
205  };
206 
208 
209 #if defined(__cpp_if_constexpr) && (__cpp_if_constexpr >= 201606L)
210  template <typename Func, typename... BoundArgs>
211  unsigned int SignalManager::connect(String widgetName, String signalName, Func&& handler, const BoundArgs&... args)
212  {
213  const unsigned int id = generateUniqueId();
214 
215  if constexpr (std::is_convertible_v<Func, std::function<void(const BoundArgs&...)>>
216  && std::is_invocable_v<decltype(&handler), BoundArgs...>
217  && !std::is_function_v<Func>)
218  {
219  // Reference to function
220  m_signals[id] = {widgetName, signalName, makeSignal([=, f=std::function<void(const BoundArgs&...)>(handler)]{ std::invoke(f, args...); })};
221  }
222  else if constexpr (std::is_convertible_v<Func, std::function<void(const BoundArgs&...)>>)
223  {
224  // Function pointer
225  m_signals[id] = {widgetName, signalName, makeSignal([=]{ std::invoke(handler, args...); })};
226  }
227  else if constexpr (std::is_convertible_v<Func, std::function<void(const BoundArgs&..., const std::shared_ptr<Widget>&, const String&)>>
228  && std::is_invocable_v<decltype(&handler), BoundArgs..., const std::shared_ptr<Widget>&, const String&>
229  && !std::is_function_v<Func>)
230  {
231  // Reference to function with caller arguments
232  m_signals[id] = {widgetName, signalName, makeSignalEx([=, f=std::function<void(const BoundArgs&..., const std::shared_ptr<Widget>& w, const String& s)>(handler)](const std::shared_ptr<Widget>& w, const String& s){ std::invoke(f, args..., w, s); })};
233  }
234  else
235  {
236  // Function pointer with caller arguments
237  m_signals[id] = {widgetName, signalName, makeSignalEx([=](const std::shared_ptr<Widget>& w, const String& s){ std::invoke(handler, args..., w, s); })};
238  }
239 
240  connect(id);
241  return id;
242  }
243 #else
244  template <typename Func, typename... Args, typename std::enable_if<std::is_convertible<Func, std::function<void(const Args&...)>>::value>::type*>
245  unsigned int SignalManager::connect(String widgetName, String signalName, Func&& handler, const Args&... args)
246  {
247  const unsigned int id = generateUniqueId();
248  m_signals[id] = {widgetName, signalName, makeSignal([f=std::function<void(const Args&...)>(handler),args...](){ f(args...); })};
249 
250  connect(id);
251  return id;
252  }
253 
254  template <typename Func, typename... BoundArgs, typename std::enable_if<!std::is_convertible<Func, std::function<void(const BoundArgs&...)>>::value // Ambigious otherwise when passing bind expression
255  && std::is_convertible<Func, std::function<void(const BoundArgs&..., std::shared_ptr<Widget>, const String&)>>::value>::type*>
256  unsigned int SignalManager::connect(String widgetName, String signalName, Func&& handler, BoundArgs&&... args)
257  {
258  const unsigned int id = generateUniqueId();
259  m_signals[id] = {widgetName, signalName, makeSignalEx(
260  [f=std::function<void(const BoundArgs&..., const std::shared_ptr<Widget>&, const String&)>(handler), args...]
261  (const std::shared_ptr<Widget>& w, const String& s)
262  { f(args..., w, s); }
263  )};
264 
265  connect(id);
266  return id;
267  }
268 #endif
269 
271 }
272 
274 
275 #endif // TGUI_SIGNAL_MANAGER_HPP
unsigned int connect(String widgetName, String signalName, Func &&handler, const Args &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: SignalManager.hpp:245
std::shared_ptr< Widget > Ptr
Shared widget pointer.
Definition: Widget.hpp:72
std::shared_ptr< SignalManager > Ptr
Shared widget pointer.
Definition: SignalManager.hpp:44
Namespace that contains all TGUI functions and classes.
Definition: AbsoluteOrRelativeValue.hpp:35
Definition: SignalManager.hpp:60
Definition: SignalManager.hpp:40
Wrapper class to store strings.
Definition: String.hpp:70
The parent class for every widget.
Definition: Widget.hpp:68
Definition: SignalManager.hpp:53
std::shared_ptr< const SignalManager > ConstPtr
Shared constant widget pointer.
Definition: SignalManager.hpp:45