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 | 6bd6730d2f34d6a588603fa618e21fe4080a04e6 | 
| parent | 1e00242536889538bf5d6cb1b1ba8490603481cf | 
| author | Dimitrije Dobrota < mail@dimitrijedobrota.com > | 
| date | Thu, 13 Feb 2025 12:27:17 +0100 | 
Remove callback, prefer inheritance
| M | CMakeLists.txt | | | + - | 
| M | example/example.cpp | | | ++++++++++++++++++++++++++++++++++++++++++++ -------------------------------------- | 
| M | include/display/layout.hpp | | | + - | 
| M | include/display/layout_free.hpp | | | ---------- | 
| M | include/display/layout_rigid.hpp | | | + ---- | 
| M | include/display/window_pivot.hpp | | | +++ -------- | 
| D | source/layout.cpp | | | --------------------------- | 
| M | source/layout_free.cpp | | | --------- | 
| M | source/layout_rigid.cpp | | | +++ -------- | 
| M | source/window_pivot.cpp | | | ------- | 
10 files changed, 71 insertions(+), 129 deletions(-)
diff --git a/ CMakeLists.txt b/ CMakeLists.txt
          @@ -4,7 +4,7 @@ 
          include(cmake/prelude.cmake)
        
        
          project(
              display
              VERSION 0.1.18
              VERSION 0.1.19
              DESCRIPTION "TUI library"
              HOMEPAGE_URL "https://example.com/"
              LANGUAGES CXX
        
        diff --git a/ example/example.cpp b/ example/example.cpp
@@ -10,44 +10,69 @@
namespace
          {
          void renderer(const display::WindowPivot& win, display::place_t plc)
          class WindowCustom : public display::WindowPivot
          {
            using display::place_t;
          public:
            WindowCustom(display::dim_t dim, display::piv_t piv)
                : WindowPivot(display::pos_t(), dim, piv)
            {
            }
            static int color_red = 0;
            color_red = (color_red + 25) % 256;
            void render(display::place_t plc) const override
            {
              static int color_red = 0;
              color_red = (color_red + 25) % 256;
            const auto [start, end] = plc;
              const auto [start, end] = plc;
            std::cout << alec::background(color_red, 65, 65);
            for (auto ypos = start.y; ypos < end.y; ypos++) {
              std::cout << alec::cursor_position(ypos + 1, start.x + 1);
              std::cout << std::string(end.x - start.x, ' ');
              std::cout << alec::background(color_red, 65, 65);
              for (auto ypos = start.y; ypos < end.y; ypos++) {
                std::cout << alec::cursor_position(ypos + 1, start.x + 1);
                std::cout << std::string(end.x - start.x, ' ');
              }
              std::cout << alec::background_v<alec::Color::DEFAULT>;
              std::cout << std::flush;
            }
            std::cout << alec::background_v<alec::Color::DEFAULT>;
            std::cout << std::flush;
          };
            (void)win;
          }
          void fill(display::LayoutFree& layout)
          class LayoutCustom : public display::LayoutFree
          {
            using display::pos_t, display::dim_t, display::piv_t;
            using display::PvtX, display::PvtY;
            using display::WindowPivot;
            // clang-format off
            layout.append<WindowPivot>(renderer, pos_t(), dim_t(12, 4), piv_t(PvtX::Left, PvtY::Top));
            layout.append<WindowPivot>(renderer, pos_t(), dim_t(12, 4), piv_t(PvtX::Center, PvtY::Top));
            layout.append<WindowPivot>(renderer, pos_t(), dim_t(12, 4), piv_t(PvtX::Right, PvtY::Top));
            layout.append<WindowPivot>(renderer, pos_t(), dim_t(12, 4), piv_t(PvtX::Right, PvtY::Center));
            layout.append<WindowPivot>(renderer, pos_t(), dim_t(12, 4), piv_t(PvtX::Right, PvtY::Bottom));
            layout.append<WindowPivot>(renderer, pos_t(), dim_t(12, 4), piv_t(PvtX::Center, PvtY::Bottom));
            layout.append<WindowPivot>(renderer, pos_t(), dim_t(12, 4), piv_t(PvtX::Left, PvtY::Bottom));
            layout.append<WindowPivot>(renderer, pos_t(), dim_t(12, 4), piv_t(PvtX::Left, PvtY::Center));
            layout.append<WindowPivot>(renderer, pos_t(), dim_t(12, 4), piv_t(PvtX::Center, PvtY::Center));
            // clang-format on
          }
          public:
            LayoutCustom()
            {
              using display::dim_t, display::piv_t;
              using display::PvtX, display::PvtY;
              append<WindowCustom>(dim_t(12, 4), piv_t(PvtX::Left, PvtY::Top));
              append<WindowCustom>(dim_t(12, 4), piv_t(PvtX::Center, PvtY::Top));
              append<WindowCustom>(dim_t(12, 4), piv_t(PvtX::Right, PvtY::Top));
              append<WindowCustom>(dim_t(12, 4), piv_t(PvtX::Right, PvtY::Center));
              append<WindowCustom>(dim_t(12, 4), piv_t(PvtX::Right, PvtY::Bottom));
              append<WindowCustom>(dim_t(12, 4), piv_t(PvtX::Center, PvtY::Bottom));
              append<WindowCustom>(dim_t(12, 4), piv_t(PvtX::Left, PvtY::Bottom));
              append<WindowCustom>(dim_t(12, 4), piv_t(PvtX::Left, PvtY::Center));
              append<WindowCustom>(dim_t(12, 4), piv_t(PvtX::Center, PvtY::Center));
            }
            void resize(display::dim_t dim) override
            {
              LayoutFree::resize(dim);
              const auto [width, height] = dim;
              const display::sz_t midw = width / 2;
              const display::sz_t midh = height / 2;
              get<WindowCustom>(0).pos() = {0, 0};
              get<WindowCustom>(1).pos() = {midw, 0};
              get<WindowCustom>(2).pos() = {width, 0};
              get<WindowCustom>(3).pos() = {width, midh};
              get<WindowCustom>(4).pos() = {width, height};
              get<WindowCustom>(5).pos() = {midw, height};
              get<WindowCustom>(6).pos() = {0, height};
              get<WindowCustom>(7).pos() = {0, midh};
              get<WindowCustom>(8).pos() = {midw, midh};
            }
          };
          }  // namespace
          
          @@ -57,23 +82,6 @@ 
          int main()
        
        
              using namespace std::placeholders;  // NOLINT
              using namespace display;  // NOLINT
              const auto recalc = [](LayoutFree& layout)
              {
                const auto [width, height] = layout.dim();
                const display::sz_t midw = width / 2;
                const display::sz_t midh = height / 2;
                layout.get<WindowPivot>(0).pos() = {0, 0};
                layout.get<WindowPivot>(1).pos() = {midw, 0};
                layout.get<WindowPivot>(2).pos() = {width, 0};
                layout.get<WindowPivot>(3).pos() = {width, midh};
                layout.get<WindowPivot>(4).pos() = {width, height};
                layout.get<WindowPivot>(5).pos() = {midw, height};
                layout.get<WindowPivot>(6).pos() = {0, height};
                layout.get<WindowPivot>(7).pos() = {0, midh};
                layout.get<WindowPivot>(8).pos() = {midw, midh};
              };
              auto& display = Display::display();
              // clang-format off
        
        
          @@ -84,12 +92,12 @@ 
          int main()
        
        
              };
              // clang-format on
              auto& layout = display.screen().set_layout<LayoutRigid>(split, nullptr);
              fill(layout[0].set_layout<LayoutFree>(recalc));
              fill(layout[1].set_layout<LayoutFree>(recalc));
              fill(layout[2].set_layout<LayoutFree>(recalc));
              fill(layout[3].set_layout<LayoutFree>(recalc));
              fill(layout[4].set_layout<LayoutFree>(recalc));
              auto& layout = display.screen().set_layout<LayoutRigid>(split);
              layout[0].set_layout<LayoutCustom>();
              layout[1].set_layout<LayoutCustom>();
              layout[2].set_layout<LayoutCustom>();
              layout[3].set_layout<LayoutCustom>();
              layout[4].set_layout<LayoutCustom>();
              for (display.set_resized(); true;) {
                const auto evnt = display.get_event();
        
        diff --git a/ include/display/layout.hpp b/ include/display/layout.hpp
          @@ -21,7 +21,7 @@ 
          public:
        
        
            const dim_t& dim() const { return m_dim; }
            dim_t& dim() { return m_dim; }
            virtual void resize(dim_t dim) = 0;
            virtual void resize(dim_t dim) { m_dim = dim; }
            virtual void render(pos_t pos) const = 0;
          private:
        
        diff --git a/ include/display/layout_free.hpp b/ include/display/layout_free.hpp
          @@ -14,13 +14,6 @@ 
          namespace display
        
        
          class LayoutFree : public Layout
          {
          public:
            using recalc_f = std::function<void(LayoutFree&)>;
            LayoutFree(recalc_f f_recalc)  // NOLINT
                : m_recalc(std::move(f_recalc))
            {
            }
            Window* operator[](std::size_t idx) { return m_wins[idx].get(); }
            const Window* operator[](std::size_t idx) const { return m_wins[idx].get(); }
          
          @@ -43,12 +36,9 @@ 
          public:
        
        
              return *dynamic_cast<T*>(m_wins[idx].get());
            }
            void resize(dim_t dim) override;
            void render(pos_t pos) const override;
          private:
            recalc_f m_recalc;
            std::vector<std::unique_ptr<Window>> m_wins;
          };
          diff --git a/ include/display/layout_rigid.hpp b/ include/display/layout_rigid.hpp
