diff --git a/examples/targetSel/include/README b/examples/targetSel/include/README new file mode 100644 index 00000000..194dcd43 --- /dev/null +++ b/examples/targetSel/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/examples/targetSel/targetSel/targetSel.ino b/examples/targetSel/targetSel/targetSel.ino new file mode 100644 index 00000000..9c3b3fb3 --- /dev/null +++ b/examples/targetSel/targetSel/targetSel.ino @@ -0,0 +1,164 @@ +/******************** +Arduino generic menu system + +Rui Azevedo - ruihfazevedo(@rrob@)gmail.com + +output: Serial +input: Serial + +user defined array menu (userMenu plugin) +*/ + +#include +#include +#include +#include + +using namespace Menu; + +#define MAX_DEPTH 4 + +enum SelTest {Zero=0,One,Two}; +enum ChooseTest {First=1,Second=2,Third=3,Last=-1}; +constexpr int dataSz=3; +constexpr int nameSz=20; + +struct Data { + char name[nameSz+1]=" "; + bool valid=0; + SelTest selTest=Zero; + ChooseTest chooseTest=First; + //how to copy this data, being a simple data c++ will generate this for you + // Data& operator=(Data& o){ + // strcpy(name,o.name); + // valid=o.valid; + // selTest=o.selTest; + // chooseTest=o.chooseTest; + // return o; + // } +}; + +Data myTargets[dataSz];//our data +//a temp. to be edited +//the data type must have assignment operator +//because we will later on move data back and forth between the actual data and this template +//menu edit is wired to this temp. and menu eventd will deal with the copy-call +Data target; + + +char* constMEM alphaNum MEMMODE=" 0123456789.ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz,\\|!\"#$%&/()=?~*^+-{}[]€"; +char* constMEM alphaNumMask[] MEMMODE={alphaNum}; + +TOGGLE(target.valid,editValid,"Valid: ",doNothing,noEvent,noStyle//,doExit,enterEvent,noStyle + ,VALUE("On",HIGH,doNothing,noEvent) + ,VALUE("Off",LOW,doNothing,noEvent) +); + +SELECT(target.selTest,selMenu,"Select",doNothing,noEvent,noStyle + ,VALUE("Zero",Zero,doNothing,noEvent) + ,VALUE("One",One,doNothing,noEvent) + ,VALUE("Two",Two,doNothing,noEvent) +); + +CHOOSE(target.chooseTest,chooseMenu,"Choose",doNothing,noEvent,noStyle + ,VALUE("First",First,doNothing,noEvent) + ,VALUE("Second",Second,doNothing,noEvent) + ,VALUE("Third",Third,doNothing,noEvent) + ,VALUE("Last",Last,doNothing,noEvent) +); + +result saveTarget(eventMask e,navNode& nav) { + _trace(MENU_DEBUG_OUT<<"saveTarget"<path[nav.root->level-1].sel;//get selection of previous level + myTargets[n]=target; + return quit; +} + +//if you want to print the recird name as the title, +//then you MUST create a customized print menu to replace this default one +MENU(targetEdit,"Target edit",doNothing,noEvent,wrapStyle + ,EDIT("Name",target.name,alphaNumMask,doNothing,noEvent,noStyle) + ,SUBMENU(editValid) + ,SUBMENU(selMenu) + ,SUBMENU(chooseMenu) + ,OP("Save",saveTarget,enterEvent) + ,EXIT("_style();} inline eventMask events() const {return shadow->_events();} + virtual idx_t sz() const {return 0;} inline bool is(systemStyles chk) const {return (sysStyles()&chk)==chk;} inline bool has(systemStyles chk) const {return sysStyles()&chk;} inline bool is(styles chk) const {return (style()&chk)==chk;} diff --git a/src/macros.h b/src/macros.h index 831afa0f..34eca2b0 100644 --- a/src/macros.h +++ b/src/macros.h @@ -20,9 +20,9 @@ #endif #if defined(USE_PGM) || (defined(pgm_read_ptr_near) && !defined(MENU_USERAM)) //storing some values into avr flash memory (saving ram space) - #ifdef MENU_DEBUG - #warning "Using PGM" - #endif + // #ifdef MENU_DEBUG + // #warning "Using PGM" + // #endif #define USING_PGM #define MEMMODE PROGMEM #define constMEM const @@ -39,9 +39,9 @@ #define memEnum(addr) (sizeof(int)==1?memByte(addr):memWord(addr)) #else //use ram on non-avr devices or when explicit - #ifdef MENU_DEBUG - #warning "Using RAM" - #endif + // #ifdef MENU_DEBUG + // #warning "Using RAM" + // #endif #define USING_RAM #define MEMMODE #define constMEM diff --git a/src/menuBase.h b/src/menuBase.h index 5798582d..dde85bde 100644 --- a/src/menuBase.h +++ b/src/menuBase.h @@ -70,13 +70,13 @@ www.r-site.net enum result {proceed=0,quit}; enum systemStyles { - _noStyle=0, - _menuData=1, - _canNav=1<<1, - _parentDraw=1<<2, - _isVariant=1<<3, - _asPad=1<<4, - _Exit=1<<5 + _noStyle=0,// 000000 + _menuData=1,// 000001 + _canNav=1<<1,// 000010 + _parentDraw=1<<2,//000100 + _isVariant=1<<3,// 001000 + _asPad=1<<4,// 010000 + _Exit=1<<5// 100000 }; //showTitle and noTitle override the default enum styles { diff --git a/src/menuIO/serialOut.cpp b/src/menuIO/serialOut.cpp index 04137a23..9e7b7746 100644 --- a/src/menuIO/serialOut.cpp +++ b/src/menuIO/serialOut.cpp @@ -3,7 +3,7 @@ namespace Menu { #ifdef MENU_DEBUG - constexpr idx_t w=16; + constexpr idx_t w=20; #else constexpr idx_t w=40; #endif diff --git a/src/menuIo.cpp b/src/menuIo.cpp index ec9c0a01..7cc5c3d9 100644 --- a/src/menuIo.cpp +++ b/src/menuIo.cpp @@ -44,12 +44,18 @@ menuOut& menuOut::fill( idx_t menuOut::printRaw(const char* at,idx_t len) { trace(MENU_DEBUG_OUT<<"menuOut::printRaw"<out.doNav(cmd,*this);*/ case upCmd: // trace(MENU_DEBUG_OUT<<"up"<=sz()) {if(wrap()) nsel=0; else nsel=sz()-1;} - // trace(MENU_DEBUG_OUT<<"new sel:"<=sz()) {if(wrap()) nsel=0; else nsel=sz()-1;} + // trace(MENU_DEBUG_OUT<<"new sel:"<isVariant()) root->out.doNav(cmd,*this);*/ case downCmd: - // trace(MENU_DEBUG_OUT<<"down"<is(_asPad)) { - nsel--; - if (nsel<0) {if(wrap()) nsel=sz()-1; else nsel=0;} + if(sz()) { + nsel--; + if (nsel<0) {if(wrap()) nsel=sz()-1; else nsel=0;} + } break; } case escCmd: @@ -180,7 +184,7 @@ void navRoot::doNav(navCmd cmd) { } navCmd navRoot::enter() { - trace(MENU_DEBUG_OUT<<"navRoot::enter"<navFocus==this&&cmd.cmd==enterCmd) { + _trace(MENU_DEBUG_OUT<<"no sub levels! submenu:"<<(subMenu?"yes":"no")<<" level:"<level<<"\n"); + //just send the event, but do not open (as this menu is representing the item) + // nav.root->path[nav.root->level-1].event(enterEvent); + // nav.event(enterEvent); + // if(enterEvent&&) operator()(enterEvent, nav, *this); + nav.event(enterEvent); + if(subMenu) { + assert(nav.root->levelmaxDepth); + nav.root->active().dirty=true; + nav.root->level++; + nav.root->navFocus=nav.root->node().target=subMenu; + nav.root->node().sel=0; + } + } else menuNode::doNav(nav,cmd); + } + }; + + //user menu to use std containers or other structure that provide a size() function + //not tested yes, please provide feedback + template + class StdMenu:UserMenu { + T& src; + StdMenu(constText* text,T& src,action a=noAction,eventMask e=noEvent,styles style=wrapStyle) + :menuNode(text,0,NULL,a,e),src(src) {} + StdMenu(constText* text,T& src,menu& subMenu,action a=noAction,eventMask e=noEvent,styles style=wrapStyle) + :menuNode(text,0,NULL,subMenu,a,e),src(src) {} + idx_t sz() const override {return src.size();} + }; +};