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));
59 return *
static_cast<const std::decay_t<Type>*
>(obj);
62 template <typename Type, typename std::enable_if<std::is_same<Type, std::string>::value>::type* =
nullptr>
63 decltype(
auto) dereference(const
void* obj)
66 return static_cast<std::string
>(*
static_cast<const sf::String*
>(obj));
69 template <typename Type, typename std::enable_if<std::is_same<Type, sf::Vector2f>::value>::type* =
nullptr>
70 decltype(
auto) dereference(const
void* obj)
73 return static_cast<sf::Vector2f
>(*
static_cast<const Vector2f*
>(obj));
76 template <typename Type, typename std::enable_if<!std::is_same<Type, std::string>::value && !std::is_same<Type, sf::Vector2f>::value>::type* =
nullptr>
77 decltype(
auto) dereference(const
void* obj)
79 return *
static_cast<const typename std::decay<Type>::type*
>(obj);
83 #if !defined(__cpp_lib_invoke) || (__cpp_lib_invoke < 201411L)
86 template <
typename Func,
typename... Args,
typename std::enable_if<std::is_member_pointer<typename std::decay<Func>::type>::value>::type* =
nullptr>
87 void invokeFunc(Func&& func, Args&&... args)
89 std::mem_fn(func)(std::forward<Args>(args)...);
92 template <
typename Func,
typename... Args,
typename std::enable_if<!std::is_member_pointer<typename std::decay<Func>::type>::value>::type* =
nullptr>
93 void invokeFunc(Func&& func, Args&&... args)
95 std::forward<Func>(func)(std::forward<Args>(args)...);
100 template <
typename... Args>
103 template <
typename Arg,
typename... AllArgs,
typename BoundArg,
typename... BoundArgs>
104 struct binder<TypeSet<Arg, AllArgs...>, TypeSet<BoundArg, BoundArgs...>>
105 : binder<TypeSet<AllArgs...>, TypeSet<BoundArgs...>>
109 template <
typename... UnboundArgs>
110 struct binder<TypeSet<std::shared_ptr<Widget>, std::string, UnboundArgs...>, TypeSet<>>
112 template <
typename Func,
typename... BoundArgs>
113 static decltype(
auto) bind(Signal& signal, Func&& func, BoundArgs&&... args)
115 return bindImpl(std::index_sequence_for<UnboundArgs...>{}, signal, std::forward<Func>(func), std::forward<BoundArgs>(args)...);
120 template <
typename Func,
typename... BoundArgs, std::size_t... Indices>
121 static decltype(
auto) bindImpl(std::index_sequence<Indices...>, Signal& signal, Func&& func, BoundArgs&&... args)
123 const std::size_t offset = (
sizeof...(UnboundArgs) > 0) ? signal.validateTypes({
typeid(UnboundArgs)...}) : 0;
124 #if defined(__cpp_lib_invoke) && (__cpp_lib_invoke >= 201411L)
125 return [=,o=offset](
const std::shared_ptr<Widget>& widget,
const std::string& signalName) {
130 internal_signal::dereference<UnboundArgs>(internal_signal::parameters[o + Indices])...);
132 return [=,o=offset](
const std::shared_ptr<Widget>& widget,
const std::string& signalName) {
137 internal_signal::dereference<UnboundArgs>(internal_signal::parameters[o + Indices])...);
143 template <
typename... UnboundArgs>
144 struct binder<TypeSet<UnboundArgs...>, TypeSet<>>
146 template <
typename Func,
typename... BoundArgs>
147 static decltype(
auto) bind(Signal& signal, Func&& func, BoundArgs&&... args)
149 return bindImpl(std::index_sequence_for<UnboundArgs...>{}, signal, std::forward<Func>(func), std::forward<BoundArgs>(args)...);
154 template <
typename Func,
typename... BoundArgs, std::size_t... Indices>
155 static decltype(
auto) bindImpl(std::index_sequence<Indices...>, Signal& signal, Func&& func, BoundArgs&&... args)
157 const std::size_t offset = (
sizeof...(UnboundArgs) > 0) ? signal.validateTypes({
typeid(UnboundArgs)...}) : 0;
158 #if defined(__cpp_lib_invoke) && (__cpp_lib_invoke >= 201411L)
162 internal_signal::dereference<UnboundArgs>(internal_signal::parameters[o + Indices])...);
167 internal_signal::dereference<UnboundArgs>(internal_signal::parameters[o + Indices])...);
174 #if defined(__cpp_noexcept_function_type) && (__cpp_noexcept_function_type >= 201510L)
176 template <
typename Enable,
typename Func,
typename... BoundArgs>
180 template <
typename... Args,
typename... BoundArgs>
181 struct func_traits<void, void(*)(Args...), BoundArgs...> : binder<TypeSet<std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
182 template <
typename... Args,
typename... BoundArgs>
183 struct func_traits<void, void(*)(Args...) noexcept, BoundArgs...> : binder<TypeSet<std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
186 template <
typename Class,
typename... Args,
typename... BoundArgs>
187 struct func_traits<void, void(Class::*)(Args...), BoundArgs...> : binder<TypeSet<Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
188 template <
typename Class,
typename... Args,
typename... BoundArgs>
189 struct func_traits<void, void(Class::*)(Args...) noexcept, BoundArgs...> : binder<TypeSet<Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
190 template <
typename Class,
typename... Args,
typename... BoundArgs>
191 struct func_traits<void, void(Class::*)(Args...) volatile, BoundArgs...> : binder<TypeSet<Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
192 template <
typename Class,
typename... Args,
typename... BoundArgs>
193 struct func_traits<void, void(Class::*)(Args...) volatile noexcept, BoundArgs...> : binder<TypeSet<Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
194 template <
typename Class,
typename... Args,
typename... BoundArgs>
195 struct func_traits<void, void(Class::*)(Args...) &, BoundArgs...> : binder<TypeSet<Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
196 template <
typename Class,
typename... Args,
typename... BoundArgs>
197 struct func_traits<void, void(Class::*)(Args...) & noexcept, BoundArgs...> : binder<TypeSet<Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
198 template <
typename Class,
typename... Args,
typename... BoundArgs>
199 struct func_traits<void, void(Class::*)(Args...) volatile &, BoundArgs...> : binder<TypeSet<Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
200 template <
typename Class,
typename... Args,
typename... BoundArgs>
201 struct func_traits<void, void(Class::*)(Args...) volatile & noexcept, BoundArgs...> : binder<TypeSet<Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
202 template <
typename Class,
typename... Args,
typename... BoundArgs>
203 struct func_traits<void, void(Class::*)(Args...) &&, BoundArgs...> : binder<TypeSet<Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
204 template <
typename Class,
typename... Args,
typename... BoundArgs>
205 struct func_traits<void, void(Class::*)(Args...) && noexcept, BoundArgs...> : binder<TypeSet<Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
206 template <
typename Class,
typename... Args,
typename... BoundArgs>
207 struct func_traits<void, void(Class::*)(Args...) volatile &&, BoundArgs...> : binder<TypeSet<Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
208 template <
typename Class,
typename... Args,
typename... BoundArgs>
209 struct func_traits<void, void(Class::*)(Args...) volatile && noexcept, BoundArgs...> : binder<TypeSet<Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
212 template <
typename Class,
typename... Args,
typename... BoundArgs>
213 struct func_traits<void, void(Class::*)(Args...) const, BoundArgs...> : binder<TypeSet<const Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
214 template <
typename Class,
typename... Args,
typename... BoundArgs>
215 struct func_traits<void, void(Class::*)(Args...) const noexcept, BoundArgs...> : binder<TypeSet<const Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
216 template <
typename Class,
typename... Args,
typename... BoundArgs>
217 struct func_traits<void, void(Class::*)(Args...) volatile const, BoundArgs...> : binder<TypeSet<const Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
218 template <
typename Class,
typename... Args,
typename... BoundArgs>
219 struct func_traits<void, void(Class::*)(Args...) volatile const noexcept, BoundArgs...> : binder<TypeSet<const Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
220 template <
typename Class,
typename... Args,
typename... BoundArgs>
221 struct func_traits<void, void(Class::*)(Args...) const &, BoundArgs...> : binder<TypeSet<const Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
222 template <
typename Class,
typename... Args,
typename... BoundArgs>
223 struct func_traits<void, void(Class::*)(Args...) const & noexcept, BoundArgs...> : binder<TypeSet<const Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
224 template <
typename Class,
typename... Args,
typename... BoundArgs>
225 struct func_traits<void, void(Class::*)(Args...) volatile const &, BoundArgs...> : binder<TypeSet<const Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
226 template <
typename Class,
typename... Args,
typename... BoundArgs>
227 struct func_traits<void, void(Class::*)(Args...) volatile const & noexcept, BoundArgs...> : binder<TypeSet<const Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
228 template <
typename Class,
typename... Args,
typename... BoundArgs>
229 struct func_traits<void, void(Class::*)(Args...) const &&, BoundArgs...> : binder<TypeSet<const Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
230 template <
typename Class,
typename... Args,
typename... BoundArgs>
231 struct func_traits<void, void(Class::*)(Args...) const && noexcept, BoundArgs...> : binder<TypeSet<const Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
232 template <
typename Class,
typename... Args,
typename... BoundArgs>
233 struct func_traits<void, void(Class::*)(Args...) volatile const &&, BoundArgs...> : binder<TypeSet<const Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
234 template <
typename Class,
typename... Args,
typename... BoundArgs>
235 struct func_traits<void, void(Class::*)(Args...) volatile const && noexcept, BoundArgs...> : binder<TypeSet<const Class*, std::decay_t<Args>...>, TypeSet<BoundArgs...>> {};
238 template <
typename Func,
typename... BoundArgs>
239 struct func_traits<void_t<decltype(&Func::operator())>, Func, BoundArgs...> :
public func_traits<
void, decltype(&Func::operator()), Func*, BoundArgs...> {};
242 template <
typename Enable,
typename Func,
typename... BoundArgs>
246 template <
typename Func,
typename... BoundArgs>
247 struct func_traits<void_t<decltype(&Func::operator())>, Func, BoundArgs...>
248 :
public func_traits<
void, decltype(&Func::operator()), Func*, BoundArgs...>
253 template <
typename Class,
typename... Args,
typename... BoundArgs>
254 struct func_traits<void, void(Class::*)(Args...), BoundArgs...>
255 : binder<TypeSet<Class*, typename std::decay<Args>::type...>, TypeSet<BoundArgs...>>
260 template <
typename Class,
typename... Args,
typename... BoundArgs>
261 struct func_traits<void, void(Class::*)(Args...) const, BoundArgs...>
262 : binder<TypeSet<const Class*, typename std::decay<Args>::type...>, TypeSet<BoundArgs...>>
267 template <
typename... Args,
typename... BoundArgs>
268 struct func_traits<void, void(*)(Args...), BoundArgs...>
269 : binder<TypeSet<typename std::decay<Args>::type...>, TypeSet<BoundArgs...>>
277 #if defined(__cpp_if_constexpr) && (__cpp_if_constexpr >= 201606L)
278 template <
typename Func,
typename... BoundArgs>
284 if constexpr (std::is_convertible_v<Func, std::function<
void(
const BoundArgs&...)>>
285 && std::is_invocable_v<decltype(&handler), BoundArgs...>
286 && !std::is_function_v<Func>)
289 id = signal.connect([=, f=std::function<
void(
const BoundArgs&...)>(handler)]{ std::invoke(f, args...); });
291 else if constexpr (std::is_convertible_v<Func, std::function<
void(
const BoundArgs&...)>>)
294 id = signal.connect([=]{ std::invoke(handler, args...); });
296 else if constexpr (std::is_convertible_v<Func, std::function<
void(
const BoundArgs&...,
const std::shared_ptr<Widget>&,
const std::string&)>>
297 && std::is_invocable_v<decltype(&handler), BoundArgs...,
const std::shared_ptr<Widget>&,
const std::string&>
298 && !std::is_function_v<Func>)
301 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); });
303 else if constexpr (std::is_convertible_v<Func, std::function<
void(
const BoundArgs&...,
const std::shared_ptr<Widget>&,
const std::string&)>>)
306 id = signal.connect([=](
const std::shared_ptr<Widget>& w,
const std::string& s){ std::invoke(handler, args..., w, s); });
311 using binder = internal_signal::func_traits<void, std::decay_t<Func>, BoundArgs...>;
312 id = signal.connect(binder::bind(signal, std::forward<Func>(handler), args...));
315 m_connectedSignals[id] =
toLower(signalName);
320 template <
typename Func,
typename... Args,
typename std::enable_if<std::is_convertible<Func, std::function<void(
const Args&...)>>::value>::type*>
323 const unsigned int id =
getSignal(
toLower(signalName)).
connect([f=std::function<
void(
const Args&...)>(handler),args...](){ f(args...); });
324 m_connectedSignals[id] =
toLower(signalName);
328 template <
typename Func,
typename... BoundArgs,
typename std::enable_if<!std::is_convertible<Func, std::function<void(
const BoundArgs&...)>>::value
329 && std::is_convertible<Func, std::function<void(
const BoundArgs&..., std::shared_ptr<Widget>,
const std::string&)>>::value>::type*>
333 [f=std::function<
void(
const BoundArgs&...,
const std::shared_ptr<Widget>&,
const std::string&)>(handler), args...]
334 (
const std::shared_ptr<Widget>& w,
const std::string& s)
335 { f(args..., w, s); }
338 m_connectedSignals[id] =
toLower(signalName);
342 template <
typename Func,
typename... BoundArgs,
typename std::enable_if<!std::is_convertible<Func, std::function<void(
const BoundArgs&...)>>::value
343 && !std::is_convertible<Func, std::function<void(
const BoundArgs&..., std::shared_ptr<Widget>,
const std::string&)>>::value>::type*>
347 using binder = internal_signal::func_traits<void, typename std::decay<Func>::type, BoundArgs...>;
348 const unsigned int id = signal.
connect(binder::bind(signal, std::forward<Func>(handler), std::forward<BoundArgs>(args)...));
349 m_connectedSignals[id] =
toLower(signalName);
356 template <
typename Func,
typename... BoundArgs>
359 unsigned int lastId = 0;
360 for (
auto& signalName : signalNames)
361 lastId =
connect(std::move(signalName), handler, args...);
369 #endif // TGUI_SIGNAL_IMPL_HPP