arduino-menusystem icon indicating copy to clipboard operation
arduino-menusystem copied to clipboard

Load MenuItems dynamically

Open skytracer opened this issue 9 years ago • 20 comments

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

skytracer avatar Apr 02 '16 11:04 skytracer

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.

jonblack avatar Apr 02 '16 16:04 jonblack

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

skytracer avatar Apr 04 '16 07:04 skytracer

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.

jonblack avatar Apr 04 '16 16:04 jonblack

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.

gzabusek avatar Apr 26 '16 15:04 gzabusek

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.

jonblack avatar Jun 02 '16 14:06 jonblack

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.

eadf avatar Jun 02 '16 19:06 eadf

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 :)

gzabusek avatar Jun 02 '16 21:06 gzabusek

@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.

jonblack avatar Jun 03 '16 07:06 jonblack

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 avatar Jun 03 '16 07:06 eadf

@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.

jonblack avatar Jun 03 '16 08:06 jonblack

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.

eadf avatar Jun 03 '16 08:06 eadf

In your example when does the NumericMenuItem subclass get created?

jonblack avatar Jun 03 '16 08:06 jonblack

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.

eadf avatar Jun 03 '16 08:06 eadf

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?

jonblack avatar Jun 03 '16 08:06 jonblack

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.

eadf avatar Jun 03 '16 08:06 eadf

I agree memory use is important. It's been on my mind for a while (pun intended!) :smile: I've created #35 for this.

jonblack avatar Jun 03 '16 10:06 jonblack

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.

jonblack avatar Jun 14 '16 10:06 jonblack

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!

ymazar avatar Jun 22 '16 23:06 ymazar

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.

jonblack avatar Jun 23 '16 08:06 jonblack

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.

jonblack avatar Aug 09 '17 11:08 jonblack