1 #ifndef TERMOX_WIDGET_LAYOUT_HPP
2 #define TERMOX_WIDGET_LAYOUT_HPP
10 #include <termox/common/transform_view.hpp>
11 #include <termox/system/event.hpp>
12 #include <termox/system/system.hpp>
13 #include <termox/widget/area.hpp>
14 #include <termox/widget/point.hpp>
15 #include <termox/widget/widget.hpp>
17 namespace ox::layout {
22 template <
typename Child = W
idget>
25 using Child_t = Child;
28 std::vector<std::unique_ptr<Child_t>> children;
31 static_assert(std::is_base_of_v<Widget, Child_t>,
32 "Layout: Child type must be a Widget type.");
35 template <
typename UnaryPredicate>
36 using enable_if_invocable = std::enable_if_t<
37 std::is_invocable_v<UnaryPredicate,
38 std::add_lvalue_reference_t<Child_t>>,
42 template <
typename... Widgets>
43 Layout(std::unique_ptr<Widgets>... children)
48 Layout(Parameters parameters)
50 for (
auto& child : parameters.children)
58 auto constexpr downcast = [](
auto& widg_ptr) -> Child_t& {
59 return static_cast<Child_t&
>(*widg_ptr);
67 auto constexpr downcast = [](
auto const& widg_ptr) -> Child_t
const& {
68 return static_cast<Child_t const&
>(*widg_ptr);
77 template <
typename W
idget_t>
81 static_assert(std::is_base_of_v<Child_t, Widget_t>,
82 "Layout::insert: Widget_t must be a Child_t type");
85 children_.emplace(this->iter_at(index), std::move(w));
86 inserted.set_parent(
this);
94 template <
typename W
idget_t>
102 template <
typename Widget_t = Child_t,
typename... Args>
106 std::make_unique<Widget_t>(std::forward<Args>(args)...));
110 template <
typename W
idget_t = Child_t>
111 auto make_child(
typename Widget_t::Parameters p) -> Widget_t&
113 return this->
append_child(std::make_unique<Widget_t>(std::move(p)));
119 -> std::unique_ptr<Widget>
121 auto const at = this->find_iter(child);
122 if (at == std::end(children_))
124 auto removed = this->iter_remove(at);
125 this->uninitialize(*removed);
131 template <
typename UnaryPredicate,
132 typename = enable_if_invocable<UnaryPredicate>>
134 -> std::unique_ptr<Widget>
137 this->
find_child_if(std::forward<UnaryPredicate>(predicate));
144 -> std::unique_ptr<Widget>
148 auto removed = this->iter_remove(this->iter_at(index));
149 this->uninitialize(*removed);
158 if (removed ==
nullptr)
166 template <
typename UnaryPredicate,
167 typename = enable_if_invocable<UnaryPredicate>>
171 this->
find_child_if(std::forward<UnaryPredicate>(predicate));
172 if (found ==
nullptr)
183 if (removed ==
nullptr)
199 std::iter_swap(this->iter_at(index_a), this->iter_at(index_b));
207 template <
typename UnaryPredicate>
213 std::find_if(std::cbegin(view), std::cend(view),
214 std::forward<UnaryPredicate>(predicate));
215 return found == std::cend(view) ? nullptr : std::addressof(*found);
221 template <
typename UnaryPredicate>
226 std::find_if(std::begin(view), std::end(view),
227 std::forward<UnaryPredicate>(predicate));
228 return found == std::end(view) ? nullptr : std::addressof(*found);
235 [&](Child_t
const& w) {
return w.name() ==
name; });
243 [&](Child_t
const& w) {
return w.name() ==
name; });
250 auto const found = std::find_if(
251 std::cbegin(children_), std::cend(children_),
252 [w](std::unique_ptr<Widget>
const& x) {
return x.get() == w; });
253 if (found == std::cend(children_))
255 return std::distance(std::cbegin(children_), found);
261 auto const begin = std::cbegin(children_);
262 auto const end = std::cend(children_);
263 return std::find_if(begin, end, [w](
auto const& w_ptr) {
264 return w_ptr.get() == w;
274 return std::find(std::begin(d), std::end(d), descendant) != std::end(d);
294 [[nodiscard]]
auto iter_at(std::size_t index) -> Children_t::iterator
296 return std::next(std::begin(children_), index);
300 [[nodiscard]]
auto iter_at(std::size_t index)
const
301 -> Children_t::const_iterator
303 return std::next(std::cbegin(children_), index);
307 [[nodiscard]]
auto is_target(Child_t
const* target)
309 return [target](std::unique_ptr<Widget>
const& w) ->
bool {
310 return w.get() == target;
315 [[nodiscard]]
auto find_iter(Child_t
const* w)
const
316 -> Children_t::const_iterator
318 return std::find_if(std::cbegin(children_), std::cend(children_),
323 [[nodiscard]]
auto find_iter(Child_t
const* w) -> Children_t::iterator
325 return std::find_if(std::begin(children_), std::end(children_),
330 [[nodiscard]]
auto iter_remove(Children_t::iterator at)
331 -> std::unique_ptr<Widget>
333 auto removed = std::move(*at);
339 void uninitialize(
Widget& w)
343 w.set_parent(
nullptr);
347 [[nodiscard]]
auto is_layout_type() const ->
bool final
override
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 find_child_by_name(std::string const &name) -> Child_t *
Find a child widget by name, returns nullptr if not found.
Definition: layout.hpp:232
void update() final override
Post a paint event to this Widget.
Definition: layout.hpp:277
auto contains_child(Widget const *w) const -> bool
Returns true if w is a child of *this.
Definition: layout.hpp:259
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 contains_descendant(Widget const *descendant) const -> bool
Returns true if descendant is a child or some other child's child etc.
Definition: layout.hpp:270
void swap_children(std::size_t index_a, std::size_t index_b)
Swap two child widgets, no index range check.
Definition: layout.hpp:197
auto find_child_position(Widget const *w) const -> std::size_t
Finds the index of the given child pointer in the child container.
Definition: layout.hpp:248
auto find_child_if(UnaryPredicate &&predicate) const -> Child_t const *
Find first child satisfying predicate.
Definition: layout.hpp:208
auto insert_child(std::unique_ptr< Widget_t > w, std::size_t index) -> Widget_t &
Inserts w at index, sending child added event to *this.
Definition: layout.hpp:78
auto find_child_if(UnaryPredicate &&predicate) -> Child_t *
Find first child satisfying predicate.
Definition: layout.hpp:222
auto get_children() const
Return a const View of all children.
Definition: layout.hpp:65
auto make_child(Args &&... args) -> Widget_t &
Create a Widget and append it to the child container.
Definition: layout.hpp:103
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 find_child_by_name(std::string const &name) const -> Child_t const *
Find a child widget by name, returns nullptr if not found.
Definition: layout.hpp:239
auto make_child(typename Widget_t::Parameters p) -> Widget_t &
Helper so Parameters type does not have to be specified at call site.
Definition: layout.hpp:111
auto append_child(std::unique_ptr< Widget_t > w) -> Widget_t &
Move w to the end of the child container. Forwards to insert_child()
Definition: layout.hpp:95
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
Definition: layout.hpp:286
Definition: layout.hpp:280
Definition: layout.hpp:27