jonblack / arduino-menusystem

Arduino library for implementing a menu system
MIT License
194 stars 85 forks source link

Menu call back procedure #50

Closed stathej closed 7 years ago

stathej commented 7 years ago

I have tried without much success to add a function call to the Menu class similar to the MenuItem, so that when a menu is selected some code can be executed before the submenu is drawn. I copied the SelectFnPtr select_fn, and thought I had correctly added it to the Menu class but it will not compile.

Is there already a way to call a subroutine when a Menu is selected or can only MenuItem do this. If it is only MenuItem can these be nested?

This is what I am trying to achieve

lvl 0 rootmenu lvl A menu call sub lvl AA numericmenu lvl AB numericmenu lvl B menu2 call sub lvl BA mumericmenu ect.

Thanks

Jonathan

jonblack commented 7 years ago

Only a MenuItem has a callback associated with it.

This library follows the composite design pattern. A Menu can hold zero or more MenuComponent's (a Menu or a MenuItem).

Take a look at the examples which include nested menus.

stathej commented 7 years ago

I can nest menus without a problem, what I was trying to achieve is one root menu with five sub menus. Each of the submenus would contain a pair of numeric menus so there would be 3 layers in total. This works with Menu but not MenuItem.

What I was hoping to do was run some code when a sub menu was selected before a numeric menu was selected and adjusted. Am I missing something can I use a MenuItem as a submenu to hold a numericmenuitem ?

If not is there an easy way to detect every time a submenu is selected.

jonblack commented 7 years ago

You want this:

Menu (root - created for you automatically)
  Menu (submenu1)
    NumericMenuItem1
    NumericMenuItem2
  Menu (submenu2)
    NumericMenuItem1
    NumericMenuItem2
  Menu (submenu3)
    NumericMenuItem1
    NumericMenuItem2
  Menu (submenu4)
    NumericMenuItem1
    NumericMenuItem2
  Menu (submenu5)
    NumericMenuItem1
    NumericMenuItem2

I recommend you read up on the composite design pattern. Once you understand how that works, it'll make a lot more sense.

stathej commented 7 years ago

The above structure is correct and I successfully have that created and working, all I was hoping to achieve was to detect when one of the submenus was accessed before the numeric menu. If adding the code to execute a sub when the menu is selected for my proposed layout is not possible I will just look at procedurally checking when a submenu is open.

I will have a look at the design pattern doc tomorrow but was hoping for an easier way of detecting when a menu was selected similar to the MenuItem.

jonblack commented 7 years ago

I'm curious. What do you want to do when the Menu is selected but before the submenu displays?

stathej commented 7 years ago

I will be using a rotary encoder to drive the menu and the menu text element formatted to an int for display on Nixie tubes. First pair of tubes would display the sub menu as a number and the second pair would display the value from the numeric menu item. As the rotary encoder only has one button I was hoping to change the function of the button press action after the sub menu was selected. I would need to do similar things with the numeric menu items as well but they already have call backs.

It's all down to going retro and not having a true text display and only one physical button to do the select with. I had a brief flick through the Wikipedia doc whilst at work but visual basic was more my style than c++ and I'm no master with that. If I duplicated the menu functions to make menu2 and added the selectedfnptr to the code removing the friendship to menu component at the same time would I be along the write lines or am I fighting a loosing battle making menu call a subroutine?

jonblack commented 7 years ago

There are four actions that need supporting in the menu system:

As I understand it, you have the following:

When in the root, you perform the following:

What else do you need to do in this workflow that I'm missing?

stathej commented 7 years ago

You are correct in the menu flow structure with the rotary encoder. With the display being on digits displayed on the Nixie tubes the desire was to detect when Menu was selected. If for instance you select Menu1 the plan was to call a script which would format the menu into an int value to display on the Nixie tube. With the first pair of tubes in the display showing the menu as a number the script would then instruct the code to the next pair of tubes and select the first numericmenuitem so that it was in edit mode. When the encoder select was pressed again the the numericmenuitem would be stored and it would have focus. If I have it figured correctly a numericmenuitem with focus would then call it's own attached subroutine which would be set up to select the last pair of Nixie tubes and place the second numericmenuitem into edit mode. The last part of the sequence would be to have its subroutine return back to the root level when it regaines focus so that the cycle my be continued with another menu item.

If I could attach subroutine calls to each of the items in the menu, I would only need 3 so that the encoder would automatically walk through the menu selecting the right pair of display tubes after each press of select. That is why I was trying to figure out how to call a subroutine with menu, so that a can select the correct display tubes and display a numeric value which would give a numeric menu level for the two values to be edited next.

jonblack commented 7 years ago

So when a Menu is selected one set of nixie tubes will display that menu as a number. A second set of nixie tubes will display the first NumericMenuItem value, which will automatically be in edit mode; turning the rotary encoder will change this value. Selecting to go out of edit mode will automatically move to the next NumericMenuItem placing that automatically in edit mode. I'm going to assume that after the last NumericMenuItem has been edited, it will automatically go back up one level.

In effect what you're doing is forcing the user to edit each value in turn, rather than allowing them to select what they want to change first. The menu callback also allows you to switch between output device (nixie tube).

A callback for when the menu is selected seems like a reasonable solution to this. It could also be useful for #20.