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 | ef565de7fa473b6bff7980e0a675cc362e891d05 | 
| parent | 71668e6f08aea9bf597a67acffb6ae933620f078 | 
| author | Dimitrije Dobrota < mail@dimitrijedobrota.com > | 
| date | Sat, 15 Feb 2025 15:45:21 +0100 | 
Enforce elems having apos and dim on construction
* Experiment with widget render on construction
* Enforce construtor param order as it will be automatically filled by
  parent calsses on insertion
* Windows behave like other elements
| M | CMakeLists.txt | | | + - | 
| M | example/example.cpp | | | +++++++++++++++++++++++++++++ ---------------- | 
| M | include/display/display.hpp | | | ++ | 
| M | include/display/layout.hpp | | | ++ - | 
| M | include/display/layout_free.hpp | | | ++++ --- | 
| M | include/display/layout_rigid.hpp | | | ++ -- | 
| M | include/display/screen.hpp | | | +++ -- | 
| M | include/display/window.hpp | | | +++++++++++++++++ ---- | 
| M | include/display/window_pivot.hpp | | | ++++ -------------- | 
| M | source/display.cpp | | | +++++++++ -- | 
| M | source/layout_rigid.cpp | | | ++++ -- | 
| M | source/window_pivot.cpp | | | +++++++ -------- | 
12 files changed, 84 insertions(+), 55 deletions(-)
diff --git a/ CMakeLists.txt b/ CMakeLists.txt
          @@ -4,7 +4,7 @@ 
          include(cmake/prelude.cmake)
        
        
          project(
              display
              VERSION 0.1.21
              VERSION 0.1.22
              DESCRIPTION "TUI library"
              HOMEPAGE_URL "https://example.com/"
              LANGUAGES CXX
        
        diff --git a/ example/example.cpp b/ example/example.cpp
          @@ -14,9 +14,14 @@ 
          namespace
        
        
          class WindowCustom : public display::WindowPivot
          {
          public:
            WindowCustom(display::dim_t dim, display::piv_t piv)
                : WindowPivot(display::pos_t(), dim, piv)
            WindowCustom(display::apos_t apos,
                         display::dim_t adim,
                         display::pos_t pos,
                         display::dim_t dim,
                         display::piv_t piv)
                : WindowPivot(apos, adim, pos, dim, piv)
            {
                render();
            }
            void render() const override
        
        
          @@ -24,8 +29,9 @@ 
          public:
        
        
              static int color_red = 0;
              color_red = (color_red + 25) % 256;
              const auto [x, y] = apos();
              const auto [w, h] = apos();
              const auto [apos, adim] = place();
              const auto [x, y] = apos;
              const auto [w, h] = adim;
              std::cout << alec::background(color_red, 65, 65);
          
          @@ -42,20 +48,27 @@ 
          public:
        
        
          class LayoutCustom : public display::LayoutFree
          {
          public:
            LayoutCustom()
            LayoutCustom(display::apos_t apos, display::dim_t dim)
                : LayoutFree(apos, dim)
            {
              using display::dim_t, display::piv_t;
              using display::pos_t, 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));
              const auto [width, height] = dim;
              const display::sz_t midw = width / 2;
              const display::sz_t midh = height / 2;
              // clang-format off
              append<WindowCustom>(pos_t(   0,       0), dim_t(12, 4), piv_t(  PvtX::Left,    PvtY::Top));
              append<WindowCustom>(pos_t(midw,       0), dim_t(12, 4), piv_t(PvtX::Center,    PvtY::Top));
              append<WindowCustom>(pos_t(width,      0), dim_t(12, 4), piv_t( PvtX::Right,    PvtY::Top));
              append<WindowCustom>(pos_t(width,   midh), dim_t(12, 4), piv_t( PvtX::Right, PvtY::Center));
              append<WindowCustom>(pos_t(width, height), dim_t(12, 4), piv_t (PvtX::Right, PvtY::Bottom));
              append<WindowCustom>(pos_t(midw,  height), dim_t(12, 4), piv_t(PvtX::Center, PvtY::Bottom));
              append<WindowCustom>(pos_t(   0,  height), dim_t(12, 4), piv_t(  PvtX::Left, PvtY::Bottom));
              append<WindowCustom>(pos_t(   0,    midh), dim_t(12, 4), piv_t(  PvtX::Left, PvtY::Center));
              append<WindowCustom>(pos_t(midw,    midh), dim_t(12, 4), piv_t(PvtX::Center, PvtY::Center));
              // clang-format on
            }
            void resize(display::apos_t apos, display::dim_t dim) override
        
        
          @@ -102,7 +115,7 @@ 
          int main()
        
        
              layout[3].set_layout<LayoutCustom>();
              layout[4].set_layout<LayoutCustom>();
              for (display.set_resized(); true;) {
              while (true) {
                const auto evnt = display.get_event();
                if (evnt.type() == event::Type::RESIZE) {
                  std::cout << alec::erase_display_v<alec::Motion::WHOLE>;
        
        diff --git a/ include/display/display.hpp b/ include/display/display.hpp
          @@ -31,6 +31,8 @@ 
          private:
        
        
            Display();
            ~Display();
            void resize();
            static void handle_sigwinch(int /* unused */);
            static bool is_resize_track;
          diff --git a/ include/display/layout.hpp b/ include/display/layout.hpp
          @@ -8,8 +8,9 @@ 
          namespace display
        
        
          class Layout
          {
          public:
            explicit Layout(apos_t apos)
            explicit Layout(apos_t apos, dim_t dim)
                : m_apos(apos)
                , m_dim(dim)
            {
            }
          diff --git a/ include/display/layout_free.hpp b/ include/display/layout_free.hpp
          @@ -12,8 +12,8 @@ 
          namespace display
        
        
          class LayoutFree : public Layout
          {
          public:
            LayoutFree()
                : Layout({0, 0})
            LayoutFree(apos_t apos, dim_t dim)
                : Layout(apos, dim)
            {
            }
          
          @@ -23,7 +23,8 @@ 
          public:
        
        
            template<typename T, class... Args>
            T& append(Args&&... args)
            {
              m_wins.emplace_back(std::make_unique<T>(std::forward<Args>(args)...));
              m_wins.emplace_back(
                  std::make_unique<T>(apos(), dim(), std::forward<Args>(args)...));
              return get<T>(m_wins.size() - 1);
            }
          diff --git a/ include/display/layout_rigid.hpp b/ include/display/layout_rigid.hpp
          @@ -13,7 +13,7 @@ 
          class LayoutRigid : public Layout
        
        
          public:
            using layout_t = std::vector<std::vector<std::uint8_t>>;
            LayoutRigid(layout_t layout);  // NOLINT
            LayoutRigid(apos_t apos, dim_t dim, 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; }
        
        
          @@ -33,7 +33,7 @@ 
          private:
        
        
            struct record_t
            {
              record_t()
                  : screen(apos_t(0, 0))
                  : screen(apos_t(0, 0), dim_t(0, 0))
              {
              }
          diff --git a/ include/display/screen.hpp b/ include/display/screen.hpp
          @@ -11,8 +11,9 @@ 
          namespace display
        
        
          class Screen
          {
          public:
            explicit Screen(apos_t apos)
            explicit Screen(apos_t apos, dim_t dim)
                : m_apos(apos)
                , m_dim(dim)
            {
            }
          
          @@ -27,7 +28,7 @@ 
          public:
        
        
            template<typename T, class... Args>
            T& set_layout(Args&&... args)
            {
              m_layout = std::make_unique<T>(std::forward<Args>(args)...);
              m_layout = std::make_unique<T>(m_apos, m_dim, std::forward<Args>(args)...);
              return get_layout<T>();
            }
          diff --git a/ include/display/window.hpp b/ include/display/window.hpp
@@ -1,7 +1,5 @@
#pragma once
          #include <optional>
          #include "display/types.hpp"
          namespace display
        
        
          @@ -10,7 +8,11 @@ 
          namespace display
        
        
          class Window
          {
          public:
            Window() = default;
            Window(apos_t apos, dim_t dim)
                : m_apos(apos)
                , m_adim(dim)
            {
            }
            Window(const Window&) = delete;
            Window& operator=(const Window&) = delete;
        
        
          @@ -20,9 +22,20 @@ 
          public:
        
        
            virtual ~Window() = default;
            virtual void resize(apos_t apos, dim_t dim) = 0;
            virtual void resize(apos_t apos, dim_t adim) { m_apos = apos, m_adim = adim; }
            virtual void render() const = 0;
            virtual void input(event& /* unused */) {}
          protected:
            const auto& apos() const { return m_apos; }
            auto& apos() { return m_apos; }
            const auto& adim() const { return m_adim; }
            auto& adim() { return m_adim; }
          private:
            apos_t m_apos;
            dim_t m_adim;
          };
          }  // namespace display
        
        diff --git a/ include/display/window_pivot.hpp b/ include/display/window_pivot.hpp
          @@ -9,12 +9,11 @@ 
          namespace display
        
        
          class WindowPivot : public Window
          {
          public:
            WindowPivot(pos_t pos, dim_t dim, piv_t piv = {})
                : m_pos(pos)
            WindowPivot(apos_t apos, dim_t adim, pos_t pos, dim_t dim, piv_t piv = {})
                : Window(apos, adim)
                , m_pos(pos)
                , m_dim(dim)
                , m_piv(piv)
                , m_apos(0, 0)
                , m_adim(0, 0)
            {
            }
          
          @@ -27,22 +26,13 @@ 
          public:
        
        
            const auto& piv() const { return m_piv; }
            auto& piv() { return m_piv; }
            void resize(apos_t apos, dim_t dim) override;
          protected:
            const auto& apos() const { return m_apos; }
            auto& apos() { return m_apos; }
            const auto& adim() const { return m_adim; }
            auto& adim() { return m_adim; }
            std::tuple<apos_t, dim_t> place() const;
          private:
            pos_t m_pos;
            dim_t m_dim;
            piv_t m_piv;
            apos_t m_apos;
            dim_t m_adim;
          };
          }  // namespace display
        
        diff --git a/ source/display.cpp b/ source/display.cpp
          @@ -28,7 +28,7 @@ 
          Display& Display::display()
        
        
          }
          Display::Display()
              : m_screen(apos_t(0, 0))
              : m_screen(apos_t(0, 0), alec::get_screen_size())
          {
            struct sigaction old_sig_action = {};
            sigaction(SIGWINCH, nullptr, &old_sig_action);
        
        
          @@ -46,6 +46,8 @@ 
          Display::Display()
        
        
            alec::init_buffer(STDIN_FILENO);
            write<alec::abuf_enable_v>();
            write<alec::cursor_hide_v>();
            resize();
          }
          Display::~Display()
        
        
          @@ -72,8 +74,8 @@ 
          event Display::get_event()  // NOLINT
        
        
          void Display::set_resized()
          {
            m_screen.resize(apos_t(0, 0), alec::get_screen_size());
            m_is_resized = true;
            resize();
          }
          void Display::reset_resized()
        
        
          @@ -86,6 +88,11 @@ 
          bool Display::get_resized() const
        
        
            return m_is_resized;
          }
          void Display::resize()
          {
            m_screen.resize(apos_t(0, 0), alec::get_screen_size());
          }
          void Display::render()
          {
            m_screen.render();
        
        diff --git a/ source/layout_rigid.cpp b/ source/layout_rigid.cpp
@@ -6,8 +6,8 @@
namespace display
          {
          LayoutRigid::LayoutRigid(layout_t layout)
              : Layout(apos_t(0, 0))
          LayoutRigid::LayoutRigid(apos_t apos, dim_t dim, layout_t layout)
              : Layout(apos, dim)
              , m_grid(static_cast<sz_t>(layout[0].size()),
                       static_cast<sz_t>(layout.size()))
              , m_recs(count_and_pad(layout))
        
        
          @@ -58,6 +58,8 @@ 
          LayoutRigid::LayoutRigid(layout_t layout)
        
        
                total += cnt, cnt = 0;
              }
            }
            LayoutRigid::resize(apos, dim);
          }
          std::size_t LayoutRigid::count_and_pad(layout_t& layout) const
        
        diff --git a/ source/window_pivot.cpp b/ source/window_pivot.cpp
@@ -5,16 +5,16 @@
namespace display
          {
          void WindowPivot::resize(apos_t apos, dim_t dim)
          std::tuple<apos_t, dim_t> WindowPivot::place() const
          {
            const auto [cols, rows] = dim;
            const auto [cols, rows] = adim();
            const auto [posx, posy] = pos();
            if (posx > cols || posy > rows) {
              return;
              return {{0, 0}, {0, 0}};
            }
            const auto [wdth, hght] = this->dim();
            const auto [wdth, hght] = dim();
            const display::sz_t zero = 0;
            const sz_t wdthm = wdth / 2;
            const sz_t hghtm = hght / 2;
        
        
          @@ -29,7 +29,7 @@ 
          void WindowPivot::resize(apos_t apos, dim_t dim)
        
        
                break;
              case PvtX::Center:
                start.x = sub_lim(posx, wdthm, zero);
                end.x = add_lim(posx, wdthm, cols);
                end.x = add_lim(start.x, wdth, cols);
                break;
              case PvtX::Right:
                end.x = posx;
        
        
          @@ -44,7 +44,7 @@ 
          void WindowPivot::resize(apos_t apos, dim_t dim)
        
        
                break;
              case PvtY::Center:
                start.y = sub_lim(posy, hghtm, zero);
                end.y = add_lim(posy, hghtm, rows);
                end.y = add_lim(start.y, hght, rows);
                break;
              case PvtY::Bottom:
                end.y = posy;
        
        
          @@ -52,8 +52,7 @@ 
          void WindowPivot::resize(apos_t apos, dim_t dim)
        
        
                break;
            }
            m_apos = apos + start;
            m_adim = end - start;
            return {apos() + start, end - start};
          }
          }  // namespace display