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 }