|
|
@@ -0,0 +1,417 @@
|
|
|
+#include "cEventDispatcher.h"
|
|
|
+
|
|
|
+// Specializations for common types
|
|
|
+
|
|
|
+/**
|
|
|
+ * Specialization of getTypeName for int.
|
|
|
+ *
|
|
|
+ * @return The name of the type ("int")
|
|
|
+ */
|
|
|
+template <>
|
|
|
+const char* cEventDispatcher::getTypeName<void>()
|
|
|
+{
|
|
|
+ return "void";
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * Specialization of getTypeName for int.
|
|
|
+ *
|
|
|
+ * @return The name of the type ("int")
|
|
|
+ */
|
|
|
+template <>
|
|
|
+const char* cEventDispatcher::getTypeName<int>()
|
|
|
+{
|
|
|
+ return "int";
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Specialization of getTypeName for float.
|
|
|
+ *
|
|
|
+ * @return The name of the type ("float")
|
|
|
+ */
|
|
|
+template <>
|
|
|
+const char* cEventDispatcher::getTypeName<float>()
|
|
|
+{
|
|
|
+ return "float";
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Specialization of getTypeName for double.
|
|
|
+ *
|
|
|
+ * @return The name of the type ("double")
|
|
|
+ */
|
|
|
+template <>
|
|
|
+const char* cEventDispatcher::getTypeName<double>()
|
|
|
+{
|
|
|
+ return "double";
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Specialization of getTypeName for const char*.
|
|
|
+ *
|
|
|
+ * @return The name of the type ("const char*")
|
|
|
+ */
|
|
|
+template <>
|
|
|
+const char* cEventDispatcher::getTypeName<const char*>()
|
|
|
+{
|
|
|
+ return "const char*";
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Specialization of getTypeName for bool.
|
|
|
+ *
|
|
|
+ * @return The name of the type ("bool")
|
|
|
+ */
|
|
|
+template <>
|
|
|
+const char* cEventDispatcher::getTypeName<bool>()
|
|
|
+{
|
|
|
+ return "bool";
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Prints the names of all types in Args to std::cout, separated by spaces.
|
|
|
+ * The output is not terminated by a newline.
|
|
|
+ *
|
|
|
+ * This is mostly useful for debugging purposes.
|
|
|
+ */
|
|
|
+template <typename... Args>
|
|
|
+void cEventDispatcher::printArgs()
|
|
|
+{
|
|
|
+ using expander = int[];
|
|
|
+ (void)expander {
|
|
|
+ 0, (std::cout << getTypeName<Args>() << " ", 0)...
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
+// For const member function pointers
|
|
|
+/**
|
|
|
+ * Specialization of FunctionTraits for const call operator.
|
|
|
+ * This specialization is used to extract the return type and argument types
|
|
|
+ * from a const call operator.
|
|
|
+ *
|
|
|
+ * @tparam C The class type.
|
|
|
+ * @tparam R The return type of the const call operator.
|
|
|
+ * @tparam Args The argument types of the const call operator.
|
|
|
+ */
|
|
|
+template <typename C, typename R, typename... Args>
|
|
|
+struct cEventDispatcher::FunctionTraits<R(C::*)(Args...) const>
|
|
|
+{
|
|
|
+ using ReturnType = R;
|
|
|
+ using ArgsTuple = std::tuple<Args...>;
|
|
|
+};
|
|
|
+
|
|
|
+// For member function pointers
|
|
|
+/**
|
|
|
+ * Specialization of FunctionTraits for member functions.
|
|
|
+ * This specialization is used to extract the return type and argument types
|
|
|
+ * from a member function pointer.
|
|
|
+ *
|
|
|
+ * @tparam C The class type.
|
|
|
+ * @tparam R The return type of the member function.
|
|
|
+ * @tparam Args The argument types of the member function.
|
|
|
+ */
|
|
|
+template <typename C, typename R, typename... Args>
|
|
|
+struct cEventDispatcher::FunctionTraits<R(C::*)(Args...)>
|
|
|
+{
|
|
|
+ using ReturnType = R;
|
|
|
+ using ArgsTuple = std::tuple<Args...>;
|
|
|
+};
|
|
|
+
|
|
|
+/**
|
|
|
+ * Specialization of FunctionTraits for function pointers.
|
|
|
+ * This specialization is used to extract the return type and argument types
|
|
|
+ * from a function pointer.
|
|
|
+ *
|
|
|
+ * @tparam R The return type of the function.
|
|
|
+ * @tparam Args The argument types of the function.
|
|
|
+ */
|
|
|
+template <typename R, typename... Args>
|
|
|
+struct cEventDispatcher::FunctionTraits<R(*)(Args...)>
|
|
|
+{
|
|
|
+ using ReturnType = R;
|
|
|
+ using ArgsTuple = std::tuple<Args...>;
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+#if 1
|
|
|
+struct Button
|
|
|
+{
|
|
|
+ int onClick(int x)
|
|
|
+ {
|
|
|
+ std::cout << "Button::onClick(" << x << ")\n";
|
|
|
+ return x;
|
|
|
+ }
|
|
|
+ int onClick_1(int x)
|
|
|
+ {
|
|
|
+ std::cout << "Button::onClick_1(" << x << ")\n";
|
|
|
+ return x * 2;
|
|
|
+ }
|
|
|
+ int onClick_2(int x)
|
|
|
+ {
|
|
|
+ std::cout << "Button::onClick_2(" << x << ")\n";
|
|
|
+ return x;
|
|
|
+ }
|
|
|
+ int onClick_3(int x)
|
|
|
+ {
|
|
|
+ std::cout << "Button::onClick_2(" << x << ")\n";
|
|
|
+ return x;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+struct Widget
|
|
|
+{
|
|
|
+ void update()
|
|
|
+ {
|
|
|
+ std::cout << "Widget::update()\n";
|
|
|
+ }
|
|
|
+
|
|
|
+ bool draw()
|
|
|
+ {
|
|
|
+ std::cout << "Widget::draw()\n";
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool onClick_1(int x)
|
|
|
+ {
|
|
|
+ std::cout << "Widget::onClick_1(" << x << ")\n";
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool onClick_2(int x)
|
|
|
+ {
|
|
|
+ std::cout << "Widget::onClick_2(" << x << ")\n";
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool onClick_3(int x)
|
|
|
+ {
|
|
|
+ std::cout << "Widget::onClick_3(" << x << ")\n";
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool onClick_4(int x)
|
|
|
+ {
|
|
|
+ std::cout << "Widget::onClick_4(" << x << ")\n";
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ const char* onHover(const char* msg)
|
|
|
+ {
|
|
|
+ std::cout << "Widget::onHover_3(" << msg << ")\n";
|
|
|
+ return msg;
|
|
|
+ }
|
|
|
+
|
|
|
+ int onClick_5(int x)
|
|
|
+ {
|
|
|
+ std::cout << "Widget::onHover_4(" << x << ")\n";
|
|
|
+ return x * 2;
|
|
|
+ }
|
|
|
+
|
|
|
+ int globalIntHandler(int x, int y)
|
|
|
+ {
|
|
|
+ std::cout << "Widget::globalIntHandler(" << x << "," << y << ") return: " << x * y << std::endl;
|
|
|
+ return x * y;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+bool globalHandler(int x)
|
|
|
+{
|
|
|
+ std::cout << "free standing globalHandler(" << x << ") return: true" << std::endl;
|
|
|
+ return x > 0;
|
|
|
+}
|
|
|
+
|
|
|
+bool globalHandler1(int x)
|
|
|
+{
|
|
|
+ std::cout << "free standing globalHandler_1(" << x << ") return: false" << std::endl;
|
|
|
+ return x < 0;
|
|
|
+}
|
|
|
+
|
|
|
+int globalIntHandler(int x, int y)
|
|
|
+{
|
|
|
+ std::cout << "free standing globalIntHandler(" << x << "," << y <<") return: " << x*y << std::endl;
|
|
|
+ return x * y;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+int main()
|
|
|
+{
|
|
|
+ cEventDispatcher dispatcher;
|
|
|
+ Widget w;
|
|
|
+ Button b;
|
|
|
+
|
|
|
+ // Register handlers and keep their IDs for removal
|
|
|
+ std::cout << "------------------------- void foo() --------------------------------" << std::endl;
|
|
|
+ std::cout << ">> addHandler(EventTypeDisp::Down, [&w]() -> void { w.update(); });" << std::endl;
|
|
|
+ auto id1_1 = dispatcher.addHandler(EventTypeDisp::Down, [&w]() -> void { w.update(); });
|
|
|
+ std::cout << ">> emit(EventTypeDisp::Down);" << std::endl;
|
|
|
+ dispatcher.emit(EventTypeDisp::Down);
|
|
|
+
|
|
|
+ // Register handlers and keep their IDs for removal
|
|
|
+ std::cout << "------------------------- bool foo() --------------------------------" << std::endl;
|
|
|
+ std::cout << ">> addHandler(EventTypeDisp::Down, [&w]() -> bool { w.update(); });" << std::endl;
|
|
|
+ auto id1_2 = dispatcher.addHandler(EventTypeDisp::Down, [&w]() -> bool { return w.draw(); });
|
|
|
+ std::cout << ">> emit<bool>(EventTypeDisp::Down);" << std::endl;
|
|
|
+ auto id1_2_results = dispatcher.emit<bool>(EventTypeDisp::Down);
|
|
|
+
|
|
|
+ std::cout << "Down results: ";
|
|
|
+ for (bool b : id1_2_results)
|
|
|
+ std::cout << b << " ";
|
|
|
+ std::cout << "\n";
|
|
|
+
|
|
|
+ // Register handlers and keep their IDs for removal
|
|
|
+ std::cout << "------------------------- bool foo(int) --------------------------------" << std::endl;
|
|
|
+ std::cout << "Click Handler registered ...(globalHandler, globalHandler1, lambda)" << std::endl;
|
|
|
+ std::cout << ">> addHandler(EventTypeDisp::Click, globalHandler) - Free Function" << std::endl;
|
|
|
+ auto id2_1 = dispatcher.addHandler(EventTypeDisp::Click, globalHandler);
|
|
|
+ std::cout << ">> addHandler(EventTypeDisp::Click, globalHandler1) - Free Function" << std::endl;
|
|
|
+ auto id2_2 = dispatcher.addHandler(EventTypeDisp::Click, globalHandler1);
|
|
|
+ std::cout << ">> addHandler(EventTypeDisp::Click, [](int x) -> bool {} - Lambda Function" << std::endl;
|
|
|
+ auto id2_3 = dispatcher.addHandler(EventTypeDisp::Click, [](int x) -> bool
|
|
|
+ {
|
|
|
+ std::cout << "function lambda(" << x << ") return true\n";
|
|
|
+ return x % 2 == 0;
|
|
|
+ });
|
|
|
+
|
|
|
+ std::cout << "\n--------- emit<bool>(EventTypeDisp::Click, 42) --------" << std::endl;
|
|
|
+ std::cout << "---------- supposely 3 functions ----------" << std::endl;
|
|
|
+ auto id2_results = dispatcher.emit<bool>(EventTypeDisp::Click, 42);
|
|
|
+ std::cout << "-----------------" << std::endl;
|
|
|
+ std::cout << "Click results: ";
|
|
|
+ for (bool b : id2_results)
|
|
|
+ std::cout << b << " ";
|
|
|
+ std::cout << "\n";
|
|
|
+
|
|
|
+ std::cout << "-----------------------------------------------------------------------" << std::endl;
|
|
|
+ std::cout << " Remove Handler globalHandler and Lambda Function" << std::endl;
|
|
|
+ dispatcher.removeHandler(EventTypeDisp::Click, id2_1);
|
|
|
+ dispatcher.removeHandler(EventTypeDisp::Click, id2_3);
|
|
|
+ // dispatcher.removeHandler(EventTypeDisp::Click, id1_1);
|
|
|
+
|
|
|
+ std::cout << "\n--------- emit<bool>(EventTypeDisp::Click, 27) --------" << std::endl;
|
|
|
+ std::cout << "---------- supposely 1 functions ----------" << std::endl;
|
|
|
+ id2_results = dispatcher.emit<bool>(EventTypeDisp::Click, 27);
|
|
|
+ std::cout << "-----------------" << std::endl;
|
|
|
+ std::cout << "Click results: ";
|
|
|
+ for (bool b : id2_results)
|
|
|
+ std::cout << b << " ";
|
|
|
+ std::cout << "\n";
|
|
|
+
|
|
|
+ std::cout << "------------------------------------------------------------" << std::endl;
|
|
|
+ std::cout << "New Click Handler registered ... (onClick, onClick_1, onClick_2, onClick_3)" << std::endl;
|
|
|
+ std::cout << "\n>> addHandler(EventTypeDisp::Click, [&w](int x) -> bool { return w.onClick_1(x); }" << std::ends;
|
|
|
+ auto id3_1 = dispatcher.addHandler(EventTypeDisp::Click, [&w](int x) -> bool
|
|
|
+ { return w.onClick_1(x); });
|
|
|
+ std::cout << "\n>> addHandler(EventTypeDisp::Click, [&w](int x) -> bool { return w.onClick_2(x); }" << std::ends;
|
|
|
+ auto id3_2 = dispatcher.addHandler(EventTypeDisp::Click, [&w](int x) -> bool
|
|
|
+ { return w.onClick_2(x); });
|
|
|
+ std::cout << "\n>> addHandler(EventTypeDisp::Click, [&w](int x) -> bool { return w.onClick_3(x); }" << std::ends;
|
|
|
+ auto id3_3 = dispatcher.addHandler(EventTypeDisp::Click, [&w](int x) -> bool
|
|
|
+ { return w.onClick_3(x); });
|
|
|
+ std::cout << "\n>> addHandler(EventTypeDisp::Click, [&w](int x) -> bool { return w.onClick_4(x); }" << std::ends;
|
|
|
+ auto id3_4 = dispatcher.addHandler(EventTypeDisp::Click, [&w](int x) -> bool
|
|
|
+ { return w.onClick_4(x); });
|
|
|
+
|
|
|
+ std::cout << "\n--------- dispatcher.emit<bool>(EventTypeDisp::Click, 24) --------" << std::ends;
|
|
|
+ std::cout << "\n--------- supposely 5 functions --------\n"
|
|
|
+ << std::ends;
|
|
|
+ // Emit events; collect return values if any
|
|
|
+ auto clickResults_3 = dispatcher.emit<bool>(EventTypeDisp::Click, 24);
|
|
|
+ std::cout << "-----------------" << std::endl;
|
|
|
+ std::cout << "Click results: ";
|
|
|
+ if (clickResults_3.size() == 0)
|
|
|
+ std::cout << "Error" << std::endl;
|
|
|
+ for (bool b : clickResults_3)
|
|
|
+ std::cout << b << " ";
|
|
|
+ std::cout << "\n";
|
|
|
+
|
|
|
+ std::cout << "------------------ const char* foo(const char*) ---------------------" << std::endl;
|
|
|
+ std::cout << "New Hover Handler registered ... (onHover)" << std::endl;
|
|
|
+ std::cout << ">> addHandler(EventTypeDisp::Hover, [&w](const char* msg) -> const char* { return w.onHover(msg); })" << std::endl;
|
|
|
+
|
|
|
+ auto id4_1 = dispatcher.addHandler(EventTypeDisp::Hover, [&w](const char* msg) -> const char*
|
|
|
+ { return w.onHover(msg); });
|
|
|
+ auto id4_1_results_a = dispatcher.emit<const char*>(EventTypeDisp::Hover, static_cast<const char*>("hello"));
|
|
|
+ auto id4_1_results_b = dispatcher.emit<const char*>(EventTypeDisp::Hover, static_cast<const char*>("Thank you"));
|
|
|
+ std::copy(id4_1_results_b.begin(), id4_1_results_b.end(), std::back_inserter(id4_1_results_a));
|
|
|
+
|
|
|
+ std::cout << "-----------------" << std::endl;
|
|
|
+ std::cout << "Hover results: ";
|
|
|
+ for (const char* b : id4_1_results_a)
|
|
|
+ std::cout << b << " ";
|
|
|
+ std::cout << "\n";
|
|
|
+
|
|
|
+ std::cout << "------------------------------------------------------------" << std::endl;
|
|
|
+ std::cout << "New Click Handler registered ... (lambda)" << std::endl;
|
|
|
+ std::cout << ">> addHandler(EventTypeDisp::Click, [&w,&b](int x) -> int { return b.onClick_1(w.onClick_4(x)); }" << std::endl;
|
|
|
+ dispatcher.addHandler(EventTypeDisp::Click, [&w, &b](int x) -> int
|
|
|
+ { return b.onClick_1(w.onClick_5(x)); });
|
|
|
+ auto clickResultsInt = dispatcher.emit<int>(EventTypeDisp::Click, 7);
|
|
|
+ std::cout << "-----------------" << std::endl;
|
|
|
+ std::cout << "Click results: ";
|
|
|
+ for (int b : clickResultsInt)
|
|
|
+ std::cout << b << " ";
|
|
|
+ std::cout << "\n";
|
|
|
+
|
|
|
+ // Remove a handler and emit again
|
|
|
+ std::cout << "------------------------------------------------------------" << std::endl;
|
|
|
+ std::cout << "------------------------------------------------------------" << std::endl;
|
|
|
+ std::cout << "Remove Handler Click ID 1 ...\n"
|
|
|
+ << std::endl;
|
|
|
+
|
|
|
+ dispatcher.removeHandler(EventTypeDisp::Click, id2_2);
|
|
|
+ auto clickResults_4 = dispatcher.emit<bool>(EventTypeDisp::Click, 7);
|
|
|
+ std::cout << "Click results after removal: ";
|
|
|
+ for (bool b : clickResults_4)
|
|
|
+ std::cout << b << " ";
|
|
|
+ std::cout << "\n";
|
|
|
+
|
|
|
+ std::cout << "------------------------- int foo(int, int) -------------------------" << std::endl;
|
|
|
+ std::cout << ">> addHandler(EventTypeDisp::Click, globalIntHandler1) - Free Function" << std::endl;
|
|
|
+ // dispatcher.addHandler(EventTypeDisp::Hover, [](int x, int y) -> int { return x + y; });
|
|
|
+ auto id5_1 = dispatcher.addHandler(EventTypeDisp::Hover, globalIntHandler);
|
|
|
+ std::cout << ">> addHandler(EventTypeDisp::Hover, [](int x, int y) -> int { return x + y; }); - Lambda" << std::endl;
|
|
|
+ auto id5_2 = dispatcher.addHandler(EventTypeDisp::Hover, [](int x, int y) -> int { std::cout << "Lambda Function: " << x+y << std::endl; return x + y; });
|
|
|
+ std::cout << ">> addHandler(EventTypeDisp::Hover, [&w](int x, int y) { return w.globalIntHandler(x, y); }); - Call class member" << std::endl;
|
|
|
+ auto id5_3 = dispatcher.addHandler(EventTypeDisp::Hover, [&w](int x, int y) { return w.globalIntHandler(x, y); });
|
|
|
+
|
|
|
+ clickResultsInt = dispatcher.emit<int>(EventTypeDisp::Hover, 7,8);
|
|
|
+ std::cout << "Hover results: ";
|
|
|
+ for (int b : clickResultsInt)
|
|
|
+ std::cout << b << " ";
|
|
|
+ std::cout << "\n";
|
|
|
+
|
|
|
+ std::cout << "------------------------- float foo(int, int) -------------------------" << std::endl;
|
|
|
+ std::cout << ">> addHandler(EventTypeDisp::Hover, [](int x, int y) -> float { return x / y; }); - Lambda" << std::endl;
|
|
|
+ auto id5_4 = dispatcher.addHandler(EventTypeDisp::Hover, [](int x, int y) -> float {
|
|
|
+ float result = float(x) / float(y);
|
|
|
+ std::cout << "Lambda Function: " << result << std::endl;
|
|
|
+ return result;
|
|
|
+ });
|
|
|
+
|
|
|
+ auto id5_4_result = dispatcher.emit<float>(EventTypeDisp::Hover, 7, 8);
|
|
|
+ std::cout << "Hover results: ";
|
|
|
+ for (float b : id5_4_result)
|
|
|
+ std::cout << b << " ";
|
|
|
+ std::cout << "\n";
|
|
|
+
|
|
|
+ std::cout << "------------------------- float foo(float, float) -------------------------" << std::endl;
|
|
|
+ std::cout << ">> addHandler(EventTypeDisp::Hover, [](float x, float y) -> float { return y / x; }); - Lambda" << std::endl;
|
|
|
+ auto id5_5 = dispatcher.addHandler(EventTypeDisp::Hover, [](float x, float y) -> float {
|
|
|
+ float result = y / x;
|
|
|
+ std::cout << "Lambda Function: " << result << std::endl;
|
|
|
+ return result;
|
|
|
+ });
|
|
|
+
|
|
|
+ auto id5_5_result = dispatcher.emit<float>(EventTypeDisp::Hover, (float) 7.0, (float) 8.0);
|
|
|
+ std::cout << "Hover results: ";
|
|
|
+ for (float b : id5_5_result)
|
|
|
+ std::cout << b << " ";
|
|
|
+ std::cout << "\n";
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+#endif
|