GUI.cpp
1 /* ************************************************************************** */ 2 /* */ 3 /* ::: :::::::: */ 4 /* GUI.cpp :+: :+: :+: */ 5 /* +:+ +:+ +:+ */ 6 /* By: gychoi <gychoi@student.42seoul.kr> +#+ +:+ +#+ */ 7 /* +#+#+#+#+#+ +#+ */ 8 /* Created: 2023/12/04 19:56:31 by gychoi #+# #+# */ 9 /* Updated: 2023/12/11 18:29:42 by gychoi ### ########.fr */ 10 /* */ 11 /* ************************************************************************** */ 12 13 #include "GUI.hpp" 14 15 static struct termios oldTermios; 16 static struct termios newTermios; 17 18 /* ************************************************************************** */ 19 /* Terminal Interface */ 20 /* ************************************************************************** */ 21 bool configureTerminal() 22 { 23 if (tcgetattr(STDIN_FILENO, &oldTermios)) 24 { 25 return ERR; 26 } 27 28 newTermios = oldTermios; 29 30 newTermios.c_lflag &= ~(ICANON | ECHO); 31 newTermios.c_cc[VMIN] = 0; 32 newTermios.c_cc[VTIME] = 0; 33 34 if (tcsetattr(STDIN_FILENO, TCSANOW, &newTermios)) 35 { 36 return ERR; 37 } 38 39 std::cout << "\033[?25l"; 40 return OK; 41 } 42 43 void eraseTerminal() 44 { 45 std::cout << "\033[2J\033[H"; 46 } 47 48 // remove bureaucrat and form 49 void resetTerminal() 50 { 51 std::cout << "\033[m"; 52 std::cout << "\033[?25h"; 53 eraseTerminal(); 54 drawGoodbye(); 55 tcsetattr(STDIN_FILENO, TCSANOW, &oldTermios); 56 } 57 58 /* ************************************************************************** */ 59 /* Key Input */ 60 /* ************************************************************************** */ 61 int readKey(char* buf, int k) 62 { 63 if (buf[k] == '\033' && buf[k + 1] == '[') 64 { 65 switch (buf[k + 2]) 66 { 67 case 'A': return 1; // UP 68 case 'B': return 2; // DOWN 69 case 'C': return 3; // RIGHT 70 case 'D': return 4; // LEFT 71 } 72 } 73 return 0; 74 } 75 76 int readInput(void) 77 { 78 char buf[4096]; 79 int n = read(STDIN_FILENO, buf, sizeof(buf)); 80 int final_key = 0; 81 82 if (n < 0) 83 { 84 status.isError = true; 85 status.errorMessage = "FATAL: Cannot read key"; 86 return 42; 87 } 88 else if (n == 0) 89 { 90 return 0; 91 } 92 else if (n == 1) 93 { 94 if (buf[0] == '\n') 95 { 96 return 5; 97 } 98 else if (static_cast<int>(buf[0]) == 8 99 || static_cast<int>(buf[0]) == 127) 100 { 101 return 7; 102 } 103 else 104 { 105 status.letter = buf[0]; 106 return 6; 107 } 108 } 109 else 110 { 111 for (int k = 0; k <= n - 3; k += 3) 112 { 113 int key = readKey(buf, k); 114 if (key == 0) 115 { 116 continue; 117 } 118 final_key = key; 119 } 120 } 121 return final_key; 122 } 123 124 void controlKey(int key) 125 { 126 switch(key) 127 { 128 case NONE: 129 break; 130 case UP: 131 if (status.select > 0) 132 { 133 status.select--; 134 } 135 break; 136 case DOWN: 137 if ((status.stage == LOBBY || status.stage == FORM) 138 && status.select < 3) 139 { 140 status.select++; 141 } 142 else if (status.stage == CHECK 143 && status.select 144 < getArraySize(status.shrubberyArray, 8) - 1) 145 { 146 status.select++; 147 } 148 break; 149 case LEFT: 150 status.yesNo = true; 151 break; 152 case RIGHT: 153 status.yesNo = false; 154 break; 155 case ENTER: 156 status.pressEnter = true; 157 break; 158 case LETTER: 159 status.pressLetter = true; 160 break; 161 case BACKSPACE: 162 status.pressLetter = true; 163 status.pressBackSpace = true; 164 break; 165 default: 166 break; 167 } 168 status.renderStop = false; 169 } 170 171 void makeBuffer() 172 { 173 if (status.pressLetter == false) 174 { 175 return; 176 } 177 178 switch(status.stage) 179 { 180 case LOGIN: 181 switch(status.select) 182 { 183 case ID: 184 if (status.pressBackSpace == true) 185 { 186 if (status.bureaucratInfo.name.length() == 0) 187 { 188 break; 189 } 190 191 status.bureaucratInfo.name.erase( 192 status.bureaucratInfo.name.length() - 1 193 ); 194 } 195 else if (status.bureaucratInfo.name.length() < 8) 196 { 197 status.bureaucratInfo.name += status.letter; 198 } 199 break; 200 case GRADE: 201 if (status.pressBackSpace == true) 202 { 203 if (status.bureaucratInfo.grade.length() == 0) 204 { 205 break; 206 } 207 208 status.bureaucratInfo.grade.erase( 209 status.bureaucratInfo.grade.length() - 1 210 ); 211 } 212 else if (status.bureaucratInfo.grade.length() < 3) 213 { 214 status.bureaucratInfo.grade += status.letter; 215 } 216 break; 217 default: 218 break; 219 } 220 break; 221 case MESSAGE: 222 if (status.popUp == NAME 223 && status.pressBackSpace == true) 224 { 225 if (status.formInfo.name.length() == 0) 226 { 227 break; 228 } 229 230 status.formInfo.name.erase( 231 status.formInfo.name.length() - 1 232 ); 233 } 234 else if (status.popUp == NAME 235 && status.formInfo.name.length() < 8) 236 { 237 status.formInfo.name += status.letter; 238 } 239 break; 240 default: 241 break; 242 } 243 status.pressLetter = false; 244 status.pressBackSpace = false; 245 } 246 247 /* ************************************************************************** */ 248 /* Mandatory */ 249 /* ************************************************************************** */ 250 251 bool createBureaucrat() 252 { 253 status.create = true; 254 255 for (size_t i = 0; i < status.bureaucratInfo.grade.length(); ++i) 256 { 257 if (!std::isdigit(status.bureaucratInfo.grade[i])) 258 { 259 status.create = false; 260 break; 261 } 262 } 263 264 if (status.create == false) 265 { 266 status.isError = true; 267 status.errorMessage = "ERROR: Grade must be a number"; 268 } 269 return status.create; 270 } 271 272 void makeBureaucrat() 273 { 274 std::string const& name = status.bureaucratInfo.name; 275 int grade = std::atoi(status.bureaucratInfo.grade.c_str()); 276 277 Bureaucrat* bureaucrat = new Bureaucrat(name, grade); 278 279 status.bureaucratInfo.bureaucrat = bureaucrat; 280 status.bureaucratInfo.name.clear(); 281 status.bureaucratInfo.grade.clear(); 282 } 283 284 void deleteBureaucrat() 285 { 286 status.bureaucratInfo.name.clear(); 287 status.bureaucratInfo.grade.clear(); 288 delete status.bureaucratInfo.bureaucrat; 289 status.bureaucratInfo.bureaucrat = 0; 290 } 291 292 void createForm() 293 { 294 Intern intern; 295 296 switch (status.select) 297 { 298 case SHRUBBERY: 299 status.formInfo.form = intern.makeForm("shrubbery creation", 300 status.formInfo.name); 301 break; 302 case ROBOTOMY: 303 status.formInfo.form = intern.makeForm("robotomy request", 304 status.formInfo.name); 305 break; 306 case PRESIDENT: 307 status.formInfo.form = intern.makeForm("presidential pardon", 308 status.formInfo.name); 309 break; 310 default: 311 break; 312 } 313 } 314 315 void signForm() 316 { 317 try 318 { 319 if (status.bureaucratInfo.bureaucrat == 0) 320 { 321 throw std::logic_error("ERROR: bureaucrat not found"); 322 } 323 else 324 { 325 status.bureaucratInfo.bureaucrat->signForm(*status.formInfo.form); 326 } 327 } 328 catch (std::exception & e) 329 { 330 initStatus(); 331 status.stage = FORM; 332 throw; 333 }; 334 } 335 336 void executeForm() 337 { 338 try 339 { 340 if (status.bureaucratInfo.bureaucrat == 0) 341 { 342 throw std::logic_error("ERROR: bureaucrat not found"); 343 } 344 else 345 { 346 status.bureaucratInfo.bureaucrat->executeForm 347 (*status.formInfo.form); 348 } 349 } 350 catch (std::exception & e) 351 { 352 initStatus(); 353 status.stage = FORM; 354 throw; 355 } 356 catch (std::string & s) 357 { 358 status.formInfo.message = s; 359 }; 360 } 361 362 void deleteForm() 363 { 364 status.formInfo.name.clear(); 365 status.formInfo.message.clear(); 366 delete status.formInfo.form; 367 status.formInfo.form = 0; 368 } 369 370 /* ************************************************************************** */ 371 /* Logic */ 372 /* ************************************************************************** */ 373 374 void initStatus() 375 { 376 status.renderSpeed = 0.1f; 377 status.renderStop = false; 378 status.letter = '\0'; 379 // need to keep status.stage info 380 status.select = 0; 381 status.create = false; 382 status.popUp = false; 383 status.pressEnter = false; 384 status.yesNo = false; 385 status.pressLetter = false; 386 status.pressBackSpace = false; 387 // need to keey shrubberyArray 388 status.filename.clear(); 389 status.isError = false; 390 status.errorMessage.clear(); 391 } 392 393 void deleteInfo() 394 { 395 switch (status.stage) 396 { 397 case LOGIN: 398 deleteBureaucrat(); 399 break; 400 case FORM: 401 deleteForm(); 402 break; 403 default: 404 break; 405 } 406 } 407 408 void setStage() 409 { 410 if (status.renderStop == true) 411 { 412 return; 413 } 414 415 eraseTerminal(); 416 417 switch (status.stage) 418 { 419 case LOGIN: 420 drawLogin(); 421 break; 422 case LOBBY: 423 drawLobby(); 424 break; 425 case CHECK: 426 drawCheck(); 427 break; 428 case IMAGE: 429 drawImage(); 430 break; 431 case FORM: 432 drawForm(); 433 break; 434 case MESSAGE: 435 drawForm(); 436 break; 437 default: 438 break; 439 } 440 printIfError(); 441 status.renderStop = true; 442 } 443 444 void updateStatus() 445 { 446 if (status.pressEnter == false) 447 { 448 return; 449 } 450 451 switch (status.stage) 452 { 453 case LOGIN: 454 switch (status.select) 455 { 456 case ID: 457 status.select = GRADE; 458 break; 459 case GRADE: 460 status.select = CHECK_LOGIN; 461 break; 462 case CHECK_LOGIN: 463 if (status.yesNo == true) 464 { 465 if (createBureaucrat() == true) 466 { 467 makeBureaucrat(); 468 status.stage = LOBBY; 469 initStatus(); 470 } 471 else 472 { 473 status.select = GRADE; 474 status.bureaucratInfo.grade.clear(); 475 } 476 } 477 else 478 { 479 deleteBureaucrat(); 480 deleteForm(); 481 resetTerminal(); 482 exit(0); 483 } 484 break; 485 default: 486 break; 487 } 488 break; 489 case LOBBY: 490 switch (status.select) 491 { 492 case MAKE: 493 initStatus(); 494 status.stage = FORM; 495 break; 496 case SHOW: 497 initStatus(); 498 status.stage = CHECK; 499 break; 500 case LOGOUT: 501 initStatus(); 502 deleteBureaucrat(); 503 status.stage = LOGIN; 504 break; 505 case QUIT: 506 deleteBureaucrat(); 507 deleteForm(); 508 resetTerminal(); 509 exit(0); 510 break; 511 default: 512 break; 513 } 514 break; 515 case CHECK: 516 switch (status.select) 517 { 518 case BACK: 519 initStatus(); 520 status.stage = LOBBY; 521 break; 522 default: 523 setFilename(); 524 status.stage = IMAGE; 525 break; 526 } 527 break; 528 case IMAGE: 529 status.stage = CHECK; 530 break; 531 case FORM: 532 switch (status.select) 533 { 534 case BACK: 535 initStatus(); 536 status.stage = LOBBY; 537 break; 538 case SHRUBBERY: 539 initStatus(); 540 status.select = SHRUBBERY; 541 status.popUp = NAME; 542 status.stage = MESSAGE; 543 break; 544 case ROBOTOMY: 545 initStatus(); 546 status.select = ROBOTOMY; 547 status.popUp = NAME; 548 status.stage = MESSAGE; 549 break; 550 case PRESIDENT: 551 initStatus(); 552 status.select = PRESIDENT; 553 status.popUp = NAME; 554 status.stage = MESSAGE; 555 break; 556 break; 557 default: 558 break; 559 } 560 break; 561 case MESSAGE: 562 switch (status.popUp) 563 { 564 case DISABLE: 565 break; 566 case NAME: 567 changeRenderSpeed(0.1f); 568 createForm(); 569 status.yesNo = false; 570 status.popUp = SIGN; 571 break; 572 case SIGN: 573 if (status.yesNo == true) 574 { 575 signForm(); 576 } 577 status.yesNo = false; 578 status.popUp = EXECUTE; 579 break; 580 case EXECUTE: 581 if (status.yesNo == true) 582 { 583 executeForm(); 584 status.popUp = RESULT; 585 } 586 else 587 { 588 deleteForm(); 589 initStatus(); 590 status.stage = FORM; 591 } 592 break; 593 case RESULT: 594 deleteForm(); 595 initStatus(); 596 status.stage = FORM; 597 break; 598 default: 599 break; 600 } 601 break; 602 default: 603 break; 604 } 605 status.pressEnter = false; 606 } 607 608 void updatePopUp() 609 { 610 if (status.popUp == DISABLE 611 || (status.stage != FORM && status.stage != MESSAGE)) 612 { 613 return; 614 } 615 616 switch (status.select) 617 { 618 case SHRUBBERY: 619 switch (status.popUp) 620 { 621 case NAME: 622 drawNamePopUp(); 623 break; 624 case SIGN: 625 drawSignPopUp(); 626 break; 627 case EXECUTE: 628 drawExecutePopUp(); 629 break; 630 case RESULT: 631 drawShrubberyResultPopUp(); 632 break; 633 default: 634 break; 635 } 636 break; 637 case ROBOTOMY: 638 switch (status.popUp) 639 { 640 case NAME: 641 drawNamePopUp(); 642 break; 643 case SIGN: 644 drawSignPopUp(); 645 break; 646 case EXECUTE: 647 drawExecutePopUp(); 648 break; 649 case RESULT: 650 drawRobotomyResultPopUp(); 651 break; 652 default: 653 break; 654 } 655 break; 656 case PRESIDENT: 657 switch (status.popUp) 658 { 659 case NAME: 660 drawNamePopUp(); 661 break; 662 case SIGN: 663 drawSignPopUp(); 664 break; 665 case EXECUTE: 666 drawExecutePopUp(); 667 break; 668 case RESULT: 669 drawRobotomyResultPopUp(); 670 break; 671 default: 672 break; 673 } 674 break; 675 default: 676 break; 677 } 678 } 679 680 /* ************************************************************************** */ 681 /* Graphic Interfaces */ 682 /* ************************************************************************** */ 683 684 void drawLobby() 685 { 686 std::string const menu[4] = { "Make Form", 687 "Verify Task", 688 "Logout", 689 "Quit" }; 690 std::string const welcome = "Welcome to Bureaucrat.net!"; 691 size_t remainingLines = HEIGHT - 2; 692 693 /* 694 * drawing top 695 */ 696 std::cout << "┌"; 697 for (size_t i = 0; i < WIDTH - 2; i++) 698 { 699 std::cout << "─"; 700 } 701 std::cout << "┐" << std::endl; 702 703 /* 704 * drawing header 705 */ 706 size_t sideSpace = (WIDTH - welcome.length()) / 2; 707 size_t startPos = sideSpace; 708 size_t endPos = sideSpace; 709 710 std::cout << "│"; 711 for (size_t i = 0; i < startPos - 1; i++) 712 { 713 std::cout << " "; 714 } 715 std::cout << welcome; 716 for (size_t i = 0; i < endPos - 1; i++) 717 { 718 std::cout << " "; 719 } 720 std::cout << "│" << std::endl; 721 remainingLines--; 722 723 std::cout << "├"; 724 for (size_t i = 0; i < WIDTH - 2; i++) 725 { 726 std::cout << "─"; 727 } 728 std::cout << "┤" << std::endl; 729 remainingLines--; 730 731 /* 732 * drawing menu section 733 */ 734 for (int i = 0; i < 4; i++) 735 { 736 if (status.select == i) 737 { 738 std::cout << "│ " << SELECT << menu[i]; 739 } 740 else 741 { 742 std::cout << "│ " << menu[i]; 743 } 744 745 for (size_t j = 0; j < WIDTH - menu[i].length() - 4; j++) 746 { 747 std::cout << " "; 748 } 749 std::cout << RESET << " │" << std::endl; 750 remainingLines--; 751 } 752 753 for (size_t i = 0; i < remainingLines; i++) 754 { 755 std::cout << "│"; 756 for (size_t i = 0; i < WIDTH - 2; i++) 757 { 758 std::cout << " "; 759 } 760 std::cout << "│" << std::endl; 761 } 762 763 /* 764 * drawing bottom 765 */ 766 std::cout << "└"; 767 for (size_t i = 0; i < WIDTH - 2; i++) 768 { 769 std::cout << "─"; 770 } 771 std::cout << "┘" << std::endl; 772 } 773 774 void drawCheck() 775 { 776 std::string shrubberyArray[8]; 777 std::string const banner = "Verify administration work"; 778 size_t remainingLines = HEIGHT - 2; 779 780 shrubberyArray[0] = "[Back]"; 781 findAllShrubberyFiles(shrubberyArray); 782 783 for (size_t i = 0; i < 8; i++) 784 { 785 status.shrubberyArray[i] = shrubberyArray[i]; 786 } 787 /* 788 * drawing top 789 */ 790 std::cout << "┌"; 791 for (size_t i = 0; i < WIDTH - 2; i++) 792 { 793 std::cout << "─"; 794 } 795 std::cout << "┐" << std::endl; 796 797 /* 798 * drawing header 799 */ 800 size_t sideSpace = (WIDTH - banner.length()) / 2; 801 size_t startPos = sideSpace; 802 size_t endPos = sideSpace; 803 804 std::cout << "│"; 805 for (size_t i = 0; i < startPos - 1; i++) 806 { 807 std::cout << " "; 808 } 809 std::cout << banner; 810 for (size_t i = 0; i < endPos - 1; i++) 811 { 812 std::cout << " "; 813 } 814 std::cout << "│" << std::endl; 815 remainingLines--; 816 817 std::cout << "├"; 818 for (size_t i = 0; i < WIDTH - 2; i++) 819 { 820 std::cout << "─"; 821 } 822 std::cout << "┤" << std::endl; 823 remainingLines--; 824 825 /* 826 * drawing menu section 827 */ 828 829 for (int i = 0; i < 8; i++) 830 { 831 if (status.select == i) 832 { 833 std::cout << "│ " << SELECT << shrubberyArray[i]; 834 } 835 else 836 { 837 std::cout << "│ " << shrubberyArray[i]; 838 } 839 840 for (size_t j = 0; j < WIDTH - shrubberyArray[i].length() - 4; j++) 841 { 842 std::cout << " "; 843 } 844 std::cout << RESET << " │" << std::endl; 845 remainingLines--; 846 } 847 848 for (size_t i = 0; i < remainingLines; i++) 849 { 850 std::cout << "│"; 851 for (size_t i = 0; i < WIDTH - 2; i++) 852 { 853 std::cout << " "; 854 } 855 std::cout << "│" << std::endl; 856 } 857 858 /* 859 * drawing bottom 860 */ 861 std::cout << "└"; 862 for (size_t i = 0; i < WIDTH - 2; i++) 863 { 864 std::cout << "─"; 865 } 866 std::cout << "┘" << std::endl; 867 } 868 869 void drawForm() 870 { 871 std::string const menu[4] = {"[Back]", 872 "Making shrubbery", 873 "Requesting robotomy", 874 "Pardon the president"}; 875 std::string const welcome = "Choose your work"; 876 size_t remainingLines = HEIGHT - 2; 877 878 /* 879 * drawing top 880 */ 881 std::cout << "┌"; 882 for (size_t i = 0; i < WIDTH - 2; i++) 883 { 884 std::cout << "─"; 885 } 886 std::cout << "┐" << std::endl; 887 888 /* 889 * drawing header 890 */ 891 size_t sideSpace = (WIDTH - welcome.length()) / 2; 892 size_t startPos = sideSpace; 893 size_t endPos = sideSpace; 894 895 std::cout << "│"; 896 for (size_t i = 0; i < startPos - 1; i++) 897 { 898 std::cout << " "; 899 } 900 std::cout << welcome; 901 for (size_t i = 0; i < endPos - 1; i++) 902 { 903 std::cout << " "; 904 } 905 std::cout << "│" << std::endl; 906 remainingLines--; 907 908 std::cout << "├"; 909 for (size_t i = 0; i < WIDTH - 2; i++) 910 { 911 std::cout << "─"; 912 } 913 std::cout << "┤" << std::endl; 914 remainingLines--; 915 916 /* 917 * drawing menu section 918 */ 919 for (int i = 0; i < 4; i++) 920 { 921 if (status.select == i) 922 { 923 std::cout << "│ " << SELECT << menu[i]; 924 } 925 else 926 { 927 std::cout << "│ " << menu[i]; 928 } 929 930 for (size_t j = 0; j < WIDTH - menu[i].length() - 4; j++) 931 { 932 std::cout << " "; 933 } 934 std::cout << RESET << " │" << std::endl; 935 remainingLines--; 936 } 937 938 for (size_t i = 0; i < remainingLines; i++) 939 { 940 std::cout << "│"; 941 for (size_t i = 0; i < WIDTH - 2; i++) 942 { 943 std::cout << " "; 944 } 945 std::cout << "│" << std::endl; 946 } 947 948 /* 949 * drawing bottom 950 */ 951 std::cout << "└"; 952 for (size_t i = 0; i < WIDTH - 2; i++) 953 { 954 std::cout << "─"; 955 } 956 std::cout << "┘" << std::endl; 957 } 958 959 void drawSignPopUp() 960 { 961 int startPosY = (HEIGHT - BOX_HEIGHT) / 2; 962 int startPosX = (WIDTH - BOX_WIDTH) / 2; 963 size_t remainingLines = BOX_HEIGHT - 2; 964 965 /* 966 * drawing top 967 */ 968 std::cout << "\033[" << startPosY << ";" << startPosX << "H"; 969 std::cout << "┌"; 970 for (size_t i = 0; i < BOX_WIDTH - 2; i++) 971 { 972 std::cout << "─"; 973 } 974 std::cout << "┐" << std::endl; 975 976 /* 977 * drawing header 978 */ 979 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 980 std::string const message = "Do you want to sign this Form?"; 981 982 std::cout << "│ " << message; 983 for (size_t i = 0; i < BOX_WIDTH - message.length() - 4; i++) 984 { 985 std::cout << " "; 986 } 987 std::cout << " │" << std::endl; 988 remainingLines -= 2; 989 990 /* 991 * drawing body 992 */ 993 for (size_t i = 0; i < remainingLines; i++) 994 { 995 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 996 std::cout << "│"; 997 for (size_t i = 0; i < BOX_WIDTH - 2; i++) 998 { 999 std::cout << " "; 1000 } 1001 std::cout << "│" << std::endl; 1002 } 1003 1004 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1005 std::cout << "│"; 1006 for (size_t i = 0; i < MARGIN; i++) 1007 { 1008 std::cout << " "; 1009 } 1010 1011 if (status.yesNo == true) 1012 { 1013 std::cout 1014 << SELECT << "[YES]" << RESET 1015 << " " 1016 << "[NO]"; 1017 } 1018 else 1019 { 1020 std::cout 1021 << "[YES]" 1022 << " " 1023 << SELECT << "[NO]" << RESET; 1024 } 1025 1026 for (size_t i = 0; i < MARGIN; i++) 1027 { 1028 std::cout << " "; 1029 } 1030 std::cout << "│" << std::endl; 1031 1032 /* 1033 * drawing bottom 1034 */ 1035 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1036 std::cout << "└"; 1037 for (size_t i = 0; i < BOX_WIDTH - 2; i++) 1038 { 1039 std::cout << "─"; 1040 } 1041 std::cout << "┘" << std::endl; 1042 } 1043 1044 void drawNamePopUp() 1045 { 1046 int startPosY = (HEIGHT - BOX_HEIGHT) / 2; 1047 int startPosX = (WIDTH - BOX_WIDTH) / 2; 1048 size_t remainingLines = BOX_HEIGHT - 2; 1049 1050 changeRenderSpeed(0.03f); 1051 /* 1052 * drawing top 1053 */ 1054 std::cout << "\033[" << startPosY << ";" << startPosX << "H"; 1055 std::cout << "┌"; 1056 for (size_t i = 0; i < BOX_WIDTH - 2; i++) 1057 { 1058 std::cout << "─"; 1059 } 1060 std::cout << "┐" << std::endl; 1061 1062 /* 1063 * drawing header 1064 */ 1065 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1066 std::string const message = "Enter the form name"; 1067 1068 std::cout << "│ " << message; 1069 for (size_t i = 0; i < BOX_WIDTH - message.length() - 4; i++) 1070 { 1071 std::cout << " "; 1072 } 1073 std::cout << " │" << std::endl; 1074 remainingLines--; 1075 1076 /* 1077 * drawing body 1078 */ 1079 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1080 std::cout << "│ Name: "; 1081 1082 for (size_t i = 0; i < 8; i++) 1083 { 1084 if (i < status.formInfo.name.length()) 1085 { 1086 std::cout << status.formInfo.name[i]; 1087 } 1088 else if (i == status.formInfo.name.length()) 1089 { 1090 std::cout << "▆"; 1091 } 1092 else 1093 { 1094 std::cout << "_"; 1095 } 1096 } 1097 1098 for (size_t i = 0; i < BOX_WIDTH - 2 - 15; i++) 1099 { 1100 std::cout << " "; 1101 } 1102 std::cout << "│" << std::endl; 1103 remainingLines--; 1104 1105 for (size_t i = 0; i < remainingLines; i++) 1106 { 1107 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1108 std::cout << "│"; 1109 for (size_t i = 0; i < BOX_WIDTH - 2; i++) 1110 { 1111 std::cout << " "; 1112 } 1113 std::cout << "│" << std::endl; 1114 } 1115 1116 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1117 std::string const message2 = "Press [Enter] to submit"; 1118 1119 std::cout << "│ "; 1120 for (size_t i = 0; i < BOX_WIDTH - message2.length() - 4; i++) 1121 { 1122 std::cout << " "; 1123 } 1124 std::cout << message2 << " │" << std::endl; 1125 1126 /* 1127 * drawing bottom 1128 */ 1129 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1130 std::cout << "└"; 1131 for (size_t i = 0; i < BOX_WIDTH - 2; i++) 1132 { 1133 std::cout << "─"; 1134 } 1135 std::cout << "┘" << std::endl; 1136 } 1137 1138 void drawExecutePopUp() 1139 { 1140 int startPosY = (HEIGHT - BOX_HEIGHT) / 2; 1141 int startPosX = (WIDTH - BOX_WIDTH) / 2; 1142 size_t remainingLines = BOX_HEIGHT - 2; 1143 1144 /* 1145 * drawing top 1146 */ 1147 std::cout << "\033[" << startPosY << ";" << startPosX << "H"; 1148 std::cout << "┌"; 1149 for (size_t i = 0; i < BOX_WIDTH - 2; i++) 1150 { 1151 std::cout << "─"; 1152 } 1153 std::cout << "┐" << std::endl; 1154 1155 /* 1156 * drawing header 1157 */ 1158 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1159 std::string const message = "Do you want to execute this Form?"; 1160 1161 std::cout << "│ " << message; 1162 for (size_t i = 0; i < BOX_WIDTH - message.length() - 4; i++) 1163 { 1164 std::cout << " "; 1165 } 1166 std::cout << " │" << std::endl; 1167 remainingLines -= 2; 1168 1169 /* 1170 * drawing body 1171 */ 1172 for (size_t i = 0; i < remainingLines; i++) 1173 { 1174 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1175 std::cout << "│"; 1176 for (size_t i = 0; i < BOX_WIDTH - 2; i++) 1177 { 1178 std::cout << " "; 1179 } 1180 std::cout << "│" << std::endl; 1181 } 1182 1183 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1184 std::cout << "│"; 1185 for (size_t i = 0; i < MARGIN; i++) 1186 { 1187 std::cout << " "; 1188 } 1189 1190 if (status.yesNo == true) 1191 { 1192 std::cout 1193 << SELECT << "[YES]" << RESET 1194 << " " 1195 << "[NO]"; 1196 } 1197 else 1198 { 1199 std::cout 1200 << "[YES]" 1201 << " " 1202 << SELECT << "[NO]" << RESET; 1203 } 1204 1205 for (size_t i = 0; i < MARGIN; i++) 1206 { 1207 std::cout << " "; 1208 } 1209 std::cout << "│" << std::endl; 1210 1211 /* 1212 * drawing bottom 1213 */ 1214 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1215 std::cout << "└"; 1216 for (size_t i = 0; i < BOX_WIDTH - 2; i++) 1217 { 1218 std::cout << "─"; 1219 } 1220 std::cout << "┘" << std::endl; 1221 } 1222 1223 void drawShrubberyResultPopUp() 1224 { 1225 int startPosY = (HEIGHT - BOX_HEIGHT) / 2; 1226 int startPosX = (WIDTH - BOX_WIDTH) / 2; 1227 size_t remainingLines = BOX_HEIGHT - 2; 1228 1229 /* 1230 * drawing top 1231 */ 1232 std::cout << "\033[" << startPosY << ";" << startPosX << "H"; 1233 std::cout << "┌"; 1234 for (size_t i = 0; i < BOX_WIDTH - 2; i++) 1235 { 1236 std::cout << "─"; 1237 } 1238 std::cout << "┐" << std::endl; 1239 1240 /* 1241 * drawing header 1242 */ 1243 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1244 std::string const message = "Message"; 1245 1246 std::cout << "│ " << message; 1247 for (size_t i = 0; i < BOX_WIDTH - message.length() - 4; i++) 1248 { 1249 std::cout << " "; 1250 } 1251 std::cout << " │" << std::endl; 1252 remainingLines--; 1253 1254 /* 1255 * drawing body 1256 */ 1257 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1258 std::cout << "│"; 1259 for (size_t i = 0; i < BOX_WIDTH - 2; i++) 1260 { 1261 std::cout << " "; 1262 } 1263 std::cout << "│" << std::endl; 1264 remainingLines--; 1265 1266 size_t msgLen = status.formInfo.message.length(); 1267 size_t printLen = BOX_WIDTH - 4; 1268 1269 for (size_t i = 0; i < msgLen; i += printLen) 1270 { 1271 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1272 std::cout << "│ "; 1273 for (size_t j = 0; j < BOX_WIDTH - 4 && i + j < msgLen; j++) 1274 { 1275 std::cout << status.formInfo.message[i + j]; 1276 } 1277 for (int k = 0; k < static_cast<int>(printLen - (msgLen - i)); k++) 1278 { 1279 std::cout << " "; 1280 } 1281 std::cout << " │" << std::endl; 1282 if (remainingLines > 1) 1283 { 1284 remainingLines--; 1285 } 1286 } 1287 1288 for (size_t i = 0; i < remainingLines; i++) 1289 { 1290 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1291 std::cout << "│"; 1292 for (size_t i = 0; i < BOX_WIDTH - 2; i++) 1293 { 1294 std::cout << " "; 1295 } 1296 std::cout << "│" << std::endl; 1297 } 1298 1299 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1300 std::string const message2 = "Press [Enter] to continue"; 1301 1302 std::cout << "│ "; 1303 for (size_t i = 0; i < BOX_WIDTH - message2.length() - 4; i++) 1304 { 1305 std::cout << " "; 1306 } 1307 std::cout << message2 << " │" << std::endl; 1308 1309 /* 1310 * drawing bottom 1311 */ 1312 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1313 std::cout << "└"; 1314 for (size_t i = 0; i < BOX_WIDTH - 2; i++) 1315 { 1316 std::cout << "─"; 1317 } 1318 std::cout << "┘" << std::endl; 1319 } 1320 1321 void drawRobotomyResultPopUp() 1322 { 1323 int startPosY = (HEIGHT - BOX_HEIGHT) / 2; 1324 int startPosX = (WIDTH - BOX_WIDTH) / 2; 1325 size_t remainingLines = BOX_HEIGHT - 2; 1326 1327 /* 1328 * drawing top 1329 */ 1330 std::cout << "\033[" << startPosY << ";" << startPosX << "H"; 1331 std::cout << "┌"; 1332 for (size_t i = 0; i < BOX_WIDTH - 2; i++) 1333 { 1334 std::cout << "─"; 1335 } 1336 std::cout << "┐" << std::endl; 1337 1338 /* 1339 * drawing header 1340 */ 1341 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1342 std::string const message = "Message"; 1343 1344 std::cout << "│ " << message; 1345 for (size_t i = 0; i < BOX_WIDTH - message.length() - 4; i++) 1346 { 1347 std::cout << " "; 1348 } 1349 std::cout << " │" << std::endl; 1350 remainingLines--; 1351 1352 /* 1353 * drawing body 1354 */ 1355 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1356 std::cout << "│"; 1357 for (size_t i = 0; i < BOX_WIDTH - 2; i++) 1358 { 1359 std::cout << " "; 1360 } 1361 std::cout << "│" << std::endl; 1362 remainingLines--; 1363 1364 size_t msgLen = status.formInfo.message.length(); 1365 size_t printLen = BOX_WIDTH - 4; 1366 1367 for (size_t i = 0; i < msgLen; i += printLen) 1368 { 1369 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1370 std::cout << "│ "; 1371 for (size_t j = 0; j < BOX_WIDTH - 4 && i + j < msgLen; j++) 1372 { 1373 std::cout << status.formInfo.message[i + j]; 1374 } 1375 for (int k = 0; k < static_cast<int>(printLen - (msgLen - i)); k++) 1376 { 1377 std::cout << " "; 1378 } 1379 std::cout << " │" << std::endl; 1380 if (remainingLines > 1) 1381 { 1382 remainingLines--; 1383 } 1384 } 1385 1386 for (size_t i = 0; i < remainingLines; i++) 1387 { 1388 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1389 std::cout << "│"; 1390 for (size_t i = 0; i < BOX_WIDTH - 2; i++) 1391 { 1392 std::cout << " "; 1393 } 1394 std::cout << "│" << std::endl; 1395 } 1396 1397 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1398 std::string const message2 = "Press [Enter] to continue"; 1399 1400 std::cout << "│ "; 1401 for (size_t i = 0; i < BOX_WIDTH - message2.length() - 4; i++) 1402 { 1403 std::cout << " "; 1404 } 1405 std::cout << message2 << " │" << std::endl; 1406 1407 /* 1408 * drawing bottom 1409 */ 1410 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1411 std::cout << "└"; 1412 for (size_t i = 0; i < BOX_WIDTH - 2; i++) 1413 { 1414 std::cout << "─"; 1415 } 1416 std::cout << "┘" << std::endl; 1417 } 1418 1419 void drawLogin() 1420 { 1421 int startPosY = (HEIGHT - BOX_HEIGHT) / 2; 1422 int startPosX = (WIDTH - BOX_WIDTH) / 2; 1423 size_t remainingLines = BOX_HEIGHT - 2; 1424 1425 changeRenderSpeed(0.03f); 1426 /* 1427 * drawing top 1428 */ 1429 std::cout << "\033[" << startPosY << ";" << startPosX << "H"; 1430 std::cout << "┌"; 1431 for (size_t i = 0; i < BOX_WIDTH - 2; i++) 1432 { 1433 std::cout << "─"; 1434 } 1435 std::cout << "┐" << std::endl; 1436 1437 /* 1438 * drawing header 1439 */ 1440 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1441 std::string const message = "Login"; 1442 1443 std::cout << "│ " << message; 1444 for (size_t i = 0; i < BOX_WIDTH - message.length() - 4; i++) 1445 { 1446 std::cout << " "; 1447 } 1448 std::cout << " │" << std::endl; 1449 remainingLines--; 1450 1451 /* 1452 * drawing body 1453 */ 1454 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1455 std::cout << "│ Name: "; 1456 1457 for (size_t i = 0; i < 8; i++) 1458 { 1459 if (i < status.bureaucratInfo.name.length()) 1460 { 1461 std::cout << status.bureaucratInfo.name[i]; 1462 } 1463 else if (status.select == ID 1464 && i == status.bureaucratInfo.name.length()) 1465 { 1466 std::cout << "▆"; 1467 } 1468 else 1469 { 1470 std::cout << "_"; 1471 } 1472 } 1473 1474 for (size_t i = 0; i < BOX_WIDTH - 2 - 15; i++) 1475 { 1476 std::cout << " "; 1477 } 1478 std::cout << "│" << std::endl; 1479 remainingLines--; 1480 1481 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1482 std::cout << "│ Grade: "; 1483 1484 for (size_t i = 0; i < 3; i++) 1485 { 1486 if (i < status.bureaucratInfo.grade.length()) 1487 { 1488 std::cout << status.bureaucratInfo.grade[i]; 1489 } 1490 else if (status.select == GRADE 1491 && i == status.bureaucratInfo.grade.length()) 1492 { 1493 std::cout << "▆"; 1494 } 1495 else 1496 { 1497 std::cout << "_"; 1498 } 1499 } 1500 1501 for (size_t i = 0; i < BOX_WIDTH - 2 - 11; i++) 1502 { 1503 std::cout << " "; 1504 } 1505 std::cout << "│" << std::endl; 1506 remainingLines--; 1507 1508 for (size_t i = 0; i < remainingLines - 1; i++) 1509 { 1510 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1511 std::cout << "│"; 1512 for (size_t i = 0; i < BOX_WIDTH - 2; i++) 1513 { 1514 std::cout << " "; 1515 } 1516 std::cout << "│" << std::endl; 1517 } 1518 1519 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1520 std::cout << "│"; 1521 for (size_t i = 0; i < MARGIN - 2; i++) 1522 { 1523 std::cout << " "; 1524 } 1525 1526 if (status.select == CHECK_LOGIN) 1527 { 1528 if (status.yesNo == true) 1529 { 1530 std::cout 1531 << SELECT << "[Login]" << RESET 1532 << " " 1533 << "[Quit]"; 1534 } 1535 else 1536 { 1537 std::cout 1538 << "[Login]" 1539 << " " 1540 << SELECT << "[Quit]" << RESET; 1541 } 1542 } 1543 else 1544 { 1545 std::cout << "[Login]" << " " << "[Quit]"; 1546 } 1547 1548 for (size_t i = 0; i < MARGIN - 2; i++) 1549 { 1550 std::cout << " "; 1551 } 1552 std::cout << "│" << std::endl; 1553 1554 /* 1555 * drawing bottom 1556 */ 1557 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1558 std::cout << "└"; 1559 for (size_t i = 0; i < BOX_WIDTH - 2; i++) 1560 { 1561 std::cout << "─"; 1562 } 1563 std::cout << "┘" << std::endl; 1564 } 1565 1566 void drawImage() 1567 { 1568 std::ifstream file((status.filename).c_str()); 1569 1570 if (!file.is_open()) 1571 { 1572 throw "Cannot open the file"; 1573 } 1574 1575 std::string line; 1576 size_t lineCount = 0; 1577 size_t lineLength = 0; 1578 1579 while (getline(file, line)) 1580 { 1581 size_t len = line.length(); 1582 1583 if (len > lineLength) 1584 { 1585 lineLength = len; 1586 } 1587 lineCount++; 1588 } 1589 lineLength += 2; 1590 file.clear(); 1591 file.seekg(0, file.beg); 1592 file.close(); 1593 1594 int startPosY = static_cast<int>((HEIGHT - lineCount) / 2) < 0 1595 ? (HEIGHT - BOX_HEIGHT) / 2 1596 : (HEIGHT - lineCount) / 2; 1597 int startPosX = static_cast<int>((WIDTH - lineLength) / 2) < 0 1598 ? (WIDTH - BOX_WIDTH) / 2 1599 : (WIDTH - lineLength) / 2; 1600 1601 /* 1602 * drawing top 1603 */ 1604 std::cout << "\033[" << startPosY << ";" << startPosX << "H"; 1605 std::cout << "┌"; 1606 for (size_t i = 0; i < lineLength - 2; i++) 1607 { 1608 std::cout << "─"; 1609 } 1610 std::cout << "┐" << std::endl; 1611 1612 /* 1613 * drawing body 1614 */ 1615 file.open((status.filename).c_str()); 1616 1617 if (!file.is_open()) 1618 { 1619 throw "Cannot open the file"; 1620 } 1621 1622 while (getline(file, line)) 1623 { 1624 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1625 std::cout << "│"; 1626 std::cout << line; 1627 if (line.length() < lineLength) 1628 { 1629 for (size_t i = 0; i < lineLength - line.length() - 2; i++) 1630 { 1631 std::cout << " "; 1632 } 1633 } 1634 std::cout << "│" << std::endl; 1635 } 1636 file.close(); 1637 1638 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1639 std::cout << "│"; 1640 for (size_t i = 0; i < lineLength - 2; i++) 1641 { 1642 std::cout << " "; 1643 } 1644 std::cout << "│" << std::endl; 1645 1646 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1647 std::string const message2 = "Press [Enter] to close"; 1648 1649 std::cout << "│ "; 1650 for (size_t i = 0; i < lineLength - message2.length() - 4; i++) 1651 { 1652 std::cout << " "; 1653 } 1654 std::cout << message2 << " │" << std::endl; 1655 1656 /* 1657 * drawing bottom 1658 */ 1659 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1660 std::cout << "└"; 1661 for (size_t i = 0; i < lineLength - 2; i++) 1662 { 1663 std::cout << "─"; 1664 } 1665 std::cout << "┘" << std::endl; 1666 } 1667 1668 void drawGoodbye() 1669 { 1670 int startPosY = (HEIGHT - BOX_HEIGHT) / 2; 1671 int startPosX = (WIDTH - BOX_WIDTH) / 2; 1672 1673 std::cout << "\033[" << startPosY << ";" << startPosX << "H"; 1674 std::cout << "Goodbye!" << std::endl; 1675 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1676 std::cout << " 000000000" << std::endl; 1677 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1678 std::cout << " 00 00" << std::endl; 1679 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1680 std::cout << " 00000 00 00" << std::endl; 1681 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1682 std::cout << " 0 0 00 00 00 00" << std::endl; 1683 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1684 std::cout << " 0 0 00 00 00 00" << std::endl; 1685 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1686 std::cout << " 0 0 00 00 00 00" << std::endl; 1687 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1688 std::cout << " 0 0 0 00" << std::endl; 1689 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1690 std::cout << " 000000000000 00" << std::endl; 1691 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1692 std::cout << " 0 0 00 00 00" << std::endl; 1693 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1694 std::cout << " 00 0 00 00 00" << std::endl; 1695 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1696 std::cout << " 00 00000000000 00 00 00" << std::endl; 1697 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1698 std::cout << " 0 0 0000000 00" << std::endl; 1699 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1700 std::cout << " 00 0 00" << std::endl; 1701 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1702 std::cout << " 0 000000000000 00" << std::endl; 1703 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1704 std::cout << " 00 0 00 00" << std::endl; 1705 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1706 std::cout << " 000000000000 00 00" << std::endl; 1707 std::cout << "\033[" << ++startPosY << ";" << startPosX << "H"; 1708 std::cout << " 00000000000" << std::endl; 1709 std::cout << std::endl; 1710 } 1711 1712 /* ************************************************************************** */ 1713 /* Utils */ 1714 /* ************************************************************************** */ 1715 1716 void printIfError() 1717 { 1718 if (status.isError == true) 1719 { 1720 std::cout << status.errorMessage << std::endl; 1721 } 1722 } 1723 1724 void changeRenderSpeed(float speed) 1725 { 1726 status.renderSpeed = speed; 1727 } 1728 1729 void setFilename() 1730 { 1731 status.filename = status.shrubberyArray[status.select]; 1732 } 1733 1734 void findAllShrubberyFiles(std::string shrubberyArray[]) 1735 { 1736 DIR* dir; 1737 struct dirent* ent; 1738 int index = 0; 1739 1740 if ((dir = opendir(".")) == NULL) 1741 throw "Could not open directory"; 1742 1743 while ((ent = readdir(dir)) != NULL) 1744 { 1745 size_t len = strlen(ent->d_name); 1746 if (len > 10 && std::string(ent->d_name + len - 10) == "_shrubbery") 1747 { 1748 shrubberyArray[(index++ % 7) + 1] = std::string(ent->d_name); 1749 } 1750 } 1751 closedir(dir); 1752 } 1753 1754 short getArraySize(std::string const arr[], short size) 1755 { 1756 size_t count = 0; 1757 1758 for (size_t i = 0; i < static_cast<size_t>(size); i++) 1759 { 1760 if (!arr[i].empty()) 1761 { 1762 count++; 1763 } 1764 } 1765 1766 return static_cast<short>(count); 1767 }