From ae815ec538a64370f2888a56053f80705ae46c47 Mon Sep 17 00:00:00 2001 From: lisyarus Date: Sun, 28 Jul 2024 19:28:38 +0300 Subject: [PATCH] UI library wip: event handling, auto-layout, basic layouts & buttons --- libs/ui/CMakeLists.txt | 2 +- libs/ui/include/psemek/ui/aligned.hpp | 18 ++++ libs/ui/include/psemek/ui/alignment.hpp | 42 +++++++++ libs/ui/include/psemek/ui/box_layout.hpp | 2 + libs/ui/include/psemek/ui/button.hpp | 6 +- libs/ui/include/psemek/ui/fixed_size.hpp | 29 +++++++ .../include/psemek/ui/impl/aligned_base.hpp | 29 +++++++ .../psemek/ui/impl/box_layout_base.hpp | 4 +- .../ui/include/psemek/ui/impl/button_base.hpp | 27 ++++++ libs/ui/include/psemek/ui/impl/component.hpp | 9 +- libs/ui/include/psemek/ui/impl/controller.hpp | 6 ++ .../ui/impl/default_component_factory.hpp | 14 +++ libs/ui/include/psemek/ui/impl/events.hpp | 14 +++ .../psemek/ui/impl/fixed_size_base.hpp | 28 ++++++ .../psemek/ui/impl/size_constraints.hpp | 4 + libs/ui/source/impl/aligned_base.cpp | 71 +++++++++++++++ libs/ui/source/impl/box_layout_base.cpp | 39 +++++---- libs/ui/source/impl/button_base.cpp | 47 ++++++++++ libs/ui/source/impl/container.cpp | 1 + libs/ui/source/impl/controller.cpp | 87 ++++++++++++++++++- .../source/impl/default_component_factory.cpp | 28 ++++++ libs/ui/source/impl/fixed_size_base.cpp | 65 ++++++++++++++ libs/ui/source/impl/single_container_base.cpp | 1 - libs/ui/source/impl/size_constraints.cpp | 4 - libs/ui/source/impl/stack_layout_base.cpp | 2 + 25 files changed, 547 insertions(+), 32 deletions(-) create mode 100644 libs/ui/include/psemek/ui/aligned.hpp create mode 100644 libs/ui/include/psemek/ui/fixed_size.hpp create mode 100644 libs/ui/include/psemek/ui/impl/aligned_base.hpp create mode 100644 libs/ui/include/psemek/ui/impl/button_base.hpp create mode 100644 libs/ui/include/psemek/ui/impl/default_component_factory.hpp create mode 100644 libs/ui/include/psemek/ui/impl/events.hpp create mode 100644 libs/ui/include/psemek/ui/impl/fixed_size_base.hpp create mode 100644 libs/ui/source/impl/aligned_base.cpp create mode 100644 libs/ui/source/impl/button_base.cpp create mode 100644 libs/ui/source/impl/default_component_factory.cpp create mode 100644 libs/ui/source/impl/fixed_size_base.cpp diff --git a/libs/ui/CMakeLists.txt b/libs/ui/CMakeLists.txt index f603e7af..819171b9 100644 --- a/libs/ui/CMakeLists.txt +++ b/libs/ui/CMakeLists.txt @@ -3,6 +3,6 @@ file(GLOB_RECURSE PSEMEK_UI_SOURCES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "sour psemek_add_library(psemek-ui ${PSEMEK_UI_HEADERS} ${PSEMEK_UI_SOURCES}) target_include_directories(psemek-ui PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") -target_link_libraries(psemek-ui PUBLIC psemek-util psemek-react psemek-geom psemek-gfx) +target_link_libraries(psemek-ui PUBLIC psemek-util psemek-react psemek-geom psemek-gfx psemek-app) psemek_glob_tests(psemek-ui tests) diff --git a/libs/ui/include/psemek/ui/aligned.hpp b/libs/ui/include/psemek/ui/aligned.hpp new file mode 100644 index 00000000..01e2a2e5 --- /dev/null +++ b/libs/ui/include/psemek/ui/aligned.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include +#include + +#include + +namespace psemek::ui +{ + + struct aligned + { + react::value child = {}; + react::value halign = halignment::center; + react::value valign = valignment::center; + }; + +} diff --git a/libs/ui/include/psemek/ui/alignment.hpp b/libs/ui/include/psemek/ui/alignment.hpp index 8304d99c..dbc65898 100644 --- a/libs/ui/include/psemek/ui/alignment.hpp +++ b/libs/ui/include/psemek/ui/alignment.hpp @@ -1,5 +1,8 @@ #pragma once +#include +#include + namespace psemek::ui { @@ -17,4 +20,43 @@ namespace psemek::ui bottom, }; + template + concept any_alignment = std::is_same_v || std::is_same_v; + + inline float lerp_factor(halignment h) + { + switch (h) + { + case halignment::left: return 0; + case halignment::center: return 0.5f; + case halignment::right: return 1.f; + } + + throw util::unknown_enum_value_exception{h}; + } + + inline float lerp_factor(valignment h) + { + switch (h) + { + case valignment::top: return 0.f; + case valignment::center: return 0.5f; + case valignment::bottom: return 1.f; + } + + throw util::unknown_enum_value_exception{h}; + } + + template + inline float align(geom::interval const & range, Alignment a) + { + return geom::lerp(range, lerp_factor(a)); + } + + template + inline geom::interval align(geom::interval const & range, float size, Alignment a) + { + return geom::interval{range.min, range.min + size} + (range.length() - size) * lerp_factor(a); + } + } diff --git a/libs/ui/include/psemek/ui/box_layout.hpp b/libs/ui/include/psemek/ui/box_layout.hpp index ef48f6e8..679d6ebc 100644 --- a/libs/ui/include/psemek/ui/box_layout.hpp +++ b/libs/ui/include/psemek/ui/box_layout.hpp @@ -33,12 +33,14 @@ namespace psemek::ui { using element = box_layout::element; react::value> children = {}; + react::value padding = 0.f; }; struct vertical { using element = box_layout::element; react::value> children = {}; + react::value padding = 0.f; }; } diff --git a/libs/ui/include/psemek/ui/button.hpp b/libs/ui/include/psemek/ui/button.hpp index 5dbcf9ae..bb4b8b8f 100644 --- a/libs/ui/include/psemek/ui/button.hpp +++ b/libs/ui/include/psemek/ui/button.hpp @@ -3,15 +3,13 @@ #include #include -#include - namespace psemek::ui { struct button { - react::source on_click = {}; - react::value child = {}; + react::source mouseover = {}; + react::source mousedown = {}; }; } diff --git a/libs/ui/include/psemek/ui/fixed_size.hpp b/libs/ui/include/psemek/ui/fixed_size.hpp new file mode 100644 index 00000000..9c1271c0 --- /dev/null +++ b/libs/ui/include/psemek/ui/fixed_size.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include +#include + +#include + +namespace psemek::ui +{ + + struct fixed_size + { + react::value child = {}; + react::value> size = {0.f, 0.f}; + }; + + struct fixed_width + { + react::value child = {}; + react::value width = 0.f; + }; + + struct fixed_height + { + react::value child = {}; + react::value height = 0.f; + }; + +} diff --git a/libs/ui/include/psemek/ui/impl/aligned_base.hpp b/libs/ui/include/psemek/ui/impl/aligned_base.hpp new file mode 100644 index 00000000..33efca77 --- /dev/null +++ b/libs/ui/include/psemek/ui/impl/aligned_base.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include +#include +#include + +namespace psemek::ui::impl +{ + + struct aligned_base + : single_container + { + aligned_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(aligned const & value); + + private: + react::source>> align_; + react::source> child_size_constraints_; + react::value size_constraints_; + }; + +} diff --git a/libs/ui/include/psemek/ui/impl/box_layout_base.hpp b/libs/ui/include/psemek/ui/impl/box_layout_base.hpp index ef40d72e..24ae5ed7 100644 --- a/libs/ui/include/psemek/ui/impl/box_layout_base.hpp +++ b/libs/ui/include/psemek/ui/impl/box_layout_base.hpp @@ -34,7 +34,7 @@ namespace psemek::ui::impl struct box_layout_base : container { - box_layout_base(react::value margin); + box_layout_base(); void reshape(geom::box const & new_shape) override; react::value size_constraints() const override; @@ -45,7 +45,7 @@ namespace psemek::ui::impl void update(typename detail::box_layout_type::type const & box_layout); private: - react::value margin_; + react::source> padding_; react::value>> size_policies_; react::source>> children_size_constraints_; react::value size_constraints_; diff --git a/libs/ui/include/psemek/ui/impl/button_base.hpp b/libs/ui/include/psemek/ui/impl/button_base.hpp new file mode 100644 index 00000000..3151dfe2 --- /dev/null +++ b/libs/ui/include/psemek/ui/impl/button_base.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +namespace psemek::ui::impl +{ + + struct button_base + : component + { + button_base(); + + bool on_event(mouse_move_event const & event) override; + bool on_event(mouse_button_event const & event) override; + + void update(button const & value); + + private: + bool is_mouseover_ = false; + bool is_mousedown_ = false; + + react::source mouseover_; + react::source mousedown_; + }; + +} diff --git a/libs/ui/include/psemek/ui/impl/component.hpp b/libs/ui/include/psemek/ui/impl/component.hpp index f8045f3e..2d62fcb6 100644 --- a/libs/ui/include/psemek/ui/impl/component.hpp +++ b/libs/ui/include/psemek/ui/impl/component.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -13,8 +14,6 @@ namespace psemek::ui::impl struct component { - static constexpr float infinity = std::numeric_limits::infinity(); - virtual util::span const> children() const; virtual geom::box const & shape() const; @@ -22,6 +21,12 @@ namespace psemek::ui::impl virtual react::value size_constraints() const; + virtual bool on_event(resize_event const &) { return false; } + virtual bool on_event(mouse_move_event const &) { return false; } + virtual bool on_event(mouse_wheel_event const &) { return false; } + virtual bool on_event(mouse_button_event const &) { return false; } + virtual bool on_event(key_event const &) { return false; } + virtual ~component() {} private: diff --git a/libs/ui/include/psemek/ui/impl/controller.hpp b/libs/ui/include/psemek/ui/impl/controller.hpp index 7df64682..7e05a84c 100644 --- a/libs/ui/include/psemek/ui/impl/controller.hpp +++ b/libs/ui/include/psemek/ui/impl/controller.hpp @@ -16,6 +16,12 @@ namespace psemek::ui::impl void set_ui(react::value ui); + bool on_event(resize_event const & event); + bool on_event(mouse_move_event const & event); + bool on_event(mouse_wheel_event const & event); + bool on_event(mouse_button_event const & event); + bool on_event(key_event const & event); + private: psemek_declare_pimpl }; diff --git a/libs/ui/include/psemek/ui/impl/default_component_factory.hpp b/libs/ui/include/psemek/ui/impl/default_component_factory.hpp new file mode 100644 index 00000000..616cf305 --- /dev/null +++ b/libs/ui/include/psemek/ui/impl/default_component_factory.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include + +namespace psemek::ui::impl +{ + + struct default_component_factory + : component_factory_base + { + default_component_factory(); + }; + +} diff --git a/libs/ui/include/psemek/ui/impl/events.hpp b/libs/ui/include/psemek/ui/impl/events.hpp new file mode 100644 index 00000000..6e1bf28b --- /dev/null +++ b/libs/ui/include/psemek/ui/impl/events.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include + +namespace psemek::ui::impl +{ + + using app::resize_event; + using app::mouse_move_event; + using app::mouse_button_event; + using app::mouse_wheel_event; + using app::key_event; + +} diff --git a/libs/ui/include/psemek/ui/impl/fixed_size_base.hpp b/libs/ui/include/psemek/ui/impl/fixed_size_base.hpp new file mode 100644 index 00000000..b50d1df9 --- /dev/null +++ b/libs/ui/include/psemek/ui/impl/fixed_size_base.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include +#include +#include + +namespace psemek::ui::impl +{ + + struct fixed_size_base + : single_container + { + fixed_size_base(); + + void reshape(geom::box const & new_shape) override; + react::value size_constraints() const override; + + void update(fixed_size const & value); + void update(fixed_width const & value); + void update(fixed_height const & value); + + private: + react::source, 2>>> size_; + react::source> child_size_constraints_; + react::value size_constraints_; + }; + +} diff --git a/libs/ui/include/psemek/ui/impl/size_constraints.hpp b/libs/ui/include/psemek/ui/impl/size_constraints.hpp index c6d3d21d..0b8cf5e4 100644 --- a/libs/ui/include/psemek/ui/impl/size_constraints.hpp +++ b/libs/ui/include/psemek/ui/impl/size_constraints.hpp @@ -2,6 +2,8 @@ #include +#include + namespace psemek::ui::impl { @@ -9,6 +11,8 @@ namespace psemek::ui::impl { geom::box box; + static constexpr float infinity = std::numeric_limits::infinity(); + static size_constraints max(); }; diff --git a/libs/ui/source/impl/aligned_base.cpp b/libs/ui/source/impl/aligned_base.cpp new file mode 100644 index 00000000..5fc6f7ff --- /dev/null +++ b/libs/ui/source/impl/aligned_base.cpp @@ -0,0 +1,71 @@ +#include +#include +#include + +namespace psemek::ui::impl +{ + + namespace + { + + size_constraints compute_size_constraints(size_constraints const & child_size_constraints) + { + return { + .box = {{ + {child_size_constraints.box[0].min, size_constraints::infinity}, + {child_size_constraints.box[1].min, size_constraints::infinity}, + }} + }; + } + + } + + aligned_base::aligned_base() + : align_({halignment::center, valignment::center}) + , child_size_constraints_(size_constraints::max()) + , size_constraints_(react::map(compute_size_constraints, react::join(child_size_constraints_))) + {} + + void aligned_base::reshape(geom::box const & new_shape) + { + single_container::reshape(new_shape); + + auto [ halign, valign ] = **align_; + + auto child_size_constraints = **child_size_constraints_; + + if (auto child = this->child()) + child->reshape({ + align(new_shape[0], child_size_constraints.box[0].min, halign), + align(new_shape[1], child_size_constraints.box[1].min, valign), + }); + } + + react::value aligned_base::size_constraints() const + { + return size_constraints_; + } + + void aligned_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 aligned_base::release_child() + { + child_size_constraints_.set(size_constraints::max()); + + return single_container::release_child(); + } + + void aligned_base::update(aligned const & value) + { + align_.set(react::map([](auto const & halign, auto const & valign){ return std::pair{halign, valign}; }, value.halign, value.valign)); + } + +} diff --git a/libs/ui/source/impl/box_layout_base.cpp b/libs/ui/source/impl/box_layout_base.cpp index f3208200..e74d4861 100644 --- a/libs/ui/source/impl/box_layout_base.cpp +++ b/libs/ui/source/impl/box_layout_base.cpp @@ -12,7 +12,7 @@ namespace psemek::ui::impl template size_constraints compute_size_constraints(std::vector const & size_policies, - std::vector const & children_size_constraints, float margin) + std::vector const & children_size_constraints, float padding) { size_constraints minimized = size_constraints::max(); size_constraints weight_unit = minimized; @@ -39,7 +39,7 @@ namespace psemek::ui::impl if (size_policies.size() > 0) { geom::vector shift_delta{0.f, 0.f}; - shift_delta[Dimension] = margin * (size_policies.size() - 1); + shift_delta[Dimension] = padding * (size_policies.size() - 1); result = shift(std::move(result), shift_delta); } @@ -47,18 +47,21 @@ namespace psemek::ui::impl } template - std::vector allocate(float total_size, std::vector> const & policies, - util::span const> children) + std::vector allocate(float total_size, std::vector> const & size_policies, + util::span const> children, float padding) { - std::vector result(policies.size(), 0.f); + std::vector result(size_policies.size(), 0.f); + + if (!size_policies.empty()) + total_size -= padding * (size_policies.size() - 1); float total_weight = 0.f; // First, allocate minimized elements // Also compute the total weight for weighted elements - for (std::size_t i = 0; i < policies.size(); ++i) + for (std::size_t i = 0; i < size_policies.size(); ++i) { - auto const policy = policies[i] ? *policies[i] : default_policy; + auto const policy = size_policies[i] ? *size_policies[i] : default_policy; if (std::get_if(&policy)) { @@ -72,9 +75,9 @@ namespace psemek::ui::impl } // Next, allocate weighted elements - for (std::size_t i = 0; i < policies.size(); ++i) + for (std::size_t i = 0; i < size_policies.size(); ++i) { - auto const policy = policies[i] ? *policies[i] : default_policy; + auto const policy = size_policies[i] ? *size_policies[i] : default_policy; if (auto weight = std::get_if(&policy)) { @@ -88,18 +91,18 @@ namespace psemek::ui::impl } template - box_layout_base::box_layout_base(react::value margin) - : margin_(margin) + box_layout_base::box_layout_base() + : padding_(0.f) , size_policies_({}) , children_size_constraints_() , size_constraints_( react::map( - [](auto const & size_policies, auto const & children_size_constraints, auto const & margin){ - return compute_size_constraints(size_policies, children_size_constraints, margin); + [](auto const & size_policies, auto const & children_size_constraints, auto const & padding){ + return compute_size_constraints(size_policies, children_size_constraints, padding); }, react::join(react::map(react::unpack_with_default(default_policy), size_policies_)), react::join(react::map(react::unpack, children_size_constraints_)), - margin_ + react::join(padding_) ) ) {} @@ -112,9 +115,9 @@ namespace psemek::ui::impl if (children().empty()) return; - float const margin = *margin_; + auto padding = **padding_; - auto sizes = allocate(new_shape[Dimension].length() - (children().size() - 1) * margin, *size_policies_, children()); + auto sizes = allocate(new_shape[Dimension].length(), *size_policies_, children(), padding); float pen = new_shape[Dimension].min; for (std::size_t i = 0; i < children().size(); ++i) @@ -127,7 +130,7 @@ namespace psemek::ui::impl children()[i]->reshape(child_shape); pen += sizes[i]; - pen += margin; + pen += padding; } } @@ -171,6 +174,8 @@ namespace psemek::ui::impl size_policies.push_back(child.policy); return size_policies; }, box_layout.children); + + padding_.set(box_layout.padding); } template struct box_layout_base<0>; diff --git a/libs/ui/source/impl/button_base.cpp b/libs/ui/source/impl/button_base.cpp new file mode 100644 index 00000000..572d3ca9 --- /dev/null +++ b/libs/ui/source/impl/button_base.cpp @@ -0,0 +1,47 @@ +#include +#include + +namespace psemek::ui::impl +{ + + button_base::button_base() + {} + + bool button_base::on_event(mouse_move_event const & event) + { + bool const mouseover = geom::contains(shape(), geom::cast(event.position)); + + if (is_mouseover_ != mouseover) + { + is_mouseover_ = mouseover; + mouseover_.set(is_mouseover_); + } + + return is_mouseover_; + } + + bool button_base::on_event(mouse_button_event const & event) + { + if (is_mouseover_) + { + bool const mousedown = event.button == app::mouse_button::left && event.down; + + if (is_mousedown_ != mousedown) + { + is_mousedown_ = mousedown; + mousedown_.set(is_mouseover_); + } + + return true; + } + + return false; + } + + void button_base::update(button const & value) + { + mouseover_ = value.mouseover; + mousedown_ = value.mousedown; + } + +} diff --git a/libs/ui/source/impl/container.cpp b/libs/ui/source/impl/container.cpp index 4f59955b..5f66c0fc 100644 --- a/libs/ui/source/impl/container.cpp +++ b/libs/ui/source/impl/container.cpp @@ -1,4 +1,5 @@ #include +#include namespace psemek::ui::impl { diff --git a/libs/ui/source/impl/controller.cpp b/libs/ui/source/impl/controller.cpp index 4ee790d3..98674575 100644 --- a/libs/ui/source/impl/controller.cpp +++ b/libs/ui/source/impl/controller.cpp @@ -7,9 +7,69 @@ namespace psemek::ui::impl { component_factory & factory; + geom::vector screen_size = {0, 0}; + + util::signal<>::subscription_token root_token; + util::signal<>::subscription_token root_reshape_token; + std::unique_ptr root; + impl(component_factory & factory) : factory(factory) {} + + void set_ui(react::value ui) + { + root_token = ui.subscribe([this](std::any const & value) + { + root = factory.reconciliate(std::move(root), value); + subscribe_reshape(); + }, true); + subscribe_reshape(); + } + + void subscribe_reshape() + { + root_reshape_token = nullptr; + + if (root) + root_reshape_token = root->size_constraints().subscribe([this](psemek::ui::impl::size_constraints const &) + { + do_reshape(); + }); + } + + void do_reshape() + { + if (root) + root->reshape({{{0.f, screen_size[0]}, {0.f, screen_size[1]}}}); + } + + template + bool on_event(Event const & event) + { + return on_event_impl(event, root.get()); + } + + bool on_event(resize_event const & event) + { + screen_size = event.size; + bool result = on_event_impl(event, root.get()); + do_reshape(); + return result; + } + + template + bool on_event_impl(Event const & event, component * element) + { + if (!element) + return false; + + for (auto const & child : element->children()) + if (on_event_impl(event, child.get())) + return true; + + return element->on_event(event); + } }; controller::controller(component_factory & factory) @@ -20,7 +80,32 @@ namespace psemek::ui::impl void controller::set_ui(react::value ui) { - (void)ui; + impl().set_ui(std::move(ui)); + } + + bool controller::on_event(resize_event const & event) + { + return impl().on_event(event); + } + + bool controller::on_event(mouse_move_event const & event) + { + return impl().on_event(event); + } + + bool controller::on_event(mouse_wheel_event const & event) + { + return impl().on_event(event); + } + + bool controller::on_event(mouse_button_event const & event) + { + return impl().on_event(event); + } + + bool controller::on_event(key_event const & event) + { + return impl().on_event(event); } } diff --git a/libs/ui/source/impl/default_component_factory.cpp b/libs/ui/source/impl/default_component_factory.cpp new file mode 100644 index 00000000..9f883e85 --- /dev/null +++ b/libs/ui/source/impl/default_component_factory.cpp @@ -0,0 +1,28 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace psemek::ui::impl +{ + + default_component_factory::default_component_factory() + { + register_type(); + register_type>(); + register_type>(); + register_type(); + register_type(); + register_type(); + register_type(); + register_type(); + } + +} diff --git a/libs/ui/source/impl/fixed_size_base.cpp b/libs/ui/source/impl/fixed_size_base.cpp new file mode 100644 index 00000000..330c9388 --- /dev/null +++ b/libs/ui/source/impl/fixed_size_base.cpp @@ -0,0 +1,65 @@ +#include +#include +#include +#include + +namespace psemek::ui::impl +{ + + namespace + { + + size_constraints compute_size_constraints(geom::vector, 2> const & size) + { + return { + .box = {{ + size[0] ? geom::interval::singleton(*(size[0])) : geom::interval(0.f, size_constraints::infinity), + size[1] ? geom::interval::singleton(*(size[1])) : geom::interval(0.f, size_constraints::infinity), + }}, + }; + } + + geom::box compute_shape(geom::box const & shape, geom::vector, 2> const & size) + { + return {{ + size[0] ? align(shape[0], *(size[0]), halignment::center) : shape[0], + size[1] ? align(shape[1], *(size[1]), valignment::center) : shape[1], + }}; + } + + } + + fixed_size_base::fixed_size_base() + : size_({0.f, 0.f}) + , size_constraints_(react::map(compute_size_constraints, react::join(size_))) + {} + + void fixed_size_base::reshape(geom::box const & new_shape) + { + single_container::reshape(new_shape); + + if (auto child = this->child()) + child->reshape(compute_shape(new_shape, **size_)); + } + + react::value fixed_size_base::size_constraints() const + { + return size_constraints_; + } + + void fixed_size_base::update(fixed_size const & value) + { + size_.set(react::map([](geom::vector const & size){ return geom::vector, 2>{size[0], size[1]}; }, value.size)); + } + + void fixed_size_base::update(fixed_width const & value) + { + size_.set(react::map([](float width){ return geom::vector, 2>{width, std::nullopt}; }, value.width)); + } + + void fixed_size_base::update(fixed_height const & value) + { + size_.set(react::map([](float height){ return geom::vector, 2>{std::nullopt, height}; }, value.height)); + } + +} diff --git a/libs/ui/source/impl/single_container_base.cpp b/libs/ui/source/impl/single_container_base.cpp index 2ce179f0..12064a6c 100644 --- a/libs/ui/source/impl/single_container_base.cpp +++ b/libs/ui/source/impl/single_container_base.cpp @@ -39,5 +39,4 @@ namespace psemek::ui::impl return child; } - } diff --git a/libs/ui/source/impl/size_constraints.cpp b/libs/ui/source/impl/size_constraints.cpp index 5ac0796f..beb9e9b4 100644 --- a/libs/ui/source/impl/size_constraints.cpp +++ b/libs/ui/source/impl/size_constraints.cpp @@ -1,14 +1,10 @@ #include -#include - namespace psemek::ui::impl { size_constraints size_constraints::max() { - static constexpr float infinity = std::numeric_limits::infinity(); - return {{{ {0.f, infinity}, diff --git a/libs/ui/source/impl/stack_layout_base.cpp b/libs/ui/source/impl/stack_layout_base.cpp index 03c25ab5..802a8b97 100644 --- a/libs/ui/source/impl/stack_layout_base.cpp +++ b/libs/ui/source/impl/stack_layout_base.cpp @@ -26,6 +26,8 @@ namespace psemek::ui::impl void stack_layout_base::reshape(geom::box const & new_shape) { + container::reshape(new_shape); + for (auto const & child : children()) if (child) child->reshape(new_shape);