|
@@ -7,24 +7,10 @@
|
|
|
#include <memory>
|
|
#include <memory>
|
|
|
#include <typeindex>
|
|
#include <typeindex>
|
|
|
|
|
|
|
|
-#include <iostream>
|
|
|
|
|
-#include <vector>
|
|
|
|
|
-#include <functional>
|
|
|
|
|
-#include <memory>
|
|
|
|
|
#include <typeinfo>
|
|
#include <typeinfo>
|
|
|
-#include <typeindex>
|
|
|
|
|
#include <tuple>
|
|
#include <tuple>
|
|
|
#include <stdexcept>
|
|
#include <stdexcept>
|
|
|
-#include <algorithm>
|
|
|
|
|
-
|
|
|
|
|
-#include <iostream>
|
|
|
|
|
-#include <functional>
|
|
|
|
|
#include <unordered_map>
|
|
#include <unordered_map>
|
|
|
-#include <vector>
|
|
|
|
|
-#include <tuple>
|
|
|
|
|
-#include <typeindex>
|
|
|
|
|
-#include <string>
|
|
|
|
|
-#include <algorithm>
|
|
|
|
|
#include <cassert>
|
|
#include <cassert>
|
|
|
|
|
|
|
|
enum class EventType {
|
|
enum class EventType {
|
|
@@ -56,6 +42,8 @@ public:
|
|
|
vec.end());
|
|
vec.end());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
|
+#if 0
|
|
|
// Emit: returns vector of return values from all handlers of matching type/signature
|
|
// Emit: returns vector of return values from all handlers of matching type/signature
|
|
|
template<typename R = void, typename... Args>
|
|
template<typename R = void, typename... Args>
|
|
|
std::vector<R> emit(EventType type, Args&&... args) {
|
|
std::vector<R> emit(EventType type, Args&&... args) {
|
|
@@ -72,10 +60,70 @@ public:
|
|
|
results.push_back(handler->func(std::forward<Args>(args)...));
|
|
results.push_back(handler->func(std::forward<Args>(args)...));
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+ // std::cout << "Error handler NULL" << std::endl;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
return results;
|
|
return results;
|
|
|
}
|
|
}
|
|
|
|
|
+#else
|
|
|
|
|
+ template<typename R = void, typename... Args>
|
|
|
|
|
+ std::vector<R> emit(EventType type, Args&&... args) {
|
|
|
|
|
+ // Log Args... information
|
|
|
|
|
+ // std::cout << "Args... types: ";
|
|
|
|
|
+ // printArgs<Args...>();
|
|
|
|
|
+ // std::cout << std::endl;
|
|
|
|
|
+
|
|
|
|
|
+ std::vector<R> results;
|
|
|
|
|
+ auto it = handlers.find(type);
|
|
|
|
|
+ if (it != handlers.end()) {
|
|
|
|
|
+ for (auto& handlerBase : it->second) {
|
|
|
|
|
+ std::cout << "\n------------------------- emit ------------------------" << std::endl;
|
|
|
|
|
+ if (std::is_void<R>::value) {
|
|
|
|
|
+ std::cout << "Handler is void" << std::endl;
|
|
|
|
|
+ // Call handlers with a void return type
|
|
|
|
|
+ auto handler = dynamic_cast<Handler<void, Args...>*>(handlerBase.get());
|
|
|
|
|
+ std::cout << "Dynamic cast result (void): " << handler << std::endl;
|
|
|
|
|
+ if (handler) {
|
|
|
|
|
+ handler->func(std::forward<Args>(args)...);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ std::cout << "Handler is not void" << std::endl;
|
|
|
|
|
+ // Call handlers with a non-void return type
|
|
|
|
|
+ auto handler = dynamic_cast<Handler<R, Args...>*>(handlerBase.get());
|
|
|
|
|
+ // Add debug information to identify the type mismatch issue in dynamic_cast
|
|
|
|
|
+ if (!handler) {
|
|
|
|
|
+ std::cerr << "Dynamic cast failed. Handler is NULL. Possible type mismatch or invalid handler." << std::endl;
|
|
|
|
|
+ std::cerr << "Expected Handler type: " << typeid(Handler<R, Args...>).name() << std::endl;
|
|
|
|
|
+ std::cerr << "Actual HandlerBase type: " << typeid(*handlerBase).name() << std::endl;
|
|
|
|
|
+ std::cerr << "HandlerBase pointer: " << handlerBase.get() << std::endl;
|
|
|
|
|
+ std::cerr << "Args... types: ";
|
|
|
|
|
+ printArgs<Args...>();
|
|
|
|
|
+ std::cerr << std::endl;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ std::cout << "Dynamic cast result (non-void): " << handler << std::endl;
|
|
|
|
|
+ if (handler) {
|
|
|
|
|
+ results.push_back(handler->func(std::forward<Args>(args)...));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ std::cout << "No handlers found for EventType: " << static_cast<int>(type) << std::endl;
|
|
|
|
|
+ }
|
|
|
|
|
+ return results;
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+ template<typename... Args>
|
|
|
|
|
+ void printArgs() {
|
|
|
|
|
+ using expander = int[];
|
|
|
|
|
+ (void)expander {
|
|
|
|
|
+ 0, (std::cout << typeid(Args).name() << " ", 0)...
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
|
|
|
private:
|
|
private:
|
|
|
struct HandlerBase {
|
|
struct HandlerBase {
|
|
@@ -121,30 +169,184 @@ private:
|
|
|
using ArgsTuple = std::tuple<Args...>;
|
|
using ArgsTuple = std::tuple<Args...>;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- // Implementation: avoid constructing tuple-of-references!
|
|
|
|
|
|
|
+ template<EventType T>
|
|
|
|
|
+ struct HandlerTraits;
|
|
|
|
|
+
|
|
|
|
|
+ // Specialize HandlerTraits for each EventType to define the expected return type.
|
|
|
|
|
+ template<>
|
|
|
|
|
+ struct HandlerTraits<EventType::Click> {
|
|
|
|
|
+ using ReturnType = bool; // Example: Click events return bool.
|
|
|
|
|
+ using ArgsTuple = std::tuple<int>; // Example: Click events take an int argument.
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ template<>
|
|
|
|
|
+ struct HandlerTraits<EventType::Hover> {
|
|
|
|
|
+ using ReturnType = bool; // Example: Hover events return bool.
|
|
|
|
|
+ using ArgsTuple = std::tuple<std::string>; // Example: Hover events take a string argument.
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ template<>
|
|
|
|
|
+ struct HandlerTraits<EventType::Custom> {
|
|
|
|
|
+ using ReturnType = void; // Example: Custom events return void.
|
|
|
|
|
+ using ArgsTuple = std::tuple<>; // Example: Custom events take no arguments.
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
template<typename R, typename F, typename... Args>
|
|
template<typename R, typename F, typename... Args>
|
|
|
HandlerID addHandlerImpl(EventType type, F&& f, std::tuple<Args...>*) {
|
|
HandlerID addHandlerImpl(EventType type, F&& f, std::tuple<Args...>*) {
|
|
|
- auto handler = std::make_unique<Handler<R, Args...>>(nextHandlerID, std::function<R(Args...)>(std::forward<F>(f)));
|
|
|
|
|
|
|
+ // Explicitly construct std::function with the correct return type
|
|
|
|
|
+ auto func = std::function<R(Args...)>(std::forward<F>(f));
|
|
|
|
|
+ if (!func) {
|
|
|
|
|
+ std::cerr << "Error: std::function construction failed!" << std::endl;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ auto handler = std::make_unique<Handler<R, Args...>>(nextHandlerID, func);
|
|
|
|
|
+ std::cout << "\n-------------------- AddHandlerImp --------------------" << std::endl;
|
|
|
|
|
+ std::cout << "Args... types: ";
|
|
|
|
|
+ printArgs<Args...>();
|
|
|
|
|
+ std::cout << std::endl;
|
|
|
|
|
+ std::cerr << "Expected Handler type: " << typeid(Handler<R, Args...>).name() << std::endl;
|
|
|
|
|
+ std::cerr << "Actual HandlerBase type: " << typeid(*handler).name() << std::endl;
|
|
|
|
|
+ std::cerr << "HandlerBase pointer: " << handler.get() << std::endl;
|
|
|
handlers[type].emplace_back(std::move(handler));
|
|
handlers[type].emplace_back(std::move(handler));
|
|
|
return nextHandlerID++;
|
|
return nextHandlerID++;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+#if 0
|
|
|
|
|
+ // Implementation: avoid constructing tuple-of-references!
|
|
|
|
|
+ template<typename R, typename F, typename... Args>
|
|
|
|
|
+ HandlerID addHandlerImpl(EventType type, F&& f, std::tuple<Args...>*) {
|
|
|
|
|
+ // To resolve the issues, you need to define the `HandlerTraits` struct.
|
|
|
|
|
+ // Below is the corrected code with the `HandlerTraits` definition added.
|
|
|
|
|
+ // Now the original code will work as expected.
|
|
|
|
|
+ //using ExpectedReturnType = typename HandlerTraits<EventType>::ReturnType;
|
|
|
|
|
+ //static_assert(std::is_same<R, ExpectedReturnType>::value,
|
|
|
|
|
+ // "Handler return type does not match the expected return type for this event type.");
|
|
|
|
|
+
|
|
|
|
|
+ // using ExpectedReturnType = typename HandlerTraits<EventType::Click>::ReturnType; // Default to Click
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ // Validate return type
|
|
|
|
|
+ //static_assert(std::is_same<R, ExpectedReturnType>::value,
|
|
|
|
|
+ // "Handler return type does not match the expected return type for this event type.");
|
|
|
|
|
+
|
|
|
|
|
+ // Ensure the type is correctly cast to EventType
|
|
|
|
|
+ // static_assert(std::is_enum<EventType>::value, "EventType must be an enum.");
|
|
|
|
|
+ auto eventType = static_cast<EventType>(static_cast<int>(type));
|
|
|
|
|
+// std::cout << "EventType: " << eventTypeToString(type) << std::endl;
|
|
|
|
|
+// std::cerr << "Args... types: ";
|
|
|
|
|
+// printArgs<Args...>();
|
|
|
|
|
+// std::cerr << std::endl;
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ auto func = std::function<R(Args...)>(std::forward<F>(f));
|
|
|
|
|
+ if (!func) {
|
|
|
|
|
+ std::cerr << "Error: std::function construction failed!" << std::endl;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Diagnostic information for type mismatch
|
|
|
|
|
+ // using ExpectedReturnType = typename HandlerTraits<EventType::Click>::ReturnType;
|
|
|
|
|
+ // using ExpectedReturnType = typename HandlerTraits< static_cast<EventType>(type) > ::ReturnType;
|
|
|
|
|
+
|
|
|
|
|
+ // std::cout << "Expected Return Type: " << ExpectedReturnType << std::endl;
|
|
|
|
|
+ // Replace the problematic line with the following code to fix the issue:
|
|
|
|
|
+ // std::cout << "Expected Return Type: " << typeid(ExpectedReturnType).name() << std::endl;
|
|
|
|
|
+ // static_assert(std::is_same<R, ExpectedReturnType>::value,
|
|
|
|
|
+ // "Handler return type does not match the expected return type for this event type.");
|
|
|
|
|
+
|
|
|
|
|
+ #if 0
|
|
|
|
|
+ // Diagnostic information for type mismatch
|
|
|
|
|
+ if (!std::is_same<R, typename HandlerTraits<type>::ReturnType>::value) {
|
|
|
|
|
+ std::cerr << "Type mismatch detected in addHandlerImpl!" << std::endl;
|
|
|
|
|
+ std::cerr << "Expected return type: " << typeid(typename HandlerTraits<static_cast<EventType>(type)>::ReturnType).name() << std::endl;
|
|
|
|
|
+ std::cerr << "Provided return type: " << typeid(R).name() << std::endl;
|
|
|
|
|
+ }
|
|
|
|
|
+ #endif
|
|
|
|
|
+ // std::cerr << "Type mismatch detected in addHandlerImpl!" << std::endl;
|
|
|
|
|
+ // std::cerr << "Expected return type: " << typeid(typename HandlerTraits<static_cast<EventType>(type)>::ReturnType).name() << std::endl;
|
|
|
|
|
+ //std::cerr << "Expected return type: " << typeid(ExpectedReturnType).name() << std::endl;
|
|
|
|
|
+ //std::cerr << "Provided return type: " << typeid(R).name() << std::endl;
|
|
|
|
|
+ //std::cout << "Adding handler with callable type: " << typeid(F).name() << std::endl;
|
|
|
|
|
+
|
|
|
|
|
+ auto handler = std::make_unique<Handler<R, Args...>>(nextHandlerID, func);
|
|
|
|
|
+ std::cout << "\n-------------------- AddHandlerImp --------------------" << std::endl;
|
|
|
|
|
+ std::cout << "Args... types: ";
|
|
|
|
|
+ printArgs<Args...>();
|
|
|
|
|
+ std::cout << std::endl;
|
|
|
|
|
+ std::cerr << "Expected Handler type: " << typeid(Handler<R, Args...>).name() << std::endl;
|
|
|
|
|
+ std::cerr << "Actual HandlerBase type: " << typeid(*handler).name() << std::endl;
|
|
|
|
|
+ std::cerr << "HandlerBase pointer: " << handler.get() << std::endl;
|
|
|
|
|
+ handlers[eventType].emplace_back(std::move(handler));
|
|
|
|
|
+ return nextHandlerID++;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ std::string eventTypeToString(EventType type) {
|
|
|
|
|
+ switch (type) {
|
|
|
|
|
+ case EventType::Click: return "Click";
|
|
|
|
|
+ case EventType::Hover: return "Hover";
|
|
|
|
|
+ case EventType::Custom: return "Custom";
|
|
|
|
|
+ default: return "Unknown";
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ // std::cerr << "Provided return type: " << typeid(R).name() << std::endl;
|
|
|
|
|
+ // std::cout << "Adding handler with callable type: " << typeid(F).name() << std::endl;
|
|
|
|
|
+
|
|
|
|
|
+ // auto handler = std::make_unique<Handler<R, Args...>>(nextHandlerID, std::function<R(Args...)>(std::forward<F>(f)));
|
|
|
|
|
+ // handlers[type].emplace_back(std::move(handler));
|
|
|
|
|
+ // return nextHandlerID++;
|
|
|
|
|
+ // }
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+#if 0
|
|
|
|
|
+
|
|
|
|
|
+ // Implementation: avoid constructing tuple-of-references!
|
|
|
|
|
+ template<typename R, typename F, typename... Args>
|
|
|
|
|
+ HandlerID addHandlerImpl(EventType type, F&& f, std::tuple<Args...>*) {
|
|
|
|
|
+ // Ensure the type is correctly cast to EventType
|
|
|
|
|
+ static_assert(std::is_enum<EventType>::value, "EventType must be an enum.");
|
|
|
|
|
+ auto eventType = static_cast<EventType>(type);
|
|
|
|
|
+
|
|
|
|
|
+ // Correctly construct the std::function to avoid moving from a temporary
|
|
|
|
|
+ auto func = std::function<R(Args...)>(f);
|
|
|
|
|
+ if (!func) {
|
|
|
|
|
+ std::cerr << "Error: std::function construction failed!" << std::endl;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Diagnostic information for type mismatch
|
|
|
|
|
+ using ExpectedReturnType = typename HandlerTraits<eventType>::ReturnType;
|
|
|
|
|
+ static_assert(std::is_same<R, ExpectedReturnType>::value,
|
|
|
|
|
+ "Handler return type does not match the expected return type for this event type.");
|
|
|
|
|
+
|
|
|
|
|
+ std::cerr << "Expected return type: " << typeid(ExpectedReturnType).name() << std::endl;
|
|
|
|
|
+ std::cerr << "Provided return type: " << typeid(R).name() << std::endl;
|
|
|
|
|
+ std::cout << "Adding handler with callable type: " << typeid(F).name() << std::endl;
|
|
|
|
|
+
|
|
|
|
|
+ auto handler = std::make_unique<Handler<R, Args...>>(nextHandlerID, func);
|
|
|
|
|
+ handlers[eventType].emplace_back(std::move(handler));
|
|
|
|
|
+ return nextHandlerID++;
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
struct Widget {
|
|
struct Widget {
|
|
|
- void onClick(int x) {
|
|
|
|
|
|
|
+ bool onClick(int x) {
|
|
|
std::cout << "Widget::onClick(" << x << ")\n";
|
|
std::cout << "Widget::onClick(" << x << ")\n";
|
|
|
|
|
+ return true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- void onClick_1(int x) {
|
|
|
|
|
|
|
+ bool onClick_1(int x) {
|
|
|
std::cout << "Widget::onClick_1(" << x << ")\n";
|
|
std::cout << "Widget::onClick_1(" << x << ")\n";
|
|
|
|
|
+ return false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- void onClick_2(int x) {
|
|
|
|
|
|
|
+ bool onClick_2(int x) {
|
|
|
std::cout << "Widget::onClick_2(" << x << ")\n";
|
|
std::cout << "Widget::onClick_2(" << x << ")\n";
|
|
|
|
|
+ return false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- void onClick_3(int x) {
|
|
|
|
|
|
|
+ bool onClick_3(int x) {
|
|
|
std::cout << "Widget::onClick_2(" << x << ")\n";
|
|
std::cout << "Widget::onClick_2(" << x << ")\n";
|
|
|
|
|
+ return true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
bool onHover(const std::string& msg) {
|
|
bool onHover(const std::string& msg) {
|
|
@@ -154,45 +356,74 @@ struct Widget {
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
bool globalHandler(int x) {
|
|
bool globalHandler(int x) {
|
|
|
- std::cout << "globalHandler(" << x << ")\n";
|
|
|
|
|
|
|
+ std::cout << "free standing globalHandler(" << x << ") return: true\n";
|
|
|
return x > 0;
|
|
return x > 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+bool globalHandler1(int x) {
|
|
|
|
|
+ std::cout << "free standing globalHandler_1(" << x << ") return: false\n";
|
|
|
|
|
+ return x < 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
int main() {
|
|
int main() {
|
|
|
EventDispatcher dispatcher;
|
|
EventDispatcher dispatcher;
|
|
|
Widget w;
|
|
Widget w;
|
|
|
-
|
|
|
|
|
|
|
+#if 1
|
|
|
// Register handlers and keep their IDs for removal
|
|
// Register handlers and keep their IDs for removal
|
|
|
|
|
+ std::cout << "Click Handler registered ...\n" << std::endl;
|
|
|
auto id1 = dispatcher.addHandler(EventType::Click, globalHandler);
|
|
auto id1 = dispatcher.addHandler(EventType::Click, globalHandler);
|
|
|
|
|
+ auto id1_1 = dispatcher.addHandler(EventType::Click, globalHandler1);
|
|
|
|
|
|
|
|
auto id2 = dispatcher.addHandler(EventType::Click, [](int x) {
|
|
auto id2 = dispatcher.addHandler(EventType::Click, [](int x) {
|
|
|
- std::cout << "lambda(" << x << ")\n";
|
|
|
|
|
|
|
+ std::cout << "function lambda(" << x << ") return true\n";
|
|
|
return x % 2 == 0;
|
|
return x % 2 == 0;
|
|
|
});
|
|
});
|
|
|
- auto id3 = dispatcher.addHandler(EventType::Click, [&w](int x) { w.onClick(x); });
|
|
|
|
|
- dispatcher.addHandler(EventType::Click, [&w](int x) { w.onClick_1(x); });
|
|
|
|
|
- dispatcher.addHandler(EventType::Click, [&w](int x) { w.onClick_2(x); });
|
|
|
|
|
- dispatcher.addHandler(EventType::Click, [&w](int x) { w.onClick_3(x); });
|
|
|
|
|
|
|
|
|
|
- auto id4 = dispatcher.addHandler(EventType::Hover, [&w](const std::string& msg) { return w.onHover(msg); });
|
|
|
|
|
-
|
|
|
|
|
- // Emit events; collect return values if any
|
|
|
|
|
auto clickResults = dispatcher.emit<bool>(EventType::Click, 42);
|
|
auto clickResults = dispatcher.emit<bool>(EventType::Click, 42);
|
|
|
- auto hoverResults = dispatcher.emit<bool>(EventType::Hover, std::string("hello"));
|
|
|
|
|
-
|
|
|
|
|
std::cout << "Click results: ";
|
|
std::cout << "Click results: ";
|
|
|
for (bool b : clickResults) std::cout << b << " ";
|
|
for (bool b : clickResults) std::cout << b << " ";
|
|
|
std::cout << "\n";
|
|
std::cout << "\n";
|
|
|
|
|
|
|
|
|
|
+ dispatcher.removeHandler(EventType::Click, id2);
|
|
|
|
|
+ dispatcher.removeHandler(EventType::Click, id1);
|
|
|
|
|
+ dispatcher.removeHandler(EventType::Click, id1_1);
|
|
|
|
|
+
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+ std::cout << "------------------------------------------------------------" << std::endl;
|
|
|
|
|
+ std::cout << "New Click Handler registered ... (onClick, onClick_1, onClick_2, onClick_3)" << std::endl;
|
|
|
|
|
+ auto id3 = dispatcher.addHandler(EventType::Click, [&w](int x) { w.onClick(x); });
|
|
|
|
|
+ dispatcher.addHandler(EventType::Click, [&w](int x) -> bool { return w.onClick_1(x); });
|
|
|
|
|
+ dispatcher.addHandler(EventType::Click, [&w](int x) -> bool { return w.onClick_2(x); });
|
|
|
|
|
+ dispatcher.addHandler(EventType::Click, [&w](int x) -> bool { return w.onClick_3(x); });
|
|
|
|
|
+
|
|
|
|
|
+ // Emit events; collect return values if any
|
|
|
|
|
+ auto clickResults_1 = dispatcher.emit<bool>(EventType::Click, 24);
|
|
|
|
|
+ std::cout << "Click results: ";
|
|
|
|
|
+ if (clickResults_1.size() == 0)
|
|
|
|
|
+ std::cout << "Error" << std::endl;
|
|
|
|
|
+ for (bool b : clickResults_1) std::cout << b << " ";
|
|
|
|
|
+ std::cout << "\n";
|
|
|
|
|
+
|
|
|
|
|
+ std::cout << "------------------------------------------------------------" << std::endl;
|
|
|
|
|
+ std::cout << "Hover Handler registered ...\n" << std::endl;
|
|
|
|
|
+ auto id4 = dispatcher.addHandler(EventType::Hover, [&w](const std::string& msg) { return w.onHover(msg); });
|
|
|
|
|
+ auto hoverResults = dispatcher.emit<bool>(EventType::Hover, std::string("hello"));
|
|
|
|
|
+
|
|
|
std::cout << "Hover results: ";
|
|
std::cout << "Hover results: ";
|
|
|
for (bool b : hoverResults) std::cout << b << " ";
|
|
for (bool b : hoverResults) std::cout << b << " ";
|
|
|
std::cout << "\n";
|
|
std::cout << "\n";
|
|
|
|
|
|
|
|
|
|
+
|
|
|
// Remove a handler and emit again
|
|
// Remove a handler and emit again
|
|
|
- dispatcher.removeHandler(EventType::Click, id1);
|
|
|
|
|
- clickResults = dispatcher.emit<bool>(EventType::Click, 7);
|
|
|
|
|
|
|
+ std::cout << "------------------------------------------------------------" << std::endl;
|
|
|
|
|
+ std::cout << "Remove Handler Click ID 1 ...\n" << std::endl;
|
|
|
|
|
+
|
|
|
|
|
+// dispatcher.removeHandler(EventType::Click, id1);
|
|
|
|
|
+// clickResults = dispatcher.emit<bool>(EventType::Click, 7);
|
|
|
std::cout << "Click results after removal: ";
|
|
std::cout << "Click results after removal: ";
|
|
|
- for (bool b : clickResults) std::cout << b << " ";
|
|
|
|
|
|
|
+// for (bool b : clickResults) std::cout << b << " ";
|
|
|
std::cout << "\n";
|
|
std::cout << "\n";
|
|
|
}
|
|
}
|
|
|
|
|
|