Library to display menus on TextLCDs. Interaction with functions Up,Down and Select (Buttons or RPG) Based on menu-library from pyeh9
Fork of Menu by
Library to display menus on TextLCDs. Interaction with functions Up,Down and Select (Buttons or RPG) Based on menu-library from pyeh9
Navigator.cpp@11:6814cbc83ae0, 2016-01-13 (annotated)
- Committer:
- charly
- Date:
- Wed Jan 13 19:59:21 2016 +0000
- Revision:
- 11:6814cbc83ae0
- Parent:
- 10:2b6ddf53b05e
added show_longtext() to display a long text. With scrollbars.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
pyeh9 | 1:84d263c8932d | 1 | #include "Navigator.h" |
pyeh9 | 1:84d263c8932d | 2 | |
charly | 5:91b1bc68290b | 3 | Navigator::Navigator(Menu *root, TextLCD_Base *lcd) : activeMenu(root), lcd(lcd) |
pyeh9 | 1:84d263c8932d | 4 | { |
charly | 5:91b1bc68290b | 5 | |
charly | 5:91b1bc68290b | 6 | _cursorPos = 0; |
charly | 5:91b1bc68290b | 7 | _cursorLine = 1; |
charly | 5:91b1bc68290b | 8 | _display_rows = lcd->rows(); |
charly | 10:2b6ddf53b05e | 9 | _display_cols = lcd->columns(); |
charly | 10:2b6ddf53b05e | 10 | |
charly | 8:fbaeab73fe1a | 11 | activeMenu->CurrentSelection = _cursorPos; |
charly | 5:91b1bc68290b | 12 | |
charly | 10:2b6ddf53b05e | 13 | _wait_for_select = false; |
charly | 10:2b6ddf53b05e | 14 | _wait_for_yesno = false; |
charly | 10:2b6ddf53b05e | 15 | |
charly | 11:6814cbc83ae0 | 16 | _start_line = 0; |
charly | 11:6814cbc83ae0 | 17 | |
pyeh9 | 2:2654dc659298 | 18 | printMenu(); |
pyeh9 | 2:2654dc659298 | 19 | printCursor(); |
pyeh9 | 1:84d263c8932d | 20 | } |
pyeh9 | 1:84d263c8932d | 21 | |
pyeh9 | 1:84d263c8932d | 22 | void Navigator::printMenu() |
charly | 5:91b1bc68290b | 23 | { |
charly | 5:91b1bc68290b | 24 | int index =0; |
pyeh9 | 1:84d263c8932d | 25 | lcd->cls(); |
charly | 5:91b1bc68290b | 26 | |
charly | 5:91b1bc68290b | 27 | for(int row=0; row < _display_rows; row++) { |
charly | 5:91b1bc68290b | 28 | |
charly | 5:91b1bc68290b | 29 | lcd->locate(0,row); |
charly | 5:91b1bc68290b | 30 | index = row + _cursorPos - (_cursorLine-1); // index into selection for this line |
charly | 5:91b1bc68290b | 31 | //should we display a menu on this line? |
charly | 5:91b1bc68290b | 32 | if (index <= activeMenu->selections.size()-1 ) { |
charly | 5:91b1bc68290b | 33 | lcd->printf(" %s", activeMenu->selections[index].selText); |
pyeh9 | 1:84d263c8932d | 34 | } |
pyeh9 | 1:84d263c8932d | 35 | } |
pyeh9 | 1:84d263c8932d | 36 | } |
pyeh9 | 1:84d263c8932d | 37 | |
pyeh9 | 1:84d263c8932d | 38 | void Navigator::printCursor() |
charly | 5:91b1bc68290b | 39 | { |
charly | 5:91b1bc68290b | 40 | if(activeMenu->selections[_cursorPos].childMenu == NULL) printf("No child menu\n"); |
charly | 5:91b1bc68290b | 41 | else printf("child menu: %s\n", activeMenu->selections[_cursorPos].childMenu->menuID); |
charly | 5:91b1bc68290b | 42 | |
pyeh9 | 1:84d263c8932d | 43 | lcd->locate(0,0); |
charly | 5:91b1bc68290b | 44 | for (int row=0; row<_display_rows; row++) { |
charly | 5:91b1bc68290b | 45 | lcd->locate(0,row); |
charly | 5:91b1bc68290b | 46 | if (row == _cursorLine-1) { |
charly | 5:91b1bc68290b | 47 | //we are on Cursor-Line |
charly | 5:91b1bc68290b | 48 | //print cursor |
charly | 5:91b1bc68290b | 49 | lcd->putc('>'); |
charly | 5:91b1bc68290b | 50 | } else { |
charly | 5:91b1bc68290b | 51 | //on other lines print a space |
charly | 5:91b1bc68290b | 52 | lcd->putc(' '); |
charly | 5:91b1bc68290b | 53 | } |
pyeh9 | 1:84d263c8932d | 54 | } |
pyeh9 | 1:84d263c8932d | 55 | } |
pyeh9 | 1:84d263c8932d | 56 | |
pyeh9 | 1:84d263c8932d | 57 | |
charly | 10:2b6ddf53b05e | 58 | void Navigator::show_yes_no(bool yesorno) |
charly | 10:2b6ddf53b05e | 59 | { |
charly | 10:2b6ddf53b05e | 60 | // MenuItem is a Yes/no question? |
charly | 10:2b6ddf53b05e | 61 | // show the text in yesnodata and wait for a yes or no |
charly | 10:2b6ddf53b05e | 62 | lcd->cls(); |
charly | 10:2b6ddf53b05e | 63 | //printf("YesNo: \n"); |
charly | 10:2b6ddf53b05e | 64 | //printf("%s <Yes><No>",activeMenu->selections[_cursorPos].menu_parameter->text); |
charly | 10:2b6ddf53b05e | 65 | if (activeMenu->selections[_cursorPos].menu_parameter->text != NULL) { |
charly | 10:2b6ddf53b05e | 66 | if (yesorno) { |
charly | 10:2b6ddf53b05e | 67 | // Yes is default |
charly | 10:2b6ddf53b05e | 68 | lcd->printf("%s <Yes> No ",activeMenu->selections[_cursorPos].menu_parameter->text); |
charly | 10:2b6ddf53b05e | 69 | } else { |
charly | 10:2b6ddf53b05e | 70 | //No is default |
charly | 10:2b6ddf53b05e | 71 | lcd->printf("%s Yes <No>",activeMenu->selections[_cursorPos].menu_parameter->text); |
charly | 10:2b6ddf53b05e | 72 | } |
charly | 10:2b6ddf53b05e | 73 | activeMenu->selections[_cursorPos].menu_parameter->yes_no = yesorno; |
charly | 10:2b6ddf53b05e | 74 | } |
charly | 10:2b6ddf53b05e | 75 | } |
charly | 10:2b6ddf53b05e | 76 | |
charly | 11:6814cbc83ae0 | 77 | void Navigator::show_longtext(void) |
charly | 11:6814cbc83ae0 | 78 | { |
charly | 11:6814cbc83ae0 | 79 | int maxchunksize = _display_cols - 1; // one column for "Scrollbar" |
charly | 11:6814cbc83ae0 | 80 | // MenuItem is a long_text |
charly | 11:6814cbc83ae0 | 81 | // show the text , support scrolling up/down, wait for select |
charly | 11:6814cbc83ae0 | 82 | lcd->cls(); |
charly | 11:6814cbc83ae0 | 83 | if (activeMenu->selections[_cursorPos].menu_parameter->text != NULL) { |
charly | 11:6814cbc83ae0 | 84 | //show text starting a correct position |
charly | 11:6814cbc83ae0 | 85 | for (int row=0; row< _display_rows; row++) { |
charly | 11:6814cbc83ae0 | 86 | lcd->locate(0,row); |
charly | 11:6814cbc83ae0 | 87 | lcd->printf("%-*.*s", maxchunksize,maxchunksize, activeMenu->selections[_cursorPos].menu_parameter->text + ((_start_line+row)*(_display_cols - 1))); |
charly | 11:6814cbc83ae0 | 88 | if ((row == 0)&& (_start_line > 0)) lcd->printf("^"); |
charly | 11:6814cbc83ae0 | 89 | else if (row == _display_rows-1) lcd->printf("v"); |
charly | 11:6814cbc83ae0 | 90 | else lcd->printf("|"); |
charly | 11:6814cbc83ae0 | 91 | } |
charly | 11:6814cbc83ae0 | 92 | } |
charly | 11:6814cbc83ae0 | 93 | } |
charly | 11:6814cbc83ae0 | 94 | |
charly | 3:cfc36b42ae75 | 95 | void Navigator::select() |
charly | 3:cfc36b42ae75 | 96 | { |
charly | 11:6814cbc83ae0 | 97 | // user ressed the select button |
charly | 8:fbaeab73fe1a | 98 | Menu *lastMenu; |
charly | 10:2b6ddf53b05e | 99 | |
charly | 10:2b6ddf53b05e | 100 | // are we waiting for a Select()? |
charly | 10:2b6ddf53b05e | 101 | if (_wait_for_select) { |
charly | 10:2b6ddf53b05e | 102 | _wait_for_select = false; |
charly | 10:2b6ddf53b05e | 103 | // show the menu again |
charly | 10:2b6ddf53b05e | 104 | printMenu(); |
charly | 10:2b6ddf53b05e | 105 | printCursor(); |
charly | 10:2b6ddf53b05e | 106 | |
charly | 10:2b6ddf53b05e | 107 | } else if (_wait_for_yesno) { |
charly | 10:2b6ddf53b05e | 108 | // user selected a value |
charly | 10:2b6ddf53b05e | 109 | _wait_for_yesno = false; |
charly | 10:2b6ddf53b05e | 110 | // show the menu again |
charly | 10:2b6ddf53b05e | 111 | printMenu(); |
charly | 10:2b6ddf53b05e | 112 | printCursor(); |
charly | 10:2b6ddf53b05e | 113 | } else if(activeMenu->selections[_cursorPos].itemMode == MenuItem::mode_yes_no) { |
charly | 10:2b6ddf53b05e | 114 | show_yes_no(activeMenu->selections[_cursorPos].menu_parameter->yes_no); |
charly | 10:2b6ddf53b05e | 115 | _wait_for_yesno = true; |
charly | 11:6814cbc83ae0 | 116 | } else if(activeMenu->selections[_cursorPos].itemMode == MenuItem::mode_show_longtext) { |
charly | 11:6814cbc83ae0 | 117 | show_longtext(); |
charly | 11:6814cbc83ae0 | 118 | _wait_for_select = true; |
charly | 10:2b6ddf53b05e | 119 | } else { |
charly | 10:2b6ddf53b05e | 120 | // normal mneuItem |
charly | 10:2b6ddf53b05e | 121 | if(activeMenu->selections[_cursorPos].userAction != NULL) { |
charly | 10:2b6ddf53b05e | 122 | //execute function |
charly | 10:2b6ddf53b05e | 123 | (activeMenu->selections[_cursorPos].userAction)(); |
charly | 10:2b6ddf53b05e | 124 | // refresh the Menu |
charly | 10:2b6ddf53b05e | 125 | //printMenu(); |
charly | 10:2b6ddf53b05e | 126 | //printCursor(); |
charly | 10:2b6ddf53b05e | 127 | } |
charly | 10:2b6ddf53b05e | 128 | //change the menu? |
charly | 10:2b6ddf53b05e | 129 | if(activeMenu->selections[_cursorPos].childMenu != NULL) { |
charly | 10:2b6ddf53b05e | 130 | lastMenu = activeMenu; |
charly | 10:2b6ddf53b05e | 131 | |
charly | 10:2b6ddf53b05e | 132 | //change to childMenu |
charly | 10:2b6ddf53b05e | 133 | activeMenu = activeMenu->selections[_cursorPos].childMenu; |
charly | 10:2b6ddf53b05e | 134 | |
charly | 10:2b6ddf53b05e | 135 | // if we went up one level, set CurrectSelection of SubMenu to zero, if we come back again |
charly | 10:2b6ddf53b05e | 136 | if (activeMenu->selections[activeMenu->CurrentSelection].childMenu == lastMenu) { |
charly | 10:2b6ddf53b05e | 137 | //reset menuposition of submenu to zero |
charly | 10:2b6ddf53b05e | 138 | lastMenu->CurrentSelection = 0; |
charly | 10:2b6ddf53b05e | 139 | } |
charly | 10:2b6ddf53b05e | 140 | |
charly | 10:2b6ddf53b05e | 141 | // return to last position from that menu, if we went up on level |
charly | 10:2b6ddf53b05e | 142 | _cursorPos = activeMenu->CurrentSelection; |
charly | 10:2b6ddf53b05e | 143 | |
charly | 10:2b6ddf53b05e | 144 | _cursorLine = 1; |
charly | 10:2b6ddf53b05e | 145 | printMenu(); |
charly | 10:2b6ddf53b05e | 146 | printCursor(); |
charly | 10:2b6ddf53b05e | 147 | } |
charly | 10:2b6ddf53b05e | 148 | // only accept select after showing this menu/user_action ? |
charly | 11:6814cbc83ae0 | 149 | if ((activeMenu->selections[_cursorPos].itemMode == MenuItem::mode_wait_select) || |
charly | 11:6814cbc83ae0 | 150 | (activeMenu->selections[_cursorPos].itemMode == MenuItem::mode_show_longtext)) { |
charly | 10:2b6ddf53b05e | 151 | _wait_for_select = true; |
charly | 10:2b6ddf53b05e | 152 | } |
charly | 5:91b1bc68290b | 153 | } |
charly | 10:2b6ddf53b05e | 154 | } |
charly | 10:2b6ddf53b05e | 155 | |
charly | 10:2b6ddf53b05e | 156 | void Navigator::moveUp() |
charly | 10:2b6ddf53b05e | 157 | { |
charly | 11:6814cbc83ae0 | 158 | if (_wait_for_yesno) { |
charly | 10:2b6ddf53b05e | 159 | // change Yes/no Selection |
charly | 10:2b6ddf53b05e | 160 | show_yes_no( ! activeMenu->selections[_cursorPos].menu_parameter->yes_no); |
charly | 10:2b6ddf53b05e | 161 | |
charly | 11:6814cbc83ae0 | 162 | } else if(activeMenu->selections[_cursorPos].itemMode == MenuItem::mode_show_longtext) { |
charly | 11:6814cbc83ae0 | 163 | // show a long text |
charly | 11:6814cbc83ae0 | 164 | // can we scoll further up? |
charly | 11:6814cbc83ae0 | 165 | if (_start_line >= 1) { |
charly | 11:6814cbc83ae0 | 166 | _start_line--; |
charly | 11:6814cbc83ae0 | 167 | show_longtext(); |
charly | 11:6814cbc83ae0 | 168 | } |
charly | 11:6814cbc83ae0 | 169 | } else |
charly | 11:6814cbc83ae0 | 170 | // only if we don't wait for a select() |
charly | 11:6814cbc83ae0 | 171 | if (! _wait_for_select) { |
charly | 11:6814cbc83ae0 | 172 | // Show the MenuItems |
charly | 11:6814cbc83ae0 | 173 | // allready on TOP of Display? |
charly | 11:6814cbc83ae0 | 174 | if(_cursorLine > 1) { |
charly | 11:6814cbc83ae0 | 175 | // scroll up cursor one line |
charly | 11:6814cbc83ae0 | 176 | _cursorLine--; |
charly | 11:6814cbc83ae0 | 177 | } |
charly | 10:2b6ddf53b05e | 178 | |
charly | 11:6814cbc83ae0 | 179 | if(_cursorPos > 0) { |
charly | 11:6814cbc83ae0 | 180 | //scroll up one item |
charly | 11:6814cbc83ae0 | 181 | _cursorPos--; |
charly | 11:6814cbc83ae0 | 182 | activeMenu->CurrentSelection = _cursorPos; |
charly | 11:6814cbc83ae0 | 183 | |
charly | 11:6814cbc83ae0 | 184 | } |
charly | 11:6814cbc83ae0 | 185 | printMenu(); |
charly | 11:6814cbc83ae0 | 186 | printCursor(); |
charly | 10:2b6ddf53b05e | 187 | } |
charly | 3:cfc36b42ae75 | 188 | } |
pyeh9 | 1:84d263c8932d | 189 | |
pyeh9 | 1:84d263c8932d | 190 | void Navigator::moveDown() |
pyeh9 | 1:84d263c8932d | 191 | { |
charly | 10:2b6ddf53b05e | 192 | if (_wait_for_yesno) { |
charly | 10:2b6ddf53b05e | 193 | // change Yes/no Selection |
charly | 10:2b6ddf53b05e | 194 | show_yes_no( ! activeMenu->selections[_cursorPos].menu_parameter->yes_no); |
charly | 11:6814cbc83ae0 | 195 | } else if(activeMenu->selections[_cursorPos].itemMode == MenuItem::mode_show_longtext) { |
charly | 11:6814cbc83ae0 | 196 | // show a long text |
charly | 11:6814cbc83ae0 | 197 | // can we scoll further down? |
charly | 11:6814cbc83ae0 | 198 | if ((_start_line+_display_rows)*(_display_cols-1) < strlen(activeMenu->selections[_cursorPos].menu_parameter->text)) { |
charly | 11:6814cbc83ae0 | 199 | _start_line++; |
charly | 11:6814cbc83ae0 | 200 | show_longtext(); |
charly | 11:6814cbc83ae0 | 201 | } |
charly | 11:6814cbc83ae0 | 202 | } else |
charly | 11:6814cbc83ae0 | 203 | // only if we don't wait for a select() |
charly | 11:6814cbc83ae0 | 204 | if (! _wait_for_select) { |
charly | 11:6814cbc83ae0 | 205 | //Show the menuItem |
charly | 11:6814cbc83ae0 | 206 | // allready on last line of display? |
charly | 11:6814cbc83ae0 | 207 | if (_cursorPos == activeMenu->selections.size()-1) { |
charly | 11:6814cbc83ae0 | 208 | //stay on this line |
charly | 10:2b6ddf53b05e | 209 | } else { |
charly | 11:6814cbc83ae0 | 210 | // move down |
charly | 11:6814cbc83ae0 | 211 | if(_cursorLine < _display_rows) { |
charly | 11:6814cbc83ae0 | 212 | // Only move down cursor |
charly | 11:6814cbc83ae0 | 213 | _cursorLine++; |
charly | 11:6814cbc83ae0 | 214 | _cursorPos++; |
charly | 11:6814cbc83ae0 | 215 | } else { |
charly | 11:6814cbc83ae0 | 216 | // on last Display-Line scroll down Menu |
charly | 11:6814cbc83ae0 | 217 | _cursorPos++; |
charly | 11:6814cbc83ae0 | 218 | } |
charly | 11:6814cbc83ae0 | 219 | // save currentPosition in Menu |
charly | 11:6814cbc83ae0 | 220 | activeMenu->CurrentSelection = _cursorPos; |
charly | 5:91b1bc68290b | 221 | |
charly | 11:6814cbc83ae0 | 222 | } |
charly | 5:91b1bc68290b | 223 | |
charly | 11:6814cbc83ae0 | 224 | printMenu(); |
charly | 11:6814cbc83ae0 | 225 | printCursor(); |
charly | 11:6814cbc83ae0 | 226 | } |
charly | 10:2b6ddf53b05e | 227 | } |