|
@@ -13,6 +13,61 @@
|
|
|
#include <unordered_map>
|
|
#include <unordered_map>
|
|
|
#include <cassert>
|
|
#include <cassert>
|
|
|
|
|
|
|
|
|
|
+#include <iostream>
|
|
|
|
|
+#include <fstream>
|
|
|
|
|
+#include <string>
|
|
|
|
|
+#include <mutex>
|
|
|
|
|
+
|
|
|
|
|
+enum class LogLevel {
|
|
|
|
|
+ DEBUG,
|
|
|
|
|
+ INFO,
|
|
|
|
|
+ WARN,
|
|
|
|
|
+ ERROR
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+class Logger {
|
|
|
|
|
+public:
|
|
|
|
|
+ static Logger& getInstance() {
|
|
|
|
|
+ static Logger instance;
|
|
|
|
|
+ return instance;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void setLogLevel(LogLevel level) {
|
|
|
|
|
+ minLogLevel = level;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void log(LogLevel level, const std::string& message) {
|
|
|
|
|
+ if (level >= minLogLevel) {
|
|
|
|
|
+ std::lock_guard<std::mutex> lock(logMutex);
|
|
|
|
|
+ std::ostream& out = (level == LogLevel::ERROR) ? std::cerr : std::cout;
|
|
|
|
|
+ out << "[" << logLevelToString(level) << "] " << message << std::endl;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void debug(const std::string& message) { log(LogLevel::DEBUG, message); }
|
|
|
|
|
+ void info(const std::string& message) { log(LogLevel::INFO, message); }
|
|
|
|
|
+ void warn(const std::string& message) { log(LogLevel::WARN, message); }
|
|
|
|
|
+ void error(const std::string& message) { log(LogLevel::ERROR, message); }
|
|
|
|
|
+
|
|
|
|
|
+private:
|
|
|
|
|
+ LogLevel minLogLevel = LogLevel::DEBUG;
|
|
|
|
|
+ std::mutex logMutex;
|
|
|
|
|
+
|
|
|
|
|
+ Logger() = default;
|
|
|
|
|
+ ~Logger() = default;
|
|
|
|
|
+
|
|
|
|
|
+ std::string logLevelToString(LogLevel level) {
|
|
|
|
|
+ switch (level) {
|
|
|
|
|
+ case LogLevel::DEBUG: return "DEBUG";
|
|
|
|
|
+ case LogLevel::INFO: return "INFO";
|
|
|
|
|
+ case LogLevel::WARN: return "WARN";
|
|
|
|
|
+ case LogLevel::ERROR: return "ERROR";
|
|
|
|
|
+ default: return "UNKNOWN";
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
enum class EventType {
|
|
enum class EventType {
|
|
|
Click,
|
|
Click,
|
|
|
Hover,
|
|
Hover,
|
|
@@ -43,29 +98,6 @@ public:
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
-#if 0
|
|
|
|
|
- // Emit: returns vector of return values from all handlers of matching type/signature
|
|
|
|
|
- template<typename R = void, typename... Args>
|
|
|
|
|
- std::vector<R> emit(EventType type, Args&&... args) {
|
|
|
|
|
- std::vector<R> results;
|
|
|
|
|
- auto it = handlers.find(type);
|
|
|
|
|
- if (it != handlers.end()) {
|
|
|
|
|
- for (auto& handlerBase : it->second) {
|
|
|
|
|
- auto handler = dynamic_cast<Handler<R, Args...>*>(handlerBase.get());
|
|
|
|
|
- if (handler) {
|
|
|
|
|
- if constexpr (std::is_void_v<R>) {
|
|
|
|
|
- handler->func(std::forward<Args>(args)...);
|
|
|
|
|
- }
|
|
|
|
|
- else {
|
|
|
|
|
- results.push_back(handler->func(std::forward<Args>(args)...));
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- // std::cout << "Error handler NULL" << std::endl;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- return results;
|
|
|
|
|
- }
|
|
|
|
|
-#else
|
|
|
|
|
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) {
|
|
|
// Log Args... information
|
|
// Log Args... information
|
|
@@ -77,22 +109,23 @@ public:
|
|
|
auto it = handlers.find(type);
|
|
auto it = handlers.find(type);
|
|
|
if (it != handlers.end()) {
|
|
if (it != handlers.end()) {
|
|
|
for (auto& handlerBase : it->second) {
|
|
for (auto& handlerBase : it->second) {
|
|
|
- std::cout << "\n------------------------- emit ------------------------" << std::endl;
|
|
|
|
|
|
|
+ // std::cout << "\n------------------------- emit ------------------------" << std::endl;
|
|
|
if (std::is_void<R>::value) {
|
|
if (std::is_void<R>::value) {
|
|
|
- std::cout << "Handler is void" << std::endl;
|
|
|
|
|
|
|
+ // std::cout << "Handler is void" << std::endl;
|
|
|
// Call handlers with a void return type
|
|
// Call handlers with a void return type
|
|
|
auto handler = dynamic_cast<Handler<void, Args...>*>(handlerBase.get());
|
|
auto handler = dynamic_cast<Handler<void, Args...>*>(handlerBase.get());
|
|
|
- std::cout << "Dynamic cast result (void): " << handler << std::endl;
|
|
|
|
|
|
|
+ // std::cout << "Dynamic cast result (void): " << handler << std::endl;
|
|
|
if (handler) {
|
|
if (handler) {
|
|
|
handler->func(std::forward<Args>(args)...);
|
|
handler->func(std::forward<Args>(args)...);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
else {
|
|
else {
|
|
|
- std::cout << "Handler is not void" << std::endl;
|
|
|
|
|
|
|
+ // std::cout << "Handler is not void" << std::endl;
|
|
|
// Call handlers with a non-void return type
|
|
// Call handlers with a non-void return type
|
|
|
auto handler = dynamic_cast<Handler<R, Args...>*>(handlerBase.get());
|
|
auto handler = dynamic_cast<Handler<R, Args...>*>(handlerBase.get());
|
|
|
// Add debug information to identify the type mismatch issue in dynamic_cast
|
|
// Add debug information to identify the type mismatch issue in dynamic_cast
|
|
|
if (!handler) {
|
|
if (!handler) {
|
|
|
|
|
+ std::cerr << "\n------------------------- emit ------------------------" << std::endl;
|
|
|
std::cerr << "Dynamic cast failed. Handler is NULL. Possible type mismatch or invalid handler." << std::endl;
|
|
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 << "Expected Handler type: " << typeid(Handler<R, Args...>).name() << std::endl;
|
|
|
std::cerr << "Actual HandlerBase type: " << typeid(*handlerBase).name() << std::endl;
|
|
std::cerr << "Actual HandlerBase type: " << typeid(*handlerBase).name() << std::endl;
|
|
@@ -102,7 +135,7 @@ public:
|
|
|
std::cerr << std::endl;
|
|
std::cerr << std::endl;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- std::cout << "Dynamic cast result (non-void): " << handler << std::endl;
|
|
|
|
|
|
|
+ // std::cout << "Dynamic cast result (non-void): " << handler << std::endl;
|
|
|
if (handler) {
|
|
if (handler) {
|
|
|
results.push_back(handler->func(std::forward<Args>(args)...));
|
|
results.push_back(handler->func(std::forward<Args>(args)...));
|
|
|
}
|
|
}
|
|
@@ -110,11 +143,10 @@ public:
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
else {
|
|
else {
|
|
|
- std::cout << "No handlers found for EventType: " << static_cast<int>(type) << std::endl;
|
|
|
|
|
|
|
+ std::cerr << "No handlers found for EventType: " << static_cast<int>(type) << std::endl;
|
|
|
}
|
|
}
|
|
|
return results;
|
|
return results;
|
|
|
}
|
|
}
|
|
|
-#endif
|
|
|
|
|
|
|
|
|
|
template<typename... Args>
|
|
template<typename... Args>
|
|
|
void printArgs() {
|
|
void printArgs() {
|
|
@@ -200,13 +232,15 @@ private:
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
auto handler = std::make_unique<Handler<R, Args...>>(nextHandlerID, func);
|
|
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;
|
|
|
|
|
|
|
+ if (!handler) {
|
|
|
|
|
+ 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++;
|
|
|
}
|
|
}
|
|
@@ -296,36 +330,6 @@ private:
|
|
|
// return nextHandlerID++;
|
|
// return nextHandlerID++;
|
|
|
// }
|
|
// }
|
|
|
#endif
|
|
#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 {
|
|
@@ -349,57 +353,73 @@ struct Widget {
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- bool onHover(const std::string& msg) {
|
|
|
|
|
|
|
+ const char* onHover(const char* msg) {
|
|
|
std::cout << "Widget::onHover_3(" << msg << ")\n";
|
|
std::cout << "Widget::onHover_3(" << msg << ")\n";
|
|
|
- return true;
|
|
|
|
|
|
|
+ return msg;
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
bool globalHandler(int x) {
|
|
bool globalHandler(int x) {
|
|
|
- std::cout << "free standing globalHandler(" << x << ") return: true\n";
|
|
|
|
|
|
|
+ std::cout << "free standing globalHandler(" << x << ") return: true" << std::endl;
|
|
|
return x > 0;
|
|
return x > 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
bool globalHandler1(int x) {
|
|
bool globalHandler1(int x) {
|
|
|
- std::cout << "free standing globalHandler_1(" << x << ") return: false\n";
|
|
|
|
|
|
|
+ std::cout << "free standing globalHandler_1(" << x << ") return: false" << std::endl;
|
|
|
return x < 0;
|
|
return x < 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
int main() {
|
|
int main() {
|
|
|
EventDispatcher dispatcher;
|
|
EventDispatcher dispatcher;
|
|
|
Widget w;
|
|
Widget w;
|
|
|
#if 1
|
|
#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;
|
|
|
|
|
|
|
+ std::cout << "Click Handler registered ...(globalHandler, globalHandler1, lambda)" << std::endl;
|
|
|
|
|
+ std::cout << ">> dispatcher.addHandler(EventType::Click, globalHandler)" << std::endl;
|
|
|
auto id1 = dispatcher.addHandler(EventType::Click, globalHandler);
|
|
auto id1 = dispatcher.addHandler(EventType::Click, globalHandler);
|
|
|
|
|
+ std::cout << ">> dispatcher.addHandler(EventType::Click, globalHandler1)" << std::endl;
|
|
|
auto id1_1 = dispatcher.addHandler(EventType::Click, globalHandler1);
|
|
auto id1_1 = dispatcher.addHandler(EventType::Click, globalHandler1);
|
|
|
|
|
|
|
|
- auto id2 = dispatcher.addHandler(EventType::Click, [](int x) {
|
|
|
|
|
|
|
+ std::cout << ">> dispatcher.addHandler(EventType::Click, [](int x) -> bool {}" << std::endl;
|
|
|
|
|
+ auto id2 = dispatcher.addHandler(EventType::Click, [](int x) -> bool {
|
|
|
std::cout << "function lambda(" << x << ") return true\n";
|
|
std::cout << "function lambda(" << x << ") return true\n";
|
|
|
return x % 2 == 0;
|
|
return x % 2 == 0;
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
|
|
+ std::cout << "\n--------- dispatcher.emit<bool>(EventType::Click, 42) --------" << std::endl;
|
|
|
|
|
+ std::cout << "--------- supposely 3 functions --------" << std::endl;
|
|
|
|
|
+
|
|
|
auto clickResults = dispatcher.emit<bool>(EventType::Click, 42);
|
|
auto clickResults = dispatcher.emit<bool>(EventType::Click, 42);
|
|
|
|
|
+ std::cout << "-----------------" << std::endl;
|
|
|
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, id2);
|
|
|
dispatcher.removeHandler(EventType::Click, id1);
|
|
dispatcher.removeHandler(EventType::Click, id1);
|
|
|
- dispatcher.removeHandler(EventType::Click, id1_1);
|
|
|
|
|
|
|
+ // dispatcher.removeHandler(EventType::Click, id1_1);
|
|
|
|
|
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
std::cout << "------------------------------------------------------------" << std::endl;
|
|
std::cout << "------------------------------------------------------------" << std::endl;
|
|
|
std::cout << "New Click Handler registered ... (onClick, onClick_1, onClick_2, onClick_3)" << 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); });
|
|
|
|
|
|
|
+ std::cout << "\n>> dispatcher.addHandler(EventType::Click, [&w](int x) -> bool { return w.onClick(x); }" << std::ends;
|
|
|
|
|
+ auto id3 = dispatcher.addHandler(EventType::Click, [&w](int x) -> bool { return w.onClick(x); });
|
|
|
|
|
+ std::cout << "\n>> dispatcher.addHandler(EventType::Click, [&w](int x) -> bool { return w.onClick_1(x); }" << std::ends;
|
|
|
dispatcher.addHandler(EventType::Click, [&w](int x) -> bool { return w.onClick_1(x); });
|
|
dispatcher.addHandler(EventType::Click, [&w](int x) -> bool { return w.onClick_1(x); });
|
|
|
|
|
+ std::cout << "\n>> dispatcher.addHandler(EventType::Click, [&w](int x) -> bool { return w.onClick_2(x); }" << std::ends;
|
|
|
dispatcher.addHandler(EventType::Click, [&w](int x) -> bool { return w.onClick_2(x); });
|
|
dispatcher.addHandler(EventType::Click, [&w](int x) -> bool { return w.onClick_2(x); });
|
|
|
|
|
+ std::cout << "\n>> dispatcher.addHandler(EventType::Click, [&w](int x) -> bool { return w.onClick_3(x); }" << std::ends;
|
|
|
dispatcher.addHandler(EventType::Click, [&w](int x) -> bool { return w.onClick_3(x); });
|
|
dispatcher.addHandler(EventType::Click, [&w](int x) -> bool { return w.onClick_3(x); });
|
|
|
|
|
|
|
|
|
|
+ std::cout << "\n--------- dispatcher.emit<bool>(EventType::Click, 24) --------" << std::ends;
|
|
|
|
|
+ std::cout << "\n--------- supposely 5 functions --------\n" << std::ends;
|
|
|
// Emit events; collect return values if any
|
|
// Emit events; collect return values if any
|
|
|
auto clickResults_1 = dispatcher.emit<bool>(EventType::Click, 24);
|
|
auto clickResults_1 = dispatcher.emit<bool>(EventType::Click, 24);
|
|
|
|
|
+ std::cout << "-----------------" << std::endl;
|
|
|
std::cout << "Click results: ";
|
|
std::cout << "Click results: ";
|
|
|
if (clickResults_1.size() == 0)
|
|
if (clickResults_1.size() == 0)
|
|
|
std::cout << "Error" << std::endl;
|
|
std::cout << "Error" << std::endl;
|
|
@@ -407,23 +427,28 @@ int main() {
|
|
|
std::cout << "\n";
|
|
std::cout << "\n";
|
|
|
|
|
|
|
|
std::cout << "------------------------------------------------------------" << std::endl;
|
|
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 << "New Hover Handler registered ... (onHover)" << std::endl;
|
|
|
|
|
+ std::cout << ">> dispatcher.addHandler(EventType::Hover, [&w](const char* msg) -> const char* { return w.onHover(msg); })" << std::endl;
|
|
|
|
|
|
|
|
|
|
+ auto id4 = dispatcher.addHandler(EventType::Hover, [&w](const char* msg) -> const char* { return w.onHover(msg); });
|
|
|
|
|
+ auto hoverResults = dispatcher.emit<const char*>(EventType::Hover, static_cast < const char*>("hello"));
|
|
|
|
|
+ auto hoverResults2 = dispatcher.emit<const char*>(EventType::Hover, static_cast <const char*>("Thank you"));
|
|
|
|
|
+ std::copy(hoverResults2.begin(), hoverResults2.end(), std::back_inserter(hoverResults));
|
|
|
|
|
+
|
|
|
|
|
+ std::cout << "-----------------" << std::endl;
|
|
|
std::cout << "Hover results: ";
|
|
std::cout << "Hover results: ";
|
|
|
- for (bool b : hoverResults) std::cout << b << " ";
|
|
|
|
|
|
|
+ for (const char* b : hoverResults) std::cout << b << " ";
|
|
|
std::cout << "\n";
|
|
std::cout << "\n";
|
|
|
|
|
|
|
|
-
|
|
|
|
|
// Remove a handler and emit again
|
|
// Remove a handler and emit again
|
|
|
std::cout << "------------------------------------------------------------" << std::endl;
|
|
std::cout << "------------------------------------------------------------" << std::endl;
|
|
|
|
|
+ std::cout << "------------------------------------------------------------" << std::endl;
|
|
|
std::cout << "Remove Handler Click ID 1 ...\n" << std::endl;
|
|
std::cout << "Remove Handler Click ID 1 ...\n" << std::endl;
|
|
|
|
|
|
|
|
-// dispatcher.removeHandler(EventType::Click, id1);
|
|
|
|
|
-// clickResults = dispatcher.emit<bool>(EventType::Click, 7);
|
|
|
|
|
|
|
+ dispatcher.removeHandler(EventType::Click, id1_1);
|
|
|
|
|
+ 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";
|
|
|
}
|
|
}
|
|
|
|
|
|