@@ -1,6 +1,5 @@
#pragma once
          #include <functional>
          #include <vector>
          #include "display/screen.hpp"
        
        
          @@ -12,10 +11,9 @@ 
          namespace display
        
        
          class LayoutRigid : public Layout
          {
          public:
            using recalc_f = std::function<void(LayoutRigid&)>;
            using layout_t = std::vector<std::vector<std::uint8_t>>;
            LayoutRigid(layout_t layout, recalc_f f_recalc);
            LayoutRigid(layout_t layout);  // NOLINT
            const auto& operator[](std::size_t idx) const { return m_recs[idx].screen; }
            auto& operator[](std::size_t idx) { return m_recs[idx].screen; }
        
        
          @@ -29,7 +27,6 @@ 
          private:
        
        
            std::size_t count_and_pad(layout_t& layout) const;
            recalc_f m_recalc;
            dim_t m_grid;
            struct record_t
        
        diff --git a/ include/display/window_pivot.hpp b/ include/display/window_pivot.hpp
@@ -1,5 +1,4 @@
#pragma once
          #include <functional>
          #include "display/types.hpp"
          #include "display/window.hpp"
        
        
          @@ -10,11 +9,8 @@ 
          namespace display
        
        
          class WindowPivot : public Window
          {
          public:
            using render_f = std::function<void(const WindowPivot&, place_t place)>;
            WindowPivot(render_f frender, pos_t pos, dim_t dim, piv_t piv = {})
                : m_renderer(std::move(frender))
                , m_pos(pos)
            WindowPivot(pos_t pos, dim_t dim, piv_t piv = {})
                : m_pos(pos)
                , m_dim(dim)
                , m_piv(piv)
            {
        
        
          @@ -30,10 +26,9 @@ 
          public:
        
        
            auto& piv() { return m_piv; }
            std::optional<place_t> place(dim_t bounds) override;
            void render(place_t place) const override;
            void render(place_t place) const override = 0;
          private:
            render_f m_renderer;
            pos_t m_pos;
            dim_t m_dim;
            piv_t m_piv;
        
        diff --git a/ source/layout.cpp b/ source/layout.cpp
@@ -1,27 +0,0 @@
#include "display/layout_rigid.hpp"
          namespace display
          {
          void LayoutRigid::resize(dim_t dim)
          {
            this->dim() = dim;
            const sz_t mid = this->dim().height / 2;
            m_screen1.resize({dim.width, mid});
            m_screen2.resize({dim.width, mid});
            if (m_recalc != nullptr) {
              m_recalc(*this);
            }
          }
          int LayoutRigid::render(pos_t pos) const
          {
            const sz_t mid = this->dim().height / 2;
            m_screen1.render(pos + pos_t(0, 0));
            m_screen2.render(pos + pos_t(0, mid + 1));
            return 0;
          }
          }  // namespace display
        
        diff --git a/ source/layout_free.cpp b/ source/layout_free.cpp
@@ -3,15 +3,6 @@
namespace display
          {
          void LayoutFree::resize(dim_t dim)
          {
            this->dim() = dim;
            if (m_recalc != nullptr) {
              m_recalc(*this);
            }
          }
          void LayoutFree::render(pos_t pos) const
          {
            for (const auto& win : m_wins) {
        
        diff --git a/ source/layout_rigid.cpp b/ source/layout_rigid.cpp
@@ -6,9 +6,8 @@
namespace display
          {
          LayoutRigid::LayoutRigid(layout_t layout, recalc_f f_recalc)
              : m_recalc(std::move(f_recalc))
              , m_grid(static_cast<sz_t>(layout[0].size()),
          LayoutRigid::LayoutRigid(layout_t layout)
              : m_grid(static_cast<sz_t>(layout[0].size()),
                       static_cast<sz_t>(layout.size()))
              , m_recs(count_and_pad(layout))
          {
        
        
          @@ -95,16 +94,12 @@ 
          auto LayoutRigid::calc_height(dim_t share) const
        
        
          void LayoutRigid::resize(dim_t dim)
          {
            this->dim() = dim;
            Layout::resize(dim);
            for (auto& [screen, _, rdim] : m_recs) {
              const dim_t size = {calc_width(rdim), calc_height(rdim)};
              screen.resize(size);
            }
            if (m_recalc != nullptr) {
              m_recalc(*this);
            }
          }
          void LayoutRigid::render(pos_t pos) const
        
        diff --git a/ source/window_pivot.cpp b/ source/window_pivot.cpp
@@ -5,13 +5,6 @@
namespace display
          {
          void WindowPivot::render(place_t place) const
          {
            if (m_renderer != nullptr) {
              m_renderer(*this, place);
            }
          }
          std::optional<place_t> WindowPivot::place(dim_t bounds)
          {
            const auto [cols, rows] = bounds;