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 }