From 4fde43313ca3ae4b8da8d5c516a2a06e14a226d7 Mon Sep 17 00:00:00 2001 From: lisyarus Date: Sat, 10 Aug 2024 11:58:21 +0300 Subject: [PATCH] Reactive UI library wip: add floating, shape_reader and storage --- libs/ui/include/psemek/ui/floating.hpp | 20 +++++++ .../include/psemek/ui/impl/floating_base.hpp | 28 +++++++++ .../psemek/ui/impl/shape_reader_base.hpp | 23 ++++++++ .../include/psemek/ui/impl/storage_base.hpp | 29 +++++++++ libs/ui/include/psemek/ui/shape_reader.hpp | 17 ++++++ libs/ui/include/psemek/ui/storage.hpp | 19 ++++++ .../source/impl/default_component_factory.cpp | 5 ++ libs/ui/source/impl/floating_base.cpp | 49 +++++++++++++++ libs/ui/source/impl/shape_reader_base.cpp | 35 +++++++++++ libs/ui/source/impl/storage_base.cpp | 59 +++++++++++++++++++ 10 files changed, 284 insertions(+) create mode 100644 libs/ui/include/psemek/ui/floating.hpp create mode 100644 libs/ui/include/psemek/ui/impl/floating_base.hpp create mode 100644 libs/ui/include/psemek/ui/impl/shape_reader_base.hpp create mode 100644 libs/ui/include/psemek/ui/impl/storage_base.hpp create mode 100644 libs/ui/include/psemek/ui/shape_reader.hpp create mode 100644 libs/ui/include/psemek/ui/storage.hpp create mode 100644 libs/ui/source/impl/floating_base.cpp create mode 100644 libs/ui/source/impl/shape_reader_base.cpp create mode 100644 libs/ui/source/impl/storage_base.cpp diff --git a/libs/ui/include/psemek/ui/floating.hpp b/libs/ui/include/psemek/ui/floating.hpp new file mode 100644 index 00000000..f9099dbd --- /dev/null +++ b/libs/ui/include/psemek/ui/floating.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include +#include +#include + +#include + +namespace psemek::ui +{ + + struct floating + { + react::value child = {}; + react::value> anchor = {0.f, 0.f}; + react::value halign = halignment::center; + react::value valign = valignment::center; + }; + +} diff --git a/libs/ui/include/psemek/ui/impl/floating_base.hpp b/libs/ui/include/psemek/ui/impl/floating_base.hpp new file mode 100644 index 00000000..99589fbb --- /dev/null +++ b/libs/ui/include/psemek/ui/impl/floating_base.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include +#include +#include + +namespace psemek::ui::impl +{ + + struct floating_base + : single_container + { + floating_base(); + + void reshape(geom::box const & new_shape) override; + react::value size_constraints() const override; + + void update(floating const & value); + + private: + react::value> anchor_ = geom::point{0.f, 0.f}; + react::value halign_ = halignment::center; + react::value valign_ = valignment::center; + + react::value size_constraints_; + }; + +} diff --git a/libs/ui/include/psemek/ui/impl/shape_reader_base.hpp b/libs/ui/include/psemek/ui/impl/shape_reader_base.hpp new file mode 100644 index 00000000..1d65b895 --- /dev/null +++ b/libs/ui/include/psemek/ui/impl/shape_reader_base.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include +#include + +namespace psemek::ui::impl +{ + + struct shape_reader_base + : single_container + { + shape_reader_base(); + + void reshape(geom::box const & new_shape) override; + react::value size_constraints() const override; + + void update(shape_reader const & value); + + private: + react::source> shape_ = {}; + }; + +} diff --git a/libs/ui/include/psemek/ui/impl/storage_base.hpp b/libs/ui/include/psemek/ui/impl/storage_base.hpp new file mode 100644 index 00000000..d34498b4 --- /dev/null +++ b/libs/ui/include/psemek/ui/impl/storage_base.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include +#include +#include + +namespace psemek::ui::impl +{ + + struct storage_base + : single_container + { + storage_base(); + + void reshape(geom::box const & new_shape) override; + react::value size_constraints() const override; + + void set_child(std::unique_ptr child) override; + std::unique_ptr release_child() override; + + void update(storage const & value); + + private: + util::hash_map> values_; + react::source> child_size_constraints_; + react::value size_constraints_; + }; + +} diff --git a/libs/ui/include/psemek/ui/shape_reader.hpp b/libs/ui/include/psemek/ui/shape_reader.hpp new file mode 100644 index 00000000..96b14717 --- /dev/null +++ b/libs/ui/include/psemek/ui/shape_reader.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include +#include + +#include + +namespace psemek::ui +{ + + struct shape_reader + { + react::value child = {}; + react::source> shape = {}; + }; + +} diff --git a/libs/ui/include/psemek/ui/storage.hpp b/libs/ui/include/psemek/ui/storage.hpp new file mode 100644 index 00000000..261ddf59 --- /dev/null +++ b/libs/ui/include/psemek/ui/storage.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include +#include +#include + +#include + +namespace psemek::ui +{ + + struct storage + { + react::value child = {}; + + util::hash_map> values = {}; + }; + +} diff --git a/libs/ui/source/impl/default_component_factory.cpp b/libs/ui/source/impl/default_component_factory.cpp index 6817eef7..0be79d31 100644 --- a/libs/ui/source/impl/default_component_factory.cpp +++ b/libs/ui/source/impl/default_component_factory.cpp @@ -13,6 +13,9 @@ #include #include #include +#include +#include +#include namespace psemek::ui::impl { @@ -31,6 +34,8 @@ namespace psemek::ui::impl register_type(); register_type(); register_type(); + register_type(); + register_type(); } } diff --git a/libs/ui/source/impl/floating_base.cpp b/libs/ui/source/impl/floating_base.cpp new file mode 100644 index 00000000..eba71e26 --- /dev/null +++ b/libs/ui/source/impl/floating_base.cpp @@ -0,0 +1,49 @@ +#include +#include +#include +#include + +namespace psemek::ui::impl +{ + + namespace + { + + geom::box compute_child_shape(geom::box const & size_constraints, geom::point const & anchor, halignment halign, valignment valign) + { + geom::vector size{size_constraints[0].min, size_constraints[1].min}; + + geom::box result; + result[0] = geom::interval{- size[0], 0.f} + (1.f - lerp_factor(halign)) * size[0] + anchor[0]; + result[1] = geom::interval{- size[1], 0.f} + (1.f - lerp_factor(valign)) * size[1] + anchor[1]; + + return result; + } + + } + + floating_base::floating_base() + : size_constraints_(impl::size_constraints::max()) + {} + + void floating_base::reshape(geom::box const & new_shape) + { + single_container::reshape(new_shape); + + if (auto child = this->child()) + child->reshape(compute_child_shape((*(child->size_constraints())).box, *anchor_, *halign_, *valign_)); + } + + react::value floating_base::size_constraints() const + { + return size_constraints_; + } + + void floating_base::update(floating const & value) + { + anchor_ = value.anchor; + halign_ = value.halign; + valign_ = value.valign; + } + +} diff --git a/libs/ui/source/impl/shape_reader_base.cpp b/libs/ui/source/impl/shape_reader_base.cpp new file mode 100644 index 00000000..406b6d62 --- /dev/null +++ b/libs/ui/source/impl/shape_reader_base.cpp @@ -0,0 +1,35 @@ +#include + +namespace psemek::ui::impl +{ + + shape_reader_base::shape_reader_base() + : shape_(geom::box{{{0.f, 0.f}, {0.f, 0.f}}}) + {} + + void shape_reader_base::reshape(geom::box const & new_shape) + { + single_container::reshape(new_shape); + + if (auto child = this->child()) + child->reshape(new_shape); + + shape_.set(new_shape); + } + + react::value shape_reader_base::size_constraints() const + { + if (auto child = this->child()) + return child->size_constraints(); + + return size_constraints::max(); + } + + void shape_reader_base::update(shape_reader const & value) + { + shape_ = value.shape; + + shape_.set(shape()); + } + +} diff --git a/libs/ui/source/impl/storage_base.cpp b/libs/ui/source/impl/storage_base.cpp new file mode 100644 index 00000000..50fa51c0 --- /dev/null +++ b/libs/ui/source/impl/storage_base.cpp @@ -0,0 +1,59 @@ +#include + +#include + +namespace psemek::ui::impl +{ + + storage_base::storage_base() + : child_size_constraints_(size_constraints::max()) + , size_constraints_(react::join(child_size_constraints_)) + {} + + void storage_base::reshape(geom::box const & new_shape) + { + single_container::reshape(new_shape); + + if (auto child = this->child()) + child->reshape(new_shape); + } + + react::value storage_base::size_constraints() const + { + if (auto child = this->child()) + return child->size_constraints(); + + return impl::size_constraints::max(); + } + + void storage_base::set_child(std::unique_ptr child) + { + if (child) + child_size_constraints_.set(child->size_constraints()); + else + child_size_constraints_.set(size_constraints::max()); + single_container::set_child(std::move(child)); + } + + std::unique_ptr storage_base::release_child() + { + child_size_constraints_.set(size_constraints::max()); + return single_container::release_child(); + } + + void storage_base::update(storage const & value) + { + util::hash_map> new_values; + + for (auto const & p : value.values) + { + auto & v = (new_values[p.first] = p.second); + + if (auto it = values_.find(p.first); it != values_.end()) + v.set(*(it->second)); + } + + values_ = std::move(new_values); + } + +}