TermOx
fixed.hpp
1 #ifndef TERMOX_WIDGET_LAYOUT_FIXED_HPP
2 #define TERMOX_WIDGET_LAYOUT_FIXED_HPP
3 #include <cassert>
4 
5 #include <termox/widget/layouts/horizontal.hpp>
6 #include <termox/widget/layouts/vertical.hpp>
7 #include <termox/widget/pipe.hpp>
8 #include <termox/widget/widget.hpp>
9 
10 namespace ox {
11 
13 template <template <typename> typename Layout_t, typename Widget_t>
14 class Fixed : public Layout_t<Widget> {
15  private:
16  using Base_t = Layout_t<Widget>;
17 
18  static auto constexpr is_horizontal = layout::is_horizontal_v<Base_t>;
19 
20  public:
21  Widget& buffer_1;
22  Widget_t& widget;
23  Widget& buffer_2;
24 
25  public:
26  template <typename... Args>
27  Fixed(int offset_1, int offset_2, Args&&... args)
28  : buffer_1{this->template make_child()},
29  widget{
30  this->template make_child<Widget_t>(std::forward<Args>(args)...)},
31  buffer_2{this->template make_child()},
32  offset_1_{offset_1},
33  offset_2_{offset_2}
34  {
35  assert(offset_1_ >= 0 && offset_2_ >= 0);
36  this->update_policies(offset_1_, offset_2_);
37  if constexpr (is_horizontal) {
38  buffer_1 | pipe::fixed_width(offset_1_);
39  buffer_2 | pipe::fixed_width(offset_2_);
40  }
41  else {
42  buffer_1 | pipe::fixed_height(offset_1_);
43  buffer_2 | pipe::fixed_height(offset_2_);
44  }
45  }
46 
47  template <typename... Args>
48  Fixed(int offset, Args&&... args)
49  : Fixed{offset, offset, std::forward<Args>(args)...}
50  {}
51 
52  protected:
53  auto child_polished_event(Widget& child) -> bool override
54  {
55  if (&child == &widget)
56  this->update_policies(offset_1_, offset_2_);
57  return Base_t::child_polished_event(child);
58  }
59 
60  private:
61  int offset_1_;
62  int offset_2_;
63 
64  private:
65  void update_policies(int offset_1, int offset_2)
66  {
67  auto const offset_policy = [=](Size_policy& sp) {
68  auto const offset_total = offset_1 + offset_2;
69  sp.hint(sp.hint() + offset_total);
70  sp.min(sp.min() + offset_total);
71  if (sp.max() != Size_policy::maximum_max)
72  sp.max(sp.max() + offset_total);
73  };
74 
75  this->height_policy = widget.height_policy;
76  this->width_policy = widget.width_policy;
77 
78  if constexpr (is_horizontal)
79  offset_policy(this->width_policy);
80  else
81  offset_policy(this->width_policy);
82  }
83 };
84 
85 template <typename Widget_t>
87 
88 template <typename Widget_t, typename... Args>
89 [[nodiscard]] inline auto hfixed(Args&&... args)
90  -> std::unique_ptr<HFixed<Widget_t>>
91 {
92  return std::make_unique<HFixed<Widget_t>>(std::forward<Args>(args)...);
93 }
94 
95 template <typename Widget_t>
96 using VFixed = Fixed<layout::Vertical, Widget_t>;
97 
98 template <typename Widget_t, typename... Args>
99 [[nodiscard]] inline auto vfixed(Args&&... args)
100  -> std::unique_ptr<VFixed<Widget_t>>
101 {
102  return std::make_unique<VFixed<Widget_t>>(std::forward<Args>(args)...);
103 }
104 
105 template <typename Widget_t>
106 class Fixed_2d : public HFixed<VFixed<Widget_t>> {
107  using Base_t = HFixed<VFixed<Widget_t>>;
108 
109  public:
110  template <typename... Args>
111  Fixed_2d(int north, int south, int east, int west, Args&&... args)
112  : Base_t{west, east, north, south, std::forward<Args>(args)...}
113  {}
114 
115  public:
116  Widget_t& widget = this->Base_t::widget.widget;
117 };
118 
119 template <typename Widget_t, typename... Args>
120 [[nodiscard]] inline auto fixed_2d(Args&&... args)
121  -> std::unique_ptr<Fixed_2d<Widget_t>>
122 {
123  return std::make_unique<Fixed_2d<Widget_t>>(std::forward<Args>(args)...);
124 }
125 
126 } // namespace ox
127 #endif // TERMOX_WIDGET_LAYOUT_FIXED_HPP
Definition: fixed.hpp:106
Fixed offset before and after Widget_t object.
Definition: fixed.hpp:14
Defines how a Layout should resize a Widget in one length Dimension.
Definition: size_policy.hpp:11
static constexpr auto maximum_max
Largest possible value for max().
Definition: size_policy.hpp:26
Definition: widget.hpp:31