displayLayout 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 (6054B)
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 display; // NOLINT
13 class WindowCustom : public WindowPivot
14 {
15 public:
16 explicit WindowCustom(plc_t aplc, piv_t piv, dim_t dim)
17 : WindowPivot(aplc, pad_t(0, 0), piv, dim)
18 {
19 }
21 void render() const override
22 {
23 static int color_red = 0;
25 color_red = (color_red + 25) % 256;
26 std::cout << alec::background(color_red, 65, 65);
28 line_reset();
29 for (auto i = hgt_t(0); i < hgt(); i++) {
30 line_empty();
31 }
33 std::cout << alec::background_v<alec::Color::DEFAULT>;
34 std::cout << std::flush;
35 }
36 };
38 class LayoutCustom : public LayoutRigid<Layout<WindowCustom>>
39 {
40 public:
41 explicit LayoutCustom(plc_t aplc)
42 : LayoutRigid(aplc, {{0, 1, 2}, {7, 8, 3}, {6, 5, 4}})
43 {
44 emplace().emplace_child(piv_t(PvtX::Left, PvtY::Top), dim_t(12, 4));
45 emplace().emplace_child(piv_t(PvtX::Center, PvtY::Top), dim_t(12, 4));
46 emplace().emplace_child(piv_t(PvtX::Right, PvtY::Top), dim_t(12, 4));
47 emplace().emplace_child(piv_t(PvtX::Right, PvtY::Center), dim_t(12, 4));
48 emplace().emplace_child(piv_t(PvtX::Right, PvtY::Bottom), dim_t(12, 4));
49 emplace().emplace_child(piv_t(PvtX::Center, PvtY::Bottom), dim_t(12, 4));
50 emplace().emplace_child(piv_t(PvtX::Left, PvtY::Bottom), dim_t(12, 4));
51 emplace().emplace_child(piv_t(PvtX::Left, PvtY::Center), dim_t(12, 4));
52 emplace().emplace_child(piv_t(PvtX::Center, PvtY::Center), dim_t(12, 4));
53 }
54 };
56 class LayoutRigidBorder : public LayoutRigid<LayoutCustom>
57 {
58 public:
59 LayoutRigidBorder(plc_t aplc, const layout_t& layout)
60 : LayoutRigid<LayoutCustom>(aplc, layout)
61 {
62 const auto [m, n] = get_grid();
64 const auto valid = [&](std::size_t xpos, std::size_t ypos)
65 { return xpos < n && ypos < m; };
67 const auto get = [&](std::size_t xpos, std::size_t ypos) -> std::uint8_t
68 { return valid(xpos, ypos) ? layout[xpos][ypos] : 0xFF; };
70 for (std::size_t i = 0; i <= n; i++) {
71 for (std::size_t j = 0; j <= m; j++) {
72 const std::uint8_t ptl = get(i - 1, j - 1);
73 const std::uint8_t ptr = get(i - 1, j);
74 const std::uint8_t pbl = get(i, j - 1);
75 const std::uint8_t pbr = get(i, j);
77 uint8_t mask = 0;
78 mask |= static_cast<uint8_t>(((ptl != ptr) ? 1U : 0U) << 0U); // Top
79 mask |= static_cast<uint8_t>(((ptr != pbr) ? 1U : 0U) << 1U); // Right
80 mask |= static_cast<uint8_t>(((pbr != pbl) ? 1U : 0U) << 2U); // Bottom
81 mask |= static_cast<uint8_t>(((pbl != ptl) ? 1U : 0U) << 3U); // Left
83 m_corners.emplace_back(mask, wth_t(j), hgt_t(i));
84 }
85 }
86 }
88 template<class... Args>
89 LayoutCustom& emplace(Args&&... args)
90 {
91 return LayoutMulti<LayoutCustom>::template emplace<LayoutCustom>(
92 place(size()), std::forward<Args>(args)...);
93 }
95 void resize(plc_t aplc) override
96 {
97 LayoutRigid<LayoutCustom>::resize(aplc);
99 for (std::size_t i = 0; i < size(); i++) {
100 get(i).resize(place(i));
101 }
102 }
104 void render() const override
105 {
106 LayoutRigid<LayoutCustom>::render();
107 for (std::size_t i = 0; i < size(); i++) {
108 const auto [pos, dim] = LayoutRigid<LayoutCustom>::place(i);
110 // Top of each element
111 set_cursor(pos.x + 1, pos.y);
112 for (auto j = wth_t(1); j < dim.width; j++) {
113 std::cout << "─";
114 }
116 // Left of each element
117 for (auto j = pos.y + 1; j < pos.y + dim.height; j++) {
118 set_cursor(pos.x, j) << "│";
119 }
120 }
122 // Right of the layout
123 for (auto j = aypos() + 1; j < aypos() + ahgt(); j++) {
124 set_cursor(axpos() + awth() - 1, j) << "│";
125 }
127 // Bottom of the layout
128 set_cursor(axpos() + 1, aypos() + ahgt() - 1);
129 for (auto i = wth_t(2); i < awth(); i++) {
130 std::cout << "─";
131 }
133 const auto [m, n] = get_grid();
134 const auto [w, h] = adim();
135 const auto unw = w / m;
136 const auto unh = h / n;
137 for (const auto [mask, wth, hgt] : m_corners) {
138 const auto xloc = wth != m ? xpos_t((wth * unw).value()) : axpos() + w;
139 const auto yloc = hgt != n ? ypos_t((hgt * unh).value()) : aypos() + h;
140 set_cursor(xloc, yloc) << corner_t::lookup[mask]; // NOLINT
141 };
143 std::cout << std::flush;
144 }
146 private:
147 plc_t place(std::size_t idx)
148 {
149 const auto [pos, dim] = LayoutRigid<LayoutCustom>::place(idx);
150 dim_t sub = {1, 1};
152 if (get_record(idx).addw) {
153 sub.width += 1;
154 }
156 if (get_record(idx).addh) {
157 sub.height += 1;
158 }
160 return {pos + pos_t(1, 1), dim - sub};
161 }
163 struct corner_t
164 {
165 // clang-format off
166 constexpr static const char* lookup[] = { // NOLINT
167 "", "", "", "└", "", "│", "┌", "├",
168 "", "┘", "─", "┴", "┐", "┤", "┬", "┼"
169 };
170 // clang-format on
172 corner_t(std::uint8_t maskv, wth_t wigth, hgt_t height) // NOLINT
173 : mask(maskv)
174 , wth(wigth)
175 , hgt(height)
176 {
177 }
179 std::uint8_t mask;
180 wth_t wth;
181 hgt_t hgt;
182 };
184 std::vector<corner_t> m_corners;
185 };
187 } // namespace
189 int main()
190 {
191 try {
192 using namespace display; // NOLINT
194 auto& display = Display::display();
196 // clang-format off
197 const LayoutRigid<>::layout_t split = {
198 {1, 1, 2},
199 {0, 4, 2},
200 {3, 4, 2},
201 };
202 // clang-format on
204 auto& layout = display.layout().emplace_child<LayoutRigidBorder>(split);
205 layout.emplace();
206 layout.emplace();
207 layout.emplace();
208 layout.emplace();
209 layout.emplace();
211 display.render();
212 while (true) {
213 const auto evnt = display.get_event();
214 if (evnt.type() == event::Type::RESIZE) {
215 std::cout << alec::erase_display_v<alec::Motion::WHOLE>;
216 display.render();
217 continue;
218 }
220 if (evnt.type() == event::Type::KEY && evnt.key() == 'q') {
221 break;
222 }
223 }
224 } catch (std::exception& err) {
225 std::cout << err.what() << '\n' << std::flush;
226 }
228 return 0;
229 }