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 | de1902c7b94dae6042963b6eee1bb79dd9a3f891 | 
| parent | e6af90c90ead078a849819036ea5a91775caf259 | 
| author | Dimitrije Dobrota < mail@dimitrijedobrota.com > | 
| date | Wed, 19 Feb 2025 00:04:40 +0100 | 
Great simplification by cutting out BS
* padd_t with all 4 directions
* No more WindowPadding and WindowTypes
* Every windows specifies it's own padding
* Window::render() draws it to screen
* Opionaly Window::render_border() draws a border around everything
* No need for WindowPivot to be a template
| M | CMakeLists.txt | | | + -- | 
| M | example/example.cpp | | | ++ -- | 
| M | example/navig/navig.cpp | | | +++++ ----- | 
| M | include/display/types.hpp | | | +++++++++++++++++++++++++++++++++++++ | 
| M | include/display/window.hpp | | | +++++++++++++++++++ ----------- | 
| D | include/display/window_padd.hpp | | | ---------------------------------------------------------------------------- | 
| M | include/display/window_pivot.hpp | | | ++++++ ----------- | 
| M | source/window.cpp | | | +++++++++++++++++++++++++++++++++++++++++++++++++ ----- | 
| D | source/window_padd.cpp | | | ------------------------------------------------------------------------ | 
| M | source/window_pivot.cpp | | | +++ -- | 
10 files changed, 122 insertions(+), 186 deletions(-)
diff --git a/ CMakeLists.txt b/ CMakeLists.txt
          @@ -4,7 +4,7 @@ 
          include(cmake/prelude.cmake)
        
        
          project(
              display
              VERSION 0.1.31
              VERSION 0.1.32
              DESCRIPTION "TUI library"
              HOMEPAGE_URL "git://git.dimitrijedobrota.com/display.git"
              LANGUAGES CXX
        
        
          @@ -21,7 +21,6 @@ 
          add_library(
        
        
              display_display
              source/display.cpp
              source/window.cpp
              source/window_padd.cpp
              source/window_pivot.cpp
          )
          target_link_libraries(display_display PUBLIC alec::alec)
        
        diff --git a/ example/example.cpp b/ example/example.cpp
          @@ -12,11 +12,11 @@ 
          namespace
        
        
          using display::PvtX, display::PvtY;
          using display::sz_t, display::dim_t, display::piv_t, display::place_t;
          class WindowCustom : public display::WindowPivot<display::Window>
          class WindowCustom : public display::WindowPivot
          {
          public:
            explicit WindowCustom(place_t aplc, piv_t piv, dim_t dim)
                : WindowPivot(aplc, piv, dim)
                : WindowPivot(aplc, {0, 0}, piv, dim)
            {
            }
          diff --git a/ example/navig/navig.cpp b/ example/navig/navig.cpp
@@ -6,7 +6,6 @@
#include "display/display.hpp"
          #include "display/layout.hpp"
          #include "display/window_padd.hpp"
          #include "display/window_pivot.hpp"
          #include "menu.hpp"
          
          @@ -15,15 +14,15 @@ 
          namespace
        
        
          bool is_finished = false;  // NOLINT
          using display::WindowPivot, display::WindowPadd, display::WindowType;
          using display::WindowPivot;
          class WindowCustom : public WindowPivot<WindowPadd<WindowType::BorderBox>>
          class WindowCustom : public WindowPivot
          {
          public:
            WindowCustom(display::place_t aplc,
                         display::piv_t piv,
                         const example::menu_t& menu)
                : WindowPivot(aplc, piv, calc_dim(menu))
                : WindowPivot(aplc, {4, 5, 2, 4}, piv, calc_dim(menu))
                , m_menu(menu)
            {
            }
        
        
          @@ -47,7 +46,8 @@ 
          public:
        
        
                }
              }
              WindowPadd<WindowType::BorderBox>::render();
              WindowPivot::render();
              Window::render_border();
              std::cout << alec::background_v<alec::Color::DEFAULT>;
              std::cout << std::flush;
        
        diff --git a/ include/display/types.hpp b/ include/display/types.hpp
          @@ -12,6 +12,35 @@ 
          using event = alec::event;
        
        
          using sz_t = std::uint16_t;
          struct padd_t
          {
            padd_t()
                : padd_t(0, 0, 0, 0)
            {
            }
            padd_t(sz_t width, sz_t height)  // NOLINT
                : padd_t(width, width, height, height)
            {
            }
            padd_t(sz_t leftpos, sz_t rightpos, sz_t toppos, sz_t bottompos)  // NOLINT
                : left(leftpos)
                , right(rightpos)
                , top(toppos)
                , bottom(bottompos)
            {
            }
            sz_t width() const { return left + right; }
            sz_t height() const { return top + bottom; }
            sz_t left;
            sz_t right;
            sz_t top;
            sz_t bottom;
          };
          struct dim_t
          {
            dim_t()
        
        
          @@ -39,6 +68,14 @@ 
          struct dim_t
        
        
              };
            }
            dim_t operator+(padd_t rhs) const
            {
              return {
                  static_cast<sz_t>(width + rhs.width()),
                  static_cast<sz_t>(height + rhs.height()),
              };
            }
            sz_t width;
            sz_t height;
          };
        
        diff --git a/ include/display/window.hpp b/ include/display/window.hpp
