1 #ifndef TERMOX_WIDGET_BORDER_DEV_HPP
2 #define TERMOX_WIDGET_BORDER_DEV_HPP
9 #include <termox/painter/color.hpp>
10 #include <termox/widget/focus_policy.hpp>
11 #include <termox/widget/layouts/horizontal.hpp>
12 #include <termox/widget/layouts/vertical.hpp>
13 #include <termox/widget/tuple.hpp>
14 #include <termox/widget/widget.hpp>
15 #include <termox/widget/widgets/tile.hpp>
22 using Wall = std::optional<Glyph>;
36 namespace ox::detail {
40 auto constexpr pipe_all(Border& b, T x) -> Border&
42 if (b.north.has_value())
44 if (b.south.has_value())
46 if (b.east.has_value())
48 if (b.west.has_value())
60 [[nodiscard]]
auto constexpr operator|(Border b, Background_color bg) -> Border
62 return detail::pipe_all(b, bg);
65 auto constexpr operator|=(Border& b, Background_color bg) -> Border&
67 return detail::pipe_all(b, bg);
70 [[nodiscard]]
auto constexpr operator|(Border b, Foreground_color fg) -> Border
72 return detail::pipe_all(b, fg);
75 auto constexpr operator|=(Border& b, Foreground_color fg) -> Border&
77 return detail::pipe_all(b, fg);
80 [[nodiscard]]
auto constexpr operator|(Border b, Traits t) -> Border
82 return detail::pipe_all(b, t);
85 auto constexpr operator|=(Border& b, Traits t) -> Border&
87 return detail::pipe_all(b, t);
91 [[nodiscard]]
auto drop_north(Border b) -> Border;
94 [[nodiscard]]
auto drop_south(Border b) -> Border;
97 [[nodiscard]]
auto drop_east(Border b) -> Border;
100 [[nodiscard]]
auto drop_west(Border b) -> Border;
103 [[nodiscard]]
auto take_north(Border b) -> Border;
106 [[nodiscard]]
auto take_south(Border b) -> Border;
109 [[nodiscard]]
auto take_east(Border b) -> Border;
112 [[nodiscard]]
auto take_west(Border b) -> Border;
116 namespace ox::border {
118 [[nodiscard]]
auto constexpr none() -> Border
120 return {std::nullopt, std::nullopt, std::nullopt, std::nullopt,
121 U
' ', U
' ', U
' ', U
' '};
124 [[nodiscard]]
auto constexpr squared() -> Border
126 return {U
'─', U
'─', U
'│', U
'│', U
'┌', U
'┐', U
'└', U
'┘'};
129 [[nodiscard]]
auto constexpr rounded() -> Border
131 return {U
'─', U
'─', U
'│', U
'│', U
'╭', U
'╮', U
'╰', U
'╯'};
134 [[nodiscard]]
auto constexpr plus_corners() -> Border
136 return {U
'─', U
'─', U
'│', U
'│', U
'+', U
'+', U
'+', U
'+'};
139 [[nodiscard]]
auto constexpr asterisk() -> Border
141 return {U
'*', U
'*', U
'*', U
'*', U
'*', U
'*', U
'*', U
'*'};
144 [[nodiscard]]
auto constexpr doubled() -> Border
146 return {U
'═', U
'═', U
'║', U
'║', U
'╔', U
'╗', U
'╚', U
'╝'};
149 [[nodiscard]]
auto constexpr bold() -> Border
151 return {U
'━', U
'━', U
'┃', U
'┃', U
'┏', U
'┓', U
'┗', U
'┛'};
154 [[nodiscard]]
auto constexpr dashed_1() -> Border
156 return {U
'╶', U
'╶', U
'╷', U
'╷', U
'┌', U
'┐', U
'└', U
'┘'};
159 [[nodiscard]]
auto constexpr bold_dashed_1() -> Border
161 return {U
'╺', U
'╺', U
'╻', U
'╻', U
'┏', U
'┓', U
'┗', U
'┛'};
164 [[nodiscard]]
auto constexpr dashed_2() -> Border
166 return {U
'╌', U
'╌', U
'╎', U
'╎', U
'┌', U
'┐', U
'└', U
'┘'};
169 [[nodiscard]]
auto constexpr bold_dashed_2() -> Border
171 return {U
'╍', U
'╍', U
'╏', U
'╏', U
'┏', U
'┓', U
'┗', U
'┛'};
174 [[nodiscard]]
auto constexpr dashed_3() -> Border
176 return {U
'┄', U
'┄', U
'┆', U
'┆', U
'┌', U
'┐', U
'└', U
'┘'};
179 [[nodiscard]]
auto constexpr bold_dashed_3() -> Border
181 return {U
'┅', U
'┅', U
'┇', U
'┇', U
'┏', U
'┓', U
'┗', U
'┛'};
184 [[nodiscard]]
auto constexpr dashed_4() -> Border
186 return {U
'┈', U
'┈', U
'┊', U
'┊', U
'┌', U
'┐', U
'└', U
'┘'};
189 [[nodiscard]]
auto constexpr bold_dashed_4() -> Border
191 return {U
'┉', U
'┉', U
'┋', U
'┋', U
'┏', U
'┓', U
'┗', U
'┛'};
194 [[nodiscard]]
auto constexpr block_1() -> Border
196 return {U
'█', U
'█', U
'█', U
'█', U
'█', U
'█', U
'█', U
'█'};
199 [[nodiscard]]
auto constexpr block_2() -> Border
201 return {U
'▓', U
'▓', U
'▓', U
'▓', U
'▓', U
'▓', U
'▓', U
'▓'};
204 [[nodiscard]]
auto constexpr block_3() -> Border
206 return {U
'▒', U
'▒', U
'▒', U
'▒', U
'▒', U
'▒', U
'▒', U
'▒'};
209 [[nodiscard]]
auto constexpr block_4() -> Border
211 return {U
'░', U
'░', U
'░', U
'░', U
'░', U
'░', U
'░', U
'░'};
214 [[nodiscard]]
auto constexpr half_block() -> Border
216 return {U
'▄' | Trait::Inverse,
218 U
'▌' | Trait::Inverse,
232 template <
typename W
idget_t,
typename Column = layout::Vertical<>>
239 template <
template <
typename>
typename Layout_t>
240 class Wall :
public Widget {
244 if constexpr (layout::is_vertical_v<Layout_t<Widget>>)
256 [[nodiscard]]
auto glyph()
const ->
Glyph
262 using HWall = Wall<layout::Horizontal>;
263 using VWall = Wall<layout::Vertical>;
268 typename Widget_t::Parameters wrapped_parameters;
278 template <
typename... Args>
282 std::forward<Args>(wrapped_args)...)},
283 border_{std::move(b)}
293 border_{
border::rounded()}
298 explicit Bordered(Parameters p)
299 : Bordered{std::move(p.
border), std::move(p.wrapped_parameters)}
307 border_{
border::rounded()}
309 static_assert(std::is_base_of<Widget, Widget_t>::value,
310 "Bordered: Widget_t must be a Widget type");
318 this->delete_all_border_pieces(border_);
320 this->build_border_pieces(border_);
332 void build_border_pieces(
Border const& b)
334 auto const left_column =
335 b.west.has_value() ? std::optional{0} : std::nullopt;
336 auto const mid_column = b.west.has_value() ? 1 : 0;
337 auto const right_column =
338 b.east.has_value() ? std::optional{mid_column + 1} : std::nullopt;
340 auto const fp = wrapped.focus_policy;
341 auto const init = [&](
auto& w) {
347 if (left_column.has_value()) {
349 this->
insert_child(std::make_unique<Column>(), *left_column);
351 if (b.north.has_value())
352 init(lc.template make_child<Corner>(b.nw_corner));
353 init(lc.template make_child<VWall>(*b.west));
354 if (b.south.has_value())
355 init(lc.template make_child<Corner>(b.sw_corner));
357 if (right_column.has_value()) {
359 this->
insert_child(std::make_unique<Column>(), *right_column);
361 if (b.north.has_value())
362 init(rc.template make_child<Corner>(b.ne_corner));
363 init(rc.template make_child<VWall>(*b.east));
364 if (b.south.has_value())
365 init(rc.template make_child<Corner>(b.se_corner));
367 if (b.north.has_value()) {
369 std::make_unique<HWall>(*b.north), 0));
371 if (b.south.has_value()) {
372 init(this->
get_children()[mid_column].
template make_child<HWall>(
378 void delete_all_border_pieces(Border b)
380 auto const left_column =
381 b.west.has_value() ? std::optional{0} : std::nullopt;
382 auto const mid_column = b.west.has_value() ? 1 : 0;
383 auto const right_column =
384 b.east.has_value() ? std::optional{mid_column + 1} : std::nullopt;
387 if (b.south.has_value()) {
388 auto const back = b.north.has_value() ? 2 : 1;
389 this->
get_children()[mid_column].remove_and_delete_child_at(back);
391 if (b.north.has_value())
392 this->
get_children()[mid_column].remove_and_delete_child_at(0);
393 if (right_column.has_value())
395 if (left_column.has_value())
405 this->build_border_pieces(border_);
410 template <
typename W
idget_t>
411 [[nodiscard]]
auto bordered(
typename Bordered<Widget_t>::Parameters p = {
413 {}}) -> std::unique_ptr<Bordered<Widget_t>>
415 return std::make_unique<Bordered<Widget_t>>(std::move(p));
419 template <
typename Widget_t,
typename... Args>
420 [[nodiscard]]
auto bordered(Border b = border::rounded(),
421 Args&&... wrapped_args)
423 return std::make_unique<Bordered<Widget_t>>(
424 std::move(b), std::forward<Args>(wrapped_args)...);
427 template <
typename W
idget_t>
428 [[nodiscard]]
auto bordered(std::unique_ptr<Widget_t> w_ptr)
429 -> std::unique_ptr<Bordered<Widget_t>>
431 return std::make_unique<Bordered<Widget_t>>(std::move(w_ptr));
Creates a Bordered widget, which wraps the template type in a Border.
Definition: bordered.hpp:233
Bordered(std::unique_ptr< Widget_t > w_ptr)
Create a border around an existing Widget.
Definition: bordered.hpp:304
sl::Signal< void()> border_set
Called on set_border(...) after the Border has been set.
Definition: bordered.hpp:275
auto border() const -> Border
Return the currenly set Border.
Definition: bordered.hpp:325
void set_border(Border b)
Set the currently used Border, updating the display.
Definition: bordered.hpp:316
static auto fixed(int hint) -> Size_policy
Fixed: hint is the only acceptable size.
Definition: size_policy.cpp:55
static void set_focus(Widget &w)
Give program focus to w.
Definition: system.cpp:39
A unit width/height Widget that can display a single Glyph.
Definition: tile.hpp:12
auto get_children()
Return a View of all children.
Definition: layout.hpp:56
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 make_child(Args &&... args) -> Widget_t &
Create a Widget and append it to the child container.
Definition: layout.hpp:103
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
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
Defines which border walls are enabled and how they are displayed.
Definition: bordered.hpp:21
Definition: bordered.hpp:266
Holds a description of a paintable tile on the screen.
Definition: glyph.hpp:11