ui.cpp (10471B)
1 #include <chrono> 2 #include <map> 3 #include <mutex> 4 #include <ncurses.h> 5 #include <panel.h> 6 #include <string> 7 #include <thread> 8 #include <vector> 9 10 #include "colors.hpp" 11 #include "maze_gen.hpp" 12 #include "pathfinding.hpp" 13 #include "state.hpp" 14 #include "ui.hpp" 15 16 static std::string Option( 17 const std::vector<std::string>& options, 18 const std::string& current) 19 { 20 // getting the right size for the sub window 21 int win_height = options.size() + 2; 22 int win_width = options[0].size(); 23 for (std::string opt : options) 24 if (opt.size() > win_width) 25 win_width = opt.size(); 26 win_width += 2 + 10; 27 int y_max, x_mas; 28 // creating and rendering the sub window 29 s::ui_is_open = true; 30 while (!s::ui_render_is_safe) { 31 std::this_thread::sleep_for(std::chrono::milliseconds(1)); 32 } 33 s::draw.lock(); 34 attron(COLOR_PAIR(black)); 35 getmaxyx(stdscr, y_max, x_mas); 36 WINDOW* win = newwin( 37 win_height, 38 win_width, 39 (y_max / 2) - (win_height / 2), 40 (x_mas / 2) - (win_width / 2)); 41 PANEL* pan = new_panel(win); 42 box(win, 0, 0); 43 int highlight = 0; 44 // putting the highlight on the currently selected option 45 for (int i = 0; i < options.size(); ++i) 46 if (options[i] == current) 47 highlight = i; 48 int key; 49 while (true) { 50 for (int y = 0; y < options.size(); ++y) { 51 if (y == highlight) 52 wattron(win, A_REVERSE); 53 // prints the option 54 mvwprintw(win, y + 1, 2, options[y].c_str()); 55 // prints white space up to the selection box for proper 56 // highlighting 57 for (int x = options[y].size() + 2; x < win_width - 2; ++x) 58 mvwprintw(win, y + 1, x, " "); 59 // prints the selection box 60 mvwprintw(win, y + 1, win_width - 5, "[ ]"); 61 if (options[y] == current) 62 mvwprintw(win, y + 1, win_width - 4, "*"); 63 wattroff(win, A_REVERSE); 64 } 65 getkey: 66 key = wgetch(win); 67 switch (key) { 68 case 'j': 69 case KEY_DOWN: 70 ++highlight; 71 if (highlight >= options.size()) 72 highlight = 0; 73 break; 74 case 'k': 75 case KEY_UP: 76 --highlight; 77 if (highlight < 0) 78 highlight = options.size() - 1; 79 break; 80 case 10: // enter 81 case 32: // space 82 case 'l': 83 hide_panel(pan); 84 del_panel(pan); 85 update_panels(); 86 attroff(COLOR_PAIR(black)); 87 s::draw.unlock(); 88 s::ui_is_open = false; 89 return options[highlight]; 90 break; 91 case 27: // escape 92 case 'h': 93 case 'q': 94 hide_panel(pan); 95 del_panel(pan); 96 update_panels(); 97 attroff(COLOR_PAIR(black)); 98 s::draw.unlock(); 99 s::ui_is_open = false; 100 return current; 101 break; 102 default: 103 goto getkey; 104 break; 105 } 106 } 107 } 108 109 static std::string Option(const std::vector<std::string>& options) 110 { 111 // getting the right size for the sub window 112 int win_height = options.size() + 2; 113 int win_width = options[0].size(); 114 for (std::string opt : options) 115 if (opt.size() > win_width) 116 win_width = opt.size(); 117 win_width += 2 + 10; 118 int y_max, x_mas; 119 // creating and rendering the sub window 120 s::ui_is_open = true; 121 while (!s::ui_render_is_safe) { 122 std::this_thread::sleep_for(std::chrono::milliseconds(1)); 123 } 124 s::draw.lock(); 125 attron(COLOR_PAIR(black)); 126 getmaxyx(stdscr, y_max, x_mas); 127 WINDOW* win = newwin( 128 win_height, 129 win_width, 130 (y_max / 2) - (win_height / 2), 131 (x_mas / 2) - (win_width / 2)); 132 PANEL* pan = new_panel(win); 133 box(win, 0, 0); 134 int highlight = 0; 135 int key; 136 while (true) { 137 for (int y = 0; y < options.size(); ++y) { 138 if (y == highlight) 139 wattron(win, A_REVERSE); 140 // prints the option 141 mvwprintw(win, y + 1, 2, options[y].c_str()); 142 // prints white space up to the selection box for proper 143 // highlighting 144 for (int x = options[y].size() + 2; x < win_width - 2; ++x) 145 mvwprintw(win, y + 1, x, " "); 146 wattroff(win, A_REVERSE); 147 } 148 getkey: 149 key = wgetch(win); 150 switch (key) { 151 case 'j': 152 case KEY_DOWN: 153 ++highlight; 154 if (highlight >= options.size()) 155 highlight = 0; 156 break; 157 case 'k': 158 case KEY_UP: 159 --highlight; 160 if (highlight < 0) 161 highlight = options.size() - 1; 162 break; 163 case 10: // enter 164 case 32: // space 165 case 'l': 166 hide_panel(pan); 167 del_panel(pan); 168 update_panels(); 169 attroff(COLOR_PAIR(black)); 170 s::draw.unlock(); 171 s::ui_is_open = false; 172 return options[highlight]; 173 break; 174 case 27: // escape 175 case 'h': 176 case 'q': 177 hide_panel(pan); 178 del_panel(pan); 179 update_panels(); 180 attroff(COLOR_PAIR(black)); 181 s::draw.unlock(); 182 s::ui_is_open = false; 183 return ""; 184 break; 185 default: 186 goto getkey; 187 break; 188 } 189 } 190 } 191 192 void ui::RenderUI() 193 { 194 std::vector<std::string> choices = { 195 "Maze generator =>", 196 "Pathfinder =>", 197 "Render maze generation", 198 "Render path-finding", 199 "Soft time of maze generation", 200 "Hard time of maze generation", 201 "Soft time of path-finding", 202 "Hard time of path-finding", 203 "Hard time for final path drawing", 204 "Time between maze generation" 205 }; 206 207 std::string mmenu; 208 /* std::string mmenu = choices[0]; */ 209 while (true) { 210 211 mmenu = Option(choices); 212 /* mmenu = Option(choices, mmenu); */ 213 214 if (mmenu == "") 215 break; 216 217 if (mmenu == "Maze generator =>") { 218 std::vector<std::string> names; 219 // extracts the keys from the generators map and puts them in names 220 for (std::map<std::string, 221 void (*)( 222 bool*field, 223 const int&width, 224 const int&height)>::iterator it 225 = generators.begin(); 226 it != generators.end(); 227 ++it) { 228 names.push_back(it->first); 229 } 230 s::generator = Option(names, s::generator); 231 } 232 233 if (mmenu == "Pathfinder =>") { 234 std::vector<std::string> names; 235 // extracts the keys from the pathfinders map and puts them in names 236 for (std::map<std::string, 237 std::vector<vec2<int>> (*)( 238 const bool*field, 239 const int&width, 240 const int&height, 241 const vec2<int>&start, 242 const std::vector<vec2<int>>&exits)>::iterator it 243 = pathfinders.begin(); 244 it != pathfinders.end(); ++it) { 245 names.push_back(it->first); 246 } 247 s::pathfinder = Option(names, s::pathfinder); 248 } 249 } 250 } 251 252 void ui::ExecuteKeys() 253 { 254 int width, height; 255 int c; 256 while (true) { 257 getmaxyx(stdscr, height, width); 258 c = getch(); 259 s::draw.lock(); 260 attron(COLOR_PAIR(white)); 261 // clears the top portion of the screen of previous text 262 for (int i = 0; i <= width; ++i) { 263 mvprintw(0, i, " "); 264 } 265 // handles key presses 266 switch (c) { 267 case 'k': 268 s::time_hard_maze_gen += 1; 269 mvprintw(0, 0, "Maze generation hard time: %d", s::time_hard_maze_gen); 270 attroff(COLOR_PAIR(white)); 271 refresh(); 272 s::draw.unlock(); 273 break; 274 case 'K': 275 s::time_soft_maze_gen += 1; 276 mvprintw(0, 0, "Maze generation soft time: %d", s::time_soft_maze_gen); 277 attroff(COLOR_PAIR(white)); 278 refresh(); 279 s::draw.unlock(); 280 break; 281 case 'j': 282 s::time_hard_maze_gen -= 1; 283 mvprintw(0, 0, "Maze generation hard time: %d", s::time_hard_maze_gen); 284 attroff(COLOR_PAIR(white)); 285 refresh(); 286 s::draw.unlock(); 287 break; 288 case 'J': 289 s::time_soft_maze_gen -= 1; 290 mvprintw(0, 0, "Maze generation soft time: %d", s::time_soft_maze_gen); 291 attroff(COLOR_PAIR(white)); 292 refresh(); 293 s::draw.unlock(); 294 break; 295 case 'i': 296 s::time_hard_pathfinding += 1; 297 mvprintw(0, 0, "Pathfinding hard time: %d", s::time_hard_pathfinding); 298 attroff(COLOR_PAIR(white)); 299 refresh(); 300 s::draw.unlock(); 301 break; 302 case 'I': 303 s::time_soft_pathfinding += 1; 304 mvprintw(0, 0, "Pathfinding soft time: %d", s::time_soft_pathfinding); 305 attroff(COLOR_PAIR(white)); 306 refresh(); 307 s::draw.unlock(); 308 break; 309 case 'u': 310 s::time_hard_pathfinding -= 1; 311 mvprintw(0, 0, "Pathfinding hard time: %d", s::time_hard_pathfinding); 312 attroff(COLOR_PAIR(white)); 313 refresh(); 314 s::draw.unlock(); 315 break; 316 case 'U': 317 s::time_soft_pathfinding -= 1; 318 mvprintw(0, 0, "Pathfinding soft time: %d", s::time_soft_pathfinding); 319 attroff(COLOR_PAIR(white)); 320 refresh(); 321 s::draw.unlock(); 322 break; 323 case 27: 324 attroff(COLOR_PAIR(white)); 325 s::draw.unlock(); 326 RenderUI(); 327 break; 328 case 'q': 329 attroff(COLOR_PAIR(white)); 330 s::draw.unlock(); 331 endwin(); 332 exit(0); 333 default: 334 mvprintw(0, 0, "Unknown mapping: <%d>", c); 335 attroff(COLOR_PAIR(white)); 336 refresh(); 337 s::draw.unlock(); 338 break; 339 } 340 std::this_thread::sleep_for(std::chrono::milliseconds(3)); 341 } 342 }