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 | 6bc9907460f1b64a63df06d9088dd9748711d06b | 
| parent | 814dee099d96d33f03b392643ab6720446680955 | 
| author | Dimitrije Dobrota < mail@dimitrijedobrota.com > | 
| date | Mon, 10 Feb 2025 11:15:23 +0100 | 
Tight coupling that automaticaly handles resize
| M | CMakeLists.txt | | | ++ - | 
| M | example/example.cpp | | | ++++++++++++++++++++++++++ ---------------------------- | 
| M | include/display/display.hpp | | | +++++ | 
| M | include/display/layout.hpp | | | +++++++++++++++++ - | 
| A | include/display/screen.hpp | | | +++++++++++++++++++++++++++++++ | 
| M | include/display/types.hpp | | | +++++++ | 
| M | include/display/window.hpp | | | +++++++ | 
| M | source/display.cpp | | | ++ | 
| M | source/layout.cpp | | | ++++++++++++++ | 
| A | source/screen.cpp | | | +++++++++++++++++++++++++++++ | 
| M | source/window.cpp | | | ++ -- | 
11 files changed, 142 insertions(+), 32 deletions(-)
diff --git a/ CMakeLists.txt b/ CMakeLists.txt
          @@ -4,7 +4,7 @@ 
          include(cmake/prelude.cmake)
        
        
          project(
              display
              VERSION 0.1.11
              VERSION 0.1.12
              DESCRIPTION "TUI library"
              HOMEPAGE_URL "https://example.com/"
              LANGUAGES CXX
        
        
          @@ -21,6 +21,7 @@ 
          add_library(
        
        
              display_display
              source/display.cpp
              source/layout.cpp
              source/screen.cpp
              source/window.cpp
          )
          target_link_libraries(display_display PUBLIC alec::alec)
        
        diff --git a/ example/example.cpp b/ example/example.cpp
          @@ -28,35 +28,35 @@ 
          int renderer(display::Window& win)
        
        
            return 0;
          }
          void recalculator(display::LayoutFree& layout)
          {
            const auto [width, height] = layout.dim();
            const display::sz_t midw = width / 2;
            const display::sz_t midh = height / 2;
            layout[4].pos() = {0, 0};
            layout[5].pos() = {midw, 0};
            layout[6].pos() = {width, 0};
            layout[7].pos() = {width, midh};
            layout[0].pos() = {width, height};
            layout[1].pos() = {midw, height};
            layout[2].pos() = {0, height};
            layout[3].pos() = {0, midh};
            layout[8].pos() = {midw, midh};
          }
          }  // namespace
          int main()
          {
            try {
              using display::Display;
              using display::PvtX, display::PvtY;
              auto& disp = Display::display();
              display::LayoutFree layout;
              auto redraw = [&]()
              {
                const auto [cols, rows] = alec::get_screen_size();
                const display::sz_t colsm = cols / 2;
                const display::sz_t rowm = rows / 2;
                layout[4].pos() = {0, 0};
                layout[5].pos() = {colsm, 0};
                layout[6].pos() = {cols, 0};
                layout[7].pos() = {cols, rowm};
                layout[0].pos() = {cols, rows};
                layout[1].pos() = {colsm, rows};
                layout[2].pos() = {0, rows};
                layout[3].pos() = {0, rowm};
                layout[8].pos() = {colsm, rowm};
                layout.render(renderer);
              };
              using display::PvtX, display::PvtY;
              display::LayoutFree layout(recalculator);
              disp.screen().set_layout(&layout);
              layout.append({{}, {20, 10}, {PvtX::Left, PvtY::Top}});
              layout.append({{}, {20, 10}, {PvtX::Center, PvtY::Top}});
        
        
          @@ -68,19 +68,17 @@ 
          int main()
        
        
              layout.append({{}, {20, 10}, {PvtX::Left, PvtY::Center}});
              layout.append({{}, {20, 10}, {PvtX::Center, PvtY::Center}});
              redraw();
              using display::event;
              for (disp.set_resized(); true;) {
                using display::event;
              while (true) {
                const auto event = disp.get_event();
                if (event.type() == event::Type::RESIZE) {
                const auto evnt = disp.get_event();
                if (evnt.type() == event::Type::RESIZE) {
                  std::cout << alec::erase_display_v<alec::Motion::WHOLE>;
                  redraw();
                  layout.render(renderer);
                  continue;
                }
                if (event.type() == event::Type::KEY && event.key() == 'q') {
                if (evnt.type() == event::Type::KEY && evnt.key() == 'q') {
                  break;
                }
              }
        
        diff --git a/ include/display/display.hpp b/ include/display/display.hpp
@@ -2,6 +2,8 @@
#include <alec/alec.hpp>
          #include "display/screen.hpp"
          namespace display
          {
          
          @@ -17,6 +19,8 @@ 
          public:
        
        
            Display& operator=(const Display&) = delete;
            Display& operator=(Display&&) = delete;
            Screen& screen() { return m_screen; }
            event get_event();
            bool get_resized() const;
        
        
          @@ -30,6 +34,7 @@ 
          private:
        
        
            static void handle_sigwinch(int /* unused */);
            static bool is_resize_track;
            Screen m_screen;
            bool m_is_resized = false;
          };
          diff --git a/ include/display/layout.hpp b/ include/display/layout.hpp
@@ -7,21 +7,37 @@
namespace display
          {
          class Screen;
          class LayoutFree
          {
          public:
            using render_f = int(Window&);
            using recalc_f = void(LayoutFree&);
            LayoutFree(recalc_f f_recalc)  // NOLINT
                : m_recalc(f_recalc)
            {
            }
            dim_t dim() const;
            Screen* get_screen() { return m_screen; }
            void set_screen(Screen* screen) { m_screen = screen; }
            const auto& operator[](std::size_t idx) const { return m_windows[idx]; }
            auto& operator[](std::size_t idx) { return m_windows[idx]; }
            void append(Window window);
            void recalc();
            int render(render_f renderer);
          private:
            std::vector<Window> m_windows;
            bool m_is_sorted = true;
            recalc_f* m_recalc;
            Screen* m_screen = nullptr;
          };
          class LayoutRigid
        
        diff --git a/ include/display/screen.hpp b/ include/display/screen.hpp
@@ -0,0 +1,31 @@
#pragma once
          #include "display/types.hpp"
          namespace display
          {
          class LayoutFree;
          class Screen
          {
          public:
            Screen(dim_t dim)  // NOLINT
                : m_dim(dim)
            {
            }
            const auto& dim() const { return m_dim; }
            LayoutFree* get_layout() { return m_layout; }
            void set_layout(LayoutFree* layout);
            void resize(dim_t dim);
          private:
            dim_t m_dim;
            LayoutFree* m_layout = nullptr;
          };
          }  // namespace display
        
        diff --git a/ include/display/types.hpp b/ include/display/types.hpp
@@ -1,6 +1,7 @@
#pragma once
          #include <cstdint>
          #include <utility>
          namespace display
          {
        
        
          @@ -15,6 +16,12 @@ 
          struct dim_t
        
        
            {
            }
            dim_t(std::pair<sz_t, sz_t> pair)  // NOLINT
                : width(std::get<0>(pair))
                , height(std::get<1>(pair))
            {
            }
            sz_t width;
            sz_t height;
          };
        
        diff --git a/ include/display/window.hpp b/ include/display/window.hpp
@@ -7,6 +7,8 @@
namespace display
          {
          class LayoutFree;
          class Window
          {
          public:
        
        
          @@ -26,12 +28,17 @@ 
          public:
        
        
            const auto& piv() const { return m_piv; }
            auto& piv() { return m_piv; }
            LayoutFree* get_layout() { return m_layout; }
            void set_layout(LayoutFree* layout) { m_layout = layout; }
            std::optional<place_t> place() const;
          private:
            pos_t m_pos;
            dim_t m_dim;
            piv_t m_piv;
            LayoutFree* m_layout = nullptr;
          };
          }  // namespace display
        
        diff --git a/ source/display.cpp b/ source/display.cpp
          @@ -28,6 +28,7 @@ 
          Display& Display::display()
        
        
          }
          Display::Display()
              : m_screen(alec::get_screen_size())
          {
            struct sigaction old_sig_action = {};
            sigaction(SIGWINCH, nullptr, &old_sig_action);
        
        
          @@ -71,6 +72,7 @@ 
          event Display::get_event()  // NOLINT
        
        
          void Display::set_resized()
          {
            m_screen.resize(alec::get_screen_size());
            m_is_resized = true;
          }
          diff --git a/ source/layout.cpp b/ source/layout.cpp
@@ -3,15 +3,29 @@
#include "display/layout.hpp"
          #include "display/screen.hpp"
          #include "display/window.hpp"
          namespace display
          {
          dim_t LayoutFree::dim() const
          {
            return m_screen != nullptr ? m_screen->dim() : dim_t();
          }
          void LayoutFree::append(Window window)
          {
            m_windows.push_back(window);
            m_windows.back().set_layout(this);
            m_is_sorted = false;
          }
          void LayoutFree::recalc()
          {
            m_recalc(*this);
          }
          int LayoutFree::render(render_f renderer)
          {
            static std::vector<std::uint8_t> idxs;
        
        diff --git a/ source/screen.cpp b/ source/screen.cpp
@@ -0,0 +1,29 @@
#include "display/screen.hpp"
          #include "display/layout.hpp"
          namespace display
          {
          void Screen::set_layout(LayoutFree* layout)
          {
            if (m_layout != nullptr) {
              m_layout->set_screen(nullptr);
            }
            m_layout = layout;
            if (m_layout != nullptr) {
              m_layout->set_screen(this);
            }
          }
          void Screen::resize(dim_t dim)
          {
            m_dim = dim;
            if (m_layout != nullptr) {
              m_layout->recalc();
            }
          }
          }  // namespace display
        
        diff --git a/ source/window.cpp b/ source/window.cpp
@@ -1,6 +1,6 @@
#include "display/window.hpp"
          #include "alec/alec.hpp"
          #include "display/layout.hpp"
          #include "display/utility.hpp"
          namespace display
        
        
          @@ -8,7 +8,7 @@ 
          namespace display
        
        
          std::optional<place_t> Window::place() const
          {
            const auto [cols, rows] = alec::get_screen_size();
            const auto [cols, rows] = m_layout->dim();
            const auto [posx, posy, _] = pos();
            if (posx > cols || posy > rows) {