TermOx
pair.hpp
1 #ifndef TERMOX_WIDGET_PAIR_HPP
2 #define TERMOX_WIDGET_PAIR_HPP
3 #include <memory>
4 
5 #include <termox/widget/layouts/horizontal.hpp>
6 #include <termox/widget/layouts/stack.hpp>
7 #include <termox/widget/layouts/vertical.hpp>
8 #include <type_traits>
9 
10 namespace ox {
11 
13 template <typename Layout_t, typename First, typename Second>
14 struct Pair : Layout_t {
15  public:
16  struct Parameters {
17  typename First::Parameters first;
18  typename Second::Parameters second;
19  };
20 
21  public:
22  First& first;
23  Second& second;
24 
25  public:
27  Pair()
28  : first{this->template make_child<First>()},
29  second{this->template make_child<Second>()}
30  {}
31 
32  explicit Pair(Parameters p)
33  : first{this->make_child_maybe_with_parameters<First>(
34  std::move(p.first))},
35  second{this->make_child_maybe_with_parameters<Second>(
36  std::move(p.second))}
37  {}
38 
40  Pair(typename First::Parameters a, typename Second::Parameters b)
41  : first{this->make_child_maybe_with_parameters<First>(std::move(a))},
42  second{this->make_child_maybe_with_parameters<Second>(std::move(b))}
43  {}
44 
46  Pair(std::unique_ptr<First> a, std::unique_ptr<Second> b)
47  : Layout_t{std::move(a), std::move(b)},
48  first{static_cast<First&>(this->get_children()[0])},
49  second{static_cast<Second&>(this->get_children()[1])}
50  {}
51 
52  public:
54  template <std::size_t Index>
55  [[nodiscard]] auto get() -> auto&
56  {
57  static_assert(Index < 2, "Pair::get() only has two elements.");
58  if constexpr (Index == 0)
59  return first;
60  else if constexpr (Index == 1)
61  return second;
62  }
63 
65  template <std::size_t Index>
66  [[nodiscard]] auto get() const -> auto const&
67  {
68  static_assert(Index < 2, "Pair::get() only has two elements.");
69  if constexpr (Index == 0)
70  return first;
71  else if constexpr (Index == 1)
72  return second;
73  }
74 
75  private:
76  using Layout_t::append_child;
77  using Layout_t::delete_all_children;
78  using Layout_t::insert_child;
79  using Layout_t::make_child;
80  using Layout_t::remove_and_delete_child;
81  using Layout_t::remove_and_delete_child_at;
82  using Layout_t::remove_and_delete_child_if;
83  using Layout_t::remove_child;
84  using Layout_t::remove_child_at;
85  using Layout_t::remove_child_if;
86  using Layout_t::swap_children;
87 
88  private:
89  template <typename Widget_t>
90  [[nodiscard]] auto make_child_maybe_with_parameters(
91  typename Widget_t::Parameters p) -> Widget_t&
92  {
93  if constexpr (std::is_constructible_v<Widget_t,
94  typename Widget_t::Parameters>) {
95  return this->template make_child<Widget_t>(std::move(p));
96  }
97  else
98  return this->template make_child<Widget_t>();
99  }
100 };
101 
103 template <typename Layout_t, typename First, typename Second>
104 [[nodiscard]] auto pair() -> std::unique_ptr<Pair<Layout_t, First, Second>>
105 {
106  return std::make_unique<Pair<Layout_t, First, Second>>();
107 }
108 
110 template <typename Layout_t, typename First, typename Second>
111 [[nodiscard]] auto pair(typename First::Parameters a,
112  typename Second::Parameters b)
113  -> std::unique_ptr<Pair<Layout_t, First, Second>>
114 {
115  return std::make_unique<Pair<Layout_t, First, Second>>(std::move(a),
116  std::move(b));
117 }
118 
120 template <typename Layout_t, typename First, typename Second>
121 [[nodiscard]] auto pair(std::unique_ptr<First> a, std::unique_ptr<Second> b)
122  -> std::unique_ptr<Pair<Layout_t, First, Second>>
123 {
124  return std::make_unique<Pair<Layout_t, First, Second>>(std::move(a),
125  std::move(b));
126 }
127 
129 template <typename First, typename Second>
130 using VPair = Pair<layout::Vertical<>, First, Second>;
131 
133 template <typename First, typename Second>
134 [[nodiscard]] auto vpair() -> std::unique_ptr<VPair<First, Second>>
135 {
136  return std::make_unique<VPair<First, Second>>();
137 }
138 
140 template <typename First, typename Second>
141 [[nodiscard]] auto vpair(typename First::Parameters a,
142  typename Second::Parameters b)
143  -> std::unique_ptr<VPair<First, Second>>
144 {
145  return std::make_unique<VPair<First, Second>>(std::move(a), std::move(b));
146 }
147 
149 template <typename First, typename Second>
150 [[nodiscard]] auto vpair(std::unique_ptr<First> a, std::unique_ptr<Second> b)
151  -> std::unique_ptr<VPair<First, Second>>
152 {
153  return std::make_unique<VPair<First, Second>>(std::move(a), std::move(b));
154 }
155 
157 template <typename First, typename Second>
158 using HPair = Pair<layout::Horizontal<>, First, Second>;
159 
161 template <typename First, typename Second>
162 [[nodiscard]] auto hpair() -> std::unique_ptr<HPair<First, Second>>
163 {
164  return std::make_unique<HPair<First, Second>>();
165 }
166 
168 template <typename First, typename Second>
169 [[nodiscard]] auto hpair(typename First::Parameters a,
170  typename Second::Parameters b)
171  -> std::unique_ptr<HPair<First, Second>>
172 {
173  return std::make_unique<HPair<First, Second>>(std::move(a), std::move(b));
174 }
175 
177 template <typename First, typename Second>
178 [[nodiscard]] auto hpair(std::unique_ptr<First> a, std::unique_ptr<Second> b)
179  -> std::unique_ptr<HPair<First, Second>>
180 {
181  return std::make_unique<HPair<First, Second>>(std::move(a), std::move(b));
182 }
183 
185 template <typename First, typename Second>
186 using SPair = Pair<layout::Stack<>, First, Second>;
187 
189 template <typename First, typename Second>
190 [[nodiscard]] auto spair() -> std::unique_ptr<SPair<First, Second>>
191 {
192  return std::make_unique<SPair<First, Second>>();
193 }
194 
196 template <typename First, typename Second>
197 [[nodiscard]] auto spair(typename First::Parameters a,
198  typename Second::Parameters b)
199  -> std::unique_ptr<SPair<First, Second>>
200 {
201  return std::make_unique<SPair<First, Second>>(std::move(a), std::move(b));
202 }
203 
205 template <typename First, typename Second>
206 [[nodiscard]] auto spair(std::unique_ptr<First> a, std::unique_ptr<Second> b)
207  -> std::unique_ptr<SPair<First, Second>>
208 {
209  return std::make_unique<SPair<First, Second>>(std::move(a), std::move(b));
210 }
211 
212 } // namespace ox
213 #endif // TERMOX_WIDGET_PAIR_HPP
Definition: pair.hpp:16
Heterogeneous pair of Widgets within a Layout.
Definition: pair.hpp:14
Pair()
Widgets are default constructed.
Definition: pair.hpp:27
Pair(std::unique_ptr< First > a, std::unique_ptr< Second > b)
Existing Widgets are moved into the Pair.
Definition: pair.hpp:46
auto get() -> auto &
Get child by index.
Definition: pair.hpp:55
Pair(typename First::Parameters a, typename Second::Parameters b)
Widgets are constructed with passed in First/Second::Parameters objects.
Definition: pair.hpp:40
auto get() const -> auto const &
Get child by index.
Definition: pair.hpp:66