@@ -5,23 +5,23 @@
namespace display
          {
          class Window : public Element
          {
          public:
            using ustring = std::basic_string<unsigned char>;
            explicit Window(place_t aplc, dim_t padding = {0, 0})
            explicit Window(place_t aplc, padd_t padd)
                : Element(aplc)
                , m_padding(padding)
                , m_padd(padd)
            {
            }
            void render() const override;
            void clear() const override;
            void input(event& /* unused */) override {}
            void render_border() const;
          protected:
            static dim_t padding() { return {0, 0}; }
            padd_t padd() const { return m_padd; }
            static std::ostream& set_cursor(sz_t posy, sz_t posx);
            std::ostream& line_next() const;
        
        
          @@ -35,13 +35,21 @@ 
          protected:
        
        
            place_t plc() const { return {pos(), dim()}; }
            pos_t pos() const { return {xpos(), ypos()}; }
            dim_t dim() const { return {wth(), hgt()}; }
            sz_t xpos() const { return axpos() + (m_padding.width / 2); }
            sz_t ypos() const { return aypos() + (m_padding.height / 2); }
            sz_t wth() const { return awth() - m_padding.width; }
            sz_t hgt() const { return ahgt() - m_padding.height; }
            sz_t xpos() const { return axpos() + m_padd.left; }
            sz_t ypos() const { return aypos() + m_padd.top; }
            sz_t wth() const { return awth() - m_padd.width(); }
            sz_t hgt() const { return ahgt() - m_padd.height(); }
          private:
            dim_t m_padding;
            using Element::adim;
            using Element::ahgt;
            using Element::aplc;
            using Element::apos;
            using Element::awth;
            using Element::axpos;
            using Element::aypos;
            padd_t m_padd;
            mutable display::sz_t m_ypos = 0;
          };
        
        diff --git a/ include/display/window_padd.hpp b/ include/display/window_padd.hpp
@@ -1,76 +0,0 @@
#pragma once
          #include "display/window.hpp"
          namespace display
          {
          enum class WindowType : std::uint8_t
          {
            Bare,
            Border,
            Box,
            BorderBox,
          };
          template<WindowType T>
          class WindowPadd : public Window
          {
          public:
            explicit WindowPadd(place_t aplc)
                : Window(aplc, padding())
            {
            }
            void render() const override;
          protected:
            static dim_t padding();
          private:
            using Element::adim;
            using Element::ahgt;
            using Element::aplc;
            using Element::apos;
            using Element::awth;
            using Element::axpos;
            using Element::aypos;
          };
          template<>
          inline dim_t WindowPadd<WindowType::Bare>::padding()
          {
            return {0, 0};
          }
          template<>
          inline dim_t WindowPadd<WindowType::Border>::padding()
          {
            return {2, 2};
          }
          template<>
          inline dim_t WindowPadd<WindowType::Box>::padding()
          {
            return {2, 2};
          }
          template<>
          inline dim_t WindowPadd<WindowType::BorderBox>::padding()
          {
            return {4, 2};
          }
          template<>
          void WindowPadd<WindowType::Bare>::render() const;
          template<>
          void WindowPadd<WindowType::Border>::render() const;
          template<>
          void WindowPadd<WindowType::Box>::render() const;
          template<>
          void WindowPadd<WindowType::BorderBox>::render() const;
          }  // namespace display
        
        diff --git a/ include/display/window_pivot.hpp b/ include/display/window_pivot.hpp
@@ -5,18 +5,11 @@
namespace display
          {
          place_t WindowPivot_place(place_t aplc,  // NOLINT
                                    piv_t piv,
                                    dim_t dim,
                                    dim_t padding);
          template<typename T>
            requires(std::is_base_of_v<Window, T>)
          class WindowPivot : public T
          class WindowPivot : public Window
          {
          public:
            WindowPivot(place_t aplc, piv_t piv, dim_t dim)
                : T(WindowPivot_place(aplc, piv, dim, T::padding()))
            WindowPivot(place_t aplc, padd_t padd, piv_t piv, dim_t dim)
                : Window(place(aplc, piv, dim + padd), padd)
                , m_piv(piv)
                , m_dim(dim)
            {
        
        
          @@ -24,10 +17,12 @@ 
          public:
        
        
            void resize(place_t aplc) override
            {
              T::resize(WindowPivot_place(aplc, m_piv, m_dim, T::padding()));
              Window::resize(place(aplc, m_piv, m_dim + padd()));
            }
          private:
            static place_t place(place_t aplc, piv_t piv, dim_t dim);
            piv_t m_piv;
            dim_t m_dim;
          };
        
        diff --git a/ source/window.cpp b/ source/window.cpp
@@ -7,6 +7,41 @@
namespace display
          {
          void Window::render() const
          {
            const auto space = std::string(awth(), ' ');
            for (sz_t i = aypos(); i < aypos() + m_padd.top; i++) {
              set_cursor(i, axpos()) << space;
            }
            for (sz_t i = aypos() + ahgt() - m_padd.bottom; i < aypos() + ahgt(); i++) {
              set_cursor(i, axpos()) << space;
            }
          }
          void Window::render_border() const
          {
            set_cursor(aypos(), axpos());
            std::cout << "┌";
            for (sz_t i = 2; i < awth(); i++) {
              std::cout << "─";
            }
            std::cout << "┐";
            for (sz_t i = aypos() + 1; i < aypos() + ahgt(); i++) {
              set_cursor(i, axpos()) << "│";
              set_cursor(i, axpos() + awth() - 1) << "│";
            }
            set_cursor(aypos() + ahgt() - 1, axpos());
            std::cout << "└";
            for (sz_t i = 2; i < awth(); i++) {
              std::cout << "─";
            }
            std::cout << "┘";
          }
          void Window::clear() const
          {
            std::cout << alec::background_v<alec::Color::DEFAULT>;
        
        
          @@ -37,27 +72,36 @@ 
          std::ostream& Window::line_next() const
        
        
              return null;
            }
            return set_cursor(m_ypos++, xpos());
            return set_cursor(m_ypos++, axpos());
          }
          void Window::line_empty() const
          {
            line_next() << std::string(wth(), ' ');
            line_next() << std::string(awth(), ' ');
          }
          void Window::line_left(const std::string& text) const
          {
            line_next() << std::format("{:<{}}", text, wth());
            const auto left = std::string(m_padd.left, ' ');
            const auto right = std::string(m_padd.right, ' ');
            line_next() << left << std::format("{:<{}}", text, wth()) << right;
          }
          void Window::line_center(const std::string& text) const
          {
            line_next() << std::format("{:^{}}", text, wth());
            const auto left = std::string(m_padd.left, ' ');
            const auto right = std::string(m_padd.right, ' ');
            line_next() << left << std::format("{:^{}}", text, wth()) << right;
          }
          void Window::line_right(const std::string& text) const
          {
            line_next() << std::format("{:>{}}", text, wth());
            const auto left = std::string(m_padd.left, ' ');
            const auto right = std::string(m_padd.right, ' ');
            line_next() << left << std::format("{:>{}}", text, wth()) << right;
          }
          }  // namespace display
        
        diff --git a/ source/window_padd.cpp b/ source/window_padd.cpp
@@ -1,72 +0,0 @@
#include <iostream>
          #include "display/window_padd.hpp"
          namespace display
          {
          template<>
          void WindowPadd<WindowType::Bare>::render() const
          {
          }
          template<>
          void WindowPadd<WindowType::Border>::render() const
          {
            set_cursor(aypos(), axpos()) << std::string(awth(), ' ');
            for (sz_t i = ypos(); i < ypos() + hgt(); i++) {
              set_cursor(i, axpos()) << ' ';
              set_cursor(i, axpos() + awth() - 1) << ' ';
            }
            set_cursor(aypos() + ahgt() - 1, axpos()) << std::string(awth(), ' ');
          }
          template<>
          void WindowPadd<WindowType::Box>::render() const
          {
            set_cursor(aypos(), axpos());
            std::cout << "┌";
            for (sz_t i = 0; i < wth(); i++) {
              std::cout << "─";
            }
            std::cout << "┐";
            for (sz_t i = ypos(); i < ypos() + hgt(); i++) {
              set_cursor(i, axpos()) << "│";
              set_cursor(i, axpos() + awth() - 1) << "│";
            }
            set_cursor(aypos() + ahgt() - 1, axpos());
            std::cout << "└";
            for (sz_t i = 0; i < wth(); i++) {
              std::cout << "─";
            }
            std::cout << "┘";
          }
          template<>
          void WindowPadd<WindowType::BorderBox>::render() const
          {
            set_cursor(aypos(), axpos());
            std::cout << "┌─";
            for (sz_t i = 0; i < wth(); i++) {
              std::cout << "─";
            }
            std::cout << "─┐";
            for (sz_t i = ypos(); i < ypos() + hgt(); i++) {
              set_cursor(i, axpos()) << "│ ";
              set_cursor(i, axpos() + awth() - 2) << " │";
            }
            set_cursor(aypos() + ahgt() - 1, axpos());
            std::cout << "└─";
            for (sz_t i = 0; i < wth(); i++) {
              std::cout << "─";
            }
            std::cout << "─┘";
          }
          }  // namespace display
        
        diff --git a/ source/window_pivot.cpp b/ source/window_pivot.cpp
@@ -1,16 +1,17 @@
#include "display/window_pivot.hpp"
          #include "display/utility.hpp"
          namespace display
          {
          place_t WindowPivot_place(place_t aplc, piv_t piv, dim_t dim, dim_t padding)
          place_t WindowPivot::place(place_t aplc, piv_t piv, dim_t dim)
          {
            const auto [cols, rows] = aplc.dim;
            const sz_t colsh = cols / 2;
            const sz_t rowsh = rows / 2;
            const auto [wdth, hght] = dim + padding;
            const auto [wdth, hght] = dim;
            const sz_t wdthm = wdth / 2;
            const sz_t hghtm = hght / 2;