1 #ifndef TERMOX_WIDGET_LAYOUTS_DETAIL_LINEAR_LAYOUT_HPP
2 #define TERMOX_WIDGET_LAYOUTS_DETAIL_LINEAR_LAYOUT_HPP
5 #include <termox/system/event.hpp>
6 #include <termox/widget/layout.hpp>
7 #include <termox/widget/size_policy.hpp>
9 #include "shared_space.hpp"
10 #include "unique_space.hpp"
12 namespace ox::layout::detail {
14 template <
typename Get_policy_t,
typename Get_length_t,
typename Get_offset_t>
16 using get_policy = Get_policy_t;
17 using get_length = Get_length_t;
18 using get_offset = Get_offset_t;
21 template <
typename Primary_t,
26 using Primary = Primary_t;
27 using Secondary = Secondary_t;
28 using get_area = Get_area_t;
29 using get_point = Get_point_t;
34 template <
typename Child,
typename Parameters>
37 using Child_t = Child;
42 template <
typename UnaryPredicate>
43 using enable_if_invocable = std::enable_if_t<
44 std::is_invocable_v<UnaryPredicate,
45 std::add_lvalue_reference_t<Child_t>>,
57 [[nodiscard]]
auto remove_child(Child_t
const* child)
58 -> std::unique_ptr<Widget>
61 this->reset_offset_if_out_of_bounds();
67 template <
typename UnaryPredicate,
68 typename = enable_if_invocable<UnaryPredicate>>
70 -> std::unique_ptr<Widget>
73 std::forward<UnaryPredicate>(predicate));
74 this->reset_offset_if_out_of_bounds();
81 -> std::unique_ptr<Widget>
84 this->reset_offset_if_out_of_bounds();
93 this->reset_offset_if_out_of_bounds();
99 template <
typename UnaryPredicate,
100 typename = enable_if_invocable<UnaryPredicate>>
104 std::forward<UnaryPredicate>(predicate));
105 this->reset_offset_if_out_of_bounds();
114 this->reset_offset_if_out_of_bounds();
126 template <
typename Fn>
129 std::stable_sort(std::begin(Base_t::children_),
130 std::end(Base_t::children_),
131 [&compare](
auto const& a,
auto const& b) {
132 return compare(
static_cast<Child_t const&
>(*a),
133 static_cast<Child_t const&
>(*b));
135 this->resize_and_move_children();
143 Widget::child_offset_ = index;
144 shared_space_.set_offset(index);
145 unique_space_.set_offset(index);
151 void decrement_offset()
159 void increment_offset()
168 using Parameters_t = Parameters;
173 this->resize_and_move_children();
184 auto move_event(Point new_position, Point old_position) ->
bool override
186 this->resize_and_move_children();
192 this->resize_and_move_children();
198 this->resize_and_move_children();
204 this->resize_and_move_children();
210 this->resize_and_move_children();
215 using Length_list = std::vector<int>;
216 using Position_list = std::vector<int>;
222 void resize_and_move_children()
229 assert(ox::is_valid(child.width_policy) &&
230 ox::is_valid(child.height_policy));
234 auto const primary_lengths = shared_space_.calculate_lengths(*
this);
235 auto const primary_pos =
238 auto const secondary_lengths = unique_space_.calculate_lengths(*
this);
239 auto const secondary_pos =
240 unique_space_.calculate_positions(secondary_lengths);
242 this->send_enable_disable_events(primary_lengths, secondary_lengths);
243 this->send_resize_events(primary_lengths, secondary_lengths);
244 this->send_move_events(primary_pos, secondary_pos);
248 void send_enable_disable_events(Length_list
const& primary,
249 Length_list
const& secondary)
253 for (
auto i = 0uL; i < offset; ++i)
255 for (
auto i = 0uL; i < primary.size(); ++i) {
256 auto& child = children[offset + i];
257 if (is_valid(primary[i], secondary[i]))
264 void send_resize_events(Length_list
const& primary,
265 Length_list
const& secondary)
269 for (
auto i = 0uL; i < primary.size(); ++i) {
270 auto& child = children[offset + i];
272 typename Parameters::get_area{}(primary[i], secondary[i]);
277 void send_move_events(Position_list
const& primary,
278 Position_list
const& secondary)
282 auto const primary_offset =
283 typename Parameters::Primary::get_offset{}(*this);
284 auto const secondary_offset =
285 typename Parameters::Secondary::get_offset{}(*this);
286 for (
auto i = 0uL; i < primary.size(); ++i) {
287 auto& child = children[offset + i];
288 auto const point =
typename Parameters::get_point{}(
289 primary[i] + primary_offset, secondary[i] + secondary_offset);
299 [[nodiscard]]
static auto is_valid(std::size_t primary,
300 std::size_t secondary) ->
bool
302 return primary != 0 && secondary != 0;
306 void reset_offset_if_out_of_bounds()
static void post_event(Event e)
Append the event to the Event_queue for the thread it was called on.
Definition: system.cpp:112
Provided as a uniform interface for arranging child Widgets.
Definition: layout.hpp:23
auto remove_and_delete_child_if(UnaryPredicate &&predicate) -> bool
Erase first element that satisfies pred.
Definition: layout.hpp:168
auto get_children()
Return a View of all children.
Definition: layout.hpp:56
auto remove_child(Child_t const *child) -> std::unique_ptr< Widget >
Removes and returns the child pointed to by child.
Definition: layout.hpp:118
auto remove_and_delete_child_at(std::size_t index) -> bool
Removes the child at index and sends a Delete_event to it.
Definition: layout.hpp:180
auto remove_and_delete_child(Child_t const *child) -> bool
Removes the child with given pointer and sends a Delete_event to it.
Definition: layout.hpp:155
auto remove_child_at(std::size_t index) -> std::unique_ptr< Widget >
Removes and returns the child at index in the child container.
Definition: layout.hpp:143
void delete_all_children()
Removes all children and sends Delete_events to each.
Definition: layout.hpp:190
auto remove_child_if(UnaryPredicate &&predicate) -> std::unique_ptr< Widget >
Removes and returns the first child where predicate(child) returns true.
Definition: layout.hpp:133
Lays out Widgets in 2D, sharing space in a primary dimension.
Definition: linear_layout.hpp:35
auto remove_and_delete_child_at(std::size_t index) -> bool
Removes the child at index and sends a Delete_event to it.
Definition: linear_layout.hpp:111
auto disable_event() -> bool override
Handles Disable_event objects.
Definition: linear_layout.hpp:177
auto child_removed_event(Widget &child) -> bool override
Handles Child_removed_event objects.
Definition: linear_layout.hpp:202
auto resize_event(Area new_size, Area old_size) -> bool override
Handles Resize_event objects.
Definition: linear_layout.hpp:190
auto remove_child_if(UnaryPredicate &&predicate) -> std::unique_ptr< Widget >
Removes and returns the first child where predicate(child) returns true.
Definition: linear_layout.hpp:69
void set_child_offset(std::size_t index)
Sets the child Widget offset, does not do bounds checking.
Definition: linear_layout.hpp:140
auto remove_and_delete_child(Child_t const *child) -> bool
Removes the child with given pointer and sends a Delete_event to it.
Definition: linear_layout.hpp:90
void sort(Fn compare)
Sort children by the given comparison function.
Definition: linear_layout.hpp:127
void delete_all_children()
Removes all children and sends Delete_events to each.
Definition: linear_layout.hpp:119
auto child_added_event(Widget &child) -> bool override
Handles Child_added_event objects.
Definition: linear_layout.hpp:196
auto move_event(Point new_position, Point old_position) -> bool override
Handles Move_event objects.
Definition: linear_layout.hpp:184
auto remove_child_at(std::size_t index) -> std::unique_ptr< Widget >
Removes and returns the child at index in the child container.
Definition: linear_layout.hpp:80
auto child_polished_event(Widget &child) -> bool override
Handles Child_polished_event objects.
Definition: linear_layout.hpp:208
auto enable_event() -> bool override
Handles Enable_event objects.
Definition: linear_layout.hpp:171
auto remove_and_delete_child_if(UnaryPredicate &&predicate) -> bool
Erase first element that satisfies pred.
Definition: linear_layout.hpp:101
Divides up space between child Widgets where all Widgets share the length.
Definition: shared_space.hpp:15
auto calculate_positions(Length_list const &lengths) -> Position_list
Returns local primary dimension positions, starting at zero.
Definition: shared_space.hpp:45
Gives space to child Widgets where each gets full use of the length.
Definition: unique_space.hpp:13
Definition: linear_layout.hpp:15
Definition: linear_layout.hpp:25