diff --git a/libs/ui/CMakeLists.txt b/libs/ui/CMakeLists.txt deleted file mode 100644 index fe7055f1..00000000 --- a/libs/ui/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -file(GLOB_RECURSE PSEMEK_UI_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "include/*.hpp") -file(GLOB_RECURSE PSEMEK_UI_SOURCES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "source/*.cpp") - -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-fonts psemek-async 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 deleted file mode 100644 index 01e2a2e5..00000000 --- a/libs/ui/include/psemek/ui/aligned.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#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 deleted file mode 100644 index dbc65898..00000000 --- a/libs/ui/include/psemek/ui/alignment.hpp +++ /dev/null @@ -1,62 +0,0 @@ -#pragma once - -#include -#include - -namespace psemek::ui -{ - - enum class halignment - { - left, - center, - right, - }; - - enum class valignment - { - top, - center, - 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 deleted file mode 100644 index 679d6ebc..00000000 --- a/libs/ui/include/psemek/ui/box_layout.hpp +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include -#include - -#include -#include - -namespace psemek::ui -{ - - namespace box_layout - { - - struct minimized - {}; - - struct weight - { - float value = 1.f; - }; - - using size_policy = std::variant; - - struct element - { - react::value element; - react::value policy = {}; - std::optional key = {}; - }; - - struct horizontal - { - 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 deleted file mode 100644 index f6009e85..00000000 --- a/libs/ui/include/psemek/ui/button.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include -#include - -namespace psemek::ui -{ - - struct button - { - react::source mouseover = {}; - react::source mousedown = {}; - react::source on_mouseover = {}; - react::source on_mousedown = {}; - }; - -} diff --git a/libs/ui/include/psemek/ui/extend.hpp b/libs/ui/include/psemek/ui/extend.hpp deleted file mode 100644 index cb4eb1d2..00000000 --- a/libs/ui/include/psemek/ui/extend.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include - -#include - -namespace psemek::ui -{ - - struct extend - { - react::value child = {}; - react::value left = 0.f; - react::value right = 0.f; - react::value top = 0.f; - react::value bottom = 0.f; - }; - -} diff --git a/libs/ui/include/psemek/ui/fixed_size.hpp b/libs/ui/include/psemek/ui/fixed_size.hpp deleted file mode 100644 index 9c1271c0..00000000 --- a/libs/ui/include/psemek/ui/fixed_size.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#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/floating.hpp b/libs/ui/include/psemek/ui/floating.hpp deleted file mode 100644 index f9099dbd..00000000 --- a/libs/ui/include/psemek/ui/floating.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#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/frame.hpp b/libs/ui/include/psemek/ui/frame.hpp deleted file mode 100644 index 798ce907..00000000 --- a/libs/ui/include/psemek/ui/frame.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include - -#include - -namespace psemek::ui -{ - - struct frame - { - react::value child = {}; - react::value margin = 0.f; - }; - -} diff --git a/libs/ui/include/psemek/ui/impl/aligned_base.hpp b/libs/ui/include/psemek/ui/impl/aligned_base.hpp deleted file mode 100644 index 33efca77..00000000 --- a/libs/ui/include/psemek/ui/impl/aligned_base.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#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 deleted file mode 100644 index 6daac81d..00000000 --- a/libs/ui/include/psemek/ui/impl/box_layout_base.hpp +++ /dev/null @@ -1,57 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -namespace psemek::ui::impl -{ - - namespace detail - { - - template - struct box_layout_type; - - template <> - struct box_layout_type<0> - { - using type = box_layout::horizontal; - }; - - template <> - struct box_layout_type<1> - { - using type = box_layout::vertical; - }; - - } - - // Dimension == 0 is horizontal layout - // Dimension == 1 is vertical layout - template - struct box_layout_base - : container - { - box_layout_base(); - - void reshape(geom::box const & new_shape) override; - react::value size_constraints() const override; - - void set_children(std::vector> children) override; - std::vector> release_children() override; - - void update(typename detail::box_layout_type::type const & box_layout); - - private: - react::source> padding_; - react::source>>> size_policies_; - react::source>> children_size_constraints_; - react::value size_constraints_; - }; - - extern template struct box_layout_base<0>; - extern template struct box_layout_base<1>; - -} diff --git a/libs/ui/include/psemek/ui/impl/button_base.hpp b/libs/ui/include/psemek/ui/impl/button_base.hpp deleted file mode 100644 index 0b8f0413..00000000 --- a/libs/ui/include/psemek/ui/impl/button_base.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#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: - react::source mouseover_; - react::source mousedown_; - react::source on_mouseover_; - react::source on_mousedown_; - - bool is_mouseover_ = false; - bool is_mousedown_ = false; - }; - -} diff --git a/libs/ui/include/psemek/ui/impl/component.hpp b/libs/ui/include/psemek/ui/impl/component.hpp deleted file mode 100644 index 86a24a1f..00000000 --- a/libs/ui/include/psemek/ui/impl/component.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -namespace psemek::ui::impl -{ - - struct component - { - virtual util::span const> children() const; - - virtual geom::box const & shape() const; - virtual void reshape(geom::box const & new_shape); - - 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 void animate(float) {} - - virtual void draw(renderer &) {} - virtual void post_draw(renderer &) {} - - virtual std::optional cursor() const { return std::nullopt; } - - virtual ~component() {} - - private: - geom::box shape_; - }; - -} diff --git a/libs/ui/include/psemek/ui/impl/component_factory.hpp b/libs/ui/include/psemek/ui/impl/component_factory.hpp deleted file mode 100644 index aee2b8dd..00000000 --- a/libs/ui/include/psemek/ui/impl/component_factory.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include -#include -#include - -#include -#include -#include - -namespace psemek::ui::impl -{ - - struct component_factory - { - virtual std::unique_ptr reconciliate(std::unique_ptr root, std::any const & value, - event_state const & state, async::executor & delayed_executor, std::function request_reshape) = 0; - - virtual ~component_factory() {} - }; - -} diff --git a/libs/ui/include/psemek/ui/impl/component_factory_base.hpp b/libs/ui/include/psemek/ui/impl/component_factory_base.hpp deleted file mode 100644 index 33fecc72..00000000 --- a/libs/ui/include/psemek/ui/impl/component_factory_base.hpp +++ /dev/null @@ -1,194 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace psemek::ui::impl -{ - - struct component_not_supported_exception - : util::exception - { - component_not_supported_exception(std::type_index type, boost::stacktrace::stacktrace stacktrace = {}) - : util::exception(util::to_string("UI component ", util::type_name(type), " is not supported"), std::move(stacktrace)) - , type_(type) - {} - - std::type_index type() const - { - return type_; - } - - private: - std::type_index type_; - }; - - struct component_factory_base - : component_factory - { - std::unique_ptr reconciliate(std::unique_ptr root, std::any const & value, event_state const & state, async::executor & delayed_executor, std::function request_reshape) override - { - std::type_index type(value.type()); - if (auto it = type_factories_.find(type); it != type_factories_.end()) - return it->second(std::move(root), value, state, delayed_executor, request_reshape); - throw component_not_supported_exception(type); - } - - template - void register_type(Factory && factory) - { - type_factories_[typeid(Type)] = [this, factory = std::move(factory)](std::unique_ptr root, std::any const & value, - event_state const & state, async::executor & delayed_executor, std::function request_reshape) - { - std::unique_ptr impl; - if (root) - { - if (auto impl_raw = dynamic_cast(root.get())) - { - impl.reset(impl_raw); - root.release(); - } - } - - root.reset(); - - // prevent 'lambda capture is unused' warning - (void)this; - - if (!impl) - { - if constexpr (std::is_invocable_v) - impl = factory(state); - else - impl = factory(); - - impl->size_constraints().subscribe([request_reshape](auto const &){ request_reshape(); }, react::forever); - - request_reshape(); - } - - auto const & typed_value = *std::any_cast(&value); - - impl->update(typed_value); - - if constexpr (std::is_base_of_v) - { - impl->release_child_token(); - if (typed_value.child) - { - impl->set_child_token(typed_value.child.subscribe([this, impl = impl.get(), &state, &delayed_executor, request_reshape, holder = typed_value.child](std::any const & child){ - delayed_executor.post([this, impl, &state, &delayed_executor, request_reshape, child]{ - if (child.has_value()) - impl->set_child(reconciliate(impl->release_child(), child, state, delayed_executor, request_reshape)); - else - impl->release_child(); - request_reshape(); - }); - }, true)); - } - else - { - impl->release_child(); - } - } - else if constexpr (std::is_base_of_v) - { - if (typed_value.children) - { - impl->set_children_token(typed_value.children.subscribe([this, impl = impl.get(), &state, &delayed_executor, request_reshape, holder = typed_value.children](std::vector const & children_values){ - delayed_executor.post([this, impl, &state, &delayed_executor, request_reshape, children_values]{ - impl->release_child_tokens(); - - util::hash_map> child_by_key; - - auto old_children = impl->release_children(); - { - auto keys = impl->release_child_keys(); - - for (std::size_t i = 0; i < old_children.size(); ++i) - if (keys[i]) - child_by_key[std::move(*keys[i])] = std::move(old_children[i]); - } - - std::vector> children(children_values.size()); - std::vector> child_keys(children_values.size()); - - for (std::size_t i = 0; i < children_values.size(); ++i) - { - if (auto const & key = children_values[i].key) - { - if (auto it = child_by_key.find(*key); it != child_by_key.end()) - children[i] = std::move(it->second); - - child_keys[i] = *key; - } - - if (!children[i] && i < old_children.size() && old_children[i] && children_values[i].element) - children[i] = std::move(old_children[i]); - } - - impl->set_children(std::move(children)); - impl->set_child_keys(std::move(child_keys)); - - std::vector::subscription_token> child_tokens(children_values.size()); - - for (std::size_t i = 0; i < children_values.size(); ++i) - { - if (children_values[i].element) - { - child_tokens[i] = children_values[i].element.subscribe([this, impl, &state, &delayed_executor, request_reshape, i, holder = children_values[i].element](std::any const & value){ - delayed_executor.post([this, impl, &state, &delayed_executor, request_reshape, i, value]{ - auto children = impl->release_children(); - if (value.has_value()) - children[i] = reconciliate(std::move(children[i]), value, state, delayed_executor, request_reshape); - else - children[i] = nullptr; - impl->set_children(std::move(children)); - request_reshape(); - }); - }, true); - } - } - - impl->set_child_tokens(std::move(child_tokens)); - request_reshape(); - }); - }, true)); - } - else - { - impl->release_child_tokens(); - impl->release_child_keys(); - impl->release_children(); - } - } - - return impl; - }; - } - - template - void register_type() - { - register_type([](event_state const & state){ - if constexpr (std::is_constructible_v) - return std::make_unique(state); - else - return std::make_unique(); - }); - } - - private: - util::hash_map(std::unique_ptr, std::any const &, event_state const &, async::executor &, std::function)>> type_factories_; - }; - -} diff --git a/libs/ui/include/psemek/ui/impl/container.hpp b/libs/ui/include/psemek/ui/impl/container.hpp deleted file mode 100644 index 9ecff2f2..00000000 --- a/libs/ui/include/psemek/ui/impl/container.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include -#include -#include - -#include -#include -#include - -namespace psemek::ui::impl -{ - - struct container - : component - { - virtual void set_children(std::vector> children); - virtual void set_children_token(util::signal>::subscription_token token); - virtual void set_child_tokens(std::vector::subscription_token> tokens); - virtual void set_child_keys(std::vector> keys); - - virtual std::vector> release_children(); - virtual util::signal<>::subscription_token release_children_token(); - virtual std::vector::subscription_token> release_child_tokens(); - virtual std::vector> release_child_keys(); - - util::span const> children() const override; - - private: - util::signal<>::subscription_token children_token_; - std::vector> children_; - std::vector::subscription_token> child_tokens_; - std::vector> child_keys_; - }; - -} diff --git a/libs/ui/include/psemek/ui/impl/controller.hpp b/libs/ui/include/psemek/ui/impl/controller.hpp deleted file mode 100644 index b0b0e517..00000000 --- a/libs/ui/include/psemek/ui/impl/controller.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -#include - -namespace psemek::ui::impl -{ - - struct controller - { - controller(component_factory & factory); - ~controller(); - - void set_ui(react::value ui); - - component * root(); - - 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); - - event_state const & state(); - - void update(float dt); - void draw(renderer & renderer); - - std::optional cursor(); - - 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 deleted file mode 100644 index 616cf305..00000000 --- a/libs/ui/include/psemek/ui/impl/default_component_factory.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#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/event_state.hpp b/libs/ui/include/psemek/ui/impl/event_state.hpp deleted file mode 100644 index 0d89885a..00000000 --- a/libs/ui/include/psemek/ui/impl/event_state.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include - -namespace psemek::ui::impl -{ - - using event_state = app::event_state; - - using app::apply; - -} diff --git a/libs/ui/include/psemek/ui/impl/events.hpp b/libs/ui/include/psemek/ui/impl/events.hpp deleted file mode 100644 index 6e1bf28b..00000000 --- a/libs/ui/include/psemek/ui/impl/events.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#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/extend_base.hpp b/libs/ui/include/psemek/ui/impl/extend_base.hpp deleted file mode 100644 index 264236de..00000000 --- a/libs/ui/include/psemek/ui/impl/extend_base.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace psemek::ui::impl -{ - - struct extend_base - : single_container - { - extend_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(extend const & value); - - private: - react::source> left_; - react::source> right_; - react::source> top_; - react::source> bottom_; - react::source> child_size_constraints_; - react::value size_constraints_; - }; - -} diff --git a/libs/ui/include/psemek/ui/impl/fixed_size_base.hpp b/libs/ui/include/psemek/ui/impl/fixed_size_base.hpp deleted file mode 100644 index b50d1df9..00000000 --- a/libs/ui/include/psemek/ui/impl/fixed_size_base.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#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/floating_base.hpp b/libs/ui/include/psemek/ui/impl/floating_base.hpp deleted file mode 100644 index 99589fbb..00000000 --- a/libs/ui/include/psemek/ui/impl/floating_base.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#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/frame_base.hpp b/libs/ui/include/psemek/ui/impl/frame_base.hpp deleted file mode 100644 index 9047c590..00000000 --- a/libs/ui/include/psemek/ui/impl/frame_base.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace psemek::ui::impl -{ - - struct frame_base - : single_container - { - frame_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(frame const & value); - - private: - react::source> margin_; - react::source> child_size_constraints_; - react::value size_constraints_; - }; - -} diff --git a/libs/ui/include/psemek/ui/impl/label_base.hpp b/libs/ui/include/psemek/ui/impl/label_base.hpp deleted file mode 100644 index 24ee89f5..00000000 --- a/libs/ui/include/psemek/ui/impl/label_base.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace psemek::ui::impl -{ - - struct label_base - : component - { - label_base(); - - react::value size_constraints() const override; - - void draw(renderer & renderer) override; - - void update(label const & value); - - private: - react::source> font_; - react::source>> glyphs_; - react::value color_ = gfx::color_rgba{0, 0, 0, 255}; - react::value halign_ = halignment::center; - react::value valign_ = valignment::center; - react::value> size_; - react::value size_constraints_; - }; - -} diff --git a/libs/ui/include/psemek/ui/impl/move_base.hpp b/libs/ui/include/psemek/ui/impl/move_base.hpp deleted file mode 100644 index f151f50c..00000000 --- a/libs/ui/include/psemek/ui/impl/move_base.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace psemek::ui::impl -{ - - struct move_base - : single_container - { - move_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 animate(float dt) override; - void update(move const & value); - - private: - react::value> offset_; - react::value animation_speed_; - react::source> child_size_constraints_; - react::value size_constraints_; - - geom::vector current_offset_; - }; - -} diff --git a/libs/ui/include/psemek/ui/impl/renderer.hpp b/libs/ui/include/psemek/ui/impl/renderer.hpp deleted file mode 100644 index 115f0f8a..00000000 --- a/libs/ui/include/psemek/ui/impl/renderer.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace psemek::ui::impl -{ - - struct renderer - { - virtual void draw_glyph(fonts::texture_type const & texture, geom::box const & position, geom::box const & texcoord, gfx::color_rgba const & color) = 0; - - virtual ~renderer() {} - }; - -} diff --git a/libs/ui/include/psemek/ui/impl/shape_reader_base.hpp b/libs/ui/include/psemek/ui/impl/shape_reader_base.hpp deleted file mode 100644 index 1d65b895..00000000 --- a/libs/ui/include/psemek/ui/impl/shape_reader_base.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#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/single_container.hpp b/libs/ui/include/psemek/ui/impl/single_container.hpp deleted file mode 100644 index b049391a..00000000 --- a/libs/ui/include/psemek/ui/impl/single_container.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace psemek::ui::impl -{ - - struct single_container - : component - { - util::span const> children() const override; - - virtual void set_child(std::unique_ptr child); - virtual void set_child_token(util::signal<>::subscription_token token); - virtual component * child() const; - virtual std::unique_ptr release_child(); - virtual util::signal<>::subscription_token release_child_token(); - - private: - util::signal<>::subscription_token child_token_; - std::unique_ptr child_; - }; - -} diff --git a/libs/ui/include/psemek/ui/impl/single_container_base.hpp b/libs/ui/include/psemek/ui/impl/single_container_base.hpp deleted file mode 100644 index 20b397eb..00000000 --- a/libs/ui/include/psemek/ui/impl/single_container_base.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace psemek::ui::impl -{ - - struct single_container_base - : single_container - { - single_container_base(react::value> margin); - - 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; - - private: - react::value> margin_; - 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 deleted file mode 100644 index 0b8cf5e4..00000000 --- a/libs/ui/include/psemek/ui/impl/size_constraints.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include - -#include - -namespace psemek::ui::impl -{ - - struct size_constraints - { - geom::box box; - - static constexpr float infinity = std::numeric_limits::infinity(); - - static size_constraints max(); - }; - - size_constraints shift(size_constraints const & constraints, geom::vector const & delta); - size_constraints scale(size_constraints const & constraints, float factor, int dimension); - - float min(size_constraints const & constraints, int dimension); - - size_constraints intersect(size_constraints const & constraints1, size_constraints const & constraints2); - - geom::interval range(size_constraints const & constraints, int dimension); - - size_constraints cut(size_constraints const & constraints, int dimension, geom::interval const & range); - - size_constraints sum_along(size_constraints const & constraints1, size_constraints const & constraints2, int dimension); - -} diff --git a/libs/ui/include/psemek/ui/impl/stack_layout_base.hpp b/libs/ui/include/psemek/ui/impl/stack_layout_base.hpp deleted file mode 100644 index fc994816..00000000 --- a/libs/ui/include/psemek/ui/impl/stack_layout_base.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -namespace psemek::ui::impl -{ - - struct stack_layout_base - : container - { - stack_layout_base(); - - void reshape(geom::box const & new_shape) override; - react::value size_constraints() const override; - - void set_children(std::vector> children) override; - std::vector> release_children() override; - - void update(stack_layout const &) - {} - - private: - react::source>> children_size_constraints_; - react::value size_constraints_; - }; - -} diff --git a/libs/ui/include/psemek/ui/impl/storage_base.hpp b/libs/ui/include/psemek/ui/impl/storage_base.hpp deleted file mode 100644 index d34498b4..00000000 --- a/libs/ui/include/psemek/ui/impl/storage_base.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#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/key.hpp b/libs/ui/include/psemek/ui/key.hpp deleted file mode 100644 index 889ee31d..00000000 --- a/libs/ui/include/psemek/ui/key.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include - -namespace psemek::ui -{ - - using key = std::string; - -} diff --git a/libs/ui/include/psemek/ui/label.hpp b/libs/ui/include/psemek/ui/label.hpp deleted file mode 100644 index 120c169c..00000000 --- a/libs/ui/include/psemek/ui/label.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#include - -namespace psemek::ui -{ - - struct label - { - react::value text = {}; - react::value font = {}; - react::value color = gfx::color_rgba{0, 0, 0, 255}; - react::value halign = halignment::center; - react::value valign = valignment::center; - }; - -} diff --git a/libs/ui/include/psemek/ui/move.hpp b/libs/ui/include/psemek/ui/move.hpp deleted file mode 100644 index 5e4d99ac..00000000 --- a/libs/ui/include/psemek/ui/move.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include -#include - -#include - -namespace psemek::ui -{ - - struct move - { - react::value child = {}; - react::value> offset = geom::vector{0.f, 0.f}; - react::value animation_speed = 0.f; - }; - -} diff --git a/libs/ui/include/psemek/ui/rectangle.hpp b/libs/ui/include/psemek/ui/rectangle.hpp deleted file mode 100644 index 2f6de278..00000000 --- a/libs/ui/include/psemek/ui/rectangle.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include -#include - -namespace psemek::ui -{ - - struct rectangle - { - react::value color = {}; - }; - -} diff --git a/libs/ui/include/psemek/ui/shape_reader.hpp b/libs/ui/include/psemek/ui/shape_reader.hpp deleted file mode 100644 index 96b14717..00000000 --- a/libs/ui/include/psemek/ui/shape_reader.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#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/slider.hpp b/libs/ui/include/psemek/ui/slider.hpp deleted file mode 100644 index fc3b36c7..00000000 --- a/libs/ui/include/psemek/ui/slider.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace psemek::ui -{ - - struct slider - { - react::value> range = {}; - react::source value = {}; - }; - -} diff --git a/libs/ui/include/psemek/ui/stack_layout.hpp b/libs/ui/include/psemek/ui/stack_layout.hpp deleted file mode 100644 index 2f9fb109..00000000 --- a/libs/ui/include/psemek/ui/stack_layout.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include -#include - -#include - -namespace psemek::ui -{ - - struct stack_layout - { - struct element - { - react::value element; - std::optional key = {}; - }; - - react::value> children = {}; - }; - -} diff --git a/libs/ui/include/psemek/ui/storage.hpp b/libs/ui/include/psemek/ui/storage.hpp deleted file mode 100644 index 261ddf59..00000000 --- a/libs/ui/include/psemek/ui/storage.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#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/aligned_base.cpp b/libs/ui/source/impl/aligned_base.cpp deleted file mode 100644 index 5fc6f7ff..00000000 --- a/libs/ui/source/impl/aligned_base.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#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 deleted file mode 100644 index 114d88aa..00000000 --- a/libs/ui/source/impl/box_layout_base.cpp +++ /dev/null @@ -1,188 +0,0 @@ -#include -#include -#include - -namespace psemek::ui::impl -{ - - namespace - { - - static constexpr box_layout::size_policy default_policy = box_layout::minimized{}; - - template - size_constraints compute_size_constraints(std::vector const & size_policies, - std::vector const & children_size_constraints, float padding) - { - size_constraints minimized = size_constraints::max(); - size_constraints weight_unit = minimized; - float weight_sum = 0.f; - - for (std::size_t i = 0; i < std::min(size_policies.size(), children_size_constraints.size()); ++i) - { - if (std::get_if(&size_policies[i])) - { - minimized = sum_along(minimized, children_size_constraints[i], Dimension); - } - else if (auto weight = std::get_if(&size_policies[i])) - { - weight_unit = intersect(weight_unit, scale(children_size_constraints[i], 1.f / weight->value, Dimension)); - weight_sum += weight->value; - } - } - - auto result = std::move(minimized); - - if (weight_sum > 0.f) - result = sum_along(result, scale(weight_unit, weight_sum, Dimension), Dimension); - - if (size_policies.size() > 0) - { - geom::vector shift_delta{0.f, 0.f}; - shift_delta[Dimension] = padding * (size_policies.size() - 1); - result = shift(std::move(result), shift_delta); - } - - return result; - } - - template - std::vector allocate(float total_size, std::vector> const & size_policies, - util::span const> children, float padding) - { - std::vector result(std::min(size_policies.size(), children.size()), 0.f); - - if (!size_policies.empty()) - total_size -= padding * (result.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 < result.size(); ++i) - { - if (!children[i]) - continue; - - auto const policy = size_policies[i] ? *size_policies[i] : default_policy; - - if (std::get_if(&policy)) - { - result[i] = min(*children[i]->size_constraints(), Dimension); - total_size -= result[i]; - } - else if (auto weight = std::get_if(&policy)) - { - total_weight += weight->value; - } - } - - // Next, allocate weighted elements - for (std::size_t i = 0; i < result.size(); ++i) - { - auto const policy = size_policies[i] ? *size_policies[i] : default_policy; - - if (auto weight = std::get_if(&policy)) - { - result[i] = total_size * weight->value / total_weight; - } - } - - return result; - } - - } - - template - box_layout_base::box_layout_base() - : padding_(0.f) - , size_policies_(std::vector>{}) - , children_size_constraints_() - , size_constraints_( - react::map( - [](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), react::join(size_policies_))), - react::join(react::map(react::unpack, children_size_constraints_)), - react::join(padding_) - ) - ) - {} - - template - void box_layout_base::reshape(geom::box const & new_shape) - { - container::reshape(new_shape); - - if (children().empty()) - return; - - auto padding = **padding_; - - 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) - { - if (children()[i]) - { - geom::box child_shape; - child_shape[Dimension] = {pen, pen + sizes[i]}; - child_shape[Dimension ^ 1] = new_shape[Dimension ^ 1]; - children()[i]->reshape(child_shape); - } - - pen += sizes[i]; - pen += padding; - } - } - - template - react::value box_layout_base::size_constraints() const - { - return size_constraints_; - } - - template - void box_layout_base::set_children(std::vector> children) - { - container::set_children(std::move(children)); - - std::vector> children_size_constraints; - for (auto const & child : this->children()) - { - if (child) - children_size_constraints.push_back(child->size_constraints()); - else - children_size_constraints.push_back(size_constraints::max()); - } - children_size_constraints_.set(std::move(children_size_constraints)); - } - - template - std::vector> box_layout_base::release_children() - { - auto result = container::release_children(); - children_size_constraints_.set({}); - return result; - } - - template - void box_layout_base::update(typename detail::box_layout_type::type const & box_layout) - { - size_policies_.set(react::map([](auto const & children){ - std::vector> size_policies; - size_policies.reserve(children.size()); - for (auto const & child : children) - size_policies.push_back(child.policy); - return size_policies; - }, box_layout.children)); - - padding_.set(box_layout.padding); - } - - template struct box_layout_base<0>; - template struct box_layout_base<1>; - -} diff --git a/libs/ui/source/impl/button_base.cpp b/libs/ui/source/impl/button_base.cpp deleted file mode 100644 index f15a3115..00000000 --- a/libs/ui/source/impl/button_base.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#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_); - on_mouseover_.set(is_mouseover_); - } - - return false; - } - - bool button_base::on_event(mouse_button_event const & event) - { - bool const mousedown = event.button == app::mouse_button::left && event.down; - - if (is_mouseover_ || !mousedown) - { - if (is_mousedown_ != mousedown) - { - is_mousedown_ = mousedown; - mousedown_.set(is_mousedown_); - on_mousedown_.set(is_mousedown_); - } - - return is_mouseover_ && is_mousedown_; - } - - return false; - } - - void button_base::update(button const & value) - { - mouseover_ = value.mouseover; - mousedown_ = value.mousedown; - - on_mouseover_ = value.on_mouseover; - on_mousedown_ = value.on_mousedown; - - mouseover_.set(is_mouseover_); - mousedown_.set(is_mousedown_); - } - -} diff --git a/libs/ui/source/impl/component.cpp b/libs/ui/source/impl/component.cpp deleted file mode 100644 index 4b468176..00000000 --- a/libs/ui/source/impl/component.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include - -namespace psemek::ui::impl -{ - - util::span const> component::children() const - { - return {}; - } - - geom::box const & component::shape() const - { - return shape_; - } - - void component::reshape(geom::box const & new_shape) - { - shape_ = new_shape; - } - - react::value component::size_constraints() const - { - static react::value const result{size_constraints::max()}; - return result; - } - -} diff --git a/libs/ui/source/impl/container.cpp b/libs/ui/source/impl/container.cpp deleted file mode 100644 index 5f66c0fc..00000000 --- a/libs/ui/source/impl/container.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include - -namespace psemek::ui::impl -{ - - void container::set_children(std::vector> children) - { - children_ = std::move(children); - } - - void container::set_children_token(util::signal>::subscription_token token) - { - children_token_ = std::move(token); - } - - void container::set_child_tokens(std::vector::subscription_token> tokens) - { - child_tokens_ = std::move(tokens); - } - - void container::set_child_keys(std::vector> keys) - { - child_keys_ = std::move(keys); - } - - std::vector> container::release_children() - { - return std::move(children_); - } - - util::signal<>::subscription_token container::release_children_token() - { - return std::move(children_token_); - } - - std::vector::subscription_token> container::release_child_tokens() - { - return std::move(child_tokens_); - } - - std::vector> container::release_child_keys() - { - return std::move(child_keys_); - } - - util::span const> container::children() const - { - return children_; - } - -} diff --git a/libs/ui/source/impl/controller.cpp b/libs/ui/source/impl/controller.cpp deleted file mode 100644 index e4aa0df3..00000000 --- a/libs/ui/source/impl/controller.cpp +++ /dev/null @@ -1,180 +0,0 @@ -#include -#include -#include -#include - -namespace psemek::ui::impl -{ - - struct controller::impl - { - component_factory & factory; - event_state state; - - util::signal<>::subscription_token root_token; - std::unique_ptr root; - - async::event_loop delayed_queue; - - 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, state, delayed_queue, [this]{ delayed_queue.post([this]{ reshape(); }); }); - }, true); - } - - void reshape() - { - if (!root) - return; - - root->reshape({{{0.f, state.size[0]}, {0.f, state.size[1]}}}); - on_event_impl(mouse_move_event{state.mouse, {0, 0}}, root.get()); - } - - template - bool on_event(Event const & event) - { - apply(state, event); - return on_event_impl(event, root.get()); - } - - bool on_event(resize_event const & event) - { - apply(state, event); - delayed_queue.post([this]{ reshape(); }); - return on_event_impl(event, root.get()); - } - - template - bool on_event_impl(Event const & event, component * element) - { - if (!element) - return false; - - for (auto const & child : util::reversed(element->children())) - if (on_event_impl(event, child.get())) - return true; - - return element->on_event(event); - } - - void update(float dt) - { - delayed_queue.pump(); - animate_impl(dt, root.get()); - } - - void animate_impl(float dt, component * element) - { - if (!element) - return; - - element->animate(dt); - for (auto const & child : element->children()) - animate_impl(dt, child.get()); - } - - void draw(renderer & renderer) - { - draw_impl(renderer, root.get()); - } - - void draw_impl(renderer & renderer, component * element) - { - if (!element) - return; - - element->draw(renderer); - - for (auto const & child : element->children()) - draw_impl(renderer, child.get()); - - element->post_draw(renderer); - } - - std::optional cursor() - { - return cursor_impl(root.get()); - } - - std::optional cursor_impl(component * element) - { - if (!element) - return std::nullopt; - - for (auto const & child : util::reversed(element->children())) - if (auto cursor = cursor_impl(child.get())) - return cursor; - - return element->cursor(); - } - }; - - controller::controller(component_factory & factory) - : pimpl_(make_impl(factory)) - {} - - controller::~controller() = default; - - void controller::set_ui(react::value ui) - { - impl().set_ui(std::move(ui)); - } - - component * controller::root() - { - return impl().root.get(); - } - - 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); - } - - event_state const & controller::state() - { - return impl().state; - } - - void controller::update(float dt) - { - impl().update(dt); - } - - void controller::draw(renderer & renderer) - { - impl().draw(renderer); - } - - std::optional controller::cursor() - { - return impl().cursor(); - } - -} diff --git a/libs/ui/source/impl/default_component_factory.cpp b/libs/ui/source/impl/default_component_factory.cpp deleted file mode 100644 index 0be79d31..00000000 --- a/libs/ui/source/impl/default_component_factory.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#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(); - register_type(); - register_type(); - register_type(); - register_type(); - register_type(); - register_type(); - } - -} diff --git a/libs/ui/source/impl/extend_base.cpp b/libs/ui/source/impl/extend_base.cpp deleted file mode 100644 index 4b761397..00000000 --- a/libs/ui/source/impl/extend_base.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include -#include -#include - -namespace psemek::ui::impl -{ - - namespace - { - - geom::box compute_child_shape(geom::box shape, float left, float right, float top, float bottom) - { - shape[0].min -= left; - shape[0].max += right; - shape[1].min -= top; - shape[1].max += bottom; - return shape; - } - - } - - extend_base::extend_base() - : left_(0.f) - , right_(0.f) - , top_(0.f) - , bottom_(0.f) - , child_size_constraints_(size_constraints::max()) - , size_constraints_(react::join(child_size_constraints_)) - {} - - void extend_base::reshape(geom::box const & new_shape) - { - single_container::reshape(new_shape); - - if (auto child = this->child()) - child->reshape(compute_child_shape(new_shape, **left_, **right_, **top_, **bottom_)); - } - - react::value extend_base::size_constraints() const - { - return size_constraints_; - } - - void extend_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 extend_base::release_child() - { - child_size_constraints_.set(size_constraints::max()); - return single_container::release_child(); - } - - void extend_base::update(extend const & value) - { - left_.set(value.left); - right_.set(value.right); - top_.set(value.top); - bottom_.set(value.bottom); - } - -} diff --git a/libs/ui/source/impl/fixed_size_base.cpp b/libs/ui/source/impl/fixed_size_base.cpp deleted file mode 100644 index 330c9388..00000000 --- a/libs/ui/source/impl/fixed_size_base.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#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/floating_base.cpp b/libs/ui/source/impl/floating_base.cpp deleted file mode 100644 index eba71e26..00000000 --- a/libs/ui/source/impl/floating_base.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#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/frame_base.cpp b/libs/ui/source/impl/frame_base.cpp deleted file mode 100644 index 69afa241..00000000 --- a/libs/ui/source/impl/frame_base.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include -#include -#include - -namespace psemek::ui::impl -{ - - namespace - { - - size_constraints compute_size_constraints(size_constraints const & child_size_constraints, float margin) - { - return { child_size_constraints.box + geom::vector{2.f * margin, 2.f * margin} }; - } - - geom::box compute_child_shape(geom::box const & shape, float margin) - { - return geom::expand(shape, -margin); - } - - } - - frame_base::frame_base() - : margin_(0.f) - , child_size_constraints_(size_constraints::max()) - , size_constraints_(react::map(compute_size_constraints, react::join(child_size_constraints_), react::join(margin_))) - {} - - void frame_base::reshape(geom::box const & new_shape) - { - single_container::reshape(new_shape); - - if (auto child = this->child()) - child->reshape(compute_child_shape(new_shape, **margin_)); - } - - react::value frame_base::size_constraints() const - { - return size_constraints_; - } - - void frame_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 frame_base::release_child() - { - child_size_constraints_.set(size_constraints::max()); - return single_container::release_child(); - } - - void frame_base::update(frame const & value) - { - margin_.set(value.margin); - } - -} diff --git a/libs/ui/source/impl/label_base.cpp b/libs/ui/source/impl/label_base.cpp deleted file mode 100644 index 1e430e73..00000000 --- a/libs/ui/source/impl/label_base.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include -#include - -namespace psemek::ui::impl -{ - - label_base::label_base() - : font_(react::value(nullptr)) - , glyphs_(react::value>(std::vector{})) - , size_(react::map([](std::vector const & glyphs, fonts::font * font){ - if (!font) - return geom::vector{0.f, 0.f}; - geom::box bbox; - for (auto const & glyph : glyphs) - bbox |= glyph.position; - return geom::vector{bbox[0].length(), font->size()[1]}; - }, react::join(glyphs_), react::join(font_))) - , size_constraints_(react::map([](geom::vector const & size){ - geom::box result; - result[0].min = size[0]; - result[0].max = size_constraints::infinity; - result[1].min = size[1]; - result[1].max = size_constraints::infinity; - return impl::size_constraints{result}; - }, size_)) - {} - - react::value label_base::size_constraints() const - { - return size_constraints_; - } - - void label_base::draw(renderer & renderer) - { - if (!glyphs_ || !*glyphs_) - return; - - auto const size = *size_; - auto const shape = this->shape(); - - geom::vector origin; - origin[0] = std::round(geom::lerp(shape[0].min, shape[0].max - size[0], lerp_factor(*halign_))); - origin[1] = std::round(geom::lerp(shape[1].min, shape[1].max - size[1], lerp_factor(*valign_))); - origin[1] += std::round((size[1] + (**font_)->xheight()) / 2.f); - - for (auto const & glyph : **glyphs_) - renderer.draw_glyph(*glyph.texture, glyph.position + origin, glyph.texcoords, *color_); - } - - void label_base::update(label const & value) - { - font_.set(value.font); - glyphs_.set(react::map([](std::string const & str, fonts::font * font) -> std::vector { - if (!font) - return {}; - return font->shape(str, {}); - }, value.text, value.font)); - color_ = value.color; - halign_ = value.halign; - valign_ = value.valign; - } - -} diff --git a/libs/ui/source/impl/move_base.cpp b/libs/ui/source/impl/move_base.cpp deleted file mode 100644 index a2053d2c..00000000 --- a/libs/ui/source/impl/move_base.cpp +++ /dev/null @@ -1,85 +0,0 @@ -#include -#include -#include - -namespace psemek::ui::impl -{ - - namespace - { - - geom::box compute_child_shape(geom::box const & shape, geom::vector const & offset) - { - return shape + offset; - } - - } - - move_base::move_base() - : offset_({0.f, 0.f}) - , animation_speed_(0.f) - , child_size_constraints_(size_constraints::max()) - , size_constraints_(react::join(child_size_constraints_)) - , current_offset_{0.f, 0.f} - {} - - void move_base::reshape(geom::box const & new_shape) - { - single_container::reshape(new_shape); - - if (auto child = this->child()) - child->reshape(compute_child_shape(new_shape, current_offset_)); - } - - react::value move_base::size_constraints() const - { - return size_constraints_; - } - - void move_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 move_base::release_child() - { - child_size_constraints_.set(size_constraints::max()); - return single_container::release_child(); - } - - void move_base::animate(float dt) - { - if (*animation_speed_ == 0.f) - { - if (current_offset_ != *offset_) - { - current_offset_ = *offset_; - reshape(shape()); - } - } - else - { - auto factor = - std::expm1(- dt * (*animation_speed_)); - auto new_offset = geom::lerp(current_offset_, *offset_, factor); - if (geom::length(current_offset_ - new_offset) < 1.f / 16.f) - new_offset = *offset_; - - if (current_offset_ != *offset_) - { - current_offset_ = new_offset; - reshape(shape()); - } - } - } - - void move_base::update(move const & value) - { - offset_ = value.offset; - animation_speed_ = value.animation_speed; - } - -} diff --git a/libs/ui/source/impl/shape_reader_base.cpp b/libs/ui/source/impl/shape_reader_base.cpp deleted file mode 100644 index 406b6d62..00000000 --- a/libs/ui/source/impl/shape_reader_base.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#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/single_container.cpp b/libs/ui/source/impl/single_container.cpp deleted file mode 100644 index 318c4e48..00000000 --- a/libs/ui/source/impl/single_container.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include - -namespace psemek::ui::impl -{ - - util::span const> single_container::children() const - { - return {&child_, 1}; - } - - void single_container::set_child(std::unique_ptr child) - { - child_ = std::move(child); - } - - void single_container::set_child_token(util::signal<>::subscription_token token) - { - child_token_ = std::move(token); - } - - component * single_container::child() const - { - return child_.get(); - } - - std::unique_ptr single_container::release_child() - { - return std::move(child_); - } - - util::signal<>::subscription_token single_container::release_child_token() - { - return std::move(child_token_); - } - -} diff --git a/libs/ui/source/impl/single_container_base.cpp b/libs/ui/source/impl/single_container_base.cpp deleted file mode 100644 index 12064a6c..00000000 --- a/libs/ui/source/impl/single_container_base.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include -#include -#include - -namespace psemek::ui::impl -{ - - single_container_base::single_container_base(react::value> margin) - : margin_(margin) - , child_size_constraints_(size_constraints::max()) - , size_constraints_(react::map([](struct size_constraints const & child_constraints, geom::vector const & margin){ - return shift(child_constraints, margin); - }, react::join(child_size_constraints_), margin)) - {} - - void single_container_base::reshape(geom::box const & new_shape) - { - single_container::reshape(new_shape); - - if (child()) - child()->reshape(geom::shrink(new_shape, *margin_)); - } - - react::value single_container_base::size_constraints() const - { - return size_constraints_; - } - - void single_container_base::set_child(std::unique_ptr child) - { - single_container::set_child(std::move(child)); - child_size_constraints_.set(this->child() ? this->child()->size_constraints() : size_constraints::max()); - } - - std::unique_ptr single_container_base::release_child() - { - auto child = single_container::release_child(); - child_size_constraints_.set(size_constraints::max()); - return child; - } - -} diff --git a/libs/ui/source/impl/size_constraints.cpp b/libs/ui/source/impl/size_constraints.cpp deleted file mode 100644 index beb9e9b4..00000000 --- a/libs/ui/source/impl/size_constraints.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include - -namespace psemek::ui::impl -{ - - size_constraints size_constraints::max() - { - return - {{{ - {0.f, infinity}, - {0.f, infinity}, - }}}; - } - - size_constraints shift(size_constraints const & constraints, geom::vector const & delta) - { - return {constraints.box + delta}; - } - - size_constraints scale(size_constraints const & constraints, float factor, int dimension) - { - auto result = constraints; - result.box[dimension].min *= factor; - result.box[dimension].max *= factor; - return result; - } - - float min(size_constraints const & constraints, int dimension) - { - return constraints.box[dimension].min; - } - - size_constraints intersect(size_constraints const & constraints1, size_constraints const & constraints2) - { - return {constraints1.box & constraints2.box}; - } - - geom::interval range(size_constraints const & constraints, int dimension) - { - return constraints.box[dimension]; - } - - size_constraints cut(size_constraints const & constraints, int dimension, geom::interval const & range) - { - size_constraints result = constraints; - result.box[dimension] &= range; - return result; - } - - size_constraints sum_along(size_constraints const & constraints1, size_constraints const & constraints2, int dimension) - { - size_constraints result; - result.box[dimension].min = constraints1.box[dimension].min + constraints2.box[dimension].min; - result.box[dimension].max = constraints1.box[dimension].max + constraints2.box[dimension].max; - result.box[dimension ^ 1] = constraints1.box[dimension ^ 1] & constraints2.box[dimension ^ 1]; - return result; - } - -} diff --git a/libs/ui/source/impl/stack_layout_base.cpp b/libs/ui/source/impl/stack_layout_base.cpp deleted file mode 100644 index 802a8b97..00000000 --- a/libs/ui/source/impl/stack_layout_base.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include -#include -#include - -namespace psemek::ui::impl -{ - - namespace - { - - size_constraints compute_size_constraints(std::vector const & children_size_constraints) - { - size_constraints result = size_constraints::max(); - for (auto const & constraints : children_size_constraints) - result = intersect(result, constraints); - return result; - } - - } - - stack_layout_base::stack_layout_base() - : size_constraints_(react::map([](auto const & children_size_constraints){ - return compute_size_constraints(children_size_constraints); - }, react::join(react::map(react::unpack, children_size_constraints_)))) - {} - - 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); - } - - react::value stack_layout_base::size_constraints() const - { - return size_constraints_; - } - - void stack_layout_base::set_children(std::vector> children) - { - container::set_children(std::move(children)); - std::vector> children_size_constraints; - for (auto const & child : this->children()) - { - if (child) - children_size_constraints.push_back(child->size_constraints()); - else - children_size_constraints.push_back(size_constraints::max()); - } - children_size_constraints_.set(std::move(children_size_constraints)); - } - - std::vector> stack_layout_base::release_children() - { - auto result = container::release_children(); - children_size_constraints_.set({}); - return result; - } - - -} diff --git a/libs/ui/source/impl/storage_base.cpp b/libs/ui/source/impl/storage_base.cpp deleted file mode 100644 index 50fa51c0..00000000 --- a/libs/ui/source/impl/storage_base.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#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); - } - -} diff --git a/libs/ui/tests/layout.cpp b/libs/ui/tests/layout.cpp deleted file mode 100644 index 5d898e41..00000000 --- a/libs/ui/tests/layout.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include - -#include -#include -#include -#include -#include - -#include - -using namespace psemek; -using namespace psemek::ui; - -namespace -{ - - constexpr float layout_margin = 5.f; - - struct rectangle_impl - : impl::component - { - void update(rectangle const &) - {} - }; - - struct test_component_factory - : impl::component_factory_base - { - test_component_factory() - { - register_type(); - register_type(); - register_type>([]{ return std::make_unique>(layout_margin); }); - register_type>([]{ return std::make_unique>(layout_margin); }); - } - }; - -} diff --git a/libs/ui/tests/reconciliation.cpp b/libs/ui/tests/reconciliation.cpp deleted file mode 100644 index c93612b9..00000000 --- a/libs/ui/tests/reconciliation.cpp +++ /dev/null @@ -1,364 +0,0 @@ -#include - -#include -#include -#include -#include -#include - -#include - -using namespace psemek; -using namespace psemek::ui; - -namespace -{ - - struct rectangle_impl - : impl::component - { - void update(rectangle const &) - {} - }; - - struct label_impl - : impl::component - { - void update(label const &) - {} - }; - - struct button_impl - : impl::single_container - { - void update(button const &) - {} - }; - - struct stack_layout_impl - : impl::container - { - void update(stack_layout const &) - {} - }; - - struct test_component_factory - : impl::component_factory_base - { - int rectangle_count = 0; - int label_count = 0; - int button_count = 0; - int stack_layout_count = 0; - - test_component_factory() - { - register_type([this]{ ++rectangle_count; return std::make_unique(); }); - register_type([this]{ ++label_count; return std::make_unique(); }); - register_type([this]{ ++button_count; return std::make_unique(); }); - register_type([this]{ ++stack_layout_count; return std::make_unique(); }); - } - }; - - struct check_children_helper - { - impl::component & component; - std::size_t i = 0; - - template - void check() - { - if constexpr (std::is_same_v) - { - expect_null(component.children()[i]); - } - else - { - expect_non_null(component.children()[i]); - expect_dynamic_type(*component.children()[i], Type); - } - ++i; - } - }; - - template - void check_children(impl::component & component) - { - expect_equal(component.children().size(), sizeof...(Types)); - - check_children_helper helper{component}; - - (void)helper; - (helper.check(), ...); - } - -} - -test_case(ui_impl_factory_element) -{ - test_component_factory factory; - - auto test_ui = label{}; - auto ui_root = factory.reconciliate(nullptr, test_ui); - - expect_non_null(ui_root); - expect_dynamic_type(*ui_root, label_impl); - - expect_equal(factory.label_count, 1); -} - -test_case(ui_impl_factory_single__container) -{ - test_component_factory factory; - - auto test_ui = button{ - .child = label{} - }; - auto ui_root = factory.reconciliate(nullptr, test_ui); - - expect_non_null(ui_root); - expect_dynamic_type(*ui_root, button_impl); - check_children(*ui_root); - - expect_equal(factory.label_count, 1); - expect_equal(factory.button_count, 1); -} - -test_case(ui_impl_factory_single__container__null) -{ - test_component_factory factory; - - auto test_ui = button{}; - auto ui_root = factory.reconciliate(nullptr, test_ui); - - expect_non_null(ui_root); - expect_dynamic_type(*ui_root, button_impl); - check_children(*ui_root); - - expect_equal(factory.button_count, 1); -} - -test_case(ui_impl_factory_container) -{ - test_component_factory factory; - - auto test_ui = stack_layout{{ - {label{}}, - {button{.child = label{}}}, - {label{}}, - }}; - auto ui_root = factory.reconciliate(nullptr, test_ui); - - expect_non_null(ui_root); - expect_dynamic_type(*ui_root, stack_layout_impl); - check_children(*ui_root); - check_children(*ui_root->children()[1]); - - expect_equal(factory.label_count, 3); - expect_equal(factory.button_count, 1); - expect_equal(factory.stack_layout_count, 1); -} - -test_case(ui_impl_factory_container__null) -{ - test_component_factory factory; - - auto test_ui = stack_layout{}; - auto ui_root = factory.reconciliate(nullptr, test_ui); - - expect_non_null(ui_root); - expect_dynamic_type(*ui_root, stack_layout_impl); - check_children<>(*ui_root); - - expect_equal(factory.stack_layout_count, 1); -} - -test_case(ui_impl_factory_container__null__child) -{ - test_component_factory factory; - - auto test_ui = stack_layout{{ - {}, - {}, - }}; - auto ui_root = factory.reconciliate(nullptr, test_ui); - - expect_non_null(ui_root); - expect_dynamic_type(*ui_root, stack_layout_impl); - check_children(*ui_root); - - expect_equal(factory.stack_layout_count, 1); -} - -test_case(ui_impl_reconciliate_single__container) -{ - test_component_factory factory; - - auto child = react::source(label{}); - - expect_equal((*child).type(), typeid(label{})); - - auto test_ui = button{ - .child = child - }; - - expect_equal((*test_ui.child).type(), typeid(label{})); - - auto ui_root = factory.reconciliate(nullptr, test_ui); - - expect_non_null(ui_root); - expect_dynamic_type(*ui_root, button_impl); - check_children(*ui_root); - - expect_equal(factory.rectangle_count, 0); - expect_equal(factory.label_count, 1); - expect_equal(factory.button_count, 1); - - child.set(label{}); - - check_children(*ui_root); - - expect_equal(factory.rectangle_count, 0); - expect_equal(factory.label_count, 1); - expect_equal(factory.button_count, 1); - - child.set(rectangle{}); - - check_children(*ui_root); - - expect_equal(factory.rectangle_count, 1); - expect_equal(factory.label_count, 1); - expect_equal(factory.button_count, 1); - - child.set(label{}); - - check_children(*ui_root); - - expect_equal(factory.rectangle_count, 1); - expect_equal(factory.label_count, 2); - expect_equal(factory.button_count, 1); -} - -test_case(ui_impl_reconciliate_container__no__keys) -{ - test_component_factory factory; - - react::source> children; - - auto test_ui = stack_layout{children}; - - auto ui_root = factory.reconciliate(nullptr, test_ui); - - expect_equal(factory.stack_layout_count, 1); - expect_equal(factory.label_count, 0); - expect_equal(factory.button_count, 0); - - expect_non_null(ui_root); - expect_dynamic_type(*ui_root, stack_layout_impl); - check_children<>(*ui_root); - - children.set({{label{}}}); - - check_children(*ui_root); - - expect_equal(factory.stack_layout_count, 1); - expect_equal(factory.label_count, 1); - expect_equal(factory.button_count, 0); - - children.set({{label{}}, {label{}}}); - - check_children(*ui_root); - - expect_equal(factory.stack_layout_count, 1); - expect_equal(factory.label_count, 2); - expect_equal(factory.button_count, 0); - - children.set({{label{}}, {label{}}, {label{}}}); - - expect_equal(factory.stack_layout_count, 1); - expect_equal(factory.label_count, 3); - expect_equal(factory.button_count, 0); - - children.set({{label{}}, {button{}}, {label{}}}); - - expect_equal(factory.stack_layout_count, 1); - expect_equal(factory.label_count, 3); - expect_equal(factory.button_count, 1); - - children.set({{button{}}, {button{}}, {label{}}}); - - expect_equal(factory.stack_layout_count, 1); - expect_equal(factory.label_count, 3); - expect_equal(factory.button_count, 2); - - children.set({{button{}}, {button{}}}); - - expect_equal(factory.stack_layout_count, 1); - expect_equal(factory.label_count, 3); - expect_equal(factory.button_count, 2); - - children.set({{button{}}}); - - expect_equal(factory.stack_layout_count, 1); - expect_equal(factory.label_count, 3); - expect_equal(factory.button_count, 2); - - children.set({}); - - expect_equal(factory.stack_layout_count, 1); - expect_equal(factory.label_count, 3); - expect_equal(factory.button_count, 2); -} - -test_case(ui_impl_reconciliate_container__keys) -{ - test_component_factory factory; - - react::source> children; - - auto test_ui = stack_layout{children}; - - auto ui_root = factory.reconciliate(nullptr, test_ui); - - expect_equal(factory.stack_layout_count, 1); - expect_equal(factory.label_count, 0); - - expect_non_null(ui_root); - expect_dynamic_type(*ui_root, stack_layout_impl); - check_children<>(*ui_root); - - children.set({{label{}, "Label 0"}}); - - check_children(*ui_root); - - auto label0 = ui_root->children()[0].get(); - - expect_equal(factory.stack_layout_count, 1); - expect_equal(factory.label_count, 1); - - children.set({{label{}, "Label 0"}, {label{}, "Label 1"}}); - - check_children(*ui_root); - expect_equal(ui_root->children()[0].get(), label0); - auto label1 = ui_root->children()[1].get(); - - expect_equal(factory.stack_layout_count, 1); - expect_equal(factory.label_count, 2); - - children.set({{label{}, "Label 1"}, {label{}, "Label 0"}}); - - check_children(*ui_root); - expect_equal(ui_root->children()[0].get(), label1); - expect_equal(ui_root->children()[1].get(), label0); - - expect_equal(factory.stack_layout_count, 1); - expect_equal(factory.label_count, 2); - - children.set({{label{}, "Label 0"}, {label{}, "Label 2"}}); - - check_children(*ui_root); - expect_equal(ui_root->children()[0].get(), label0); - - expect_equal(factory.stack_layout_count, 1); - expect_equal(factory.label_count, 3); -} - diff --git a/libs/ui/tests/size_polygon_cut.cpp b/libs/ui/tests/size_polygon_cut.cpp deleted file mode 100644 index 06c8045c..00000000 --- a/libs/ui/tests/size_polygon_cut.cpp +++ /dev/null @@ -1,233 +0,0 @@ -#include - -#include - -#include - -using namespace psemek; -using namespace psemek::ui::impl; - -namespace -{ - - size_polygon normalize(size_polygon p) - { - if (p.empty()) - return p; - auto it = std::min_element(p.begin(), p.end()); - std::rotate(p.begin(), it, p.end()); - return p; - } - - void check_polygon_cut(size_polygon & polygon, int dimension, geom::interval const & range, size_polygon const & result) - { - for (int i = 0; i < polygon.size(); ++i) - { - expect_equal(normalize(cut(polygon, dimension, range)), normalize(result)); - std::rotate(polygon.begin(), polygon.end() - 1, polygon.end()); - } - } - - void check_polygon_sum(size_polygon & polygon1, size_polygon & polygon2, size_polygon const & result_x, size_polygon const & result_y) - { - for (int i1 = 0; i1 < polygon1.size(); ++i1) - { - for (int i2 = 0; i2 < polygon2.size(); ++i2) - { - expect_equal(normalize(sum_along(polygon1, polygon2, 0)), normalize(result_x)); - expect_equal(normalize(sum_along(polygon1, polygon2, 1)), normalize(result_y)); - - std::rotate(polygon2.begin(), polygon2.end() - 1, polygon2.end()); - } - - std::rotate(polygon1.begin(), polygon1.end() - 1, polygon1.end()); - } - } - -} - -test_case(ui_impl_size__polygon_cut_empty) -{ - expect_equal(cut(size_polygon{}, 0, {0.f, 10.f}), size_polygon{}); -} - -test_case(ui_impl_size__polygon_cut_point__x) -{ - size_polygon polygon{{0.f, 0.f}}; - - check_polygon_cut(polygon, 0, {-5.f, -5.f}, size_polygon{}); - check_polygon_cut(polygon, 0, {-5.f, 0.f}, polygon); - check_polygon_cut(polygon, 0, {-5.f, 5.f}, polygon); - check_polygon_cut(polygon, 0, {0.f, 0.f}, polygon); - check_polygon_cut(polygon, 0, {0.f, 5.f}, polygon); - check_polygon_cut(polygon, 0, {5.f, 5.f}, size_polygon{}); -} - -test_case(ui_impl_size__polygon_cut_point__y) -{ - size_polygon polygon{{0.f, 0.f}}; - - check_polygon_cut(polygon, 1, {-5.f, -5.f}, size_polygon{}); - check_polygon_cut(polygon, 1, {-5.f, 0.f}, polygon); - check_polygon_cut(polygon, 1, {-5.f, 5.f}, polygon); - check_polygon_cut(polygon, 1, {0.f, 0.f}, polygon); - check_polygon_cut(polygon, 1, {0.f, 5.f}, polygon); - check_polygon_cut(polygon, 1, {5.f, 5.f}, size_polygon{}); -} - -test_case(ui_impl_size__polygon_cut_segmentx__x__simple) -{ - size_polygon polygon{{0.f, 0.f}, {10.f, 0.f}}; - - check_polygon_cut(polygon, 0, {-5.f, -5.f}, size_polygon{}); - check_polygon_cut(polygon, 0, {-5.f, 5.f}, size_polygon{{0.f, 0.f}, {5.f, 0.f}}); - check_polygon_cut(polygon, 0, {-5.f, 15.f}, polygon); - check_polygon_cut(polygon, 0, {5.f, 15.f}, size_polygon{{5.f, 0.f}, {10.f, 0.f}}); - check_polygon_cut(polygon, 0, {15.f, 15.f}, size_polygon{}); -} - -test_case(ui_impl_size__polygon_cut_square__x__simple) -{ - size_polygon polygon{{0.f, 0.f}, {10.f, 0.f}, {10.f, 10.f}, {0.f, 10.f}}; - - check_polygon_cut(polygon, 0, {-10.f, -2.f}, size_polygon{}); - check_polygon_cut(polygon, 0, {-2.f, -2.f}, size_polygon{}); - check_polygon_cut(polygon, 0, {-2.f, 2.f}, size_polygon{{0.f, 0.f}, {2.f, 0.f}, {2.f, 10.f}, {0.f, 10.f}}); - check_polygon_cut(polygon, 0, {2.f, 8.f}, size_polygon{{2.f, 0.f}, {8.f, 0.f}, {8.f, 10.f}, {2.f, 10.f}}); - check_polygon_cut(polygon, 0, {5.f, 5.f}, size_polygon{{5.f, 0.f}, {5.f, 10.f}}); - check_polygon_cut(polygon, 0, {8.f, 12.f}, size_polygon{{8.f, 0.f}, {10.f, 0.f}, {10.f, 10.f}, {8.f, 10.f}}); - check_polygon_cut(polygon, 0, {12.f, 20.f}, size_polygon{}); - check_polygon_cut(polygon, 0, {12.f, 12.f}, size_polygon{}); - check_polygon_cut(polygon, 0, {-2.f, 12.f}, polygon); -} - -test_case(ui_impl_size__polygon_cut_square__x__degenerate) -{ - size_polygon polygon{{0.f, 0.f}, {10.f, 0.f}, {10.f, 10.f}, {0.f, 10.f}}; - - check_polygon_cut(polygon, 0, {-10.f, 0.f}, size_polygon{{0.f, 0.f}, {0.f, 10.f}}); - check_polygon_cut(polygon, 0, {0.f, 0.f}, size_polygon{{0.f, 0.f}, {0.f, 10.f}}); - check_polygon_cut(polygon, 0, {-2.f, 10.f}, polygon); - check_polygon_cut(polygon, 0, {0.f, 10.f}, polygon); - check_polygon_cut(polygon, 0, {0.f, 12.f}, polygon); - check_polygon_cut(polygon, 0, {10.f, 10.f}, size_polygon{{10.f, 0.f}, {10.f, 10.f}}); - check_polygon_cut(polygon, 0, {10.f, 20.f}, size_polygon{{10.f, 0.f}, {10.f, 10.f}}); -} - -test_case(ui_impl_size__polygon_cut_square__y__simple) -{ - size_polygon polygon{{0.f, 0.f}, {10.f, 0.f}, {10.f, 10.f}, {0.f, 10.f}}; - - check_polygon_cut(polygon, 1, {-10.f, -2.f}, size_polygon{}); - check_polygon_cut(polygon, 1, {-2.f, -2.f}, size_polygon{}); - check_polygon_cut(polygon, 1, {-2.f, 2.f}, size_polygon{{0.f, 0.f}, {10.f, 0.f}, {10.f, 2.f}, {0.f, 2.f}}); - check_polygon_cut(polygon, 1, {2.f, 8.f}, size_polygon{{0.f, 2.f}, {10.f, 2.f}, {10.f, 8.f}, {0.f, 8.f}}); - check_polygon_cut(polygon, 1, {5.f, 5.f}, size_polygon{{0.f, 5.f}, {10.f, 5.f}}); - check_polygon_cut(polygon, 1, {8.f, 12.f}, size_polygon{{0.f, 8.f}, {10.f, 8.f}, {10.f, 10.f}, {0.f, 10.f}}); - check_polygon_cut(polygon, 1, {12.f, 20.f}, size_polygon{}); - check_polygon_cut(polygon, 1, {12.f, 12.f}, size_polygon{}); - check_polygon_cut(polygon, 1, {-2.f, 12.f}, polygon); -} - -test_case(ui_impl_size__polygon_cut_square__y__degenerate) -{ - size_polygon polygon{{0.f, 0.f}, {10.f, 0.f}, {10.f, 10.f}, {0.f, 10.f}}; - - check_polygon_cut(polygon, 1, {-10.f, 0.f}, size_polygon{{0.f, 0.f}, {10.f, 0.f}}); - check_polygon_cut(polygon, 1, {0.f, 0.f}, size_polygon{{0.f, 0.f}, {10.f, 0.f}}); - check_polygon_cut(polygon, 1, {-2.f, 10.f}, polygon); - check_polygon_cut(polygon, 1, {0.f, 10.f}, polygon); - check_polygon_cut(polygon, 1, {0.f, 12.f}, polygon); - check_polygon_cut(polygon, 1, {10.f, 10.f}, size_polygon{{0.f, 10.f}, {10.f, 10.f}}); - check_polygon_cut(polygon, 1, {10.f, 20.f}, size_polygon{{0.f, 10.f}, {10.f, 10.f}}); -} - -test_case(ui_impl_size__polygon_cut_diamond__x__simple) -{ - size_polygon polygon{{10.f, 0.f}, {20.f, 10.f}, {10.f, 20.f}, {0.f, 10.f}}; - - check_polygon_cut(polygon, 0, {-10.f, -5.f}, size_polygon{}); - check_polygon_cut(polygon, 0, {-10.f, 5.f}, size_polygon{{0.f, 10.f}, {5.f, 5.f}, {5.f, 15.f}}); - check_polygon_cut(polygon, 0, {-10.f, 15.f}, size_polygon{{0.f, 10.f}, {10.f, 0.f}, {15.f, 5.f}, {15.f, 15.f}, {10.f, 20.f}}); - check_polygon_cut(polygon, 0, {5.f, 5.f}, size_polygon{{5.f, 5.f}, {5.f, 15.f}}); - check_polygon_cut(polygon, 0, {5.f, 15.f}, size_polygon{{5.f, 15.f}, {5.f, 5.f}, {10.f, 0.f}, {15.f, 5.f}, {15.f, 15.f}, {10.f, 20.f}}); - check_polygon_cut(polygon, 0, {5.f, 25.f}, size_polygon{{5.f, 15.f}, {5.f, 5.f}, {10.f, 0.f}, {20.f, 10.f}, {10.f, 20.f}}); - check_polygon_cut(polygon, 0, {15.f, 15.f}, size_polygon{{15.f, 5.f}, {15.f, 15.f}}); - check_polygon_cut(polygon, 0, {15.f, 25.f}, size_polygon{{15.f, 5.f}, {20.f, 10.f}, {15.f, 15.f}}); - check_polygon_cut(polygon, 0, {25.f, 30.f}, size_polygon{}); - check_polygon_cut(polygon, 0, {-5.f, 25.f}, polygon); -} - -test_case(ui_impl_size__polygon_cut_diamond__x__degenerate) -{ - size_polygon polygon{{10.f, 0.f}, {20.f, 10.f}, {10.f, 20.f}, {0.f, 10.f}}; - - check_polygon_cut(polygon, 0, {-10.f, 0.f}, size_polygon{{0.f, 10.f}}); - check_polygon_cut(polygon, 0, {-10.f, 10.f}, size_polygon{{0.f, 10.f}, {10.f, 0.f}, {10.f, 20.f}}); - check_polygon_cut(polygon, 0, {-10.f, 20.f}, polygon); - check_polygon_cut(polygon, 0, {0.f, 0.f}, size_polygon{{0.f, 10.f}}); - check_polygon_cut(polygon, 0, {0.f, 5.f}, size_polygon{{0.f, 10.f}, {5.f, 5.f}, {5.f, 15.f}}); - check_polygon_cut(polygon, 0, {0.f, 10.f}, size_polygon{{0.f, 10.f}, {10.f, 0.f}, {10.f, 20.f}}); - check_polygon_cut(polygon, 0, {0.f, 15.f}, size_polygon{{0.f, 10.f}, {10.f, 0.f}, {15.f, 5.f}, {15.f, 15.f}, {10.f, 20.f}}); - check_polygon_cut(polygon, 0, {0.f, 20.f}, polygon); - check_polygon_cut(polygon, 0, {0.f, 25.f}, polygon); - check_polygon_cut(polygon, 0, {5.f, 10.f}, size_polygon{{5.f, 5.f}, {10.f, 0.f}, {10.f, 20.f}, {5.f, 15.f}}); - check_polygon_cut(polygon, 0, {5.f, 20.f}, size_polygon{{5.f, 5.f}, {10.f, 0.f}, {20.f, 10.f}, {10.f, 20.f}, {5.f, 15.f}}); - check_polygon_cut(polygon, 0, {10.f, 10.f}, size_polygon{{10.f, 0.f}, {10.f, 20.f}}); - check_polygon_cut(polygon, 0, {10.f, 15.f}, size_polygon{{10.f, 0.f}, {15.f, 5.f}, {15.f, 15.f}, {10.f, 20.f}}); - check_polygon_cut(polygon, 0, {10.f, 20.f}, size_polygon{{10.f, 0.f}, {20.f, 10.f}, {10.f, 20.f}}); - check_polygon_cut(polygon, 0, {10.f, 25.f}, size_polygon{{10.f, 0.f}, {20.f, 10.f}, {10.f, 20.f}}); - check_polygon_cut(polygon, 0, {15.f, 20.f}, size_polygon{{15.f, 5.f}, {20.f, 10.f}, {15.f, 15.f}}); - check_polygon_cut(polygon, 0, {20.f, 20.f}, size_polygon{{20.f, 10.f}}); - check_polygon_cut(polygon, 0, {20.f, 25.f}, size_polygon{{20.f, 10.f}}); -} - -test_case(ui_impl_size__polygon_cut_diamond__y__simple) -{ - size_polygon polygon{{10.f, 0.f}, {20.f, 10.f}, {10.f, 20.f}, {0.f, 10.f}}; - - check_polygon_cut(polygon, 1, {-10.f, -5.f}, size_polygon{}); - check_polygon_cut(polygon, 1, {-10.f, 5.f}, size_polygon{{15.f, 5.f}, {5.f, 5.f}, {10.f, 0.f}}); - check_polygon_cut(polygon, 1, {-10.f, 15.f}, size_polygon{{20.f, 10.f}, {15.f, 15.f}, {5.f, 15.f}, {0.f, 10.f}, {10.f, 0.f}}); - check_polygon_cut(polygon, 1, {5.f, 5.f}, size_polygon{{15.f, 5.f}, {5.f, 5.f}}); - check_polygon_cut(polygon, 1, {5.f, 15.f}, size_polygon{{20.f, 10.f}, {15.f, 15.f}, {5.f, 15.f}, {0.f, 10.f}, {5.f, 5.f}, {15.f, 5.f}}); - check_polygon_cut(polygon, 1, {5.f, 25.f}, size_polygon{{20.f, 10.f}, {10.f, 20.f}, {0.f, 10.f}, {5.f, 5.f}, {15.f, 5.f}}); - check_polygon_cut(polygon, 1, {15.f, 15.f}, size_polygon{{15.f, 15.f}, {5.f, 15.f}}); - check_polygon_cut(polygon, 1, {15.f, 25.f}, size_polygon{{15.f, 15.f}, {10.f, 20.f}, {5.f, 15.f}}); - check_polygon_cut(polygon, 1, {25.f, 30.f}, size_polygon{}); - check_polygon_cut(polygon, 1, {-5.f, 25.f}, polygon); -} - -test_case(ui_impl_size__polygon_cut_diamond__y__degenerate) -{ - size_polygon polygon{{10.f, 0.f}, {20.f, 10.f}, {10.f, 20.f}, {0.f, 10.f}}; - - check_polygon_cut(polygon, 1, {-10.f, 0.f}, size_polygon{{10.f, 0.f}}); - check_polygon_cut(polygon, 1, {-10.f, 10.f}, size_polygon{{20.f, 10.f}, {0.f, 10.f}, {10.f, 0.f}}); - check_polygon_cut(polygon, 1, {-10.f, 20.f}, polygon); - check_polygon_cut(polygon, 1, {0.f, 0.f}, size_polygon{{10.f, 0.f}}); - check_polygon_cut(polygon, 1, {0.f, 5.f}, size_polygon{{10.f, 0.f}, {15.f, 5.f}, {5.f, 5.f}}); - check_polygon_cut(polygon, 1, {0.f, 10.f}, size_polygon{{0.f, 10.f}, {10.f, 0.f}, {20.f, 10.f}}); - check_polygon_cut(polygon, 1, {0.f, 15.f}, size_polygon{{0.f, 10.f}, {10.f, 0.f}, {20.f, 10.f}, {15.f, 15.f}, {5.f, 15.f}}); - check_polygon_cut(polygon, 1, {0.f, 20.f}, polygon); - check_polygon_cut(polygon, 1, {0.f, 25.f}, polygon); - check_polygon_cut(polygon, 1, {5.f, 10.f}, size_polygon{{5.f, 5.f}, {15.f, 5.f}, {20.f, 10.f}, {0.f, 10.f}}); - check_polygon_cut(polygon, 1, {5.f, 20.f}, size_polygon{{5.f, 5.f}, {15.f, 5.f}, {20.f, 10.f}, {10.f, 20.f}, {0.f, 10.f}}); - check_polygon_cut(polygon, 1, {10.f, 10.f}, size_polygon{{0.f, 10.f}, {20.f, 10.f}}); - check_polygon_cut(polygon, 1, {10.f, 15.f}, size_polygon{{0.f, 10.f}, {20.f, 10.f}, {15.f, 15.f}, {5.f, 15.f}}); - check_polygon_cut(polygon, 1, {10.f, 20.f}, size_polygon{{0.f, 10.f}, {20.f, 10.f}, {10.f, 20.f}}); - check_polygon_cut(polygon, 1, {10.f, 25.f}, size_polygon{{0.f, 10.f}, {20.f, 10.f}, {10.f, 20.f}}); - check_polygon_cut(polygon, 1, {15.f, 20.f}, size_polygon{{5.f, 15.f}, {15.f, 15.f}, {10.f, 20.f}}); - check_polygon_cut(polygon, 1, {20.f, 20.f}, size_polygon{{10.f, 20.f}}); - check_polygon_cut(polygon, 1, {20.f, 25.f}, size_polygon{{10.f, 20.f}}); -} - -test_case(ui_impl_size__polygon_sum_empty) -{ - size_polygon polygon; - - expect_equal(sum_along(polygon, polygon, 0), polygon); - expect_equal(sum_along(polygon, polygon, 1), polygon); - - (void)check_polygon_sum; -} diff --git a/libs/ui/tests/size_polygon_min.cpp b/libs/ui/tests/size_polygon_min.cpp deleted file mode 100644 index d3bbabfb..00000000 --- a/libs/ui/tests/size_polygon_min.cpp +++ /dev/null @@ -1,95 +0,0 @@ -#include - -#include - -#include - -using namespace psemek; -using namespace psemek::ui::impl; - -namespace -{ - - template - std::set as_set(std::vector const & v) - { - std::set result; - for (auto const & x : v) - result.insert(x); - return result; - } - - void check_polygon_min(size_polygon & polygon, size_polygon const & min_x, size_polygon const & min_y) - { - for (int i = 0; i < polygon.size(); ++i) - { - expect_equal(as_set(min(polygon, 0)), as_set(min_x)); - expect_equal(as_set(min(polygon, 1)), as_set(min_y)); - - std::rotate(polygon.begin(), polygon.end() - 1, polygon.end()); - } - } - -} - -test_case(ui_impl_size__polygon_min_empty) -{ - size_polygon polygon; - - expect_equal(min(polygon, 0), size_polygon{}); - expect_equal(min(polygon, 1), size_polygon{}); -} - -test_case(ui_impl_size__polygon_min_edge__X) -{ - size_polygon polygon{{0.f, 0.f}, {10.f, 0.f}}; - size_polygon min_x{{0.f, 0.f}}; - size_polygon min_y{{0.f, 0.f}, {10.f, 0.f}}; - - check_polygon_min(polygon, min_x, min_y); -} - -test_case(ui_impl_size__polygon_min_edge__Y) -{ - size_polygon polygon{{0.f, 0.f}, {0.f, 10.f}}; - size_polygon min_x{{0.f, 0.f}, {0.f, 10.f}}; - size_polygon min_y{{0.f, 0.f}}; - - check_polygon_min(polygon, min_x, min_y); -} - -test_case(ui_impl_size__polygon_min_edge__XY) -{ - size_polygon polygon{{0.f, 0.f}, {10.f, 10.f}}; - size_polygon min_x{{0.f, 0.f}}; - size_polygon min_y{{0.f, 0.f}}; - - check_polygon_min(polygon, min_x, min_y); -} - -test_case(ui_impl_size__polygon_min_square) -{ - size_polygon polygon{{0.f, 0.f}, {10.f, 0.f}, {10.f, 10.f}, {0.f, 10.f}}; - size_polygon min_x{{0.f, 0.f}, {0.f, 10.f}}; - size_polygon min_y{{0.f, 0.f}, {10.f, 0.f}}; - - check_polygon_min(polygon, min_x, min_y); -} - -test_case(ui_impl_size__polygon_min_diamond) -{ - size_polygon polygon{{0.f, 10.f}, {10.f, 0.f}, {20.f, 10.f}, {10.f, 20.f}}; - size_polygon min_x{{0.f, 10.f}}; - size_polygon min_y{{10.f, 0.f}}; - - check_polygon_min(polygon, min_x, min_y); -} - -test_case(ui_impl_size__polygon_min_octahedron) -{ - size_polygon polygon{{10.f, 0.f}, {20.f, 0.f}, {30.f, 10.f}, {30.f, 20.f}, {20.f, 30.f}, {10.f, 30.f}, {0.f, 20.f}, {0.f, 10.f}}; - size_polygon min_x{{0.f, 10.f}, {0.f, 20.f}}; - size_polygon min_y{{10.f, 0.f}, {20.f, 0.f}}; - - check_polygon_min(polygon, min_x, min_y); -}