Vinícius Alves
/
MenuLCD_copy
Então PARA...
menbed/menbedNavigator.cpp@0:92357d1220f3, 2017-05-19 (annotated)
- Committer:
- ViniR
- Date:
- Fri May 19 13:07:52 2017 +0000
- Revision:
- 0:92357d1220f3
Ent?o PARA...
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
ViniR | 0:92357d1220f3 | 1 | #include "mbed.h" |
ViniR | 0:92357d1220f3 | 2 | #include "include/menbedNavigator.h" |
ViniR | 0:92357d1220f3 | 3 | #include "include/menbedButtonEvent.h" |
ViniR | 0:92357d1220f3 | 4 | #include "include/menbedMenuMessage.h" |
ViniR | 0:92357d1220f3 | 5 | #include "include/menbedMenu.h" |
ViniR | 0:92357d1220f3 | 6 | #include <cstdio> |
ViniR | 0:92357d1220f3 | 7 | |
ViniR | 0:92357d1220f3 | 8 | extern void toggleLed3(); |
ViniR | 0:92357d1220f3 | 9 | |
ViniR | 0:92357d1220f3 | 10 | MenbedNavigator::MenbedNavigator(MenbedMenu *rootMenu, |
ViniR | 0:92357d1220f3 | 11 | MenbedDisplayer *displayer) : |
ViniR | 0:92357d1220f3 | 12 | activeMenu(rootMenu), displayer(displayer) |
ViniR | 0:92357d1220f3 | 13 | { |
ViniR | 0:92357d1220f3 | 14 | selectedItemIndex = -1; |
ViniR | 0:92357d1220f3 | 15 | topOfScreenItemIndex = 0; |
ViniR | 0:92357d1220f3 | 16 | paramEditMode = false; |
ViniR | 0:92357d1220f3 | 17 | |
ViniR | 0:92357d1220f3 | 18 | numLines = displayer->getDisplay()->getLines(); |
ViniR | 0:92357d1220f3 | 19 | lineLength = displayer->getDisplay()->getLineLength(); |
ViniR | 0:92357d1220f3 | 20 | } |
ViniR | 0:92357d1220f3 | 21 | |
ViniR | 0:92357d1220f3 | 22 | void MenbedNavigator::updateDisplay() |
ViniR | 0:92357d1220f3 | 23 | { |
ViniR | 0:92357d1220f3 | 24 | MenbedMenuMessage menuMsg (numLines, lineLength); |
ViniR | 0:92357d1220f3 | 25 | |
ViniR | 0:92357d1220f3 | 26 | printMenu (menuMsg.text); |
ViniR | 0:92357d1220f3 | 27 | menuMsg.showUpArrow = (topOfScreenItemIndex >= 1); |
ViniR | 0:92357d1220f3 | 28 | menuMsg.showDownArrow = (topOfScreenItemIndex + numLines < (int)(activeMenu->menuItems.size())); |
ViniR | 0:92357d1220f3 | 29 | |
ViniR | 0:92357d1220f3 | 30 | displayer->update (&menuMsg); |
ViniR | 0:92357d1220f3 | 31 | } |
ViniR | 0:92357d1220f3 | 32 | |
ViniR | 0:92357d1220f3 | 33 | |
ViniR | 0:92357d1220f3 | 34 | void MenbedNavigator::handleButtonEvent (MenbedButtonEvent buttonEvent) |
ViniR | 0:92357d1220f3 | 35 | { |
ViniR | 0:92357d1220f3 | 36 | numButtons = buttonEvent.numButtons; |
ViniR | 0:92357d1220f3 | 37 | |
ViniR | 0:92357d1220f3 | 38 | switch (buttonEvent.name) |
ViniR | 0:92357d1220f3 | 39 | { |
ViniR | 0:92357d1220f3 | 40 | case MenbedButtonEvent::ButtonSelect: // Select |
ViniR | 0:92357d1220f3 | 41 | if (!paramEditMode && (buttonEvent.action == |
ViniR | 0:92357d1220f3 | 42 | MenbedButtonEvent::BUTTON_ACTION_RELEASED_SHORT)) |
ViniR | 0:92357d1220f3 | 43 | selectItem(); |
ViniR | 0:92357d1220f3 | 44 | else if (paramEditMode && (buttonEvent.action == |
ViniR | 0:92357d1220f3 | 45 | MenbedButtonEvent::BUTTON_ACTION_RELEASED_SHORT)) |
ViniR | 0:92357d1220f3 | 46 | saveParam(); |
ViniR | 0:92357d1220f3 | 47 | else if ((numButtons < 4) && |
ViniR | 0:92357d1220f3 | 48 | paramEditMode && (buttonEvent.action == |
ViniR | 0:92357d1220f3 | 49 | MenbedButtonEvent::BUTTON_ACTION_HELD_LONG)) |
ViniR | 0:92357d1220f3 | 50 | restoreParam(); |
ViniR | 0:92357d1220f3 | 51 | else if ((numButtons < 4) && !paramEditMode && |
ViniR | 0:92357d1220f3 | 52 | (buttonEvent.action == |
ViniR | 0:92357d1220f3 | 53 | MenbedButtonEvent::BUTTON_ACTION_HELD_LONG)) |
ViniR | 0:92357d1220f3 | 54 | gotoParent(); |
ViniR | 0:92357d1220f3 | 55 | break; |
ViniR | 0:92357d1220f3 | 56 | |
ViniR | 0:92357d1220f3 | 57 | case MenbedButtonEvent::ButtonDown: |
ViniR | 0:92357d1220f3 | 58 | if (paramEditMode && |
ViniR | 0:92357d1220f3 | 59 | (buttonEvent.action == MenbedButtonEvent::BUTTON_ACTION_PUSHED)) |
ViniR | 0:92357d1220f3 | 60 | decParam(); |
ViniR | 0:92357d1220f3 | 61 | else if (!paramEditMode && |
ViniR | 0:92357d1220f3 | 62 | (buttonEvent.action == MenbedButtonEvent::BUTTON_ACTION_PUSHED)) |
ViniR | 0:92357d1220f3 | 63 | moveDown(); |
ViniR | 0:92357d1220f3 | 64 | break; |
ViniR | 0:92357d1220f3 | 65 | |
ViniR | 0:92357d1220f3 | 66 | case MenbedButtonEvent::ButtonUp: |
ViniR | 0:92357d1220f3 | 67 | if (numButtons > 2) |
ViniR | 0:92357d1220f3 | 68 | { |
ViniR | 0:92357d1220f3 | 69 | if (paramEditMode && |
ViniR | 0:92357d1220f3 | 70 | (buttonEvent.action == MenbedButtonEvent::BUTTON_ACTION_PUSHED)) |
ViniR | 0:92357d1220f3 | 71 | incParam(); |
ViniR | 0:92357d1220f3 | 72 | else if (!paramEditMode && |
ViniR | 0:92357d1220f3 | 73 | (buttonEvent.action == MenbedButtonEvent::BUTTON_ACTION_PUSHED)) |
ViniR | 0:92357d1220f3 | 74 | moveUp(); |
ViniR | 0:92357d1220f3 | 75 | } |
ViniR | 0:92357d1220f3 | 76 | break; |
ViniR | 0:92357d1220f3 | 77 | |
ViniR | 0:92357d1220f3 | 78 | case MenbedButtonEvent::ButtonCancel: |
ViniR | 0:92357d1220f3 | 79 | if (numButtons > 3) |
ViniR | 0:92357d1220f3 | 80 | { |
ViniR | 0:92357d1220f3 | 81 | if (paramEditMode && |
ViniR | 0:92357d1220f3 | 82 | (buttonEvent.action == MenbedButtonEvent::BUTTON_ACTION_PUSHED)) |
ViniR | 0:92357d1220f3 | 83 | restoreParam(); |
ViniR | 0:92357d1220f3 | 84 | else if (!paramEditMode && |
ViniR | 0:92357d1220f3 | 85 | (buttonEvent.action == MenbedButtonEvent::BUTTON_ACTION_PUSHED)) |
ViniR | 0:92357d1220f3 | 86 | gotoParent(); |
ViniR | 0:92357d1220f3 | 87 | } |
ViniR | 0:92357d1220f3 | 88 | break; |
ViniR | 0:92357d1220f3 | 89 | } |
ViniR | 0:92357d1220f3 | 90 | |
ViniR | 0:92357d1220f3 | 91 | updateDisplay(); |
ViniR | 0:92357d1220f3 | 92 | //menuRefresh_refreshed(); |
ViniR | 0:92357d1220f3 | 93 | } |
ViniR | 0:92357d1220f3 | 94 | |
ViniR | 0:92357d1220f3 | 95 | |
ViniR | 0:92357d1220f3 | 96 | void MenbedNavigator::selectItem() |
ViniR | 0:92357d1220f3 | 97 | { |
ViniR | 0:92357d1220f3 | 98 | MenbedMenu **childMenuPtr; |
ViniR | 0:92357d1220f3 | 99 | MenbedMenu *childMenu; |
ViniR | 0:92357d1220f3 | 100 | |
ViniR | 0:92357d1220f3 | 101 | if ((selectedItemIndex < 0) || |
ViniR | 0:92357d1220f3 | 102 | (selectedItemIndex >= (int)(activeMenu->menuItems.size()))) |
ViniR | 0:92357d1220f3 | 103 | return; |
ViniR | 0:92357d1220f3 | 104 | |
ViniR | 0:92357d1220f3 | 105 | // If it exists, execute the function associated with the menu item |
ViniR | 0:92357d1220f3 | 106 | if (activeMenu->menuItems[selectedItemIndex]->selFcn != NULL) |
ViniR | 0:92357d1220f3 | 107 | activeMenu->menuItems[selectedItemIndex]->selFcn(); |
ViniR | 0:92357d1220f3 | 108 | |
ViniR | 0:92357d1220f3 | 109 | // Show the child menu associated with the menu item. Initially, the first |
ViniR | 0:92357d1220f3 | 110 | // item in the child menu is placed at the top of the screen, but is it |
ViniR | 0:92357d1220f3 | 111 | // left unselected. |
ViniR | 0:92357d1220f3 | 112 | childMenuPtr = activeMenu->menuItems[selectedItemIndex]->childMenu; |
ViniR | 0:92357d1220f3 | 113 | if (childMenuPtr != NULL) |
ViniR | 0:92357d1220f3 | 114 | { |
ViniR | 0:92357d1220f3 | 115 | childMenu = *(activeMenu->menuItems[selectedItemIndex]->childMenu); |
ViniR | 0:92357d1220f3 | 116 | |
ViniR | 0:92357d1220f3 | 117 | if (!activeMenu->menuItems[selectedItemIndex]->childMenuIsAncestor) |
ViniR | 0:92357d1220f3 | 118 | { |
ViniR | 0:92357d1220f3 | 119 | childMenu->parentMenu = activeMenu; |
ViniR | 0:92357d1220f3 | 120 | childMenu->parentSelectedItemIndex = selectedItemIndex; |
ViniR | 0:92357d1220f3 | 121 | childMenu->parentTopOfScreenItemIndex = topOfScreenItemIndex; |
ViniR | 0:92357d1220f3 | 122 | } |
ViniR | 0:92357d1220f3 | 123 | else |
ViniR | 0:92357d1220f3 | 124 | childMenu->parentMenu = NULL; |
ViniR | 0:92357d1220f3 | 125 | |
ViniR | 0:92357d1220f3 | 126 | activeMenu = childMenu; |
ViniR | 0:92357d1220f3 | 127 | topOfScreenItemIndex = 0; |
ViniR | 0:92357d1220f3 | 128 | selectedItemIndex = -1; |
ViniR | 0:92357d1220f3 | 129 | } |
ViniR | 0:92357d1220f3 | 130 | // Otherwise, if the current menu item has a parameter that can be modified, |
ViniR | 0:92357d1220f3 | 131 | // we switch to the parameter editing mode. |
ViniR | 0:92357d1220f3 | 132 | else if ((activeMenu->menuItems[selectedItemIndex]->param != NULL) && |
ViniR | 0:92357d1220f3 | 133 | (activeMenu->menuItems[selectedItemIndex]->param->inc() != 0)) |
ViniR | 0:92357d1220f3 | 134 | { |
ViniR | 0:92357d1220f3 | 135 | // All incrementing and decrementing of the parameter actually happens |
ViniR | 0:92357d1220f3 | 136 | // to a shadow variable in the param structure named tempValue. The |
ViniR | 0:92357d1220f3 | 137 | // parameter value used by the other parts of the system is not updated |
ViniR | 0:92357d1220f3 | 138 | // until the user is done editing the parameter. |
ViniR | 0:92357d1220f3 | 139 | activeMenu->menuItems[selectedItemIndex]->param->initVal = |
ViniR | 0:92357d1220f3 | 140 | activeMenu->menuItems[selectedItemIndex]->param->getVal(); |
ViniR | 0:92357d1220f3 | 141 | activeMenu->menuItems[selectedItemIndex]->param->tempVal = |
ViniR | 0:92357d1220f3 | 142 | activeMenu->menuItems[selectedItemIndex]->param->initVal; |
ViniR | 0:92357d1220f3 | 143 | paramEditMode = true; |
ViniR | 0:92357d1220f3 | 144 | } |
ViniR | 0:92357d1220f3 | 145 | } |
ViniR | 0:92357d1220f3 | 146 | |
ViniR | 0:92357d1220f3 | 147 | |
ViniR | 0:92357d1220f3 | 148 | void MenbedNavigator::gotoParent() |
ViniR | 0:92357d1220f3 | 149 | { |
ViniR | 0:92357d1220f3 | 150 | if (activeMenu->parentMenu == NULL) |
ViniR | 0:92357d1220f3 | 151 | return; |
ViniR | 0:92357d1220f3 | 152 | |
ViniR | 0:92357d1220f3 | 153 | selectedItemIndex = activeMenu->parentSelectedItemIndex; |
ViniR | 0:92357d1220f3 | 154 | topOfScreenItemIndex = activeMenu->parentTopOfScreenItemIndex; |
ViniR | 0:92357d1220f3 | 155 | activeMenu = activeMenu->parentMenu; |
ViniR | 0:92357d1220f3 | 156 | } |
ViniR | 0:92357d1220f3 | 157 | |
ViniR | 0:92357d1220f3 | 158 | |
ViniR | 0:92357d1220f3 | 159 | void MenbedNavigator::moveUp() |
ViniR | 0:92357d1220f3 | 160 | { |
ViniR | 0:92357d1220f3 | 161 | // If we're already at the top of the menu, do nothing |
ViniR | 0:92357d1220f3 | 162 | if (selectedItemIndex <= -1) |
ViniR | 0:92357d1220f3 | 163 | return; |
ViniR | 0:92357d1220f3 | 164 | // If the top item of the menu is already selected, we send a NOP message |
ViniR | 0:92357d1220f3 | 165 | // which deselects the top line and displays the down arrow if the menu |
ViniR | 0:92357d1220f3 | 166 | // contains more items than can fit on the screen. In effect, this allows |
ViniR | 0:92357d1220f3 | 167 | // the user to deselect all menu items which adds a nice look to the system. |
ViniR | 0:92357d1220f3 | 168 | else if (selectedItemIndex == 0) |
ViniR | 0:92357d1220f3 | 169 | selectedItemIndex = -1; |
ViniR | 0:92357d1220f3 | 170 | // If the currently selected menu item is the also the one at the top of the |
ViniR | 0:92357d1220f3 | 171 | // screen, we need to scroll the screen down and add the item above the |
ViniR | 0:92357d1220f3 | 172 | // currently selected one to the top of the screen. |
ViniR | 0:92357d1220f3 | 173 | else if (selectedItemIndex == topOfScreenItemIndex) |
ViniR | 0:92357d1220f3 | 174 | { |
ViniR | 0:92357d1220f3 | 175 | selectedItemIndex--; |
ViniR | 0:92357d1220f3 | 176 | topOfScreenItemIndex--; |
ViniR | 0:92357d1220f3 | 177 | } |
ViniR | 0:92357d1220f3 | 178 | // The selected item is not the top item on the screen. All we need to do |
ViniR | 0:92357d1220f3 | 179 | // is select the item above the currently selected item. |
ViniR | 0:92357d1220f3 | 180 | else |
ViniR | 0:92357d1220f3 | 181 | selectedItemIndex--; |
ViniR | 0:92357d1220f3 | 182 | } |
ViniR | 0:92357d1220f3 | 183 | |
ViniR | 0:92357d1220f3 | 184 | |
ViniR | 0:92357d1220f3 | 185 | |
ViniR | 0:92357d1220f3 | 186 | void MenbedNavigator::moveDown() |
ViniR | 0:92357d1220f3 | 187 | { |
ViniR | 0:92357d1220f3 | 188 | // If the last item of the menu is already selected, our behavior depends |
ViniR | 0:92357d1220f3 | 189 | // on how many buttons are present. If there is no up button, we cycle |
ViniR | 0:92357d1220f3 | 190 | // back to the top of the menu. Otherwise, if an up button is present, |
ViniR | 0:92357d1220f3 | 191 | // we do nothing. |
ViniR | 0:92357d1220f3 | 192 | if (selectedItemIndex >= ((int)(activeMenu->menuItems.size()) - 1)) |
ViniR | 0:92357d1220f3 | 193 | { |
ViniR | 0:92357d1220f3 | 194 | if (numButtons < 3) |
ViniR | 0:92357d1220f3 | 195 | { |
ViniR | 0:92357d1220f3 | 196 | selectedItemIndex = -1; |
ViniR | 0:92357d1220f3 | 197 | topOfScreenItemIndex = 0; |
ViniR | 0:92357d1220f3 | 198 | } |
ViniR | 0:92357d1220f3 | 199 | else |
ViniR | 0:92357d1220f3 | 200 | ; |
ViniR | 0:92357d1220f3 | 201 | } |
ViniR | 0:92357d1220f3 | 202 | // If the menu item displayed at the bottom of the screen is already |
ViniR | 0:92357d1220f3 | 203 | // selected, we will need to scroll the screen up to make room for a new |
ViniR | 0:92357d1220f3 | 204 | // line at the bottom of the screen. |
ViniR | 0:92357d1220f3 | 205 | else if (selectedItemIndex == |
ViniR | 0:92357d1220f3 | 206 | (topOfScreenItemIndex + numLines - 1)) |
ViniR | 0:92357d1220f3 | 207 | { |
ViniR | 0:92357d1220f3 | 208 | selectedItemIndex++; |
ViniR | 0:92357d1220f3 | 209 | topOfScreenItemIndex++; |
ViniR | 0:92357d1220f3 | 210 | } |
ViniR | 0:92357d1220f3 | 211 | // Otherwise, if the currently selected menu item is now the one displayed |
ViniR | 0:92357d1220f3 | 212 | // at the bottom of the screen, we simply change which of the visible items |
ViniR | 0:92357d1220f3 | 213 | // is highlighted. |
ViniR | 0:92357d1220f3 | 214 | else |
ViniR | 0:92357d1220f3 | 215 | selectedItemIndex++; |
ViniR | 0:92357d1220f3 | 216 | |
ViniR | 0:92357d1220f3 | 217 | } |
ViniR | 0:92357d1220f3 | 218 | |
ViniR | 0:92357d1220f3 | 219 | |
ViniR | 0:92357d1220f3 | 220 | void MenbedNavigator::incParam() |
ViniR | 0:92357d1220f3 | 221 | { |
ViniR | 0:92357d1220f3 | 222 | float inc; |
ViniR | 0:92357d1220f3 | 223 | float tempVal; |
ViniR | 0:92357d1220f3 | 224 | |
ViniR | 0:92357d1220f3 | 225 | if (paramEditMode != true) |
ViniR | 0:92357d1220f3 | 226 | return; |
ViniR | 0:92357d1220f3 | 227 | |
ViniR | 0:92357d1220f3 | 228 | inc = activeMenu->menuItems[selectedItemIndex]->param->inc(); |
ViniR | 0:92357d1220f3 | 229 | |
ViniR | 0:92357d1220f3 | 230 | // Initialize our own local copy of the parameter's temporary value. We do |
ViniR | 0:92357d1220f3 | 231 | // this so that we can more easily check for violations of the allowed min |
ViniR | 0:92357d1220f3 | 232 | // and max values. |
ViniR | 0:92357d1220f3 | 233 | tempVal = activeMenu->menuItems[selectedItemIndex]->param->tempVal; |
ViniR | 0:92357d1220f3 | 234 | tempVal += inc; |
ViniR | 0:92357d1220f3 | 235 | |
ViniR | 0:92357d1220f3 | 236 | // Check the bounds on the parameter. |
ViniR | 0:92357d1220f3 | 237 | if (tempVal > activeMenu->menuItems[selectedItemIndex]->param->max()) |
ViniR | 0:92357d1220f3 | 238 | tempVal = activeMenu->menuItems[selectedItemIndex]->param->max(); |
ViniR | 0:92357d1220f3 | 239 | else if (tempVal < activeMenu->menuItems[selectedItemIndex]->param->min()) |
ViniR | 0:92357d1220f3 | 240 | tempVal = activeMenu->menuItems[selectedItemIndex]->param->min(); |
ViniR | 0:92357d1220f3 | 241 | |
ViniR | 0:92357d1220f3 | 242 | // Assign the local temp. value back to the temporary value in the active |
ViniR | 0:92357d1220f3 | 243 | // parameter structue. |
ViniR | 0:92357d1220f3 | 244 | activeMenu->menuItems[selectedItemIndex]->param->tempVal = tempVal; |
ViniR | 0:92357d1220f3 | 245 | |
ViniR | 0:92357d1220f3 | 246 | // If the parameter is configured to produce live updates, call the |
ViniR | 0:92357d1220f3 | 247 | // finalValFcn. |
ViniR | 0:92357d1220f3 | 248 | if (activeMenu->menuItems[selectedItemIndex]->param->liveUpdate()) |
ViniR | 0:92357d1220f3 | 249 | activeMenu->menuItems[selectedItemIndex]->param->setVal(tempVal); |
ViniR | 0:92357d1220f3 | 250 | } |
ViniR | 0:92357d1220f3 | 251 | |
ViniR | 0:92357d1220f3 | 252 | |
ViniR | 0:92357d1220f3 | 253 | void MenbedNavigator::decParam() |
ViniR | 0:92357d1220f3 | 254 | { |
ViniR | 0:92357d1220f3 | 255 | float inc; |
ViniR | 0:92357d1220f3 | 256 | float tempVal; |
ViniR | 0:92357d1220f3 | 257 | |
ViniR | 0:92357d1220f3 | 258 | if (paramEditMode != true) |
ViniR | 0:92357d1220f3 | 259 | return; |
ViniR | 0:92357d1220f3 | 260 | |
ViniR | 0:92357d1220f3 | 261 | inc = activeMenu->menuItems[selectedItemIndex]->param->inc(); |
ViniR | 0:92357d1220f3 | 262 | |
ViniR | 0:92357d1220f3 | 263 | // Initialize our own local copy of the parameter's temporary value. We do |
ViniR | 0:92357d1220f3 | 264 | // this so that we can more easily check for violations of the allowed min |
ViniR | 0:92357d1220f3 | 265 | // and max values. |
ViniR | 0:92357d1220f3 | 266 | tempVal = activeMenu->menuItems[selectedItemIndex]->param->tempVal; |
ViniR | 0:92357d1220f3 | 267 | tempVal -= inc; |
ViniR | 0:92357d1220f3 | 268 | |
ViniR | 0:92357d1220f3 | 269 | // Check the bounds on the parameter. |
ViniR | 0:92357d1220f3 | 270 | if (tempVal > activeMenu->menuItems[selectedItemIndex]->param->max()) |
ViniR | 0:92357d1220f3 | 271 | tempVal = activeMenu->menuItems[selectedItemIndex]->param->max(); |
ViniR | 0:92357d1220f3 | 272 | // If we reach the minimum parameter value when we only have a down button |
ViniR | 0:92357d1220f3 | 273 | // and not an up button connected to the system, we wrap the parameter |
ViniR | 0:92357d1220f3 | 274 | // value back around to its maximum. Otherwise, if there is an up button |
ViniR | 0:92357d1220f3 | 275 | // present, we peg the parameter at its minimum value. |
ViniR | 0:92357d1220f3 | 276 | else if (tempVal < activeMenu->menuItems[selectedItemIndex]->param->min()) |
ViniR | 0:92357d1220f3 | 277 | { |
ViniR | 0:92357d1220f3 | 278 | if (numButtons >= 3) |
ViniR | 0:92357d1220f3 | 279 | tempVal = activeMenu->menuItems[selectedItemIndex]->param->min(); |
ViniR | 0:92357d1220f3 | 280 | else |
ViniR | 0:92357d1220f3 | 281 | tempVal = activeMenu->menuItems[selectedItemIndex]->param->max(); |
ViniR | 0:92357d1220f3 | 282 | } |
ViniR | 0:92357d1220f3 | 283 | |
ViniR | 0:92357d1220f3 | 284 | // Assign the local temp. value back to the temporary value in the active |
ViniR | 0:92357d1220f3 | 285 | // parameter structue. |
ViniR | 0:92357d1220f3 | 286 | activeMenu->menuItems[selectedItemIndex]->param->tempVal = tempVal; |
ViniR | 0:92357d1220f3 | 287 | |
ViniR | 0:92357d1220f3 | 288 | // If the parameter is configured to produce live updates, call the |
ViniR | 0:92357d1220f3 | 289 | // finalValFcn. |
ViniR | 0:92357d1220f3 | 290 | if (activeMenu->menuItems[selectedItemIndex]->param->liveUpdate()) |
ViniR | 0:92357d1220f3 | 291 | activeMenu->menuItems[selectedItemIndex]->param->setVal(tempVal); |
ViniR | 0:92357d1220f3 | 292 | } |
ViniR | 0:92357d1220f3 | 293 | |
ViniR | 0:92357d1220f3 | 294 | |
ViniR | 0:92357d1220f3 | 295 | void MenbedNavigator::saveParam() |
ViniR | 0:92357d1220f3 | 296 | { |
ViniR | 0:92357d1220f3 | 297 | // Save the changes made the shadow variable tempValue to the real parameter |
ViniR | 0:92357d1220f3 | 298 | // value that is used by the rest of the application. |
ViniR | 0:92357d1220f3 | 299 | activeMenu->menuItems[selectedItemIndex]->param->setVal ( |
ViniR | 0:92357d1220f3 | 300 | activeMenu->menuItems[selectedItemIndex]->param->tempVal |
ViniR | 0:92357d1220f3 | 301 | ); |
ViniR | 0:92357d1220f3 | 302 | paramEditMode = false; |
ViniR | 0:92357d1220f3 | 303 | } |
ViniR | 0:92357d1220f3 | 304 | |
ViniR | 0:92357d1220f3 | 305 | |
ViniR | 0:92357d1220f3 | 306 | void MenbedNavigator::restoreParam() |
ViniR | 0:92357d1220f3 | 307 | { |
ViniR | 0:92357d1220f3 | 308 | // Revert any changes made the parameter by calling the finalValFcn with |
ViniR | 0:92357d1220f3 | 309 | // the initVal that was stored when we first began editing this parameter. |
ViniR | 0:92357d1220f3 | 310 | activeMenu->menuItems[selectedItemIndex]->param->setVal( |
ViniR | 0:92357d1220f3 | 311 | activeMenu->menuItems[selectedItemIndex]->param->initVal |
ViniR | 0:92357d1220f3 | 312 | ); |
ViniR | 0:92357d1220f3 | 313 | paramEditMode = false; |
ViniR | 0:92357d1220f3 | 314 | } |
ViniR | 0:92357d1220f3 | 315 | |
ViniR | 0:92357d1220f3 | 316 | |
ViniR | 0:92357d1220f3 | 317 | void MenbedNavigator::printMenu (char *menuStr) |
ViniR | 0:92357d1220f3 | 318 | { |
ViniR | 0:92357d1220f3 | 319 | uint8_t i; |
ViniR | 0:92357d1220f3 | 320 | char *lineStr = new char[lineLength]; |
ViniR | 0:92357d1220f3 | 321 | bool itemSel; |
ViniR | 0:92357d1220f3 | 322 | |
ViniR | 0:92357d1220f3 | 323 | menuStr[0] = '\0'; |
ViniR | 0:92357d1220f3 | 324 | |
ViniR | 0:92357d1220f3 | 325 | for (i=topOfScreenItemIndex; i<topOfScreenItemIndex + numLines; i++) |
ViniR | 0:92357d1220f3 | 326 | { |
ViniR | 0:92357d1220f3 | 327 | // Make sure we don't try to print more menu items than exist in the |
ViniR | 0:92357d1220f3 | 328 | // active menu. |
ViniR | 0:92357d1220f3 | 329 | if (i > ((int)activeMenu->menuItems.size() - 1)) |
ViniR | 0:92357d1220f3 | 330 | { |
ViniR | 0:92357d1220f3 | 331 | strcat (menuStr, "\n"); |
ViniR | 0:92357d1220f3 | 332 | continue; |
ViniR | 0:92357d1220f3 | 333 | } |
ViniR | 0:92357d1220f3 | 334 | |
ViniR | 0:92357d1220f3 | 335 | itemSel = (i == selectedItemIndex); |
ViniR | 0:92357d1220f3 | 336 | |
ViniR | 0:92357d1220f3 | 337 | printItem (activeMenu->menuItems[i], lineStr, itemSel, |
ViniR | 0:92357d1220f3 | 338 | paramEditMode && itemSel); |
ViniR | 0:92357d1220f3 | 339 | |
ViniR | 0:92357d1220f3 | 340 | strncat (menuStr, lineStr, lineLength); |
ViniR | 0:92357d1220f3 | 341 | strcat (menuStr, "\n"); |
ViniR | 0:92357d1220f3 | 342 | } |
ViniR | 0:92357d1220f3 | 343 | |
ViniR | 0:92357d1220f3 | 344 | delete[] lineStr; |
ViniR | 0:92357d1220f3 | 345 | } |
ViniR | 0:92357d1220f3 | 346 | |
ViniR | 0:92357d1220f3 | 347 | |
ViniR | 0:92357d1220f3 | 348 | void MenbedNavigator::printItem (MenbedMenuItem *item, char *line, bool itemSel, |
ViniR | 0:92357d1220f3 | 349 | bool paramSel) |
ViniR | 0:92357d1220f3 | 350 | { |
ViniR | 0:92357d1220f3 | 351 | uint8_t i = 0; |
ViniR | 0:92357d1220f3 | 352 | int8_t j; |
ViniR | 0:92357d1220f3 | 353 | char *tempStr = new char[lineLength]; |
ViniR | 0:92357d1220f3 | 354 | char *frontTab, *backTab; |
ViniR | 0:92357d1220f3 | 355 | char *subStr = new char[lineLength]; |
ViniR | 0:92357d1220f3 | 356 | uint8_t copySize; |
ViniR | 0:92357d1220f3 | 357 | |
ViniR | 0:92357d1220f3 | 358 | // Clear the line of text |
ViniR | 0:92357d1220f3 | 359 | line[0] = '\0'; |
ViniR | 0:92357d1220f3 | 360 | |
ViniR | 0:92357d1220f3 | 361 | // Iterate over the element in the array of text strings in the provided |
ViniR | 0:92357d1220f3 | 362 | // menu item until an empty string is found indicating the end of the text |
ViniR | 0:92357d1220f3 | 363 | // that should be printed for the current line. For safety, we assume there |
ViniR | 0:92357d1220f3 | 364 | // are a maximum of three element in the array: 1) text before the |
ViniR | 0:92357d1220f3 | 365 | // parameter, 2) the parameter, and 3) text after the parameter. |
ViniR | 0:92357d1220f3 | 366 | |
ViniR | 0:92357d1220f3 | 367 | frontTab = item->text; |
ViniR | 0:92357d1220f3 | 368 | while ((strlen (frontTab) > 0) && (i < 3)) |
ViniR | 0:92357d1220f3 | 369 | { |
ViniR | 0:92357d1220f3 | 370 | backTab = strchr (frontTab, '\t'); |
ViniR | 0:92357d1220f3 | 371 | if (backTab == NULL) |
ViniR | 0:92357d1220f3 | 372 | { |
ViniR | 0:92357d1220f3 | 373 | backTab = frontTab + strlen(frontTab); |
ViniR | 0:92357d1220f3 | 374 | i = 3; // force our way out of the while loop |
ViniR | 0:92357d1220f3 | 375 | } |
ViniR | 0:92357d1220f3 | 376 | |
ViniR | 0:92357d1220f3 | 377 | copySize = backTab - frontTab; |
ViniR | 0:92357d1220f3 | 378 | if (copySize >= lineLength) |
ViniR | 0:92357d1220f3 | 379 | copySize = lineLength - 1; |
ViniR | 0:92357d1220f3 | 380 | |
ViniR | 0:92357d1220f3 | 381 | strncpy (subStr, frontTab, copySize); |
ViniR | 0:92357d1220f3 | 382 | subStr[copySize] = '\0'; |
ViniR | 0:92357d1220f3 | 383 | |
ViniR | 0:92357d1220f3 | 384 | // If the current string in the array is a printf-style conversion |
ViniR | 0:92357d1220f3 | 385 | // specifier for a float, we replace it with the parameter value. |
ViniR | 0:92357d1220f3 | 386 | if (checkConvSpec (subStr)) |
ViniR | 0:92357d1220f3 | 387 | { |
ViniR | 0:92357d1220f3 | 388 | // If the user is currently editing the parameter, print the value |
ViniR | 0:92357d1220f3 | 389 | // of the shadow variable tempValue instead of the parameters actual |
ViniR | 0:92357d1220f3 | 390 | // value. The tempValue is not copied over to the value field of |
ViniR | 0:92357d1220f3 | 391 | // the structure until the user is done editing the parameter. To |
ViniR | 0:92357d1220f3 | 392 | // show that the parameter is being edited, we highlight the value |
ViniR | 0:92357d1220f3 | 393 | // by inverting the text. |
ViniR | 0:92357d1220f3 | 394 | if (paramSel) |
ViniR | 0:92357d1220f3 | 395 | { |
ViniR | 0:92357d1220f3 | 396 | snprintf (tempStr, lineLength, subStr, item->param->tempVal); |
ViniR | 0:92357d1220f3 | 397 | |
ViniR | 0:92357d1220f3 | 398 | // We highlight the parameter by inverting the characters on the |
ViniR | 0:92357d1220f3 | 399 | // screen. The menu system only allows the standard (0-127) |
ViniR | 0:92357d1220f3 | 400 | // ASCII character, so we use the MSB/7th bit of each character |
ViniR | 0:92357d1220f3 | 401 | // to indicate that it should be inverted when printed on the |
ViniR | 0:92357d1220f3 | 402 | // screen. |
ViniR | 0:92357d1220f3 | 403 | for (j=strlen(tempStr) - 1; j>=0; j--) |
ViniR | 0:92357d1220f3 | 404 | tempStr[j] |= 0x80; |
ViniR | 0:92357d1220f3 | 405 | |
ViniR | 0:92357d1220f3 | 406 | } |
ViniR | 0:92357d1220f3 | 407 | // If the user is not currently editing the parameter, we display |
ViniR | 0:92357d1220f3 | 408 | // the value pointed to by the value field of the param structure. |
ViniR | 0:92357d1220f3 | 409 | else |
ViniR | 0:92357d1220f3 | 410 | snprintf (tempStr, lineLength, |
ViniR | 0:92357d1220f3 | 411 | subStr, item->param->getVal()); |
ViniR | 0:92357d1220f3 | 412 | |
ViniR | 0:92357d1220f3 | 413 | // Attach the parameter string to the growing line. |
ViniR | 0:92357d1220f3 | 414 | strncat (line, tempStr, lineLength); |
ViniR | 0:92357d1220f3 | 415 | } |
ViniR | 0:92357d1220f3 | 416 | // If the string is not a printf-style conversion specifier for a float, |
ViniR | 0:92357d1220f3 | 417 | // simply catenate the string with the growing line of text. |
ViniR | 0:92357d1220f3 | 418 | else |
ViniR | 0:92357d1220f3 | 419 | { |
ViniR | 0:92357d1220f3 | 420 | strncat (line, subStr, lineLength); |
ViniR | 0:92357d1220f3 | 421 | } |
ViniR | 0:92357d1220f3 | 422 | |
ViniR | 0:92357d1220f3 | 423 | frontTab = backTab + 1; |
ViniR | 0:92357d1220f3 | 424 | i++; |
ViniR | 0:92357d1220f3 | 425 | } |
ViniR | 0:92357d1220f3 | 426 | |
ViniR | 0:92357d1220f3 | 427 | // Append a space to the very end of the line. The LCD driver looks to the |
ViniR | 0:92357d1220f3 | 428 | // last character in the line to determine whether to highlight any |
ViniR | 0:92357d1220f3 | 429 | // remaining whitespace after the text ends. This approach causes problems |
ViniR | 0:92357d1220f3 | 430 | // when the parameter is the last text on the line and we are in parameter |
ViniR | 0:92357d1220f3 | 431 | // modification mode. Without the extra space at the end of the line, the |
ViniR | 0:92357d1220f3 | 432 | // LCD controller will highlight the rest of the line even though it is only |
ViniR | 0:92357d1220f3 | 433 | // the parameter itself that should be highlighted. |
ViniR | 0:92357d1220f3 | 434 | strncat (line, " ", lineLength); |
ViniR | 0:92357d1220f3 | 435 | |
ViniR | 0:92357d1220f3 | 436 | // If the parameter has not been selected for modification but the menu item |
ViniR | 0:92357d1220f3 | 437 | // is currently selected, we highlight the entire line. In the menu system, |
ViniR | 0:92357d1220f3 | 438 | // the only allowable character are the standard ASCII codes (0-127). We |
ViniR | 0:92357d1220f3 | 439 | // use the (MSB) 7th bit of every character to indicate whether it should be |
ViniR | 0:92357d1220f3 | 440 | // highlighted/inverted. |
ViniR | 0:92357d1220f3 | 441 | if (!paramSel && itemSel) |
ViniR | 0:92357d1220f3 | 442 | { |
ViniR | 0:92357d1220f3 | 443 | // Set the MSB of each character to invert it when displayed. |
ViniR | 0:92357d1220f3 | 444 | for (j = strlen(line) - 1; j>= 0; j--) |
ViniR | 0:92357d1220f3 | 445 | line[j] |= 0x80; |
ViniR | 0:92357d1220f3 | 446 | } |
ViniR | 0:92357d1220f3 | 447 | |
ViniR | 0:92357d1220f3 | 448 | delete[] tempStr; |
ViniR | 0:92357d1220f3 | 449 | delete[] subStr; |
ViniR | 0:92357d1220f3 | 450 | } |
ViniR | 0:92357d1220f3 | 451 | |
ViniR | 0:92357d1220f3 | 452 | |
ViniR | 0:92357d1220f3 | 453 | // Returns true if the provided string is a printf-style conversion specifier |
ViniR | 0:92357d1220f3 | 454 | // for a float (conversion character is f, e, E, g, or G). Otherwise, returns |
ViniR | 0:92357d1220f3 | 455 | // false. |
ViniR | 0:92357d1220f3 | 456 | bool MenbedNavigator::checkConvSpec (const char *s) |
ViniR | 0:92357d1220f3 | 457 | { |
ViniR | 0:92357d1220f3 | 458 | char lastChar; |
ViniR | 0:92357d1220f3 | 459 | |
ViniR | 0:92357d1220f3 | 460 | // Conversion specifications must begin with a '%'. |
ViniR | 0:92357d1220f3 | 461 | if (s[0] != '%') |
ViniR | 0:92357d1220f3 | 462 | return false; |
ViniR | 0:92357d1220f3 | 463 | |
ViniR | 0:92357d1220f3 | 464 | // Identify the last last character in the conversion specification |
ViniR | 0:92357d1220f3 | 465 | lastChar = s[strlen(s) - 1]; |
ViniR | 0:92357d1220f3 | 466 | |
ViniR | 0:92357d1220f3 | 467 | // Check that the last character in the conversion specification is either a |
ViniR | 0:92357d1220f3 | 468 | // 'f', 'e', 'E', 'g', or 'G'--the conversion specifiers for floats. If it |
ViniR | 0:92357d1220f3 | 469 | // is, the conversion specification is probably a valid conversion |
ViniR | 0:92357d1220f3 | 470 | // specification. |
ViniR | 0:92357d1220f3 | 471 | if ((lastChar == 'f') || (lastChar == 'e') || (lastChar == 'E') || |
ViniR | 0:92357d1220f3 | 472 | (lastChar == 'g') || (lastChar == 'G')) |
ViniR | 0:92357d1220f3 | 473 | return true; |
ViniR | 0:92357d1220f3 | 474 | |
ViniR | 0:92357d1220f3 | 475 | // Otherwise, it is not. |
ViniR | 0:92357d1220f3 | 476 | return false; |
ViniR | 0:92357d1220f3 | 477 | } |