Skip to content

Commit 7b99212

Browse files
committed
testing loop menus and draw
1 parent 6154d36 commit 7b99212

File tree

4 files changed

+148
-132
lines changed

4 files changed

+148
-132
lines changed

macros.h

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
class prompt;
2+
class menu;
3+
class menuOut;
4+
template <typename T> class menuField;
5+
6+
#define CONCATENATE(arg1, arg2) CONCATENATE1(arg1, arg2)
7+
#define CONCATENATE1(arg1, arg2) CONCATENATE2(arg1, arg2)
8+
#define CONCATENATE2(arg1, arg2) arg1##arg2
9+
10+
#define FOR_EACH_1(what, x, ...) what(x)
11+
#define FOR_EACH_2(what, x, ...)\
12+
what(x)\
13+
FOR_EACH_1(what, __VA_ARGS__)
14+
#define FOR_EACH_3(what, x, ...)\
15+
what(x)\
16+
FOR_EACH_2(what, __VA_ARGS__)
17+
#define FOR_EACH_4(what, x, ...)\
18+
what(x)\
19+
FOR_EACH_3(what, __VA_ARGS__)
20+
#define FOR_EACH_5(what, x, ...)\
21+
what(x)\
22+
FOR_EACH_4(what, __VA_ARGS__)
23+
#define FOR_EACH_6(what, x, ...)\
24+
what(x)\
25+
FOR_EACH_5(what, __VA_ARGS__)
26+
#define FOR_EACH_7(what, x, ...)\
27+
what(x)\
28+
FOR_EACH_6(what, __VA_ARGS__)
29+
#define FOR_EACH_8(what, x, ...)\
30+
what(x)\
31+
FOR_EACH_7(what, __VA_ARGS__)
32+
#define FOR_EACH_9(what, x, ...)\
33+
what(x)\
34+
FOR_EACH_8(what, __VA_ARGS__)
35+
#define FOR_EACH_10(what, x, ...)\
36+
what(x)\
37+
FOR_EACH_9(what, __VA_ARGS__)
38+
#define FOR_EACH_11(what, x, ...)\
39+
what(x)\
40+
FOR_EACH_10(what, __VA_ARGS__)
41+
#define FOR_EACH_12(what, x, ...)\
42+
what(x)\
43+
FOR_EACH_11(what, __VA_ARGS__)
44+
#define FOR_EACH_13(what, x, ...)\
45+
what(x)\
46+
FOR_EACH_12(what, __VA_ARGS__)
47+
#define FOR_EACH_14(what, x, ...)\
48+
what(x)\
49+
FOR_EACH_13(what, __VA_ARGS__)
50+
#define FOR_EACH_15(what, x, ...)\
51+
what(x)\
52+
FOR_EACH_14(what, __VA_ARGS__)
53+
#define FOR_EACH_16(what, x, ...)\
54+
what(x)\
55+
FOR_EACH_15(what, __VA_ARGS__)
56+
57+
#define FOR_EACH_NARG(...) FOR_EACH_NARG_(__VA_ARGS__, FOR_EACH_RSEQ_N())
58+
#define FOR_EACH_NARG_(...) FOR_EACH_ARG_N(__VA_ARGS__)
59+
#define FOR_EACH_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, N, ...) N
60+
#define FOR_EACH_RSEQ_N() 16,15,14,13,12,11,10,9,8, 7, 6, 5, 4, 3, 2, 1, 0
61+
62+
#define FOR_EACH_(N, what, x, ...) CONCATENATE(FOR_EACH_, N)(what, x, __VA_ARGS__)
63+
#define FOR_EACH(what, x, ...) FOR_EACH_(FOR_EACH_NARG(x, __VA_ARGS__), what, x, __VA_ARGS__)
64+
65+
#define DECL(x) DECL_##x
66+
#define DEF(x) DEF_##x,
67+
68+
#define MENU(id,text,...)\
69+
FOR_EACH(DECL,__VA_ARGS__)\
70+
prompt* const id##_data[]={\
71+
FOR_EACH(DEF,__VA_ARGS__)\
72+
};\
73+
menu id (text,sizeof(id##_data)/sizeof(prompt*),id##_data);
74+
75+
#define CHOOSE(target,id,text,...)\
76+
FOR_EACH(menuValue<typeof(target)> DECL_VALUE,__VA_ARGS__)\
77+
menuValue<typeof(target)>* const id##_data[]={\
78+
FOR_EACH(DEF,__VA_ARGS__)\
79+
};\
80+
menuChoice<typeof(target)> id (text,sizeof(id##_data)/sizeof(prompt*),id##_data,target);
81+
82+
#define TOGGLE(target,id,text,...)\
83+
FOR_EACH(menuValue<typeof(target)> DECL_VALUE,__VA_ARGS__)\
84+
menuValue<typeof(target)>* const id##_data[]={\
85+
FOR_EACH(DEF,__VA_ARGS__)\
86+
};\
87+
menuToggle<typeof(target)> id (text,sizeof(id##_data)/sizeof(prompt*),id##_data,target);
88+
89+
/*#define GET_MACRO(_1,_2,NAME,...) NAME
90+
#define VALUE(...) GET_MACRO(__VA_ARGS__, EXPLICIT_VALUE, IMPLICIT_VALUE)(__VA_ARGS__)*/
91+
92+
#define OP(...) OP_(__COUNTER__,__VA_ARGS__)
93+
#define FIELD(...) FIELD_(__COUNTER__,__VA_ARGS__)
94+
#define VALUE(...) VALUE_(__COUNTER__,__VA_ARGS__)
95+
#define TEXTFIELD(...) TEXTFIELD_(__COUNTER__,__VA_ARGS__)
96+
97+
#define DECL_OP_(cnt,...) prompt op##cnt(__VA_ARGS__);
98+
#define DECL_FIELD_(cnt,target,...) menuField<typeof(target)> _menuField##cnt(target,__VA_ARGS__);
99+
#define DECL_TEXTFIELD_(cnt,target,...) menuTextField _menuTextField##cnt(target,__VA_ARGS__);
100+
#define DECL_SUBMENU(id)
101+
#define DECL_VALUE(...) _##__VA_ARGS__
102+
#define _VALUE_(cnt,...) choice##cnt(__VA_ARGS__);
103+
104+
#define DEF_OP_(cnt,...) &op##cnt
105+
#define DEF_FIELD_(cnt,...) &_menuField##cnt
106+
#define DEF_TEXTFIELD_(cnt,...) &_menuTextField##cnt
107+
#define DEF_SUBMENU(id) &id
108+
#define DEF_VALUE(id) &id
109+
#define DEF_VALUE_(cnt,...) &choice##cnt

menu.cpp

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,11 @@ char menu::downCode='-';
2424
char menu::enabledCursor='>';
2525
char menu::disabledCursor='-';
2626
prompt menu::exitOption(menu::exit);
27+
bool menu::wrapMenus=false;
2728
menuNode* menuNode::activeNode=NULL;
2829

2930
bool menuOut::needRedraw(menu& m,int i) {return (drawn!=&m)||(top!=lastTop)||(m.sel!=lastSel&&((i==m.sel)||(i==lastSel)));}
3031

31-
#ifndef LOOP_MENU
32-
#define LOOP_MENU false
33-
#endif
34-
3532
//menu navigation engine
3633
//iteract with input until a selection is done, return the selection
3734
int menu::menuKeys(menuOut &p,Stream& c,bool canExit) {
@@ -42,29 +39,26 @@ int menu::menuKeys(menuOut &p,Stream& c,bool canExit) {
4239
if (ch==menu::downCode) {
4340
sel--;
4441
if (sel<0) {
45-
#if LOOP_MENU
42+
if (wrapMenus) {
4643
sel=sz-(canExit?0:1);
4744
if (sel+1>=p.maxY) p.top=sel-p.maxY+1;
48-
#else
49-
sel=0;
50-
#endif
45+
} else sel=0;
5146
}
5247
if (p.top>sel) p.top=sel;
5348
} else if (ch==menu::upCode) {
5449
sel++;
5550
if (sel>(sz-(canExit?0:1))) {
56-
#if LOOP_MENU
51+
if (wrapMenus) {
5752
sel=0;
5853
p.top=0;
59-
#else
60-
sel=sz-(canExit?0:1);
61-
#endif
54+
} else sel=sz-(canExit?0:1);
6255
}
6356
if (sel+1>p.maxY) p.top=sel-p.maxY+1;
6457
} else if (ch==menu::escCode) {
6558
op=-1;
66-
} else
59+
} else {
6760
op=ch-'1';
61+
}
6862
} else {
6963
op=sel==sz?-1:sel;
7064
}
@@ -80,7 +74,7 @@ int menu::menuKeys(menuOut &p,Stream& c,bool canExit) {
8074
//input scan: call the navigation function (self)
8175
void menu::activate(menuOut& p,Stream& c,bool canExit) {
8276
if (activeNode!=this) {
83-
action(*this,p,c);
77+
action(*this,p,c);
8478
previousMenu=(menu*)activeNode;
8579
activeNode=this;
8680
sel=0;

menu.h

Lines changed: 25 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -29,117 +29,9 @@ v2.1 - Add full support of SetPosition(x,y) to move the menu inside the screen (
2929
#include <HardwareSerial.h>
3030
//#include <Flash.h>
3131

32-
//#include <streamFlow.h>
32+
#include <streamFlow.h>
3333

34-
class prompt;
35-
class menu;
36-
class menuOut;
37-
template <typename T> class menuField;
38-
39-
#define CONCATENATE(arg1, arg2) CONCATENATE1(arg1, arg2)
40-
#define CONCATENATE1(arg1, arg2) CONCATENATE2(arg1, arg2)
41-
#define CONCATENATE2(arg1, arg2) arg1##arg2
42-
43-
#define FOR_EACH_1(what, x, ...) what(x)
44-
#define FOR_EACH_2(what, x, ...)\
45-
what(x)\
46-
FOR_EACH_1(what, __VA_ARGS__)
47-
#define FOR_EACH_3(what, x, ...)\
48-
what(x)\
49-
FOR_EACH_2(what, __VA_ARGS__)
50-
#define FOR_EACH_4(what, x, ...)\
51-
what(x)\
52-
FOR_EACH_3(what, __VA_ARGS__)
53-
#define FOR_EACH_5(what, x, ...)\
54-
what(x)\
55-
FOR_EACH_4(what, __VA_ARGS__)
56-
#define FOR_EACH_6(what, x, ...)\
57-
what(x)\
58-
FOR_EACH_5(what, __VA_ARGS__)
59-
#define FOR_EACH_7(what, x, ...)\
60-
what(x)\
61-
FOR_EACH_6(what, __VA_ARGS__)
62-
#define FOR_EACH_8(what, x, ...)\
63-
what(x)\
64-
FOR_EACH_7(what, __VA_ARGS__)
65-
#define FOR_EACH_9(what, x, ...)\
66-
what(x)\
67-
FOR_EACH_8(what, __VA_ARGS__)
68-
#define FOR_EACH_10(what, x, ...)\
69-
what(x)\
70-
FOR_EACH_9(what, __VA_ARGS__)
71-
#define FOR_EACH_11(what, x, ...)\
72-
what(x)\
73-
FOR_EACH_10(what, __VA_ARGS__)
74-
#define FOR_EACH_12(what, x, ...)\
75-
what(x)\
76-
FOR_EACH_11(what, __VA_ARGS__)
77-
#define FOR_EACH_13(what, x, ...)\
78-
what(x)\
79-
FOR_EACH_12(what, __VA_ARGS__)
80-
#define FOR_EACH_14(what, x, ...)\
81-
what(x)\
82-
FOR_EACH_13(what, __VA_ARGS__)
83-
#define FOR_EACH_15(what, x, ...)\
84-
what(x)\
85-
FOR_EACH_14(what, __VA_ARGS__)
86-
#define FOR_EACH_16(what, x, ...)\
87-
what(x)\
88-
FOR_EACH_15(what, __VA_ARGS__)
89-
90-
#define FOR_EACH_NARG(...) FOR_EACH_NARG_(__VA_ARGS__, FOR_EACH_RSEQ_N())
91-
#define FOR_EACH_NARG_(...) FOR_EACH_ARG_N(__VA_ARGS__)
92-
#define FOR_EACH_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, N, ...) N
93-
#define FOR_EACH_RSEQ_N() 16,15,14,13,12,11,10,9,8, 7, 6, 5, 4, 3, 2, 1, 0
94-
95-
#define FOR_EACH_(N, what, x, ...) CONCATENATE(FOR_EACH_, N)(what, x, __VA_ARGS__)
96-
#define FOR_EACH(what, x, ...) FOR_EACH_(FOR_EACH_NARG(x, __VA_ARGS__), what, x, __VA_ARGS__)
97-
98-
#define DECL(x) DECL_##x
99-
#define DEF(x) DEF_##x,
100-
101-
#define MENU(id,text,...)\
102-
FOR_EACH(DECL,__VA_ARGS__)\
103-
prompt* const id##_data[]={\
104-
FOR_EACH(DEF,__VA_ARGS__)\
105-
};\
106-
menu id (text,sizeof(id##_data)/sizeof(prompt*),id##_data);
107-
108-
#define CHOOSE(target,id,text,...)\
109-
FOR_EACH(menuValue<typeof(target)> DECL_VALUE,__VA_ARGS__)\
110-
menuValue<typeof(target)>* const id##_data[]={\
111-
FOR_EACH(DEF,__VA_ARGS__)\
112-
};\
113-
menuChoice<typeof(target)> id (text,sizeof(id##_data)/sizeof(prompt*),id##_data,target);
114-
115-
#define TOGGLE(target,id,text,...)\
116-
FOR_EACH(menuValue<typeof(target)> DECL_VALUE,__VA_ARGS__)\
117-
menuValue<typeof(target)>* const id##_data[]={\
118-
FOR_EACH(DEF,__VA_ARGS__)\
119-
};\
120-
menuToggle<typeof(target)> id (text,sizeof(id##_data)/sizeof(prompt*),id##_data,target);
121-
122-
/*#define GET_MACRO(_1,_2,NAME,...) NAME
123-
#define VALUE(...) GET_MACRO(__VA_ARGS__, EXPLICIT_VALUE, IMPLICIT_VALUE)(__VA_ARGS__)*/
124-
125-
#define OP(...) OP_(__COUNTER__,__VA_ARGS__)
126-
#define FIELD(...) FIELD_(__COUNTER__,__VA_ARGS__)
127-
#define VALUE(...) VALUE_(__COUNTER__,__VA_ARGS__)
128-
#define TEXTFIELD(...) TEXTFIELD_(__COUNTER__,__VA_ARGS__)
129-
130-
#define DECL_OP_(cnt,...) prompt op##cnt(__VA_ARGS__);
131-
#define DECL_FIELD_(cnt,target,...) menuField<typeof(target)> _menuField##cnt(target,__VA_ARGS__);
132-
#define DECL_TEXTFIELD_(cnt,target,...) menuTextField _menuTextField##cnt(target,__VA_ARGS__);
133-
#define DECL_SUBMENU(id)
134-
#define DECL_VALUE(...) _##__VA_ARGS__
135-
#define _VALUE_(cnt,...) choice##cnt(__VA_ARGS__);
136-
137-
#define DEF_OP_(cnt,...) &op##cnt
138-
#define DEF_FIELD_(cnt,...) &_menuField##cnt
139-
#define DEF_TEXTFIELD_(cnt,...) &_menuTextField##cnt
140-
#define DEF_SUBMENU(id) &id
141-
#define DEF_VALUE(id) &id
142-
#define DEF_VALUE_(cnt,...) &choice##cnt
34+
#include <macros.h>
14335

14436
/////////////////////////////////////////////////////////
14537
// menu pure virtual output device, use derived
@@ -192,26 +84,37 @@ v2.1 - Add full support of SetPosition(x,y) to move the menu inside the screen (
19284
// prompt -> the associated prompt object that trigged the call
19385
// menuOut -> the device we were using to display the menu.. you migh want to draw on it
19486
// Stream -> the input stream we are using to play the menu, can be a serial or an encoder or keyboard stream
87+
88+
89+
/*template<void (*T)(prompt &p, menuOut &o, Stream &i)>
90+
int devoid(prompt &p, menuOut &o, Stream &i) {T(p,o,i);return 0;}
91+
92+
template<>
93+
int (*)(prompt &p, menuOut &o, Stream &i) operator(void (*f)(prompt &p, menuOut &o, Stream &i)) {return devoid<f>;}*/
94+
95+
#define promptFeedback void
96+
19597
class promptAction {
19698
public:
197-
typedef void (*callback)(prompt &p, menuOut &o, Stream &i);//callback fynction type
99+
typedef promptFeedback (*callback)(prompt &p, menuOut &o, Stream &i);//callback fynction type
198100
callback hFn;//the hooked callback function
101+
199102
//cast no arguments or partial arguments to be accepted as promptActions
200103
inline promptAction() {}
201-
inline promptAction(void (*f)()):hFn((callback)f) {}
202-
inline promptAction(void (*f)(prompt&)):hFn((callback)f) {}
203-
inline promptAction(void (*f)(prompt&,menuOut&)):hFn((callback)f) {}
104+
inline promptAction(promptFeedback (*f)()):hFn((callback)f) {}
105+
inline promptAction(promptFeedback (*f)(prompt&)):hFn((callback)f) {}
106+
inline promptAction(promptFeedback (*f)(prompt&,menuOut&)):hFn((callback)f) {}
204107
inline promptAction(callback f):hFn(f) {}
205108
//use this objects as a function (replacing functions)
206-
inline void operator()(prompt &p, menuOut &o, Stream &i) {hFn(p,o,i );}
109+
inline promptFeedback operator()(prompt &p, menuOut &o, Stream &i) {return hFn(p,o,i);}
207110
};
208111

209112
//holds a menu option
210113
//a menu is also a prompt so we can have sub-menus
211114
class prompt {
212115
public:
213116
const char* text;
214-
static void nothing() {}
117+
static promptFeedback nothing() {}
215118
promptAction action;
216119
bool enabled;
217120
inline prompt(const char * text):text(text),enabled(true),action(nothing) {}
@@ -221,6 +124,7 @@ v2.1 - Add full support of SetPosition(x,y) to move the menu inside the screen (
221124
p.print(text);
222125
}
223126
virtual void activate(menuOut& p,Stream&c,bool) {
127+
//Serial.println("prompt::activate");
224128
action(*this,p,c);
225129
}
226130
virtual bool isMenu() const {return false;}
@@ -248,6 +152,11 @@ v2.1 - Add full support of SetPosition(x,y) to move the menu inside the screen (
248152
static char enabledCursor;//character to be used as navigation cursor
249153
static char disabledCursor;//to be used when navigating over disabled options
250154
static prompt exitOption;//option to append to menu allowing exit when no escape button/key is available
155+
static bool wrapMenus;//loop menu ends
156+
enum feedback {//
157+
cont=0,
158+
quit
159+
};
251160
const int sz;
252161
int sel;//selection
253162
prompt* const* data;// PROGMEM;

menuFields.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,10 @@ v2.0 - Calling action on every elements
5252
const char* units;
5353
T low,high,step,tune;
5454
bool tunning;
55-
void (*func)();
55+
promptFeedback (*func)();
5656
char ch;
5757
T tmp;
58-
menuField(T &value,const char * text,const char *units,T low,T high,T step,T tune=0,void (*func)()=nothing)
58+
menuField(T &value,const char * text,const char *units,T low,T high,T step,T tune=0,promptFeedback (*func)()=nothing)
5959
:menuNode(text),value(value),units(units),low(low),high(high),step(step),tune(tune),func(func),tunning(false),ch(0),tmp(0) {}
6060
virtual void printTo(menuOut& p) {
6161
p.print(text);
@@ -78,6 +78,7 @@ v2.0 - Calling action on every elements
7878
p.lastSel=-1;
7979
previousMenu->printMenu(p,previousMenu->canExit);
8080
}
81+
previousMenu->printMenu(p,previousMenu->canExit);
8182
if (!c.available()) return;
8283
if (strchr(numericChars,c.peek())) {//a numeric value was entered
8384
value=c.parseFloat();
@@ -139,6 +140,8 @@ v2.0 - Calling action on every elements
139140
this->menu::previousMenu=(menu*)menu::activeNode;
140141
menu::activeNode=this;
141142
this->canExit=false;
143+
if (p.top>menu::sel) p.top=menu::sel;
144+
else if (menu::sel+1>p.maxY) p.top=menu::sel-p.maxY+1;
142145
}
143146
int op=-1;
144147
menu::printMenu(p,false);
@@ -163,6 +166,7 @@ v2.0 - Calling action on every elements
163166
menuSelect<T>(target,text,sz,data) {menuSelect<T>::sync();}
164167

165168
void activate(menuOut& p,Stream& c,bool canExit) {
169+
//Serial.println("entering toggle");
166170
menuSelect<T>::action(*this,p,c);
167171
/*ox=activeNode->ox;
168172
oy=activeNode->oy;*/

0 commit comments

Comments
 (0)