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();}
+ };
+};