Closed Redferne closed 7 years ago
yes, some sort of... see:
https://github.com/neu-rah/ArduinoMenu/blob/master/src/menu.h#L521 https://github.com/neu-rah/ArduinoMenu/blob/master/src/menu.h#L583
however it will be called on poll if your device requires constant redraw otherwise only on entry and exit.
This can also be done outside the menu system, by not calling the menu poll and using the display for whatever purposes...
note: on system that do not require constant redraw it can be forced by invalidating the current draw (see force draw/update)
I'm using the SSD1351 (Adafruit GFX) and it does not require constant redraw. I tried to define the display as menuOut::redraw and got the desired effect, the IdleScreen or "Device Monitor" updates for each call to nav.doOutput(). However this causes all menus to continuously update :-1: I could not find any reference to force draw/update, but there is a dirty bit? Please advice, it would be so nice to be able to define "live" panels where as its possible to continuously monitor certain parameters.
A general menu timeout would also be very nice, a callback function which would be called when there has been no input for x milliseconds.
I know this can be done outside the library but somehow it feels natural to have the design completely menu/input driven.
its is possible to monitor parameters (fields) as the menu will set the redraw flags whenever the values change (comparing to internal stored values).
https://github.com/neu-rah/ArduinoMenu/blob/master/src/menu.h#L144
Yes. This works beautifully for the known datatypes, int, float. But not for char * "string". I managed to use the prompt class for custom data types. It prints the fix.dateTime once, but It does not redraw when changed?
class infoTime:public prompt {
public:
infoTime(const promptShadow& p):prompt(p) {}
idx_t printTo(navRoot &root,bool sel,menuOut& out, idx_t idx,idx_t len) override {
root.active().dirty=true; // <--- This does not work
out << fix.dateTime;
return 0;
}
};
MENU(gpsMenu,"- GPS Info -",showEvent,anyEvent,noStyle
,altOP(infoTime, "", updateEvent,anyEvent)
,....
);
Change the text and force update:
gpsMenu.data[0]->text = "Updated Text";
But it does not compile. Please advice
nope, the printTo will only be called if menu has changed, so signalling dirty inside wont help... instead overload
virtual bool changed(const navNode &nav,const menuOut& out,bool sub=true) {return dirty;}
https://github.com/neu-rah/ArduinoMenu/blob/master/src/menu.h#L78
where you can always return true (can result in flicking or menu over usage) or use some timed thing to reduce the redraw rate, or even better detect when your information has changed to signal the draw needs.
Some progress. Below class uses redraw_menu flag to signal dirty. But if I ever return false from the overridden changed(), prompt is not redrawn anymore. "Tick!" output is correct (once per second), however the display is not updated.
So basically I set redraw_menu = true every second, to get a new timestamp written to the display. nav.poll() is called every 100ms, my hope was that the below prompt would redraw every second and not cause to much CPU load. Please advice :cry:
class infoTime:public prompt {
public:
infoTime(const promptShadow& p):prompt(p) {}
bool changed(const navNode &nav,const menuOut& out,bool sub) override {
if (redraw_menu) {
Serial.println(F("Tick!"));
redraw_menu = false;
return true;
}
return false;
}
idx_t printTo(navRoot &root,bool sel,menuOut& out, idx_t idx,idx_t len) override {
out.setColor(valColor,sel,enabled,true);
PrintLocalTime(out, true);
return 16;
}
};
MENU(gpsMenu,">GPS Info<",doNothing,noEvent,wrapStyle
,altOP(infoTime, "", showEvent,anyEvent)
....
hi! this one seems to update when used on my serial example
int cnt=0;
class altPrompt:public prompt {
public:
altPrompt(const promptShadow& p):prompt(p) {}
idx_t printTo(navRoot &root,bool sel,menuOut& out, idx_t idx,idx_t len) override {
return out.printRaw(String(cnt++).c_str(),len);
}
virtual bool changed(const navNode &nav,const menuOut& out,bool sub=true) {return true;}
};
p.s. i'm testing this on an esp (so all memory is ram, no flash) therefor this might not work on the uno or other avrs, just because i'm printing a ram string... so replace that with your own print stuff on avr's
Yes. I've tried your solution, but problem is that the same line is redrawn continuously even if the string has not changed. I only want it to redraw when there is new data in the string or if I set a flag to trigger redraw as my example above (redraw_menu). Any ideas?
yes it does, you can compare with last drawn value and only signal changed when its updated... or if you have an updating function then signal that for changed
here's a thing i was loading on uno right now
//customizing a prompt look!
//by extending the prompt class
//this prompt will count seconds and update himself on the screen.
class altPrompt:public prompt {
public:
unsigned int t=0;
unsigned int last=0;
altPrompt(const promptShadow& p):prompt(p) {}
idx_t printTo(navRoot &root,bool sel,menuOut& out, idx_t idx,idx_t len) override {
last=t;
return out.printRaw(String(t).c_str(),len);
}
virtual bool changed(const navNode &nav,const menuOut& out,bool sub=true) {
t=millis()/1000;
return last!=t;
}
};
this one has internal status and last drawn control to avoid constant redraw
Wonderful! :grinning: It works perfectly. Thank you!
Hi,
This is more a question than issue. Is it possible to define an Idle "Screen" which is continuously updated? Some thing like this:
So that the information submenu is called/updated with every call to nav.poll();
Thanks!