#include "menu.h" using namespace Menu; //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // navNode - Navigation layer controller // //////////////////////////////////////////////////////////////////////////////// // navCmd navNode::navKeys(char ch) { // trace(Serial<<"navNode::navKeys"<navCodes)/sizeof(navCode);i++) // if (options->navCodes[i].ch==ch) return options->navCodes[i].cmd; // return noCmd; // } // generic navigation (aux function) navCmd navNode::doNavigation(navCmd cmd) { trace(Serial<<"navNode::doNavigation"<isVariant()) root->out.doNav(cmd,*this);*/ case upCmd: // trace(Serial<<"up"<=sz()) {if(wrap()) nsel=0; else nsel=sz()-1;} // trace(Serial<<"new sel:"<isVariant()) root->out.doNav(cmd,*this);*/ case downCmd: // trace(Serial<<"down"<is(_asPad)) { nsel--; if (nsel<0) {if(wrap()) nsel=sz()-1; else nsel=0;} break; } case escCmd: assert(root); rCmd=root->exit(); break; case enterCmd: assert(root); rCmd=root->enter(); break; case selCmd: case numValue: case idxCmd: { idx_t at=(idx_t)cmd.param;//-'1';send us numeric index pls! if (at>=0&&atsysStyles()&(_parentDraw|_isVariant)) { trace(Serial<<"setting dirty"<dirty=true; //this works but might be too much, we dont want to invaludate all the menu! // if (_parentDraw/*&&root->level*/) root->path[root->level-1].target->dirty=true; } else { operator[](osel).dirty=true; operator[](nsel).dirty=true; } //send focus In/Out events if (selBlurEvent&target->events()) target->operator()(selBlurEvent,*this,*target); event(blurEvent,osel); sel=nsel; if (cmd.cmd==selCmd||cmd.cmd==idxCmd) {//do accelerator and enter the option assert(root); rCmd=root->enter(); }//other commands up/down just receive focus events event(focusEvent,nsel); if (selFocusEvent&target->events()) target->operator()(selFocusEvent,*this,*target); } //else its an enter/esc or a non-changing index! //Serial<<"doNavigation returning "<parseInput(node(),in);//deliver navigation input task to target... } } trace(Serial<<"navRoot::doInput ended!"<doNav(node(),cmd); } } navCmd navRoot::enter() { trace(Serial<<"navRoot::enter"<dirty=true; if (!isMenu) in.fieldOn(); } return rCmd; } return noCmd; } navCmd navRoot::exit() { trace(Serial<<"navRoot::exit"<dirty=true; if (navFocus->isMenu()) { if (level) { level--; node().event(exitEvent,node().sel); } else if (canExit) { node().event(exitEvent,node().sel); idleOn(idleTask); } } else { node().event(exitEvent,node().sel); in.fieldOff(); } active().dirty=true; navFocus=&active(); return escCmd; } bool navRoot::changed(const menuOut& out) { if (sleepTask) return idleChanged; if (node().changed(out)) { lastChanged=millis(); return true; } else if (canExit&&timeOut&&(millis()-lastChanged)/1000>timeOut) idleOn(idleTask); return false; } #ifdef MENU_ASYNC // prompt* navRoot::seek(char* uri) { // StringStream s(uri); // size_t len = std::count(s.begin(), s.end(), '/'); // if (uri[0]=='/') s>>'/'; else len++; // assert(len<(1<<(sizeof(idx_t)<<3))); // idx_t sel[len]; // for(int n=0;n>sel[n]; // s>>'/'; // } // return seek(sel,len); // } // prompt* navRoot::seek(idx_t* uri,idx_t len) { // trace(Serial<<"menuNode::seek"<=0&&uri[0]=0); // if (lvl<0) return; while(level>lvl) { trace(Serial<<"escaping "<async(at, *this, 0); else return active().async(at, *this, level+1);//TODO: check max_depth here! } menuOut& navRoot::printPath(menuOut& o,menuNode* to) const { trace(Serial<<"printPath:"); for(idx_t n=0;n