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 | 814dee099d96d33f03b392643ab6720446680955 | 
| parent | c451c9d592719287e5fe70b35cc303c4a233dce0 | 
| author | Dimitrije Dobrota < mail@dimitrijedobrota.com > | 
| date | Sun, 9 Feb 2025 12:06:12 +0100 | 
Use Singleton for better RAII and consistency
| M | CMakeLists.txt | | | + - | 
| M | example/example.cpp | | | +++++++++ ------- | 
| M | include/display/display.hpp | | | ++++++++++++++++++++++++ ----- | 
| M | source/display.cpp | | | +++++++++++++++++++++++++++++++++++++ ------------------------------------ | 
4 files changed, 71 insertions(+), 49 deletions(-)
diff --git a/ CMakeLists.txt b/ CMakeLists.txt
          @@ -4,7 +4,7 @@ 
          include(cmake/prelude.cmake)
        
        
          project(
              display
              VERSION 0.1.10
              VERSION 0.1.11
              DESCRIPTION "TUI library"
              HOMEPAGE_URL "https://example.com/"
              LANGUAGES CXX
        
        diff --git a/ example/example.cpp b/ example/example.cpp
          @@ -33,8 +33,10 @@ 
          int renderer(display::Window& win)
        
        
          int main()
          {
            try {
              display::LayoutFree layout;
              using display::Display;
              auto& disp = Display::display();
              display::LayoutFree layout;
              auto redraw = [&]()
              {
                const auto [cols, rows] = alec::get_screen_size();
        
        
          @@ -66,17 +68,19 @@ 
          int main()
        
        
              layout.append({{}, {20, 10}, {PvtX::Left, PvtY::Center}});
              layout.append({{}, {20, 10}, {PvtX::Center, PvtY::Center}});
              display::start();
              redraw();
              using display::event;
              while (true) {
                const auto event = display::get_event();
                if (event.type() == display::event::Type::RESIZE) {
                const auto event = disp.get_event();
                if (event.type() == event::Type::RESIZE) {
                  std::cout << alec::erase_display_v<alec::Motion::WHOLE>;
                  redraw();
                  continue;
                }
                if (event.type() == display::event::Type::KEY && event.key() == 'q') {
                if (event.type() == event::Type::KEY && event.key() == 'q') {
                  break;
                }
              }
        
        
          @@ -85,7 +89,5 @@ 
          int main()
        
        
              std::cout << err.what() << '\n' << std::flush;
            }
            display::stop();
            return 0;
          }
        
        diff --git a/ include/display/display.hpp b/ include/display/display.hpp
@@ -5,13 +5,32 @@
namespace display
          {
          using exit_f = void();
          using event = alec::event;
          void exit();
          void start(exit_f f_exit = exit);
          void stop(bool force = false);
          class Display
          {
          public:
            static Display& display();
            Display(const Display&) = delete;
            Display(Display&&) = delete;
            Display& operator=(const Display&) = delete;
            Display& operator=(Display&&) = delete;
            event get_event();
            bool get_resized() const;
            void set_resized();
            void reset_resized();
          private:
            Display();
            ~Display();
            static void handle_sigwinch(int /* unused */);
            static bool is_resize_track;
          event get_event();
            bool m_is_resized = false;
          };
          }  // namespace display
        
        diff --git a/ source/display.cpp b/ source/display.cpp
@@ -1,5 +1,4 @@
#include <csignal>
          #include <stdexcept>
          #include "display/display.hpp"
          
          @@ -20,40 +19,16 @@ 
          inline void write()
        
        
          namespace display
          {
          static int start_count = 0;  // NOLINT
          static bool resized = false;  // NOLINT
          bool Display::is_resize_track = false;
          void handle_sigwinch(int /* unused */)  // NOLINT misc-use-internal-linkage
          Display& Display::display()
          {
            resized = true;
            static Display instance;
            return instance;
          }
          event get_event()
          Display::Display()
          {
            if (resized) {
              resized = false;
              return {event::Type::RESIZE, 0, 0};
            }
            return alec::get_event();
          }
          void exit()
          {
            stop(/* force= */ true);
          }
          void start(exit_f f_exit)
          {
            if (start_count++ > 0) {
              // already started
              return;
            }
            if (atexit(f_exit) != 0) {
              throw std::runtime_error("Can't register new exit function");
            }
            struct sigaction old_sig_action = {};
            sigaction(SIGWINCH, nullptr, &old_sig_action);
            if (old_sig_action.sa_handler != SIG_IGN) {
        
        
          @@ -64,6 +39,7 @@ 
          void start(exit_f f_exit)
        
        
              new_sig_action.sa_flags = SA_RESTART;
              sigaction(SIGWINCH, &new_sig_action, nullptr);
              is_resize_track = true;
            }
            alec::init_buffer(STDIN_FILENO);
        
        
          @@ -71,16 +47,41 @@ 
          void start(exit_f f_exit)
        
        
            write<alec::cursor_hide_v>();
          }
          void stop(bool force)
          Display::~Display()
          {
            if (!force && --start_count > 0) {
              // still need to keep open
              return;
            }
            alec::dest_buffer();
            write<alec::cursor_show_v>();
            write<alec::abuf_disable_v>();
          }
          void Display::handle_sigwinch(int /* unused */)
          {
            Display::display().set_resized();
          }
          event Display::get_event()  // NOLINT
          {
            if (is_resize_track && m_is_resized) {
              Display::reset_resized();
              return {event::Type::RESIZE, 0, 0};
            }
            return alec::get_event();
          }
          void Display::set_resized()
          {
            m_is_resized = true;
          }
          void Display::reset_resized()
          {
            m_is_resized = false;
          }
          bool Display::get_resized() const
          {
            return m_is_resized;
          }
          }  // namespace display