diff --git a/yoga/events.cpp b/yoga/events.cpp new file mode 100644 index 00000000..19092fc5 --- /dev/null +++ b/yoga/events.cpp @@ -0,0 +1,41 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. + */ +#include "events.h" +#include +#include + +namespace facebook { +namespace yoga { + +namespace { + +// For now, a single subscriber is enough. +// This can be changed as soon as the need for more than one subscriber arises. +std::function& globalEventSubscriber() { + static std::function subscriber = nullptr; + return subscriber; +} + +} // namespace + +void Event::subscribe(std::function&& subscriber) { + if (globalEventSubscriber() != nullptr) { + throw std::logic_error( + "Yoga currently supports only one global event subscriber"); + } + globalEventSubscriber() = std::move(subscriber); +} + +void Event::publish(const YGNode& node, Type eventType, const Data& eventData) { + auto& subscriber = globalEventSubscriber(); + if (subscriber) { + subscriber(node, eventType, eventData); + } +} + +} // namespace yoga +} // namespace facebook diff --git a/yoga/events.h b/yoga/events.h new file mode 100644 index 00000000..c48fab7b --- /dev/null +++ b/yoga/events.h @@ -0,0 +1,55 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. + */ +#pragma once + +#include + +struct YGConfig; +struct YGNode; + +namespace facebook { +namespace yoga { + +struct Event { + enum Type {}; + class Data; + using Subscriber = void(const YGNode&, Type, Data); + + template + struct TypedData {}; + + class Data { + const void* data_; + + public: + template + Data(const TypedData& data) : data_{&data} {} + + template + const TypedData& get() const { + return *static_cast*>(data_); + }; + }; + + static void subscribe(std::function&& subscriber); + + template + static void publish(const YGNode& node, const TypedData& eventData = {}) { + publish(node, E, Data{eventData}); + } + + template + static void publish(const YGNode* node, const TypedData& eventData = {}) { + publish(*node, eventData); + } + +private: + static void publish(const YGNode&, Type, const Data&); +}; + +} // namespace yoga +} // namespace facebook