2021-04-06 19:31:54 +03:00
|
|
|
#include <vector>
|
2021-03-29 23:43:14 +03:00
|
|
|
#include <functional>
|
|
|
|
|
#include <string>
|
2021-04-11 12:45:39 +03:00
|
|
|
#include <unordered_map>
|
2021-03-29 23:43:14 +03:00
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
namespace events {
|
|
|
|
|
class EventId {
|
|
|
|
|
private:
|
|
|
|
|
std::string name = "";
|
|
|
|
|
|
|
|
|
|
int nameHash = std::hash<std::string>{}("");
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
EventId() = default;
|
|
|
|
|
|
2021-04-11 12:45:39 +03:00
|
|
|
EventId(std::string name) : name(name),
|
|
|
|
|
nameHash(std::hash<std::string>{}(name)) {}
|
2021-03-29 23:43:14 +03:00
|
|
|
|
|
|
|
|
bool operator==(const EventId& eId) const {
|
|
|
|
|
return nameHash == eId.nameHash && name == eId.name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool operator!=(const EventId& eId) const {
|
|
|
|
|
return !operator==(eId);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class EventData { // may be changed
|
|
|
|
|
private:
|
|
|
|
|
using T = int;
|
|
|
|
|
|
2021-04-11 12:45:39 +03:00
|
|
|
std::unordered_map<std::string, T> data;
|
2021-03-29 23:43:14 +03:00
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
EventData() {}
|
|
|
|
|
|
|
|
|
|
void setField(const std::string& key, const T& value) {
|
|
|
|
|
data[key] = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const T& getField(const std::string& key) {
|
|
|
|
|
return data[key];
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class Event {
|
|
|
|
|
private:
|
|
|
|
|
EventId id;
|
|
|
|
|
|
|
|
|
|
EventData data;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
Event(const EventId& id, const EventData& data) :
|
|
|
|
|
id(id), data(data) {}
|
|
|
|
|
|
2021-04-06 19:31:54 +03:00
|
|
|
const EventId& getEventId() const {
|
|
|
|
|
return id;
|
2021-03-29 23:43:14 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EventData& getData() {
|
|
|
|
|
return data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const EventData& getData() const {
|
|
|
|
|
return data;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class EventHandler {
|
|
|
|
|
private:
|
|
|
|
|
std::function<void(const EventData&)> handler;
|
2021-04-06 19:31:54 +03:00
|
|
|
|
|
|
|
|
static size_t lastId;
|
|
|
|
|
|
|
|
|
|
size_t id;
|
2021-03-29 23:43:14 +03:00
|
|
|
|
|
|
|
|
EventId eventId;
|
|
|
|
|
public:
|
|
|
|
|
EventHandler(std::function<void(const EventData&)> handler,
|
2021-04-06 19:31:54 +03:00
|
|
|
const EventId& eventId) : handler(handler), eventId(eventId) {
|
|
|
|
|
id = lastId;
|
|
|
|
|
++lastId;
|
|
|
|
|
}
|
2021-03-29 23:43:14 +03:00
|
|
|
|
2021-04-06 19:31:54 +03:00
|
|
|
void handleEvent(const Event& event) {
|
|
|
|
|
handler(event.getData());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t getId() const {
|
|
|
|
|
return id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const EventId& getEventId() const {
|
|
|
|
|
return eventId;
|
2021-03-29 23:43:14 +03:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class EventCenter {
|
|
|
|
|
private:
|
2021-04-11 12:45:39 +03:00
|
|
|
std::unordered_map<EventId, std::vector<EventHandler>> handlers;
|
2021-03-29 23:43:14 +03:00
|
|
|
public:
|
|
|
|
|
void addEventHandler(const EventHandler& handler) {
|
2021-04-06 19:31:54 +03:00
|
|
|
handlers[handler.getEventId()].push_back(handler);
|
2021-03-29 23:43:14 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void removeEventHandler(const EventHandler& handler) {
|
2021-04-06 19:31:54 +03:00
|
|
|
std::vector<EventHandler>& v = handlers[handler.getEventId()];
|
|
|
|
|
size_t id = handler.getId();
|
|
|
|
|
for (size_t i = 0; i < v.size(); ++i) {
|
|
|
|
|
if (v[i].getId() == id) {
|
|
|
|
|
if (i + 1 != v.size()) {
|
|
|
|
|
std::swap(v[i], v.back());
|
|
|
|
|
}
|
|
|
|
|
v.pop_back();
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-03-29 23:43:14 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void invokeEvent(const Event& event) {
|
2021-04-06 19:31:54 +03:00
|
|
|
for (auto& handler : handlers[event.getEventId()]) { // is it really work ??
|
2021-03-29 23:43:14 +03:00
|
|
|
handler.handleEvent(event);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
2021-04-06 19:31:54 +03:00
|
|
|
}
|