enhance System/Event
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
@@ -11,6 +12,7 @@
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
#include <yas/serialize.hpp>
|
||||
#include <yas/types/std/vector.hpp>
|
||||
|
||||
#include "nf7.hh"
|
||||
|
||||
@@ -20,13 +22,14 @@
|
||||
#include "common/generic_context.hh"
|
||||
#include "common/generic_memento.hh"
|
||||
#include "common/generic_type_info.hh"
|
||||
#include "common/generic_watcher.hh"
|
||||
#include "common/gui.hh"
|
||||
#include "common/life.hh"
|
||||
#include "common/logger.hh"
|
||||
#include "common/logger_ref.hh"
|
||||
#include "common/node.hh"
|
||||
#include "common/ptr_selector.hh"
|
||||
#include "common/value.hh"
|
||||
#include "common/yaml_nf7.hh"
|
||||
#include "common/yas_nf7.hh"
|
||||
|
||||
|
||||
@@ -34,29 +37,41 @@ namespace nf7 {
|
||||
namespace {
|
||||
|
||||
class Event final : public nf7::FileBase,
|
||||
public nf7::GenericConfig, public nf7::DirItem, public nf7::Node {
|
||||
public nf7::GenericConfig, public nf7::DirItem {
|
||||
public:
|
||||
static inline const nf7::GenericTypeInfo<Event> kType = {
|
||||
"System/Event", {"nf7::DirItem"}};
|
||||
static void UpdateTypeTooltip() noexcept {
|
||||
ImGui::TextUnformatted("Records log output from other files.");
|
||||
ImGui::Bullet(); ImGui::TextUnformatted("implements nf7::Node");
|
||||
}
|
||||
|
||||
class Lambda;
|
||||
|
||||
struct Data {
|
||||
nf7::File::Path handler;
|
||||
|
||||
// feature switch
|
||||
bool key = false;
|
||||
bool mouse = false;
|
||||
|
||||
std::vector<nf7::File::Path> watch;
|
||||
|
||||
Data() noexcept { }
|
||||
void serialize(auto& ar) {
|
||||
ar(handler);
|
||||
ar(handler, key, mouse, watch);
|
||||
}
|
||||
|
||||
std::string Stringify() const noexcept {
|
||||
YAML::Emitter st;
|
||||
st << YAML::BeginMap;
|
||||
st << YAML::Key << "handler";
|
||||
st << YAML::Value << handler.Stringify();
|
||||
st << YAML::Value << handler;
|
||||
st << YAML::Key << "event";
|
||||
st << YAML::BeginMap;
|
||||
st << YAML::Key << "key";
|
||||
st << YAML::Value << key;
|
||||
st << YAML::Key << "mouse";
|
||||
st << YAML::Value << mouse;
|
||||
st << YAML::Key << "watch";
|
||||
st << YAML::Value << watch;
|
||||
st << YAML::EndMap;
|
||||
st << YAML::EndMap;
|
||||
return {st.c_str(), st.size()};
|
||||
}
|
||||
@@ -64,7 +79,12 @@ class Event final : public nf7::FileBase,
|
||||
const auto yaml = YAML::Load(str);
|
||||
|
||||
Data d;
|
||||
d.handler = nf7::File::Path::Parse(yaml["handler"].as<std::string>());
|
||||
d.handler = yaml["handler"].as<nf7::File::Path>();
|
||||
|
||||
const auto& ev = yaml["event"];
|
||||
d.key = ev["key"].as<bool>();
|
||||
d.mouse = ev["mouse"].as<bool>();
|
||||
d.watch = ev["watch"].as<std::vector<nf7::File::Path>>();
|
||||
|
||||
*this = std::move(d);
|
||||
}
|
||||
@@ -73,11 +93,12 @@ class Event final : public nf7::FileBase,
|
||||
Event(nf7::Env& env, Data&& d = {}) noexcept :
|
||||
nf7::FileBase(kType, env),
|
||||
nf7::GenericConfig(mem_),
|
||||
nf7::DirItem(nf7::DirItem::kMenu),
|
||||
nf7::Node(nf7::Node::kNone),
|
||||
life_(*this), log_(*this),
|
||||
nf7::DirItem(nf7::DirItem::kMenu |
|
||||
nf7::DirItem::kTooltip),
|
||||
log_(*this),
|
||||
la_root_(std::make_shared<nf7::Node::Lambda>(*this)),
|
||||
mem_(*this, std::move(d)) {
|
||||
mem_.onCommit = [this]() { SetUpWatcher(); };
|
||||
}
|
||||
|
||||
Event(nf7::Deserializer& ar) : Event(ar.env()) {
|
||||
@@ -90,14 +111,9 @@ class Event final : public nf7::FileBase,
|
||||
return std::make_unique<Event>(env, Data {mem_.data()});
|
||||
}
|
||||
|
||||
std::shared_ptr<nf7::Node::Lambda> CreateLambda(
|
||||
const std::shared_ptr<nf7::Node::Lambda>&) noexcept override;
|
||||
nf7::Node::Meta GetMeta() const noexcept override {
|
||||
return {{"value"}, {}};
|
||||
}
|
||||
|
||||
void PostUpdate() noexcept override;
|
||||
void UpdateMenu() noexcept override;
|
||||
void UpdateTooltip() noexcept override;
|
||||
|
||||
nf7::File::Interface* interface(const std::type_info& t) noexcept override {
|
||||
return nf7::InterfaceSelector<
|
||||
@@ -105,14 +121,24 @@ class Event final : public nf7::FileBase,
|
||||
}
|
||||
|
||||
private:
|
||||
nf7::Life<Event> life_;
|
||||
nf7::LoggerRef log_;
|
||||
nf7::LoggerRef log_;
|
||||
|
||||
std::shared_ptr<nf7::Node::Lambda> la_root_;
|
||||
std::shared_ptr<nf7::Node::Lambda> la_;
|
||||
|
||||
nf7::GenericMemento<Data> mem_;
|
||||
|
||||
class Watcher final : public nf7::Env::Watcher {
|
||||
public:
|
||||
Watcher(Event& f) noexcept : nf7::Env::Watcher(f.env()), f_(f) {
|
||||
}
|
||||
private:
|
||||
Event& f_;
|
||||
|
||||
void Handle(const nf7::File::Event& e) noexcept override { f_.TriggerWatch(e); }
|
||||
};
|
||||
std::optional<Watcher> watch_;
|
||||
|
||||
|
||||
nf7::Node& GetHandler() const {
|
||||
return ResolveOrThrow(mem_->handler).interfaceOrThrow<nf7::Node>();
|
||||
@@ -138,58 +164,82 @@ class Event final : public nf7::FileBase,
|
||||
}}, la_root_);
|
||||
}
|
||||
}
|
||||
void TriggerCustomEvent(const nf7::Value& v) noexcept {
|
||||
void TriggerWatch(const nf7::File::Event& e) noexcept {
|
||||
if (auto la = CreateLambdaIf()) {
|
||||
la->Handle("custom", v, la_root_);
|
||||
std::string type;
|
||||
switch (e.type) {
|
||||
case nf7::File::Event::kAdd:
|
||||
type = "add";
|
||||
break;
|
||||
case nf7::File::Event::kUpdate:
|
||||
type = "update";
|
||||
break;
|
||||
case nf7::File::Event::kRemove:
|
||||
type = "remove";
|
||||
break;
|
||||
case nf7::File::Event::kReqFocus:
|
||||
type = "focus";
|
||||
break;
|
||||
}
|
||||
la->Handle("watch", nf7::Value {std::vector<nf7::Value::TuplePair> {
|
||||
{"file", static_cast<nf7::Value::Integer>(e.id)},
|
||||
{"type", std::move(type)},
|
||||
}}, la_root_);
|
||||
}
|
||||
}
|
||||
|
||||
void SetUpWatcher() noexcept {
|
||||
watch_.emplace(*this);
|
||||
for (const auto& p : mem_->watch)
|
||||
try {
|
||||
watch_->Watch(ResolveOrThrow(p).id());
|
||||
} catch (nf7::File::NotFoundException&) {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Event::Lambda final : public nf7::Node::Lambda {
|
||||
public:
|
||||
Lambda(Event& f, const std::shared_ptr<nf7::Node::Lambda>& parent) noexcept :
|
||||
nf7::Node::Lambda(f, parent), f_(f.life_) {
|
||||
}
|
||||
|
||||
void Handle(const nf7::Node::Lambda::Msg& in) noexcept
|
||||
try {
|
||||
f_.EnforceAlive();
|
||||
f_->TriggerCustomEvent(in.value);
|
||||
} catch (nf7::Exception&) {
|
||||
}
|
||||
|
||||
private:
|
||||
nf7::Life<Event>::Ref f_;
|
||||
};
|
||||
std::shared_ptr<nf7::Node::Lambda> Event::CreateLambda(
|
||||
const std::shared_ptr<nf7::Node::Lambda>& parent) noexcept {
|
||||
return std::make_shared<Event::Lambda>(*this, parent);
|
||||
}
|
||||
|
||||
|
||||
void Event::PostUpdate() noexcept {
|
||||
const auto& io = ImGui::GetIO();
|
||||
|
||||
for (size_t i = 0; i < ImGuiKey_KeysData_SIZE; ++i) {
|
||||
const auto& key = io.KeysData[i];
|
||||
const char* event = nullptr;
|
||||
if (key.DownDuration == 0) {
|
||||
event = "down";
|
||||
} else if (key.DownDurationPrev >= 0 && !key.Down) {
|
||||
event = "up";
|
||||
}
|
||||
if (event) {
|
||||
const auto k = static_cast<ImGuiKey>(i);
|
||||
TriggerKeyEvent(ImGui::GetKeyName(k), event);
|
||||
if (mem_->key) {
|
||||
for (size_t i = 0; i < ImGuiKey_KeysData_SIZE; ++i) {
|
||||
const auto& key = io.KeysData[i];
|
||||
const char* event = nullptr;
|
||||
if (key.DownDuration == 0) {
|
||||
event = "down";
|
||||
} else if (key.DownDurationPrev >= 0 && !key.Down) {
|
||||
event = "up";
|
||||
}
|
||||
if (event) {
|
||||
const auto k = static_cast<ImGuiKey>(i);
|
||||
TriggerKeyEvent(ImGui::GetKeyName(k), event);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mem_->mouse) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
void Event::UpdateMenu() noexcept {
|
||||
if (ImGui::MenuItem("drop handler's lambda")) {
|
||||
if (ImGui::MenuItem("drop handler lambda")) {
|
||||
la_ = nullptr;
|
||||
}
|
||||
}
|
||||
void Event::UpdateTooltip() noexcept {
|
||||
ImGui::Text("handler: %s", mem_->handler.Stringify().c_str());
|
||||
ImGui::Text("events :");
|
||||
if (mem_->key) {
|
||||
ImGui::Bullet(); ImGui::TextUnformatted("key");
|
||||
}
|
||||
if (mem_->mouse) {
|
||||
ImGui::Bullet(); ImGui::TextUnformatted("mouse");
|
||||
}
|
||||
if (mem_->watch.size() > 0) {
|
||||
ImGui::Bullet(); ImGui::TextUnformatted("watch");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace nf7
|
||||
|
||||
Reference in New Issue
Block a user