display

Layout 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 (4747B)


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 using namespace display::literals; // NOLINT(*namespace*)
14 bool is_finished = false; // NOLINT
16 using display::WindowPivot;
18 class WindowCustom : public WindowPivot
19 {
20 public:
21 WindowCustom(
22 display::plc_t aplc, display::piv_t piv, const example::menu_t& menu
23 )
24 // NOLINTNEXTLINE(*magic*)
25 : WindowPivot(aplc, {4_w, 2_h, 5_w, 4_h}, piv, calc_dim(menu))
26 , m_menu(menu)
27 {
28 }
30 void render() const override
31 {
32 std::cout << alec::background_v<alec::color::blue>;
33 line_reset();
35 line_center(m_menu.title);
36 line_empty();
37 for (std::size_t i = 0; i < m_menu.items.size(); i++) {
38 if (m_selected == i) {
39 std::cout << alec::foreground_v<alec::color::green>;
40 }
42 line_right(m_menu.items[i].prompt);
44 if (m_selected == i) {
45 std::cout << alec::foreground_v<alec::color::def>;
46 }
47 }
49 WindowPivot::render();
50 WindowPivot::render_border();
52 std::cout << alec::background_v<alec::color::def>;
53 std::cout << std::flush;
54 }
56 void input(display::event& evnt) override
57 {
58 if (evnt.type() != display::event::type::key) {
59 return;
60 }
62 if (evnt.key() == 'j') {
63 if (m_selected + 1U < m_menu.items.size()) {
64 m_selected++;
65 }
66 evnt.type() = display::event::type::none;
67 render();
68 return;
69 }
71 if (evnt.key() == 'k') {
72 if (m_selected > 0) {
73 m_selected--;
74 }
75 evnt.type() = display::event::type::none;
76 render();
77 return;
78 }
80 if (evnt.key() == 'l') {
81 m_menu.items[m_selected].callback(m_selected);
82 evnt.type() = display::event::type::none;
83 return;
84 }
86 if (evnt.key() == 'h') {
87 m_menu.callback(0);
88 evnt.type() = display::event::type::none;
89 return;
90 }
91 }
93 private:
94 static display::dim_t calc_dim(const example::menu_t& menu)
95 {
96 using wth_t = display::wth_t;
97 using hgt_t = display::hgt_t;
99 wth_t width {menu.title.size()};
100 for (const auto& item : menu.items) {
101 const wth_t lwidth {item.prompt.size()};
102 width = std::max(width, lwidth);
105 const hgt_t height {menu.items.size() + 2};
106 return {width, height};
109 example::menu_t m_menu;
110 uint8_t m_selected = 0;
111 };
113 } // namespace
115 namespace example
118 int operation1(std::size_t /* unused */) // NOLINT
120 std::cout << alec::cursor_position(1, 1) << "operation 1";
121 std::cout << alec::cursor_position(2, 1)
122 << alec::erase_line_v<alec::motion::whole>
123 << "Some operation is done";
124 std::cout << std::flush;
125 return 1;
128 int operation2(std::size_t /* unused */) // NOLINT
130 std::cout << alec::cursor_position(1, 1) << "operation 2";
131 std::cout << alec::cursor_position(2, 1)
132 << alec::erase_line_v<alec::motion::whole>
133 << "Some other operation is done";
134 std::cout << std::flush;
135 return 1;
138 int operation3(std::size_t /* unused */) // NOLINT
140 std::cout << alec::cursor_position(1, 1) << "operation 3";
141 std::cout << alec::cursor_position(2, 1)
142 << alec::erase_line_v<alec::motion::whole>
143 << "Yet another operation is done";
144 std::cout << std::flush;
145 return 1;
148 int finish(std::size_t /* unused */) // NOLINT
150 std::cout << alec::cursor_position(1, 1)
151 << alec::erase_line_v<alec::motion::whole>;
152 std::cout << "finishing...";
153 std::cout << std::flush;
154 is_finished = true;
155 return 0;
158 int menu_t::visit(const menu_t& menu)
160 using display::Display, display::Layout;
161 using display::piv_t;
163 auto& layout = Display::display().layout();
165 static std::stack<const menu_t*> stk;
167 if (!stk.empty() && stk.top()->title == menu.title) {
168 stk.pop();
169 if (stk.empty()) {
170 finish(0);
171 return 0;
173 } else {
174 stk.push(&menu);
177 layout.set_child<WindowCustom>(
178 piv_t(piv_t::x::right, piv_t::y::bottom), *stk.top()
179 );
180 layout.render();
182 return 0;
185 } // namespace example
187 int main()
189 try {
190 using namespace display; // NOLINT
192 auto& display = Display::display();
193 example::menu_main(0);
195 while (!is_finished) {
196 auto evnt = display.get_event();
197 if (evnt.type() == event::type::resize) {
198 std::cout << alec::erase_display_v<alec::motion::whole>;
199 display.render();
200 continue;
203 if (evnt.type() == event::type::key) {
204 if (evnt.key() == 'q') {
205 break;
207 display.input(evnt);
210 } catch (std::exception& err) {
211 std::cout << err.what() << '\n' << std::flush;
214 return 0;