TGUI  0.10-dev
Signal.hpp
1
2//
3// TGUI - Texus' Graphical User Interface
4// Copyright (C) 2012-2021 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/String.hpp>
33#include <TGUI/Color.hpp>
34#include <TGUI/Vector2.hpp>
35#include <TGUI/Animation.hpp>
36#include <TGUI/Filesystem.hpp>
37#include <unordered_map>
38#include <type_traits>
39#include <functional>
40#include <typeindex>
41#include <memory>
42#include <vector>
43#include <deque>
44
45#undef MessageBox // windows.h defines MessageBox when NOMB isn't defined before including windows.h
46
48
49namespace tgui
50{
51 class Widget;
52 class ChildWindow;
53
57 class TGUI_API Signal
58 {
59 public:
60
64 virtual ~Signal() = default;
65
66
73 Signal(String&& name, std::size_t extraParameters = 0) :
74 m_name{std::move(name)}
75 {
76 if (1 + extraParameters > m_parameters.size())
77 m_parameters.resize(1 + extraParameters);
78 }
79
80
84 Signal(const Signal& other);
85
86
90 Signal(Signal&& other) noexcept = default;
91
92
96 Signal& operator=(const Signal& other);
97
98
102 Signal& operator=(Signal&& other) noexcept = default;
103
104
113 template <typename Func, typename... BoundArgs>
114 unsigned int operator()(const Func& func, const BoundArgs&... args)
115 {
116 return connect(func, args...);
117 }
118
119
128 template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&...)>>::value>* = nullptr>
129 unsigned int connect(const Func& func, const BoundArgs&... args)
130 {
131 const auto id = ++m_lastSignalId;
132#if defined(__cpp_if_constexpr) && (__cpp_if_constexpr >= 201606L)
133 if constexpr(sizeof...(BoundArgs) == 0)
134 m_handlers[id] = func;
135 else
136#endif
137 {
138 m_handlers[id] = [=]{ invokeFunc(func, args...); };
139 }
140
141 return id;
142 }
143
144
153 template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&..., std::shared_ptr<Widget>, const String&)>>::value>* = nullptr>
154 unsigned int connectEx(const Func& func, const BoundArgs&... args)
155 {
156 // The name is copied so that the lambda does not depend on the 'this' pointer
157 return connect([func, name=m_name, args...](){ invokeFunc(func, args..., getWidget(), name); });
158 }
159
160
168 bool disconnect(unsigned int id);
169
170
175
176
184 bool emit(const Widget* widget);
185
186
193 {
194 return m_name;
195 }
196
197
206 void setEnabled(bool enabled)
207 {
208 m_enabled = enabled;
209 }
210
211
220 bool isEnabled() const
221 {
222 return m_enabled;
223 }
224
225
227 protected:
228
232 static std::shared_ptr<Widget> getWidget();
233
234
238 template <typename Type>
239 static const std::decay_t<Type>& dereferenceParam(std::size_t paramIndex)
240 {
241 return *static_cast<const std::decay_t<Type>*>(m_parameters[paramIndex]);
242 }
243
244
245#if defined(__cpp_lib_invoke) && (__cpp_lib_invoke >= 201411L)
246 template <typename Func, typename... Args>
247 static void invokeFunc(Func&& func, Args&&... args)
248 {
249 std::invoke(std::forward<Func>(func), std::forward<Args>(args)...);
250 }
251#else
252 // std::invoke only exists in c++17 so we use our own implementation to support c++14 compilers
253 template <typename Func, typename... Args, typename std::enable_if<std::is_member_pointer<typename std::decay<Func>::type>::value>::type* = nullptr>
254 static void invokeFunc(Func&& func, Args&&... args)
255 {
256 std::mem_fn(func)(std::forward<Args>(args)...);
257 }
258
259 template <typename Func, typename... Args, typename std::enable_if<!std::is_member_pointer<typename std::decay<Func>::type>::value>::type* = nullptr>
260 static void invokeFunc(Func&& func, Args&&... args)
261 {
262 std::forward<Func>(func)(std::forward<Args>(args)...);
263 }
264#endif
265
266
268 protected:
269
270 bool m_enabled = true;
271 String m_name;
272 std::unordered_map<unsigned int, std::function<void()>> m_handlers;
273
274 static unsigned int m_lastSignalId;
275 static std::deque<const void*> m_parameters;
276 };
277
278
285 template <typename T>
286 class SignalTyped : public Signal
287 {
288 public:
289
294 Signal{std::move(name), 1}
295 {
296 }
297
298
307 template <typename Func, typename... BoundArgs>
308 unsigned int operator()(const Func& func, const BoundArgs&... args)
309 {
310 return connect(func, args...);
311 }
312
313
322 template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&...)>>::value>* = nullptr>
323 unsigned int connect(const Func& func, const BoundArgs&... args)
324 {
325 return Signal::connect(func, args...);
326 }
327
328
337 template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&..., T)>>::value>* = nullptr>
338 unsigned int connect(const Func& func, const BoundArgs&... args)
339 {
340 return Signal::connect([=]{ invokeFunc(func, args..., dereferenceParam<T>(1)); });
341 }
342
343
352 bool emit(const Widget* widget, T param)
353 {
354 if (m_handlers.empty())
355 return false;
356
357 m_parameters[1] = static_cast<const void*>(&param);
358 return Signal::emit(widget);
359 }
360 };
361
362
369 template <typename T1, typename T2>
370 class SignalTyped2 : public Signal
371 {
372 public:
373
378 Signal{std::move(name), 2}
379 {
380 }
381
382
391 template <typename Func, typename... BoundArgs>
392 unsigned int operator()(const Func& func, const BoundArgs&... args)
393 {
394 return connect(func, args...);
395 }
396
397
406 template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&...)>>::value>* = nullptr>
407 unsigned int connect(const Func& func, const BoundArgs&... args)
408 {
409 return Signal::connect(func, args...);
410 }
411
412
421 template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&..., T1, T2)>>::value>* = nullptr>
422 unsigned int connect(const Func& func, const BoundArgs&... args)
423 {
424 return Signal::connect([=]{ invokeFunc(func, args..., dereferenceParam<T1>(1), dereferenceParam<T2>(2)); });
425 }
426
427
437 bool emit(const Widget* widget, T1 param1, T2 param2)
438 {
439 if (m_handlers.empty())
440 return false;
441
442 m_parameters[1] = static_cast<const void*>(&param1);
443 m_parameters[2] = static_cast<const void*>(&param2);
444 return Signal::emit(widget);
445 }
446 };
447
458
459
466 class TGUI_API SignalChildWindow : public Signal
467 {
468 public:
469
474 Signal{std::move(name), 1}
475 {
476 }
477
478
487 template <typename Func, typename... BoundArgs>
488 unsigned int operator()(const Func& func, const BoundArgs&... args)
489 {
490 return connect(func, args...);
491 }
492
493
502 template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&...)>>::value>* = nullptr>
503 unsigned int connect(const Func& func, const BoundArgs&... args)
504 {
505 return Signal::connect(func, args...);
506 }
507
508
517 template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&..., const std::shared_ptr<ChildWindow>&)>>::value>* = nullptr>
518 unsigned int connect(const Func& func, const BoundArgs&... args)
519 {
520 return Signal::connect([=]{ invokeFunc(func, args..., dereferenceChildWindow()); });
521 }
522
523
531 bool emit(ChildWindow* param);
532
533
535 private:
536
540 static std::shared_ptr<ChildWindow> dereferenceChildWindow();
541
542
544 };
545
546
555 class TGUI_API SignalItem : public Signal
556 {
557 public:
558
563 Signal{std::move(name), 3}
564 {
565 }
566
567
576 template <typename Func, typename... BoundArgs>
577 unsigned int operator()(const Func& func, const BoundArgs&... args)
578 {
579 return connect(func, args...);
580 }
581
582
591 template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&...)>>::value>* = nullptr>
592 unsigned int connect(const Func& func, const BoundArgs&... args)
593 {
594 return Signal::connect(func, args...);
595 }
596
597
606 template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&..., int)>>::value>* = nullptr>
607 unsigned int connect(const Func& func, const BoundArgs&... args)
608 {
609 return Signal::connect([=]{ invokeFunc(func, args..., dereferenceParam<int>(1)); });
610 }
611
612
621 template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&..., const String&)>>::value>* = nullptr>
622 unsigned int connect(const Func& func, const BoundArgs&... args)
623 {
624 return Signal::connect([=]{ invokeFunc(func, args..., dereferenceParam<String>(2)); });
625 }
626
627
636 template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&..., const String&, const String&)>>::value>* = nullptr>
637 unsigned int connect(const Func& func, const BoundArgs&... args)
638 {
639 return Signal::connect([=]{ invokeFunc(func, args..., dereferenceParam<String>(2), dereferenceParam<String>(3)); });
640 }
641
642
653 bool emit(const Widget* widget, int index, const String& item, const String& id);
654
655
657 };
658
659
668 class TGUI_API SignalAnimation : public Signal
669 {
670 public:
671
676 Signal{std::move(name), 2}
677 {
678 }
679
680
689 template <typename Func, typename... BoundArgs>
690 unsigned int operator()(const Func& func, const BoundArgs&... args)
691 {
692 return connect(func, args...);
693 }
694
695
704 template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&...)>>::value>* = nullptr>
705 unsigned int connect(const Func& func, const BoundArgs&... args)
706 {
707 return Signal::connect(func, args...);
708 }
709
710
719 template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&..., ShowAnimationType)>>::value>* = nullptr>
720 unsigned int connect(const Func& func, const BoundArgs&... args)
721 {
722 return Signal::connect([=]{ invokeFunc(func, args..., dereferenceParam<ShowAnimationType>(1)); });
723 }
724
725
734 template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&..., bool)>>::value>* = nullptr>
735 unsigned int connect(const Func& func, const BoundArgs&... args)
736 {
737 return Signal::connect([=]{ invokeFunc(func, args..., dereferenceParam<bool>(2)); });
738 }
739
740
749 template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&..., ShowAnimationType, bool)>>::value>* = nullptr>
750 unsigned int connect(const Func& func, const BoundArgs&... args)
751 {
752 return Signal::connect([=]{ invokeFunc(func, args..., dereferenceParam<ShowAnimationType>(1), dereferenceParam<bool>(2)); });
753 }
754
755
765 bool emit(const Widget* widget, ShowAnimationType type, bool visible);
766
767
769 };
770
771
779 class TGUI_API SignalItemHierarchy : public Signal
780 {
781 public:
782
787 Signal{std::move(name), 2}
788 {
789 }
790
791
800 template <typename Func, typename... BoundArgs>
801 unsigned int operator()(const Func& func, const BoundArgs&... args)
802 {
803 return connect(func, args...);
804 }
805
806
815 template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&...)>>::value>* = nullptr>
816 unsigned int connect(const Func& func, const BoundArgs&... args)
817 {
818 return Signal::connect(func, args...);
819 }
820
821
830 template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&..., const String&)>>::value>* = nullptr>
831 unsigned int connect(const Func& func, const BoundArgs&... args)
832 {
833 return Signal::connect([=]{ invokeFunc(func, args..., dereferenceParam<String>(1)); });
834 }
835
836
845 template <typename Func, typename... BoundArgs, typename std::enable_if_t<std::is_convertible<Func, std::function<void(const BoundArgs&..., const std::vector<String>&)>>::value>* = nullptr>
846 unsigned int connect(const Func& func, const BoundArgs&... args)
847 {
848 return Signal::connect([=]{ invokeFunc(func, args..., dereferenceParam<std::vector<String>>(2)); });
849 }
850
851
861 bool emit(const Widget* widget, const String& item, const std::vector<String>& fullItem);
862
863
865 };
866
868}
869
871
872#endif // TGUI_SIGNAL_HPP
Child window widget.
Definition: ChildWindow.hpp:44
Signal to which the user can subscribe to get callbacks from.
Definition: Signal.hpp:669
SignalAnimation(String &&name)
Constructor.
Definition: Signal.hpp:675
unsigned int operator()(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:690
unsigned int connect(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:705
bool emit(const Widget *widget, ShowAnimationType type, bool visible)
Call all connected signal handlers.
Signal to which the user can subscribe to get callbacks from.
Definition: Signal.hpp:467
SignalChildWindow(String &&name)
Constructor.
Definition: Signal.hpp:473
bool emit(ChildWindow *param)
Call all connected signal handlers.
unsigned int connect(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:518
unsigned int operator()(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:488
unsigned int connect(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:503
Signal to which the user can subscribe to get callbacks from.
Definition: Signal.hpp:780
unsigned int connect(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:846
unsigned int connect(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:816
SignalItemHierarchy(String &&name)
Constructor.
Definition: Signal.hpp:786
bool emit(const Widget *widget, const String &item, const std::vector< String > &fullItem)
Call all connected signal handlers.
unsigned int operator()(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:801
Signal to which the user can subscribe to get callbacks from.
Definition: Signal.hpp:556
bool emit(const Widget *widget, int index, const String &item, const String &id)
Call all connected signal handlers.
unsigned int operator()(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:577
SignalItem(String &&name)
Constructor.
Definition: Signal.hpp:562
unsigned int connect(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:592
Signal to which the user can subscribe to get callbacks from.
Definition: Signal.hpp:371
bool emit(const Widget *widget, T1 param1, T2 param2)
Call all connected signal handlers.
Definition: Signal.hpp:437
unsigned int connect(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:407
SignalTyped2(String &&name)
Constructor.
Definition: Signal.hpp:377
unsigned int operator()(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:392
Signal to which the user can subscribe to get callbacks from.
Definition: Signal.hpp:287
SignalTyped(String &&name)
Constructor.
Definition: Signal.hpp:293
unsigned int operator()(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:308
bool emit(const Widget *widget, T param)
Call all connected signal handlers.
Definition: Signal.hpp:352
unsigned int connect(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:323
Signal to which the user can subscribe to get callbacks from.
Definition: Signal.hpp:58
bool emit(const Widget *widget)
Call all connected signal handlers.
Signal(const Signal &other)
Copy constructor which will not copy the signal handlers.
static const std::decay_t< Type > & dereferenceParam(std::size_t paramIndex)
Turns the void* parameters back into its original type right before calling the callback function.
Definition: Signal.hpp:239
unsigned int operator()(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:114
bool isEnabled() const
Returns whether this signal calls the connected functions when triggered.
Definition: Signal.hpp:220
void disconnectAll()
Disconnect all signal handler from this signal.
void setEnabled(bool enabled)
Changes whether this signal calls the connected functions when triggered.
Definition: Signal.hpp:206
bool disconnect(unsigned int id)
Disconnect a signal handler from this signal.
Signal & operator=(const Signal &other)
Copy assignment operator which will not copy the signal handlers.
String getName() const
Returns the name given to the signal.
Definition: Signal.hpp:192
unsigned int connect(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:129
virtual ~Signal()=default
Default destructor.
Signal(String &&name, std::size_t extraParameters=0)
Constructor.
Definition: Signal.hpp:73
Signal & operator=(Signal &&other) noexcept=default
Default move assignment operator.
Signal(Signal &&other) noexcept=default
Default move constructor.
static std::shared_ptr< Widget > getWidget()
Extracts the widget stored in the first parameter.
unsigned int connectEx(const Func &func, const BoundArgs &... args)
Connects a signal handler that will be called when this signal is emitted.
Definition: Signal.hpp:154
Wrapper class to store strings.
Definition: String.hpp:79
The parent class for every widget.
Definition: Widget.hpp:70
Namespace that contains all TGUI functions and classes.
Definition: AbsoluteOrRelativeValue.hpp:36
ShowAnimationType
Type of animation to show/hide widget.
Definition: Animation.hpp:44