4 errors
Dependencies: KS0108_PCF8574 mbed
Diff: menbed/menbedNavigator.cpp
- Revision:
- 2:66e4ebaba5df
- Parent:
- 1:4f46d81502aa
- Child:
- 3:ec80bb6ff5da
--- a/menbed/menbedNavigator.cpp Wed Sep 05 07:22:44 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,477 +0,0 @@ -#include "mbed.h" -#include "include/menbedNavigator.h" -#include "include/menbedButtonEvent.h" -#include "include/menbedMenuMessage.h" -#include "include/menbedMenu.h" -#include <cstdio> - -extern void toggleLed3(); - -MenbedNavigator::MenbedNavigator(MenbedMenu *rootMenu, - MenbedDisplayer *displayer) : - activeMenu(rootMenu), displayer(displayer) -{ - selectedItemIndex = -1; - topOfScreenItemIndex = 0; - paramEditMode = false; - - numLines = displayer->getDisplay()->getLines(); - lineLength = displayer->getDisplay()->getLineLength(); -} - -void MenbedNavigator::updateDisplay() -{ - MenbedMenuMessage menuMsg (numLines, lineLength); - - printMenu (menuMsg.text); - menuMsg.showUpArrow = (topOfScreenItemIndex >= 1); - menuMsg.showDownArrow = (topOfScreenItemIndex + numLines < (int)(activeMenu->menuItems.size())); - - displayer->update (&menuMsg); -} - - -void MenbedNavigator::handleButtonEvent (MenbedButtonEvent buttonEvent) -{ - numButtons = buttonEvent.numButtons; - - switch (buttonEvent.name) - { - case MenbedButtonEvent::ButtonSelect: // Select - if (!paramEditMode && (buttonEvent.action == - MenbedButtonEvent::BUTTON_ACTION_RELEASED_SHORT)) - selectItem(); - else if (paramEditMode && (buttonEvent.action == - MenbedButtonEvent::BUTTON_ACTION_RELEASED_SHORT)) - saveParam(); - else if ((numButtons < 4) && - paramEditMode && (buttonEvent.action == - MenbedButtonEvent::BUTTON_ACTION_HELD_LONG)) - restoreParam(); - else if ((numButtons < 4) && !paramEditMode && - (buttonEvent.action == - MenbedButtonEvent::BUTTON_ACTION_HELD_LONG)) - gotoParent(); - break; - - case MenbedButtonEvent::ButtonDown: - if (paramEditMode && - (buttonEvent.action == MenbedButtonEvent::BUTTON_ACTION_PUSHED)) - decParam(); - else if (!paramEditMode && - (buttonEvent.action == MenbedButtonEvent::BUTTON_ACTION_PUSHED)) - moveDown(); - break; - - case MenbedButtonEvent::ButtonUp: - if (numButtons > 2) - { - if (paramEditMode && - (buttonEvent.action == MenbedButtonEvent::BUTTON_ACTION_PUSHED)) - incParam(); - else if (!paramEditMode && - (buttonEvent.action == MenbedButtonEvent::BUTTON_ACTION_PUSHED)) - moveUp(); - } - break; - - case MenbedButtonEvent::ButtonCancel: - if (numButtons > 3) - { - if (paramEditMode && - (buttonEvent.action == MenbedButtonEvent::BUTTON_ACTION_PUSHED)) - restoreParam(); - else if (!paramEditMode && - (buttonEvent.action == MenbedButtonEvent::BUTTON_ACTION_PUSHED)) - gotoParent(); - } - break; - } - - updateDisplay(); - //menuRefresh_refreshed(); -} - - -void MenbedNavigator::selectItem() -{ - MenbedMenu **childMenuPtr; - MenbedMenu *childMenu; - - if ((selectedItemIndex < 0) || - (selectedItemIndex >= (int)(activeMenu->menuItems.size()))) - return; - - // If it exists, execute the function associated with the menu item - if (activeMenu->menuItems[selectedItemIndex]->selFcn != NULL) - activeMenu->menuItems[selectedItemIndex]->selFcn(); - - // Show the child menu associated with the menu item. Initially, the first - // item in the child menu is placed at the top of the screen, but is it - // left unselected. - childMenuPtr = activeMenu->menuItems[selectedItemIndex]->childMenu; - if (childMenuPtr != NULL) - { - childMenu = *(activeMenu->menuItems[selectedItemIndex]->childMenu); - - if (!activeMenu->menuItems[selectedItemIndex]->childMenuIsAncestor) - { - childMenu->parentMenu = activeMenu; - childMenu->parentSelectedItemIndex = selectedItemIndex; - childMenu->parentTopOfScreenItemIndex = topOfScreenItemIndex; - } - else - childMenu->parentMenu = NULL; - - activeMenu = childMenu; - topOfScreenItemIndex = 0; - selectedItemIndex = -1; - } - // Otherwise, if the current menu item has a parameter that can be modified, - // we switch to the parameter editing mode. - else if ((activeMenu->menuItems[selectedItemIndex]->param != NULL) && - (activeMenu->menuItems[selectedItemIndex]->param->inc() != 0)) - { - // All incrementing and decrementing of the parameter actually happens - // to a shadow variable in the param structure named tempValue. The - // parameter value used by the other parts of the system is not updated - // until the user is done editing the parameter. - activeMenu->menuItems[selectedItemIndex]->param->initVal = - activeMenu->menuItems[selectedItemIndex]->param->getVal(); - activeMenu->menuItems[selectedItemIndex]->param->tempVal = - activeMenu->menuItems[selectedItemIndex]->param->initVal; - paramEditMode = true; - } -} - - -void MenbedNavigator::gotoParent() -{ - if (activeMenu->parentMenu == NULL) - return; - - selectedItemIndex = activeMenu->parentSelectedItemIndex; - topOfScreenItemIndex = activeMenu->parentTopOfScreenItemIndex; - activeMenu = activeMenu->parentMenu; -} - - -void MenbedNavigator::moveUp() -{ - // If we're already at the top of the menu, do nothing - if (selectedItemIndex <= -1) - return; - // If the top item of the menu is already selected, we send a NOP message - // which deselects the top line and displays the down arrow if the menu - // contains more items than can fit on the screen. In effect, this allows - // the user to deselect all menu items which adds a nice look to the system. - else if (selectedItemIndex == 0) - selectedItemIndex = -1; - // If the currently selected menu item is the also the one at the top of the - // screen, we need to scroll the screen down and add the item above the - // currently selected one to the top of the screen. - else if (selectedItemIndex == topOfScreenItemIndex) - { - selectedItemIndex--; - topOfScreenItemIndex--; - } - // The selected item is not the top item on the screen. All we need to do - // is select the item above the currently selected item. - else - selectedItemIndex--; -} - - - -void MenbedNavigator::moveDown() -{ - // If the last item of the menu is already selected, our behavior depends - // on how many buttons are present. If there is no up button, we cycle - // back to the top of the menu. Otherwise, if an up button is present, - // we do nothing. - if (selectedItemIndex >= ((int)(activeMenu->menuItems.size()) - 1)) - { - if (numButtons < 3) - { - selectedItemIndex = -1; - topOfScreenItemIndex = 0; - } - else - ; - } - // If the menu item displayed at the bottom of the screen is already - // selected, we will need to scroll the screen up to make room for a new - // line at the bottom of the screen. - else if (selectedItemIndex == - (topOfScreenItemIndex + numLines - 1)) - { - selectedItemIndex++; - topOfScreenItemIndex++; - } - // Otherwise, if the currently selected menu item is now the one displayed - // at the bottom of the screen, we simply change which of the visible items - // is highlighted. - else - selectedItemIndex++; - -} - - -void MenbedNavigator::incParam() -{ - float inc; - float tempVal; - - if (paramEditMode != true) - return; - - inc = activeMenu->menuItems[selectedItemIndex]->param->inc(); - - // Initialize our own local copy of the parameter's temporary value. We do - // this so that we can more easily check for violations of the allowed min - // and max values. - tempVal = activeMenu->menuItems[selectedItemIndex]->param->tempVal; - tempVal += inc; - - // Check the bounds on the parameter. - if (tempVal > activeMenu->menuItems[selectedItemIndex]->param->max()) - tempVal = activeMenu->menuItems[selectedItemIndex]->param->max(); - else if (tempVal < activeMenu->menuItems[selectedItemIndex]->param->min()) - tempVal = activeMenu->menuItems[selectedItemIndex]->param->min(); - - // Assign the local temp. value back to the temporary value in the active - // parameter structue. - activeMenu->menuItems[selectedItemIndex]->param->tempVal = tempVal; - - // If the parameter is configured to produce live updates, call the - // finalValFcn. - if (activeMenu->menuItems[selectedItemIndex]->param->liveUpdate()) - activeMenu->menuItems[selectedItemIndex]->param->setVal(tempVal); -} - - -void MenbedNavigator::decParam() -{ - float inc; - float tempVal; - - if (paramEditMode != true) - return; - - inc = activeMenu->menuItems[selectedItemIndex]->param->inc(); - - // Initialize our own local copy of the parameter's temporary value. We do - // this so that we can more easily check for violations of the allowed min - // and max values. - tempVal = activeMenu->menuItems[selectedItemIndex]->param->tempVal; - tempVal -= inc; - - // Check the bounds on the parameter. - if (tempVal > activeMenu->menuItems[selectedItemIndex]->param->max()) - tempVal = activeMenu->menuItems[selectedItemIndex]->param->max(); - // If we reach the minimum parameter value when we only have a down button - // and not an up button connected to the system, we wrap the parameter - // value back around to its maximum. Otherwise, if there is an up button - // present, we peg the parameter at its minimum value. - else if (tempVal < activeMenu->menuItems[selectedItemIndex]->param->min()) - { - if (numButtons >= 3) - tempVal = activeMenu->menuItems[selectedItemIndex]->param->min(); - else - tempVal = activeMenu->menuItems[selectedItemIndex]->param->max(); - } - - // Assign the local temp. value back to the temporary value in the active - // parameter structue. - activeMenu->menuItems[selectedItemIndex]->param->tempVal = tempVal; - - // If the parameter is configured to produce live updates, call the - // finalValFcn. - if (activeMenu->menuItems[selectedItemIndex]->param->liveUpdate()) - activeMenu->menuItems[selectedItemIndex]->param->setVal(tempVal); -} - - -void MenbedNavigator::saveParam() -{ - // Save the changes made the shadow variable tempValue to the real parameter - // value that is used by the rest of the application. - activeMenu->menuItems[selectedItemIndex]->param->setVal ( - activeMenu->menuItems[selectedItemIndex]->param->tempVal - ); - paramEditMode = false; -} - - -void MenbedNavigator::restoreParam() -{ - // Revert any changes made the parameter by calling the finalValFcn with - // the initVal that was stored when we first began editing this parameter. - activeMenu->menuItems[selectedItemIndex]->param->setVal( - activeMenu->menuItems[selectedItemIndex]->param->initVal - ); - paramEditMode = false; -} - - -void MenbedNavigator::printMenu (char *menuStr) -{ - uint8_t i; - char *lineStr = new char[lineLength]; - bool itemSel; - - menuStr[0] = '\0'; - - for (i=topOfScreenItemIndex; i<topOfScreenItemIndex + numLines; i++) - { - // Make sure we don't try to print more menu items than exist in the - // active menu. - if (i > ((int)activeMenu->menuItems.size() - 1)) - { - strcat (menuStr, "\n"); - continue; - } - - itemSel = (i == selectedItemIndex); - - printItem (activeMenu->menuItems[i], lineStr, itemSel, - paramEditMode && itemSel); - - strncat (menuStr, lineStr, lineLength); - strcat (menuStr, "\n"); - } - - delete[] lineStr; -} - - -void MenbedNavigator::printItem (MenbedMenuItem *item, char *line, bool itemSel, - bool paramSel) -{ - uint8_t i = 0; - int8_t j; - char *tempStr = new char[lineLength]; - char *frontTab, *backTab; - char *subStr = new char[lineLength]; - uint8_t copySize; - - // Clear the line of text - line[0] = '\0'; - - // Iterate over the element in the array of text strings in the provided - // menu item until an empty string is found indicating the end of the text - // that should be printed for the current line. For safety, we assume there - // are a maximum of three element in the array: 1) text before the - // parameter, 2) the parameter, and 3) text after the parameter. - - frontTab = item->text; - while ((strlen (frontTab) > 0) && (i < 3)) - { - backTab = strchr (frontTab, '\t'); - if (backTab == NULL) - { - backTab = frontTab + strlen(frontTab); - i = 3; // force our way out of the while loop - } - - copySize = backTab - frontTab; - if (copySize >= lineLength) - copySize = lineLength - 1; - - strncpy (subStr, frontTab, copySize); - subStr[copySize] = '\0'; - - // If the current string in the array is a printf-style conversion - // specifier for a float, we replace it with the parameter value. - if (checkConvSpec (subStr)) - { - // If the user is currently editing the parameter, print the value - // of the shadow variable tempValue instead of the parameters actual - // value. The tempValue is not copied over to the value field of - // the structure until the user is done editing the parameter. To - // show that the parameter is being edited, we highlight the value - // by inverting the text. - if (paramSel) - { - snprintf (tempStr, lineLength, subStr, item->param->tempVal); - - // We highlight the parameter by inverting the characters on the - // screen. The menu system only allows the standard (0-127) - // ASCII character, so we use the MSB/7th bit of each character - // to indicate that it should be inverted when printed on the - // screen. - for (j=strlen(tempStr) - 1; j>=0; j--) - tempStr[j] |= 0x80; - - } - // If the user is not currently editing the parameter, we display - // the value pointed to by the value field of the param structure. - else - snprintf (tempStr, lineLength, - subStr, item->param->getVal()); - - // Attach the parameter string to the growing line. - strncat (line, tempStr, lineLength); - } - // If the string is not a printf-style conversion specifier for a float, - // simply catenate the string with the growing line of text. - else - { - strncat (line, subStr, lineLength); - } - - frontTab = backTab + 1; - i++; - } - - // Append a space to the very end of the line. The LCD driver looks to the - // last character in the line to determine whether to highlight any - // remaining whitespace after the text ends. This approach causes problems - // when the parameter is the last text on the line and we are in parameter - // modification mode. Without the extra space at the end of the line, the - // LCD controller will highlight the rest of the line even though it is only - // the parameter itself that should be highlighted. - strncat (line, " ", lineLength); - - // If the parameter has not been selected for modification but the menu item - // is currently selected, we highlight the entire line. In the menu system, - // the only allowable character are the standard ASCII codes (0-127). We - // use the (MSB) 7th bit of every character to indicate whether it should be - // highlighted/inverted. - if (!paramSel && itemSel) - { - // Set the MSB of each character to invert it when displayed. - for (j = strlen(line) - 1; j>= 0; j--) - line[j] |= 0x80; - } - - delete[] tempStr; - delete[] subStr; -} - - -// Returns true if the provided string is a printf-style conversion specifier -// for a float (conversion character is f, e, E, g, or G). Otherwise, returns -// false. -bool MenbedNavigator::checkConvSpec (const char *s) -{ - char lastChar; - - // Conversion specifications must begin with a '%'. - if (s[0] != '%') - return false; - - // Identify the last last character in the conversion specification - lastChar = s[strlen(s) - 1]; - - // Check that the last character in the conversion specification is either a - // 'f', 'e', 'E', 'g', or 'G'--the conversion specifiers for floats. If it - // is, the conversion specification is probably a valid conversion - // specification. - if ((lastChar == 'f') || (lastChar == 'e') || (lastChar == 'E') || - (lastChar == 'g') || (lastChar == 'G')) - return true; - - // Otherwise, it is not. - return false; -}