arduino-menusystem
arduino-menusystem copied to clipboard
Load MenuItems dynamically
The menu items (and/or menus) can be added dynamically? For example, I have a list of log dates that I need to be added as menu items when a "Show logs" menu is selected. I am not sure whether this has a memory impact when you go back to the main menu etc
Thanks
I don't see why not. As long as you hold on to the Menu* that represents your "Show logs" menu, you should be able to dynamically add MenuItem* at runtime. Eventually you will run out of memory on the heap but I doubt it's much to worry about.
Have you tried adding menu's dynamically? I think this would be a nice example.
Running out of heap could be an issue, although I don't know what are the case for that. For example, how can I scroll though a list of logs? Having, let's say, 50 logs, read sequentially from an external EEPROM, with 5 logs per page, how these 5 MenuItems can be recreated on next page? Making 50 MenuItems and scrolling through won't work
Thanks
Since you're showing 5 per page, you could hold on to the five MenuItem's and re-use them every time the page changes . Granted, it's a bit tedious, but I can't think of another way off the top of my head. I'm planning to look all the pull requests and issues this weekend, so I'll try this out and see if I can think of a better way.
Hello there, i am in need of the same functionality. In theory dynamic menus can be created no problem. But the issue is that there is 'remove_item' missing to remove the dynamic item later (and therefore prevent memory leaks). I could implement this today, please let me know if you would like me to do it.
Issue #31 will be needed to support dynamic menus. Adding an optional callback when the Menu is selected povides a trigger for loading dynamic menu items.
Another option is to subclass Menu with DynamicMenu specifically for this purpose.
Now that #22 (NumericMenuItem) is in the code the 'show log' use case can be solved with a subclass of NumericMenuItem.
The value of the menu item can be used as the log index. And the get_composite_name() returns a sub-section/view of the log (this can be a multi row value).
While the user is 'editing' the NumericMenuItem he is actually scrolling through the log. Care has to be taken so that the _maxValue and _minValue matches the actual log size.
This can be done without dynamically adding any menuitems to the menusystem.
Hello there, I believe adding the DynamicMenu would be a nice and clean solution. Let me know if i should do it. I would be more than happy to contribute :)
@eadf That's one option. There would still need to be a way to trigger loading those items (#31). @gzabusek I'm going to look at this today and see what I come up with.
Hm, I don't think there will be any need for a trigger. To display a log we would only need one single MenuItem, a subclass of NumericMenuItem. Normally it will just display the name of the log, while in edit mode it will scroll through the log rows.
@eadf Some users might want a single MenuItem per log file. Also, users might want to do something when a dynamic menu item is selected. Adding an on_select callback to a Menu gives the client a lot of flexibility over how a dynamic menu it created. They can still create their own NumericMenuItem subclass if they want, but it shouldn't be part of the library. I want to avoid deep class hierarchies. We might need to do something about MenuItem::on_select so the callback has more information to work with.
Some users might want a single MenuItem per log file
Yes, that's what I ment. Maybe i should have typed it like this.. "To display one log we would only need one single MenuItem"
They can still create their own NumericMenuItem subclass if they want, but it shouldn't be part of the library
That is also what I envisioned, it would be impossible for us to know anything about how the end user reads the log. My point is simply that the use case "display logs" can be solved without adding dynamic menus to the library.
LogMenuItems can be added by an example, reading static data for simplicity.
In your example when does the NumericMenuItem subclass get created?
It's allocated just like any other MenuComponent. In setup() or globally (like in serial_nav.ino). When the NumericMenuItem subclass enters 'edit mode' it will have to query the actual log to fetch the valid _maxValue.
I think I understand now. I still see limitations. The number of log files could change at run time (e.g. rotating every 24 hours/every 100kb), but the menu items that represent them are only created once during setup.
In any case, it's still a novel approach and worth an example. For some people this might be enough. I still think we need the other approach though. Do you agree?
Yeah, the concept breaks down if the number of logs vary. I'm just afraid that dynamic menus will grow the codebase too much. I'm already scavenging for extra bytes (both dynamic and flash) in my small ATmega328P projects.
Esp8266 (2/4Mb flash) would be nice (read cheap) if it wasn't so limited in GPIO pins.
I'll see if I can write down an serial_log_nav.ino example this weekend.
I agree memory use is important. It's been on my mind for a while (pun intended!) :smile: I've created #35 for this.
Looking into this a bit more and it's not as trivial as it seems. The biggest issue is with memory fragmentation (see: http://www.nongnu.org/avr-libc/user-manual/malloc.html).
Storing the components as a linked-list instead of array may help. This is an item in #35.
I'll look into it more deeply at some point.
Hi guys,
I would like to use dynamic menus in order to show users a list of available WiFi networks (Shouldn't be a huge number)
After reading the comments above I couldn't understand what is the status of this issue. Is it possible to create dynamic menus? If so - can you provide a quick example? If not, when will it be available?
(I will use this opportunity to say that menusystem is great!!!)
Thanks!
Thanks, I'm glad you like it. :)
The current state is that I've looked into it and it's not so trivial. The potential problem is that freeing and reallocating memory for the dynamic components will probably lead to memory fragmentation, and then memory allocation will fail. I found a library called SimpleList which might help, but I've not tried.
It won't be in the next release unless someone else solves it before I make the release, which is currently planned for whenever it's ready. Once that release is done I plan to tackle this issue. I'm sorry that I can't be more concrete about when that will be.
A Menu now has an optional callback function, which can be used as a trigger for adding components dynamically. (see #50).
There is still the issue of dealing with memory fragmentation. I still like the idea of an object pool that gets recycled (as shown in the example in #38). An object pool breaks the current Menu interface which takes pointers to components in add_item and add_menu.
I've been thinking about moving away from allocating memory due to its inherent problems (heap fragmentation, leaks) to defining at compile time how big everything will be. For non-dynamic menus this is always known, and dynamic menus could use the object pool idea, recycling the objects to show different options in the menu.
Another option mentioned above and in #35 is storing the components in a Menu in a linked list.