Spirik / GEM

Good Enough Menu for Arduino
GNU Lesser General Public License v3.0
245 stars 36 forks source link

Add std::function callbacks feature #93

Closed vortigont closed 5 months ago

vortigont commented 6 months ago

Hi there! Would be really nice to have functional callbacks in menu items. I.e. like here. This is required to use capturing lambda functions or class instance members for menu callbacks. Thanks!

Spirik commented 6 months ago

Hi, @vortigont!

Seems like a great suggestion! I will look into it. I believe I had similar ideas when added support for current version of callbacks, but did not proceed with the implementation (probably was not sure about wide enough Arduino support: quick search gives some mixed results on <functional> support across different platforms). Also a little worried that using #include <functional> may lead to (potentially not insignificant) increase in library compiled size, but that needs to be verified.

vortigont commented 6 months ago

yes, for some platforms STL might not available. Actually most of the popular menu libs I could find (u8g2, ArduinoMenu, + some others) are not friendly to lambdas or object member callbacks, though being implemented as cpp classes. Portability is nice to have, but today is 2024 with many 32 bit MCUs around where you do not need to struggle for every byte of mem. Having some contemporary alternative would be really nice. Desperately thinking about writing some implementation of my own :)

Spirik commented 6 months ago

Technically, I can make inclusion #include <functional> optional (and update methods declaration in GEMItem.h accordingly) by implementing new configuration flag (e.g. GEM_ENABLE_FUNCTIONAL_CALLBACK).

Alternatively, in current version it is possible to enable Advanced mode and override declaration of GEMItem constructors in your own sketch (with the means to add support for std::function suitable for platform of your choice).

Spirik commented 6 months ago

And just to make sure you've considered this option (and for posterity), there is another possible workaround available in current version of GEM. As a part of a callback it is possible to pass user-defined value - it can be pointer to an object you would like to associate with the menu item. In that way while callback itself is a static function, you will have access to a desired object (and e.g. call that object's specific method or in any other way manipulate it).

See this section in wiki for details and GEMCallbackData reference in Readme.

vortigont commented 6 months ago

With (void*) pointer parameter I think it is possible to use some typecasting and lambda magic to access object instance member. I will look into it, tnx for the hint!

BTW, when working with wowki and encoder how could I move to the next char when creating strings? I was able to make only one letter elements here

Spirik commented 6 months ago

BTW, when working with wowki and encoder how could I move to the next char when creating strings? I was able to make only one letter elements here

Use simultaneous press of the knob and rotation, it will result in GEM_KEY_LEFT and GEM_KEY_RIGHT signals (see description of test bench in wiki). In wokwi you can press Space (button press) in combination with arrow keys (rotation) to navigate horizontally (do not forget to focus encoder element first).

vortigont commented 4 months ago

@Spirik just in case you might be interested I came up with own implementation of menu-like lib which is based on abstract classes and functional callbacks - MuiPlusPlus

Spirik commented 3 months ago

@Spirik just in case you might be interested I came up with own implementation of menu-like lib which is based on abstract classes and functional callbacks - MuiPlusPlus

Looks like a great option for more performant MCUs! Congrats on starting to publicly release your builds!