Closed christophepersoz closed 7 years ago
the current menu lacks many things, the most important a central navigation object and depth chain I'm working on both on version 3 and doing a lot of tests and research about flash memory c++ and harvard architecture uC as AVR's along with navigation objects i'm using events instead of just click/select. however c++ has been giving me an hard time beacause of the lack of harvard architecture support (only available for C) and the need to do static initialization of data members leading to a very complex memory model... right now its a pile of problems.
I can imagine a bit all the problem you can be facing to. At this time I really appreciate the v2.4, it's a nice build. Thanks for working on v3, and when you will looking for beta tester, do not hesitates ;)
To be back to the point, do you think I can have a feedback on entering in a SUBMENU with v2.4 ? Thanks
yes, i think, or at least we have the potential because all prompts have an associated action
https://github.com/neu-rah/ArduinoMenu/blob/master/src/menu.h#L120
and a menu is menu<-menuNode<-prompt derived and when handling keys/enter
https://github.com/neu-rah/ArduinoMenu/blob/master/src/menu.cpp#L105
the action members is called, so all we have to do is to manually define the menu action like
subMenu.action=someActionFunction;
if the action is not being called then we just have to fix the key handler and make it call the action member (but last time i checked it was working). This action function can even decide if we can enter the menu or not by its return value.
Yeah, so the track I was following yesterday was the good one. But I did not success into the activation of the SUBMENU call. How can I do that ?
I tried to poll the SUBMENU, but it does not work, that block everything - wrong way or wrong syntax. Here what I did and tried
uint8_t menuLevel = 0; // 0 means root
boolean trigA()
{
//
// mPageA.prompt::activate(_menuU8G, allIn, true);
menuLevel = 1;
return (true);
}
/* drawSettingsMenu()
Display the main settings menu
*/
void drawSettingsMenu()
{
uint8_t hFont = 7;
_U8G.setFont(u8g_font_04b_03e);
// Set mainMenu and Pages positions
mainMenu.setPosition(12,0);
mPageA.setPosition(12, 0);
mPageB.setPosition(12, 0);
mPageC.setPosition(12, 0);
mPageD.setPosition(12, 0);
mPageE.setPosition(12, 0);
mPageA.action = trigA;
switch (menuLevel)
{
case 0:
mainMenu.poll( _menuU8G,allIn );
break;
case 1:
// Does not work, clear the current mainMenu poll but does not shows up mPageA
//mPageA.activate( _menuU8G, allIn);
//mPageA.poll( _menuU8G, allIn );
break;
}
}
Also, how to know when we are coming back to the root level and change menuLevel var which have changed, and reset it to 0... that's the next step ;)
really need version 3, central nav + navigation chain + menu events (focusIn, focusOut, enter, exit)
the current poll function acts a bit like a central navigation object by redirecting to activeNode
https://github.com/neu-rah/ArduinoMenu/blob/master/src/menu.cpp#L138
Good luck for v3 !
If I'm following what you are saying about poll, that means if mPageA is the first SUBMENU inside the ROOT menu when I'm calling mPageA.poll( _menuU8G, allIn);
that should activate and shows the mPageA SUBMENU. The fact is it does not.
Am I wrong ?
activeNode is a static member of menuNode https://github.com/neu-rah/ArduinoMenu/blob/master/src/menu.h#L144 no mather what menu you call from it will redirect to the menu pointed by menuNode
you can however set menuNode::activeNode manually and see if it is the desired result
in that case you can still call your main menu poll as usual
menuNode::activeNode=&mPageA;
mainMenu.poll( _menuU8G, allIn);
Thanks for your time Rui, but sorry I don't know how to change the value of active node to true for mPageA. I tried different ways without any success. Can you show me ?
just like this:
menuNode::activeNode=&mPageA;
its static member assign and its type is prompt* (not bool) being static it exists only one variable menuNode::activeNode in the program, and you can set it to whatever prompt (pointer) you may have. after that the poll will take that menu as the current target. this allows calling always poll on the base while navigating on the system
Ohhhh! I did not imagine that like this. Thanks a lot ! I'm going to try that
Hum, it seems that something is missing. The trigger seems working, but I'm staying on the mainMenu, like if the active node is not considered. Here below the code I'm using to test the triggering. What am I doing wrong ?
boolean trigSubMenu()
{
menuLevel = mainMenu.sel;
switch (menuLevel) {
case 0:
menuNode::activeNode = &mainMenu;
break;
case 1:
menuNode::activeNode = &mPageA;
break;
case 2:
menuNode::activeNode = &mPageB;
break;
case 3:
menuNode::activeNode = &mPageC;
break;
case 4:
menuNode::activeNode = &mPageD;
break;
case 5:
menuNode::activeNode = &mPageE;
break;
}
return (true);
}
void drawSettingsMenu()
{
_U8G.setFont(u8g_font_04b_03e);
// Set mainMenu and Pages positions
mainMenu.setPosition(12,0);
mPageA.setPosition(12, 0);
mPageB.setPosition(12, 0);
mPageC.setPosition(12, 0);
mPageD.setPosition(12, 0);
mPageE.setPosition(12, 0);
mPageA.action = trigSubMenu;
mPageB.action = trigSubMenu;
mainMenu.poll( _menuU8G, allIn );
redraw = true;
}
don't know if it help but
boolean trigSubMenu()
can be
boolean trigSubMenu(prompt &p, menuOut &o, Stream &i)
but changing the active menu is not needed on your handler, that occurs on the menu system code, and probably it is overriding your setting... you can set the activeMode from outside the poll.. after that (as in an action) the result will be unpredictable because of the override a possible solution would be to change the order on the menulib, first define the activeNode and then call the action function, allowing the settings of the function to remain (action function overrides navigation), but it will probably induce other problems because of this
https://github.com/neu-rah/ArduinoMenu/blob/master/src/menu.cpp#L106
the activeNode is stored as previous node for further navigation reference...
so you need to know what member was clicked, but you do not need to work on the redirection, the menu system will activate the clicked node and do the redirection stuff.
maybe if i understand better your goal we can come up with a better solution
Hmm, I see.
Maybe I should have start by my goal, you are right, I was just wondering it was simpler than that :D
First of all, it is just a question of IHM and design for end user - it is not a functionality matter, at this time, everything is working perfectly on the menu side.
So, back to your question. I would like to have on screen, on the left side, a visual feedback of the root menu and a highlight of the SUBMENU I'm currently browsing. On the right side, at the same time, the content of the browsed submenu.
This can gives something like that,
Maybe this can be achieve in v2.4, if not, I will think about it on v3.0 ;)
i see your problem now i have a similar implementation, just by setting x offset, the problem is that your gfx driver needs the previous menu to be redrawn too. so, in addiction to setting x offset on sub-menus i would try a menuOut::printMenu with the menuNode::activeNode->previousMenu just before the poll
if (menuNode::activeNode&&menuNode::activeNode->previousMenu)
_menuU8G.printMenu(menuNode::activeNode->previousMenu,menuNode::activeNode->canExit);
mainMenu.poll( _menuU8G, allIn);
note that I've not tested this
Oh, thanks ! I'm going to try that.
just edited that, removing extra -> sory
I tried several combination to find canExit, but it does not work on this parameter,
if (menuNode::activeNode&&menuNode::activeNode->previousMenu)
_menuU8G.printMenu(menuNode::activeNode->previousMenu,menuNode::activeNode->canExit);
And the most common error I'm getting is
error: 'class menuNode' has no member named 'canExit'
if (menuNode::activeNode&&menuNode::activeNode->isMenu()&&menuNode::activeNode->previousMenu)
_menuU8G.printMenu(menuNode::activeNode->((menu*)previousMenu,menuNode::activeNode)->canExit);
Almost... but not building ;)
my fault of coz, guess i need some sleep or some coffee :D
if (menuNode::activeNode&&menuNode::activeNode->isMenu()&&menuNode::activeNode->previousMenu)
_menuU8G.printMenu(menuNode::activeNode->previousMenu,((menu*)menuNode::activeNode)->canExit);
still not sure if ((menu*)menuNode::activeNode)->canExit
shouldn't be menuNode::previousMenu->canExit
gota check the storing code to decide... or just test both
Hi Rui,
Maybe you need both, coffee and sleep ;)
I tried both, and both returns error. For the first one, MOCO.ino:1385:101: error: no matching function for call to 'menuU8G::printMenu(menu*&, bool&)'
For the second try it creates an error on menu.h as : _Arduino/libraries/Menu/src/menu.h:147:17: error: invalid use of non-static data member 'menuNode::previousMenu'
Seems hard to access to it...
Yes, indeed. and now that i had both :D
if (menuNode::activeNode&&menuNode::activeNode->isMenu()&&menuNode::activeNode->previousMenu)
gfx.printMenu(*menuNode::activeNode->previousMenu,((menu*)menuNode::activeNode)->canExit);
mainMenu.poll(gfx,Serial);
at least this compiles (did not run it.. missing the screen), i'm using output gfx and Serial as input, just change that
It seems that coffee and bed have a good influence ;)
So it does build now ;)
But... sorry... that doesn't poll the right submenu on click. And on the other - the ones that are calling trigSubMenu()
there is a kind 'strange' repeats below the Exit, that displays exit many times (but you can't access to it with the encoder. The navigation still on the menu items).
this code gave me an approximation of what you want when opening "submenu", however the first menu gets scrolled when along with the second, as a reflex of shared common variables. other elements like "choose" just render useless (but we can filter them out)
#include <Arduino.h>
#define DEBUG
#include <menu.h>
#include <menuFields.h>
#include <menuU8G.h>
#define U8_DC 9
#define U8_CS 8
#define U8_RST 7
U8GLIB_PCD8544 u8g(U8_CS, U8_DC, U8_RST) ;
//menuGFX gfx(display);
menuU8G gfx(u8g,1,0,1,1,7,9);
/*bool runMenu=true;
promptFeedback pauseMenu(prompt &p, menuOut &o, Stream &i) {
runMenu=false;
o.clear();
return false;
}*/
//#include "test_menu.h"
//#include "nomacs.h"
//aux vars
int ledCtrl=0;
bool runMenu=true;
bool scrSaverEnter=true;
int percent;//just testing changing this var
double fps=0;
unsigned long lastFpsChk=0;
int counter=0;
#define LEDPIN A4
///////////////////////////////////////////////////////////////////////////
//functions to wire as menu actions
bool pauseMenu() {
runMenu=false;
scrSaverEnter=true;
}
bool ledOn() {
Serial.println("set led on!");
digitalWrite(LEDPIN,ledCtrl=1);
return false;
}
bool ledOff() {
Serial.println("set led off!");
digitalWrite(LEDPIN,ledCtrl=0);
return false;
}
bool quit() {
Serial.println("Quiting after action call");
return true;
}
/////////////////////////////////////////////////////////////////////////
// MENU DEFINITION
// here we define the menu structure and wire actions functions to it
// empty options are just for scroll testing
/*bool setLed() {
digitalWrite(LEDPIN,ledCtrl);
return false;
}*/
TOGGLE(ledCtrl,setLed,"Led: ",
VALUE("On",HIGH,ledOn),
VALUE("Off",LOW,ledOff)
);
int selTest=0;
SELECT(selTest,selMenu,"Sel",
VALUE("Zero",0),
VALUE("One",1),
VALUE("Two",2)
);
int chooseTest=-1;
CHOOSE(chooseTest,chooseMenu,"Choose ",
VALUE("1st",1),
VALUE("2nd",2),
VALUE("3rd",3),
VALUE("last",-1)
);
MENU(subMenu,"SubMenu"
,OP("A",quit)
,OP("B",quit)
,OP("C",quit)
,OP("D",quit)
,OP("E",quit)
,OP("F",quit)
,OP("G",quit)
,OP("H",quit)
);
MENU(mainMenu,"Main menu",
SUBMENU(setLed),
OP("LED On",ledOn),
OP("LED Off",ledOff),
SUBMENU(selMenu),
SUBMENU(chooseMenu),
SUBMENU(subMenu),
FIELD(percent,"Perc","%",0,100,10,1),
FIELD(fps,"fps [","]",0,0,0,0),
FIELD(counter,"cnt [","]",0,0,0,0),
OP("Exit",pauseMenu)
);
void scrSaver() {
//if (scrSaverEnter) {
/*lcd1.clear();
lcd1.print("|www.r-site.net|");
lcd1.setCursor(0,1);
lcd1.print("|click to enter|");*/
u8g.setColorIndex(1);
u8g.drawStr(0,15,"r-site.net");
//scrSaverEnter=false;
//}
}
void setup() {
Serial.begin(115200);
Serial.println("menu test");
pinMode(LEDPIN,OUTPUT);
u8g.setFont(u8g_font_unifont);
//menu::wrapMenus=true;
u8g.setColorIndex(1);
gfx.clear();
mainMenu[7].disable();
mainMenu[8].disable();
subMenu.setPosition(5,1);
}
void draw(void) {
/* if (runMenu) {
mainMenu.poll(gfx,Serial);
} else {
u8g.setColorIndex(1);
u8g.drawStr(0,15,"r-site.net");
if (Serial.read()==menu::enterCode) runMenu=true;
}*/
if (runMenu) {
if (menuNode::activeNode&&menuNode::activeNode->isMenu()&&menuNode::activeNode->previousMenu)
gfx.printMenu(*menuNode::activeNode->previousMenu,((menu*)menuNode::activeNode)->canExit);
mainMenu.poll(gfx,Serial);
} else if (Serial.read()==menu::enterCode) runMenu=true;
else scrSaver();
//simulate the delay of your program... if this number rises too much the menu will have bad navigation experience
//if so, then the menu can be wired into a timmer... leaving the shorter end to your code while it is running
counter=millis()/1000%60;
int d=micros()-lastFpsChk;
if (d>0) {
fps=1000000.0/d;
lastFpsChk+=d;
}
delay(150);
}
void loop()
{
u8g.firstPage();
do {
draw();
} while( u8g.nextPage() );
//param=(++param)%100;//testing dynamic values
// rebuild the picture after some delay
//delay(1000);
}
Hi Rui,
Thanks, I gonna try that as soon as I can. I will keep you informed. ;)
Hi !
Just back and tried your example. I got the same kind of result as before. Never mind, I think I gonna wait for v3, no worries. I would be nice if in v3 we can call and poll any submenu of the hierarchy :)
Thanks for your time
this kind of feedback is appreciated, to handle this particular case I'm thinking to add "panels" to the nav structure (v3 has menu structure and nav structure).
(v3 already separates variables by using nav levels instead of 2.x shared/static variables that cause many mess and restrictions)
nav positioning
any flavor?
Yes a lot, thanks for asking :D
Because of the increasing CPU power of embedded boards and screen size available at cheap price, it could be nice to have en enhanced Arduino menu version with root menu on a side (left for example), an submenu on the other (right). And for smaller boards, having the previous submenu name displayed could be nice - mostly for complex menus. Maybe this can activated or not, depending on the user needs.
It could be nice to have the possibility to leave a CHOOSE (or any other edit field) once you are entered in it. For example, I currently have an option to save and load multiple configuration in EEPROM, and I had to manage this behavior by inserting a "< BACK" trick which waste a bit of SRAM adding a function and some vars.
I can easily imagine that it is not so simple. But at this time, with v2.4 I'm already really happy of the result :D
Hi Rui,
Are you interested if I have a look onto the update of the U8Glib named U8G2 ? On of the feature that I pointed out : • Full "RAM" memory buffer without picture loop (u8glib picture loop still supported). • More fonts support • High speed text only API (U8x8) for character only displays (I'm not really interested in, but you could) • 90% compatible with U8glib - which means little effort to support it.
I let you read the enhancements here : help is https://forum.arduino.cc/index.php?topic=409966.0
Christophe
yes please, we can support both:
"Limitations - Still support for some display controller is missing compared to U8glib V1 :-("
Yes I saw about the limited number of controller at this time, but it's gonna growing in the coming months, for sure. I will keep you in touch about that, I have a lot to do on my dev ;)
I have some troubles with pointers and vars which creates crash of my board... hard to be a beginner sometimes !
central navigation on v3.x gives navigation generic info and provides access to each navigation layer.
Hi Rui,
I have a mainMenu that contains 5 SUBMENU (direct sibling). Is that possible after calling
mainMenu.poll()
to have a feedback of which SUBMENU I clicked on ? Only the first level interest me.I tried to add just after the pool an action on the first SUBMENU with the following trigger code
But it removes the poll of the SUBMENU PageA, so the SUBMENU does not shows up as it should.
I know that
mainMenu.sel
returns me the level of the SUBMENU, but I don't know if I did clicked it to enter in or no.I there a workaround to have this feedback ? Thank you.