displayLayout and Rendering TUI library | 
          
| git clone git://git.dimitrijedobrota.com/display.git | 
| Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING | 
| commit | 714563ba3fb520f00631d52a401213ddd47e887b | 
| parent | 89e5b7529d229b077ff679fef4d702996a09b7a1 | 
| author | Dimitrije Dobrota < mail@dimitrijedobrota.com > | 
| date | Thu, 20 Feb 2025 19:39:09 +0100 | 
Proper, 4-way, corners for LayoutRigidBorder
| M | CMakeLists.txt | | | + - | 
| M | example/example.cpp | | | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -------- | 
| M | include/display/layout_rigid.hpp | | | +++++++++++++ ----------- | 
3 files changed, 75 insertions(+), 20 deletions(-)
diff --git a/ CMakeLists.txt b/ CMakeLists.txt
          @@ -4,7 +4,7 @@ 
          include(cmake/prelude.cmake)
        
        
          project(
              display
              VERSION 0.1.35
              VERSION 0.1.36
              DESCRIPTION "TUI library"
              HOMEPAGE_URL "git://git.dimitrijedobrota.com/display.git"
              LANGUAGES CXX
        
        diff --git a/ example/example.cpp b/ example/example.cpp
          @@ -57,9 +57,33 @@ 
          public:
        
        
          class LayoutRigidBorder : public LayoutRigid<LayoutCustom>
          {
          public:
            LayoutRigidBorder(place_t aplc, layout_t layout)
                : LayoutRigid<LayoutCustom>(aplc, std::move(layout))
            LayoutRigidBorder(place_t aplc, const layout_t& layout)
                : LayoutRigid<LayoutCustom>(aplc, layout)
            {
              auto [m, n] = get_grid();
              const auto valid = [&](std::size_t xpos, std::size_t ypos)
              { return xpos >= 0 && xpos < n && ypos >= 0 && ypos < m; };
              const auto get = [&](std::size_t xpos, std::size_t ypos) -> std::uint8_t
              { return valid(xpos, ypos) ? layout[xpos][ypos] : 0xFF; };
              for (std::size_t i = 0; i <= n; i++) {
                for (std::size_t j = 0; j <= m; j++) {
                  const std::uint8_t ptl = get(i - 1, j - 1);
                  const std::uint8_t ptr = get(i - 1, j);
                  const std::uint8_t pbl = get(i, j - 1);
                  const std::uint8_t pbr = get(i, j);
                  uint8_t mask = 0;
                  mask |= ((ptl != ptr) ? 1U : 0U) << 0U;  // Top
                  mask |= ((ptr != pbr) ? 1U : 0U) << 1U;  // Right
                  mask |= ((pbr != pbl) ? 1U : 0U) << 2U;  // Bottom
                  mask |= ((pbl != ptl) ? 1U : 0U) << 3U;  // Left
                  m_corners.emplace_back(mask, i, j);
                }
              }
            }
            template<class... Args>
        
        
          @@ -84,13 +108,11 @@ 
          public:
        
        
              for (std::size_t i = 0; i < size(); i++) {
                const auto [pos, dim] = LayoutRigid<LayoutCustom>::place(i);
                set_cursor(pos.y, pos.x);
                set_cursor(pos.y, pos.x + 1);
                std::cout << "┌";
                for (sz_t j = 1; j < dim.width; j++) {
                  std::cout << "─";
                }
                std::cout << "┐";
                for (sz_t j = pos.y + 1; j < pos.y + dim.height; j++) {
                  set_cursor(j, pos.x) << "│";
        
        
          @@ -101,12 +123,20 @@ 
          public:
        
        
                set_cursor(i, axpos() + awth() - 1) << "│";
              }
              set_cursor(aypos() + ahgt() - 1, axpos());
              std::cout << "└";
              set_cursor(aypos() + ahgt() - 1, axpos() + 1);
              for (sz_t i = 2; i < awth(); i++) {
                std::cout << "─";
              }
              std::cout << "┘";
              auto [m, n] = get_grid();
              const auto [w, h] = adim();
              const sz_t unw = w / m;
              const sz_t unh = h / n;
              for (const auto [mask, xpos, ypos] : m_corners) {
                const sz_t xloc = xpos != n ? xpos * unw : axpos() + w;
                const sz_t yloc = ypos != m ? ypos * unh : aypos() + h;
                set_cursor(yloc, xloc) << corner_t::lookup[mask];  // NOLINT
              };
              std::cout << std::flush;
            }
        
        
          @@ -127,6 +157,29 @@ 
          private:
        
        
              return {pos + pos_t(1, 1), dim - sub};
            }
            struct corner_t
            {
              // clang-format off
              constexpr static const char* lookup[] = { // NOLINT
          		"", "", "", "└", "", "│", "┌", "├",
                  "", "┘", "─", "┴", "┐", "┤", "┬", "┼"
          	};
              // clang-format on
              corner_t(std::uint8_t mask, sz_t ypos, sz_t xpos)  // NOLINT
                  : mask(mask)
                  , x(xpos)
                  , y(ypos)
              {
              }
              std::uint8_t mask;
              sz_t x;
              sz_t y;
            };
            std::vector<corner_t> m_corners;
          };
          }  // namespace
        
        diff --git a/ include/display/layout_rigid.hpp b/ include/display/layout_rigid.hpp
          @@ -58,7 +58,8 @@ 
          protected:
        
        
              return {this->apos() + start, dim};
            }
            const auto& get_record(std::size_t idx) { return m_recs[idx]; }
            const auto& get_record(std::size_t idx) const { return m_recs[idx]; }
            auto get_grid() const { return m_grid; }
            struct record_t
            {
        
        
          @@ -82,8 +83,7 @@ 
          LayoutRigid<T>::LayoutRigid(place_t aplc, layout_t layout)
        
        
                       static_cast<sz_t>(layout.size()))
              , m_recs(count_and_pad(layout))
          {
            static const auto& insert =
                [](sz_t& count, std::uint8_t cnt, sz_t& pos, std::uint8_t total)
            static const auto& insert = [](sz_t& count, sz_t cnt, sz_t& pos, sz_t total)
            {
              if (count != 0 && (pos != total || count != cnt)) {
                throw std::runtime_error("Invalid layout [Shape]");
        
        
          @@ -97,11 +97,13 @@ 
          LayoutRigid<T>::LayoutRigid(place_t aplc, layout_t layout)
        
        
              count = cnt;
            };
            for (std::size_t i = 0U; i < m_grid.height; i++) {
              uint8_t cnt = 1;
            static const sz_t one = 1;
            for (sz_t i = 0U; i < m_grid.height; i++) {
              sz_t cnt = 1;
              m_recs[layout[i][m_grid.width - 1]].addw = true;
              for (std::size_t j = 0U; j < m_grid.width; j++) {
              for (sz_t j = 0U; j < m_grid.width; j++) {
                const auto crnt = layout[i][j];
                if (crnt == layout[i][j + 1]) {
        
        
          @@ -109,16 +111,16 @@ 
          LayoutRigid<T>::LayoutRigid(place_t aplc, layout_t layout)
        
        
                  continue;
                }
                insert(m_recs[crnt].dim.width, cnt, m_recs[crnt].start.x, j - cnt + 1);
                insert(m_recs[crnt].dim.width, cnt, m_recs[crnt].start.x, j - cnt + one);
                cnt = 1;
              }
            }
            for (std::size_t j = 0U; j < m_grid.width; j++) {
              uint8_t cnt = 1;
            for (sz_t j = 0U; j < m_grid.width; j++) {
              sz_t cnt = 1;
              m_recs[layout[m_grid.height - 1][j]].addh = true;
              for (std::size_t i = 0U; i < m_grid.height; i++) {
              for (sz_t i = 0U; i < m_grid.height; i++) {
                const auto crnt = layout[i][j];
                if (crnt == layout[i + 1][j]) {
        
        
          @@ -126,7 +128,7 @@ 
          LayoutRigid<T>::LayoutRigid(place_t aplc, layout_t layout)
        
        
                  continue;
                }
                insert(m_recs[crnt].dim.height, cnt, m_recs[crnt].start.y, i - cnt + 1);
                insert(m_recs[crnt].dim.height, cnt, m_recs[crnt].start.y, i - cnt + one);
                cnt = 1;
              }
            }