TermOx
set.hpp
1 #ifndef TERMOX_WIDGET_LAYOUTS_SET_HPP
2 #define TERMOX_WIDGET_LAYOUTS_SET_HPP
3 #include <algorithm>
4 #include <functional>
5 #include <memory>
6 #include <type_traits>
7 
8 #include <termox/common/identity.hpp>
9 
10 namespace ox::layout {
11 
13 
16 template <typename Layout_t,
17  typename Projection = Identity,
18  typename Comparison = std::less<
19  std::invoke_result_t<Projection,
20  std::add_const_t<std::add_lvalue_reference_t<
21  typename Layout_t::Child_t>>>>>
22 class Set : public Layout_t {
23  public:
24  using Child_t = typename Layout_t::Child_t;
25 
26  using Key_t =
27  std::invoke_result_t<Projection,
28  std::add_const_t<std::add_lvalue_reference_t<
29  typename Layout_t::Child_t>>>;
30 
31  public:
33  auto insert_child(std::unique_ptr<Child_t> child) -> Child_t&
34  {
35  auto constexpr comp = [&](Child_t const& a, Child_t const& b) {
36  return Comparison{}(Projection{}(a), Projection{}(b));
37  };
38  auto const children = this->get_children();
39  auto iter =
40  std::upper_bound(children.begin(), children.end(), *child, comp);
41  return this->Layout_t::insert_child(std::move(child),
42  iter.underlying().underlying());
43  }
44 
46 
47  template <typename Widget_t = Child_t, typename... Args>
48  auto make_child(Args&&... args) -> Widget_t&
49  {
50  static_assert(
51  std::is_base_of_v<Child_t, Widget_t>,
52  "layout::Set::make_child: Widget_t must be a Child_t type");
53  return this->insert_child(
54  std::make_unique<Widget_t>(std::forward<Args>(args)...));
55  }
56 
58 
60  [[nodiscard]] auto find_child(Key_t const& key) -> Child_t*
61  {
62  return this->get_children().find(
63  [&key](auto const& c) { return Projection{}(c) == key; });
64  }
65 
66  private:
67  using Layout_t::append_child;
68 };
69 
71 template <typename Layout_t,
72  typename Projection = Identity,
73  typename Comparison = std::less<
74  std::invoke_result_t<Projection,
75  std::add_const_t<std::add_lvalue_reference_t<
76  typename Layout_t::Child_t>>>>,
77  typename... Args>
78 [[nodiscard]] auto set(Args&&... args)
79  -> std::unique_ptr<Set<Projection, Comparison>>
80 {
81  return std::make_unique<Set<Projection, Comparison>>(
82  std::forward<Args>(args)...);
83 }
84 
85 } // namespace ox::layout
86 #endif // TERMOX_WIDGET_LAYOUTS_SET_HPP
Provides a set-like interface to Layout_t.
Definition: set.hpp:22
auto insert_child(std::unique_ptr< Child_t > child) -> Child_t &
Insert child into correct position based on Projection and Comparison.
Definition: set.hpp:33
auto make_child(Args &&... args) -> Widget_t &
Create a Widget and insert it into the list of children.
Definition: set.hpp:48
auto find_child(Key_t const &key) -> Child_t *
Find a child widget by its key type(the result of the Projection fn).
Definition: set.hpp:60
Provides an Identity projection operator(), overloaded for any type.
Definition: identity.hpp:8