26#ifndef TGUI_SIGNAL_IMPL_HPP
27#define TGUI_SIGNAL_IMPL_HPP
29#include <TGUI/Signal.hpp>
35 namespace internal_signal
37#if defined(__cpp_lib_void_t) && (__cpp_lib_void_t >= 201411L)
46 template <
typename...>
50#if defined(__cpp_if_constexpr) && (__cpp_if_constexpr >= 201606L)
51 template <
typename Type>
52 decltype(
auto) dereference(
const void* obj)
54 if constexpr (std::is_same_v<Type, std::string>)
55 return static_cast<std::string
>(*
static_cast<const sf::String*
>(obj));
56 else if constexpr (std::is_same_v<Type, sf::Vector2f>)
57 return static_cast<sf::Vector2f
>(*
static_cast<const Vector2f*
>(obj));
58 else if constexpr (std::is_same_v<Type, sf::Color>)
59 return static_cast<sf::Color
>(*
static_cast<const Color*
>(obj));
61 return *
static_cast<const std::decay_t<Type>*
>(obj);
64 template <typename Type, typename std::enable_if<std::is_same<Type, std::string>::value>::type* =
nullptr>
65 decltype(
auto) dereference(
const void* obj)
68 return static_cast<std::string
>(*
static_cast<const sf::String*
>(obj));
71 template <typename Type, typename std::enable_if<std::is_same<Type, sf::Vector2f>::value>::type* =
nullptr>
72 decltype(
auto) dereference(
const void* obj)
75 return static_cast<sf::Vector2f
>(*
static_cast<const Vector2f*
>(obj));
78 template <typename Type, typename std::enable_if<std::is_same<Type, sf::Color>::value>::type* =
nullptr>
79 decltype(
auto) dereference(
const void* obj)
82 return static_cast<sf::Color
>(*
static_cast<const Color*
>(obj));
85 template <typename Type, typename std::enable_if<!std::is_same<Type, std::string>::value && !std::is_same<Type, sf::Vector2f>::value && !std::is_same<Type, sf::Color>::value>::type* =
nullptr>
86 decltype(
auto) dereference(
const void* obj)
88 return *
static_cast<const typename std::decay<Type>::type*
>(obj);
92#if !defined(__cpp_lib_invoke) || (__cpp_lib_invoke < 201411L)
95 template <
typename Func,
typename... Args,
typename std::enable_if<std::is_member_pointer<typename std::decay<Func>::type>::value>::type* =
nullptr>
96 void invokeFunc(Func&& func, Args&&... args)
98 std::mem_fn(func)(std::forward<Args>(args)...);
101 template <
typename Func,
typename... Args,
typename std::enable_if<!std::is_member_pointer<typename std::decay<Func>::type>::value>::type* =
nullptr>
102 void invokeFunc(Func&& func, Args&&... args)
104 std::forward<Func>(func)(std::forward<Args>(args)...);
109 template <
typename... Args>
112 template <
typename Arg,
typename... AllArgs,
typename BoundArg,
typename... BoundArgs>
113 struct binder<TypeSet<Arg, AllArgs...>, TypeSet<BoundArg, BoundArgs...>>
114 : binder<TypeSet<AllArgs...>, TypeSet<BoundArgs...>>
118 template <
typename... UnboundArgs>
119 struct binder<TypeSet<std::shared_ptr<Widget>, std::string, UnboundArgs...>, TypeSet<>>
121 template <
typename Func,
typename... BoundArgs>
122 static decltype(
auto) bind(Signal& signal, Func&& func, BoundArgs&&... args)
124 return bindImpl(std::index_sequence_for<UnboundArgs...>{}, signal, std::forward<Func>(func), std::forward<BoundArgs>(args)...);
129 template <
typename Func,
typename... BoundArgs, std::size_t... Indices>
130 static decltype(
auto) bindImpl(std::index_sequence<Indices...>, Signal& signal, Func&& func, BoundArgs&&... args)
132 const std::size_t offset = (
sizeof...(UnboundArgs) > 0) ? signal.validateTypes({
typeid(UnboundArgs)...}) : 0;
133#if defined(__cpp_lib_invoke) && (__cpp_lib_invoke >= 201411L)
134 return [=,o=offset](
const std::shared_ptr<Widget>& widget,
const std::string& signalName) {
139 internal_signal::dereference<UnboundArgs>(internal_signal::parameters[o + Indices])...);
141 return [=,o=offset](
const std::shared_ptr<Widget>& widget,
const std::string& signalName) {
146 internal_signal::dereference<UnboundArgs>(internal_signal::parameters[o + Indices])...);
152 template <
typename... UnboundArgs>
153 struct binder<TypeSet<UnboundArgs...>, TypeSet<>>
155 template <
typename Func,
typename... BoundArgs>
156 static decltype(
auto) bind(Signal& signal, Func&& func, BoundArgs&&... args)
158 return bindImpl(std::index_sequence_for<UnboundArgs...>{}, signal, std::forward<Func>(func), std::forward<BoundArgs>(args)...);
163 template <
typename Func,
typename... BoundArgs, std::size_t... Indices>
164 static decltype(
auto) bindImpl(std::index_sequence<Indices...>, Signal& signal, Func&& func, BoundArgs&&... args)
166 const std::size_t offset = (
sizeof...(UnboundArgs) > 0) ? signal.validateTypes({
typeid(UnboundArgs)...}) : 0;
167#if defined(__cpp_lib_invoke) && (__cpp_lib_invoke >= 201411L)
171 internal_signal::dereference<UnboundArgs>(internal_signal::parameters[o + Indices])...);
176 internal_signal::dereference<UnboundArgs>(internal_signal::parameters[o + Indices])...);
183#if defined(__cpp_noexcept_function_type) && (__cpp_noexcept_function_type >= 201510L)
185 template <
typename Enable,
typename Func,
typename... BoundArgs>
189 template <
typename... Args,
typename... BoundArgs>
190 struct func_traits<void, void(*)(Args...), BoundArgs...> : binder<TypeSet<std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
191 template <
typename... Args,
typename... BoundArgs>
192 struct func_traits<void, void(*)(Args...) noexcept, BoundArgs...> : binder<TypeSet<std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
195 template <
typename Class,
typename... Args,
typename... BoundArgs>
196 struct func_traits<void, void(Class::*)(Args...), BoundArgs...> : binder<TypeSet<Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
197 template <
typename Class,
typename... Args,
typename... BoundArgs>
198 struct func_traits<void, void(Class::*)(Args...) noexcept, BoundArgs...> : binder<TypeSet<Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
199 template <
typename Class,
typename... Args,
typename... BoundArgs>
200 struct func_traits<void, void(Class::*)(Args...) volatile, BoundArgs...> : binder<TypeSet<Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
201 template <
typename Class,
typename... Args,
typename... BoundArgs>
202 struct func_traits<void, void(Class::*)(Args...) volatile noexcept, BoundArgs...> : binder<TypeSet<Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
203 template <
typename Class,
typename... Args,
typename... BoundArgs>
204 struct func_traits<void, void(Class::*)(Args...) &, BoundArgs...> : binder<TypeSet<Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
205 template <
typename Class,
typename... Args,
typename... BoundArgs>
206 struct func_traits<void, void(Class::*)(Args...) & noexcept, BoundArgs...> : binder<TypeSet<Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
207 template <
typename Class,
typename... Args,
typename... BoundArgs>
208 struct func_traits<void, void(Class::*)(Args...) volatile &, BoundArgs...> : binder<TypeSet<Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
209 template <
typename Class,
typename... Args,
typename... BoundArgs>
210 struct func_traits<void, void(Class::*)(Args...) volatile & noexcept, BoundArgs...> : binder<TypeSet<Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
211 template <
typename Class,
typename... Args,
typename... BoundArgs>
212 struct func_traits<void, void(Class::*)(Args...) &&, BoundArgs...> : binder<TypeSet<Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
213 template <
typename Class,
typename... Args,
typename... BoundArgs>
214 struct func_traits<void, void(Class::*)(Args...) && noexcept, BoundArgs...> : binder<TypeSet<Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
215 template <
typename Class,
typename... Args,
typename... BoundArgs>
216 struct func_traits<void, void(Class::*)(Args...) volatile &&, BoundArgs...> : binder<TypeSet<Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
217 template <
typename Class,
typename... Args,
typename... BoundArgs>
218 struct func_traits<void, void(Class::*)(Args...) volatile && noexcept, BoundArgs...> : binder<TypeSet<Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
221 template <
typename Class,
typename... Args,
typename... BoundArgs>
222 struct func_traits<void, void(Class::*)(Args...) const, BoundArgs...> : binder<TypeSet<const Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
223 template <
typename Class,
typename... Args,
typename... BoundArgs>
224 struct func_traits<void, void(Class::*)(Args...) const noexcept, BoundArgs...> : binder<TypeSet<const Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
225 template <
typename Class,
typename... Args,
typename... BoundArgs>
226 struct func_traits<void, void(Class::*)(Args...) volatile const, BoundArgs...> : binder<TypeSet<const Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
227 template <
typename Class,
typename... Args,
typename... BoundArgs>
228 struct func_traits<void, void(Class::*)(Args...) volatile const noexcept, BoundArgs...> : binder<TypeSet<const Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
229 template <
typename Class,
typename... Args,
typename... BoundArgs>
230 struct func_traits<void, void(Class::*)(Args...) const &, BoundArgs...> : binder<TypeSet<const Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
231 template <
typename Class,
typename... Args,
typename... BoundArgs>
232 struct func_traits<void, void(Class::*)(Args...) const & noexcept, BoundArgs...> : binder<TypeSet<const Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
233 template <
typename Class,
typename... Args,
typename... BoundArgs>
234 struct func_traits<void, void(Class::*)(Args...) volatile const &, BoundArgs...> : binder<TypeSet<const Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
235 template <
typename Class,
typename... Args,
typename... BoundArgs>
236 struct func_traits<void, void(Class::*)(Args...) volatile const & noexcept, BoundArgs...> : binder<TypeSet<const Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
237 template <
typename Class,
typename... Args,
typename... BoundArgs>
238 struct func_traits<void, void(Class::*)(Args...) const &&, BoundArgs...> : binder<TypeSet<const Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
239 template <
typename Class,
typename... Args,
typename... BoundArgs>
240 struct func_traits<void, void(Class::*)(Args...) const && noexcept, BoundArgs...> : binder<TypeSet<const Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
241 template <
typename Class,
typename... Args,
typename... BoundArgs>
242 struct func_traits<void, void(Class::*)(Args...) volatile const &&, BoundArgs...> : binder<TypeSet<const Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
243 template <
typename Class,
typename... Args,
typename... BoundArgs>
244 struct func_traits<void, void(Class::*)(Args...) volatile const && noexcept, BoundArgs...> : binder<TypeSet<const Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
247 template <
typename Func,
typename... BoundArgs>
248 struct func_traits<void_t<decltype(&Func::operator())>, Func, BoundArgs...> :
public func_traits<
void,
decltype(&Func::operator()), Func*, BoundArgs...> {};
251 template <
typename Enable,
typename Func,
typename... BoundArgs>
255 template <
typename Func,
typename... BoundArgs>
256 struct func_traits<void_t<decltype(&Func::operator())>, Func, BoundArgs...>
257 :
public func_traits<
void,
decltype(&Func::operator()), Func*, BoundArgs...>
262 template <
typename Class,
typename... Args,
typename... BoundArgs>
263 struct func_traits<void, void(Class::*)(Args...), BoundArgs...>
264 : binder<TypeSet<Class*, typename std::decay<Args>::type...>, TypeSet<BoundArgs...>>
269 template <
typename Class,
typename... Args,
typename... BoundArgs>
270 struct func_traits<void, void(Class::*)(Args...) const, BoundArgs...>
271 : binder<TypeSet<const Class*, typename std::decay<Args>::type...>, TypeSet<BoundArgs...>>
276 template <
typename... Args,
typename... BoundArgs>
277 struct func_traits<void, void(*)(Args...), BoundArgs...>
278 : binder<TypeSet<typename std::decay<Args>::type...>, TypeSet<BoundArgs...>>
286#if defined(__cpp_if_constexpr) && (__cpp_if_constexpr >= 201606L)
287 template <
typename Func,
typename... BoundArgs>
293 if constexpr (std::is_convertible_v<Func, std::function<void(
const BoundArgs&...)>>
294 && std::is_invocable_v<
decltype(&handler), BoundArgs...>
295 && !std::is_function_v<Func>)
298 id = signal.connect([=, f=std::function<
void(
const BoundArgs&...)>(handler)]{ std::invoke(f, args...); });
300 else if constexpr (std::is_convertible_v<Func, std::function<void(
const BoundArgs&...)>>)
303 id = signal.connect([=]{ std::invoke(handler, args...); });
305 else if constexpr (std::is_convertible_v<Func, std::function<void(
const BoundArgs&...,
const std::shared_ptr<Widget>&,
const std::string&)>>
306 && std::is_invocable_v<
decltype(&handler), BoundArgs...,
const std::shared_ptr<Widget>&,
const std::string&>
307 && !std::is_function_v<Func>)
310 id = signal.connect([=, f=std::function<
void(
const BoundArgs&...,
const std::shared_ptr<Widget>& w,
const std::string& s)>(handler)](
const std::shared_ptr<Widget>& w,
const std::string& s){ std::invoke(f, args..., w, s); });
312 else if constexpr (std::is_convertible_v<Func, std::function<void(
const BoundArgs&...,
const std::shared_ptr<Widget>&,
const std::string&)>>)
315 id = signal.connect([=](
const std::shared_ptr<Widget>& w,
const std::string& s){ std::invoke(handler, args..., w, s); });
320 using binder = internal_signal::func_traits<void, std::decay_t<Func>, BoundArgs...>;
321 id = signal.connect(binder::bind(signal, std::forward<Func>(handler), args...));
324 m_connectedSignals[id] =
toLower(signalName);
329 template <
typename Func,
typename... Args,
typename std::enable_if<std::is_convertible<Func, std::function<void(
const Args&...)>>::value>::type*>
332 const unsigned int id =
getSignal(
toLower(signalName)).
connect([f=std::function<
void(
const Args&...)>(handler),args...](){ f(args...); });
333 m_connectedSignals[id] =
toLower(signalName);
337 template <
typename Func,
typename... BoundArgs,
typename std::enable_if<!std::is_convertible<Func, std::function<void(
const BoundArgs&...)>>::value
338 && std::is_convertible<Func, std::function<void(
const BoundArgs&..., std::shared_ptr<Widget>,
const std::string&)>>::value>::type*>
342 [f=std::function<
void(
const BoundArgs&...,
const std::shared_ptr<Widget>&,
const std::string&)>(handler), args...]
343 (
const std::shared_ptr<Widget>& w,
const std::string& s)
344 { f(args..., w, s); }
347 m_connectedSignals[id] =
toLower(signalName);
351 template <
typename Func,
typename... BoundArgs,
typename std::enable_if<!std::is_convertible<Func, std::function<void(
const BoundArgs&...)>>::value
352 && !std::is_convertible<Func, std::function<void(
const BoundArgs&..., std::shared_ptr<Widget>,
const std::string&)>>::value>::type*>
356 using binder = internal_signal::func_traits<void, typename std::decay<Func>::type, BoundArgs...>;
357 const unsigned int id = signal.
connect(binder::bind(signal, std::forward<Func>(handler), std::forward<BoundArgs>(args)...));
358 m_connectedSignals[id] =
toLower(signalName);
365 template <
typename Func,
typename... BoundArgs>
368 unsigned int lastId = 0;
369 for (
auto& signalName : signalNames)
370 lastId =
connect(std::move(signalName), handler, args...);
Signal to which the user can subscribe to get callbacks from.
Definition: Signal.hpp:231
unsigned int connect(const Delegate &handler)
Connects a signal handler that will be called when this signal is emitted.
Namespace that contains all TGUI functions and classes.
Definition: AbsoluteOrRelativeValue.hpp:37
TGUI_API std::string toLower(const std::string &str)
Converts a string to lowercase.