this locks like shit

Dependencies:   MenuLCD mbed

Fork of MenuLCD_copy by Vinícius Alves

Committer:
LucasMatBorges
Date:
Fri May 19 18:48:04 2017 +0000
Revision:
1:f105b690aeb7
Parent:
0:92357d1220f3
R?row mein

Who changed what in which revision?

UserRevisionLine numberNew 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 }