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 Peihsun Yeh

Library to display menus on TextLCDs. Interaction with functions Up,Down and Select (Buttons or RPG) Based on menu-library from pyeh9

Navigator.cpp

Committer:
charly
Date:
2016-01-13
Revision:
11:6814cbc83ae0
Parent:
10:2b6ddf53b05e

File content as of revision 11:6814cbc83ae0:

#include "Navigator.h"

Navigator::Navigator(Menu *root, TextLCD_Base *lcd) : activeMenu(root), lcd(lcd)
{

    _cursorPos = 0;
    _cursorLine = 1;
    _display_rows = lcd->rows();
    _display_cols = lcd->columns();

    activeMenu->CurrentSelection = _cursorPos;

    _wait_for_select = false;
    _wait_for_yesno  = false;

    _start_line = 0;

    printMenu();
    printCursor();
}

void Navigator::printMenu()
{
    int index =0;
    lcd->cls();

    for(int row=0; row < _display_rows; row++) {

        lcd->locate(0,row);
        index = row + _cursorPos - (_cursorLine-1);    // index into selection for this line
        //should we display a menu on this line?
        if (index <= activeMenu->selections.size()-1 ) {
            lcd->printf(" %s", activeMenu->selections[index].selText);
        }
    }
}

void Navigator::printCursor()
{
    if(activeMenu->selections[_cursorPos].childMenu == NULL) printf("No child menu\n");
    else printf("child menu: %s\n", activeMenu->selections[_cursorPos].childMenu->menuID);

    lcd->locate(0,0);
    for (int row=0; row<_display_rows; row++) {
        lcd->locate(0,row);
        if (row == _cursorLine-1) {
            //we are on Cursor-Line
            //print cursor
            lcd->putc('>');
        } else {
            //on other lines print a space
            lcd->putc(' ');
        }
    }
}


void Navigator::show_yes_no(bool yesorno)
{
    // MenuItem is a Yes/no question?
    // show the text in yesnodata and wait for a yes or no
    lcd->cls();
    //printf("YesNo: \n");
    //printf("%s <Yes><No>",activeMenu->selections[_cursorPos].menu_parameter->text);
    if (activeMenu->selections[_cursorPos].menu_parameter->text != NULL) {
        if (yesorno) {
            // Yes is default
            lcd->printf("%s <Yes> No ",activeMenu->selections[_cursorPos].menu_parameter->text);
        } else {
            //No is default
            lcd->printf("%s  Yes <No>",activeMenu->selections[_cursorPos].menu_parameter->text);
        }
        activeMenu->selections[_cursorPos].menu_parameter->yes_no = yesorno;
    }
}

void Navigator::show_longtext(void)
{
    int maxchunksize = _display_cols - 1;    // one column for "Scrollbar"
    // MenuItem is a long_text
    // show the text , support scrolling up/down, wait for select
    lcd->cls();
    if (activeMenu->selections[_cursorPos].menu_parameter->text != NULL) {
        //show text starting a correct position
        for (int row=0; row< _display_rows; row++) {
            lcd->locate(0,row);
            lcd->printf("%-*.*s", maxchunksize,maxchunksize, activeMenu->selections[_cursorPos].menu_parameter->text + ((_start_line+row)*(_display_cols - 1)));
            if ((row == 0)&& (_start_line > 0)) lcd->printf("^");
            else if (row == _display_rows-1) lcd->printf("v");
            else lcd->printf("|");
        }
    }
}

void Navigator::select()
{
    // user ressed the select button
    Menu *lastMenu;

    // are we waiting for a Select()?
    if (_wait_for_select) {
        _wait_for_select = false;
        // show the menu again
        printMenu();
        printCursor();

    } else if (_wait_for_yesno) {
        // user selected a value
        _wait_for_yesno = false;
        // show the menu again
        printMenu();
        printCursor();
    } else if(activeMenu->selections[_cursorPos].itemMode == MenuItem::mode_yes_no) {
        show_yes_no(activeMenu->selections[_cursorPos].menu_parameter->yes_no);
        _wait_for_yesno = true;
    } else if(activeMenu->selections[_cursorPos].itemMode == MenuItem::mode_show_longtext) {
        show_longtext();
        _wait_for_select = true;
    } else {
        // normal mneuItem
        if(activeMenu->selections[_cursorPos].userAction != NULL) {
            //execute function
            (activeMenu->selections[_cursorPos].userAction)();
            // refresh the Menu
            //printMenu();
            //printCursor();
        }
        //change the menu?
        if(activeMenu->selections[_cursorPos].childMenu != NULL) {
            lastMenu = activeMenu;

            //change to childMenu
            activeMenu = activeMenu->selections[_cursorPos].childMenu;

            // if we went up one level, set CurrectSelection of SubMenu to zero, if we come back again
            if (activeMenu->selections[activeMenu->CurrentSelection].childMenu == lastMenu) {
                //reset menuposition of submenu to zero
                lastMenu->CurrentSelection = 0;
            }

            // return to last position from that menu, if we went up on level
            _cursorPos = activeMenu->CurrentSelection;

            _cursorLine = 1;
            printMenu();
            printCursor();
        }
        // only accept select after showing this menu/user_action ?
        if ((activeMenu->selections[_cursorPos].itemMode == MenuItem::mode_wait_select) ||
                (activeMenu->selections[_cursorPos].itemMode == MenuItem::mode_show_longtext)) {
            _wait_for_select = true;
        }
    }
}

void Navigator::moveUp()
{
    if (_wait_for_yesno) {
        // change Yes/no Selection
        show_yes_no( ! activeMenu->selections[_cursorPos].menu_parameter->yes_no);

    } else if(activeMenu->selections[_cursorPos].itemMode == MenuItem::mode_show_longtext) {
        // show a long text
        // can we scoll further up?
        if (_start_line >= 1) {
            _start_line--;
            show_longtext();
        }
    } else
        // only if we don't wait for a select()
        if (! _wait_for_select) {
            // Show the MenuItems
            // allready on TOP of Display?
            if(_cursorLine > 1) {
                // scroll up cursor one line
                _cursorLine--;
            }

            if(_cursorPos > 0) {
                //scroll up one item
                _cursorPos--;
                activeMenu->CurrentSelection = _cursorPos;

            }
            printMenu();
            printCursor();
        }
}

void Navigator::moveDown()
{
    if (_wait_for_yesno) {
        // change Yes/no Selection
        show_yes_no( ! activeMenu->selections[_cursorPos].menu_parameter->yes_no);
    } else if(activeMenu->selections[_cursorPos].itemMode == MenuItem::mode_show_longtext) {
        // show a long text
        // can we scoll further down?
        if ((_start_line+_display_rows)*(_display_cols-1) < strlen(activeMenu->selections[_cursorPos].menu_parameter->text)) {
        _start_line++;
        show_longtext();
        }
    } else
        // only if we don't wait for a select()
        if (! _wait_for_select) {
            //Show the menuItem
            // allready on last line of display?
            if (_cursorPos == activeMenu->selections.size()-1) {
                //stay on this line
            } else {
                // move down
                if(_cursorLine < _display_rows) {
                    // Only move down cursor
                    _cursorLine++;
                    _cursorPos++;
                } else {
                    // on last Display-Line scroll down Menu
                    _cursorPos++;
                }
                // save currentPosition in Menu
                activeMenu->CurrentSelection = _cursorPos;

            }

            printMenu();
            printCursor();
        }
}