display

Layout and Rendering TUI library
git clone git://git.dimitrijedobrota.com/display.git
Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING

example.cpp (6350B)


0 #include <iostream>
2 #include <alec/alec.hpp>
4 #include "display/display.hpp"
5 #include "display/layout_rigid.hpp"
6 #include "display/window_pivot.hpp"
8 namespace
9 {
11 using namespace based::literals; // NOLINT(*namespace*)
13 using namespace display; // NOLINT(*namespace*)
14 using namespace based::literals; // NOLINT(*namespace*)
16 class WindowCustom : public WindowPivot
17 {
18 public:
19 explicit WindowCustom(plc_t aplc, piv_t piv, dim_t dim)
20 : WindowPivot(aplc, pad_t(0_w, 0_h), piv, dim)
21 {
22 }
24 void render() const override
25 {
26 static constexpr based::u8 inc = 0_u8;
27 static constexpr based::u8 mod = 256_u8;
28 static constexpr based::u8 color_green = 0_u8;
29 static constexpr based::u8 color_blue = 0_u8;
30 static based::u8 color_red = 0_u8;
32 color_red = (color_red + inc) % mod;
33 std::cout << alec::background(
34 color_red.value, color_green.value, color_blue.value
35 );
37 line_reset();
38 for (auto i = 0_h; i < hgt(); ++i) {
39 line_empty();
40 }
42 std::cout << alec::background_v<alec::color::def>;
43 std::cout << std::flush;
44 }
45 };
47 class LayoutCustom : public LayoutRigid<Layout<WindowCustom>>
48 {
49 public:
50 explicit LayoutCustom(plc_t aplc)
51 // NOLINTNEXTLINE(*magic*)
52 : LayoutRigid(aplc, {{0, 1, 2}, {7, 8, 3}, {6, 5, 4}})
53 {
54 using x = piv_t::x;
55 using y = piv_t::y;
57 const dim_t dim(12_w, 4_h);
59 append().set_child(piv_t(x::left, y::top), dim);
60 append().set_child(piv_t(x::center, y::top), dim);
61 append().set_child(piv_t(x::right, y::top), dim);
62 append().set_child(piv_t(x::right, y::center), dim);
63 append().set_child(piv_t(x::right, y::bottom), dim);
64 append().set_child(piv_t(x::center, y::bottom), dim);
65 append().set_child(piv_t(x::left, y::bottom), dim);
66 append().set_child(piv_t(x::left, y::center), dim);
67 append().set_child(piv_t(x::center, y::center), dim);
68 }
69 };
71 class LayoutRigidBorder : public LayoutRigid<LayoutCustom>
72 {
73 public:
74 LayoutRigidBorder(plc_t aplc, const layout_t& layout)
75 : LayoutRigid<LayoutCustom>(aplc, layout)
76 {
77 const auto [m, n] = get_grid();
79 const auto valid = [&](std::size_t xpos, std::size_t ypos)
80 {
81 return xpos < n.value && ypos < m.value;
82 };
84 const auto get = [&](std::size_t xpos, std::size_t ypos) -> based::bu8
85 {
86 static constexpr auto not_found = 0xFF;
87 return valid(xpos, ypos) ? layout[xpos][ypos] : not_found;
88 };
90 for (std::size_t i = 0; i <= n.value; i++) {
91 for (std::size_t j = 0; j <= m.value; j++) {
92 const based::bu8 ptl = get(i - 1, j - 1);
93 const based::bu8 ptr = get(i - 1, j);
94 const based::bu8 pbl = get(i, j - 1);
95 const based::bu8 pbr = get(i, j);
97 based::bu8 mask = 0;
98 mask |= ((ptl != ptr) ? 1U : 0U); // Top
99 mask |= ((ptr != pbr) ? 1U : 0U) << 1U; // Right
100 mask |= ((pbr != pbl) ? 1U : 0U) << 2U; // Bottom
101 mask |= ((pbl != ptl) ? 1U : 0U) << 3U; // Left
103 m_corners.emplace_back(mask, wth_t(j), hgt_t(i));
108 template<class... Args>
109 LayoutCustom& append(Args&&... args)
111 return LayoutMulti<LayoutCustom>::template append<LayoutCustom>(
112 place(size()), std::forward<Args>(args)...
113 );
116 void resize(plc_t aplc) override
118 LayoutRigid<LayoutCustom>::resize(aplc);
120 for (std::size_t i = 0; i < size(); i++) {
121 get(i).resize(place(i));
125 void render() const override
127 LayoutRigid<LayoutCustom>::render();
128 for (std::size_t i = 0; i < size(); i++) {
129 const auto [pos, dim] = LayoutRigid<LayoutCustom>::place(i);
131 // Top of each element
132 set_cursor(pos.x + 1_x, pos.y);
133 for (auto j = 1_w; j < dim.width; ++j) {
134 std::cout << "─";
137 // Left of each element
138 for (auto j = pos.y + 1_y; j < pos.y + dim.height; ++j) {
139 set_cursor(pos.x, j) << "│";
143 // Right of the layout
144 for (auto j = aypos() + 1_y; j < aypos() + ahgt(); ++j) {
145 set_cursor(axpos() + awth() - 1_w, j) << "│";
148 // Bottom of the layout
149 set_cursor(axpos() + 1_x, aypos() + ahgt() - 1_h);
150 for (auto i = 2_w; i < awth(); ++i) {
151 std::cout << "─";
154 const auto [m, n] = get_grid();
155 const auto [w, h] = adim();
156 const auto unw = w / m;
157 const auto unh = h / n;
158 for (const auto [mask, wth, hgt] : m_corners) {
159 const auto xloc = wth != m ? xpos_t((wth * unw).value) : axpos() + w;
160 const auto yloc = hgt != n ? ypos_t((hgt * unh).value) : aypos() + h;
161 set_cursor(xloc, yloc) << corner_t::lookup[mask]; // NOLINT
162 };
164 std::cout << std::flush;
167 private:
168 plc_t place(std::size_t idx)
170 const auto [pos, dim] = LayoutRigid<LayoutCustom>::place(idx);
171 dim_t sub = {1_w, 1_h};
173 if (get_record(idx).addw) {
174 sub.width += 1_w;
177 if (get_record(idx).addh) {
178 sub.height += 1_h;
181 return {pos + pos_t(1_x, 1_y), dim - sub};
184 struct corner_t
186 // clang-format off
187 constexpr static const char* lookup[] = { // NOLINT
188 "", "", "", "└", "", "│", "┌", "├",
189 "", "┘", "─", "┴", "┐", "┤", "┬", "┼"
190 };
191 // clang-format on
193 corner_t(based::bu8 msk, wth_t wth, hgt_t hgt) // NOLINT
194 : mask(msk)
195 , wigth(wth)
196 , height(hgt)
200 based::bu8 mask;
201 wth_t wigth;
202 hgt_t height;
203 };
205 std::vector<corner_t> m_corners;
206 };
208 } // namespace
210 int main()
212 try {
213 using namespace display; // NOLINT
215 auto& display = Display::display();
217 // clang-format off
218 const LayoutRigid<>::layout_t split = {
219 {1, 1, 2},
220 {0, 4, 2},
221 {3, 4, 2},
222 };
223 // clang-format on
225 auto& layout = display.layout().set_child<LayoutRigidBorder>(split);
226 layout.append();
227 layout.append();
228 layout.append();
229 layout.append();
230 layout.append();
232 display.render();
233 while (true) {
234 const auto evnt = display.get_event();
235 if (evnt.type() == event::type::resize) {
236 std::cout << alec::erase_display_v<alec::motion::whole>;
237 display.render();
238 continue;
241 if (evnt.type() == event::type::key && evnt.key() == 'q') {
242 break;
245 } catch (std::exception& err) {
246 std::cout << err.what() << '\n' << std::flush;
249 return 0;