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