displayLayout and Rendering TUI library | 
          
| git clone git://git.dimitrijedobrota.com/display.git | 
| Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING | 
navig.cpp (4591B)
    0 #include <iostream>
              1 #include <stack>
              2 #include <string>
          
              4 #include "display/display.hpp"
              5 #include "display/layout.hpp"
              6 #include "display/window_pivot.hpp"
              7 #include "menu.hpp"
          
              9 namespace
             10 {
          
             12 bool is_finished = false;  // NOLINT
          
             14 using display::WindowPivot;
          
             16 class WindowCustom : public WindowPivot
             17 {
             18 public:
             19   WindowCustom(display::plc_t aplc,
             20                display::piv_t piv,
             21                const example::menu_t& menu)
             22       : WindowPivot(aplc, {4, 2, 5, 4}, piv, calc_dim(menu))
             23       , m_menu(menu)
             24   {
             25   }
          
             27   void render() const override
             28   {
             29     std::cout << alec::background_v<alec::Color::BLUE>;
             30     line_reset();
          
             32     line_center(m_menu.title);
             33     line_empty();
             34     for (std::size_t i = 0; i < m_menu.items.size(); i++) {
             35       if (m_selected == i) {
             36         std::cout << alec::foreground_v<alec::Color::GREEN>;
             37       }
          
             39       line_right(m_menu.items[i].prompt);
          
             41       if (m_selected == i) {
             42         std::cout << alec::foreground_v<alec::Color::DEFAULT>;
             43       }
             44     }
          
             46     WindowPivot::render();
             47     WindowPivot::render_border();
          
             49     std::cout << alec::background_v<alec::Color::DEFAULT>;
             50     std::cout << std::flush;
             51   }
          
             53   void input(display::event& evnt) override
             54   {
             55     if (evnt.type() != display::event::Type::KEY) {
             56       return;
             57     }
          
             59     if (evnt.key() == 'j') {
             60       if (m_selected + 1U < m_menu.items.size()) {
             61         m_selected++;
             62       }
             63       evnt.type() = display::event::Type::NONE;
             64       render();
             65       return;
             66     }
          
             68     if (evnt.key() == 'k') {
             69       if (m_selected > 0) {
             70         m_selected--;
             71       }
             72       evnt.type() = display::event::Type::NONE;
             73       render();
             74       return;
             75     }
          
             77     if (evnt.key() == 'l') {
             78       m_menu.items[m_selected].callback(m_selected);
             79       evnt.type() = display::event::Type::NONE;
             80       return;
             81     }
          
             83     if (evnt.key() == 'h') {
             84       m_menu.callback(0);
             85       evnt.type() = display::event::Type::NONE;
             86       return;
             87     }
             88   }
          
             90 private:
             91   static display::dim_t calc_dim(const example::menu_t& menu)
             92   {
             93     std::size_t width = menu.title.size();
             94     for (const auto& item : menu.items) {
             95       width = std::max(width, item.prompt.size());
             96     }
          
             98     return {display::wth_t(width), display::hgt_t(menu.items.size() + 2)};
             99   }
          
            101   example::menu_t m_menu;
            102   uint8_t m_selected = 0;
            103 };
          
            105 }  // namespace
          
            107 namespace example
            108 {
          
            110 int operation1(std::size_t /* unused */)  // NOLINT
            111 {
            112   std::cout << alec::cursor_position(1, 1) << "operation 1";
            113   std::cout << alec::cursor_position(2, 1)
            114             << alec::erase_line_v<alec::Motion::WHOLE>
            115             << "Some operation is done";
            116   std::cout << std::flush;
            117   return 1;
            118 }
          
            120 int operation2(std::size_t /* unused */)  // NOLINT
            121 {
            122   std::cout << alec::cursor_position(1, 1) << "operation 2";
            123   std::cout << alec::cursor_position(2, 1)
            124             << alec::erase_line_v<alec::Motion::WHOLE>
            125             << "Some other operation is done";
            126   std::cout << std::flush;
            127   return 1;
            128 }
          
            130 int operation3(std::size_t /* unused */)  // NOLINT
            131 {
            132   std::cout << alec::cursor_position(1, 1) << "operation 3";
            133   std::cout << alec::cursor_position(2, 1)
            134             << alec::erase_line_v<alec::Motion::WHOLE>
            135             << "Yet another operation is done";
            136   std::cout << std::flush;
            137   return 1;
            138 }
          
            140 int finish(std::size_t /* unused */)  // NOLINT
            141 {
            142   std::cout << alec::cursor_position(1, 1)
            143             << alec::erase_line_v<alec::Motion::WHOLE>;
            144   std::cout << "finishing...";
            145   std::cout << std::flush;
            146   is_finished = true;
            147   return 0;
            148 }
          
            150 int menu_t::visit(const menu_t& menu)
            151 {
            152   using display::Display, display::Layout;
            153   using display::PvtX, display::PvtY, display::piv_t;
          
            155   auto& layout = Display::display().layout();
          
            157   static std::stack<const menu_t*> stk;
          
            159   if (!stk.empty() && stk.top()->title == menu.title) {
            160     stk.pop();
            161     if (stk.empty()) {
            162       finish(0);
            163       return 0;
            164     }
            165   } else {
            166     stk.push(&menu);
            167   }
          
            169   layout.emplace_child<WindowCustom>(piv_t(PvtX::Right, PvtY::Bottom), *stk.top());
            170   layout.render();
          
            172   return 0;
            173 }
          
            175 }  // namespace example
          
            177 int main()
            178 {
            179   try {
            180     using namespace display;  // NOLINT
          
            182     auto& display = Display::display();
            183     example::menu_main(0);
          
            185     while (!is_finished) {
            186       auto evnt = display.get_event();
            187       if (evnt.type() == event::Type::RESIZE) {
            188         std::cout << alec::erase_display_v<alec::Motion::WHOLE>;
            189         display.render();
            190         continue;
            191       }
          
            193       if (evnt.type() == event::Type::KEY) {
            194         if (evnt.key() == 'q') {
            195           break;
            196         }
            197         display.input(evnt);
            198       }
            199     }
            200   } catch (std::exception& err) {
            201     std::cout << err.what() << '\n' << std::flush;
            202   }
          
            204   return 0;
            205 }