By dave | November 10, 2020

Items that extend from runtime menu item use a callback at runtime to get every property except ID. That being the case, they don’t need an info block (that is const / in program memory) ahead of time. However, in general use they work almost identically to regular menu items in nearly every way. In addition, they are still quite memory efficient.

Runtime menu items main difference is that instead of the static data being stored in an Info structure, a “render callback” function is called to get the static values such as EEPROM address, name and even it’s current value. If you stick to creating items using the designer UI, you do not need to understand this fully. For all cases apart from list and custom scroll choice items you probably wouldn’t even see the callback.

Runtime menu item callback view

Runtime menu item association with callback

It’s important to understand that the render callbacks follow a kind of chain of command pattern, generally you provide a callback function that is capable of handling the name and EEPROM position, and then delegates everything else to the parent. For most cases, you don’t write a callback yourself, instead there’s a helper macro to handle most simple cases where everything is known upfront:

RENDERING_CALLBACK_NAME_INVOKE(fnName, parent, namepgm, eepromPosition, invoke)


  • fnName is the name to give to this function, usually something that indicates which menu it belongs to.
  • parent the parent function to call. See the types below for the appropriate one to use.
  • namepgm the name of the menu item - must be a progmem declared string
  • eepromPosition the position to use in EEPROM for storage or -1.
  • invoke the callback to invoke when changes occur.

Table of parent render functions by type

Menu Item Type Parent Render Function
BackMenuItem backSubItemRenderFn
SubMenuItem backSubItemRenderFn
TextMenuItem textItemRenderFn
IpAddressMenuItem ipAddressRenderFn
DateFormattedMenuItem dateItemRenderFn
TimeFormattedMenuItem TimeItemRenderFn
EditableLargeNumberMenuItem largeNumItemRenderFn
Rgb32MenuItem rgbAlphaItemRenderFn
ScrollChoiceMenuItem enumItemRenderFn

The callback defintion

Below is the actual callback definition, although unless you are writing your own menu item extension, implementing a list callback, or implementing a custom scroll choice renderer you won’t need to fully understand this.

int runtimeRenderingFn(RuntimeMenuItem* item, uint8_t row, RenderFnMode mode, 
                       char* buffer, int bufferSize);


  • item is the runtime item making the callback
  • row is the row number (or part in the case of multi edit items)
  • mode is one of the below RenderFnMode enumeration
  • buffer is provided for operations where a result is needed
  • bufferSize is the size of the buffer
RenderFnMode Meaning
RENDERFN_VALUE Copy the current value into buffer provided
RENDERFN_NAME Copy the name of the item at row into buffer provided
RENDERFN_EEPROM_POS Return the eeprom position for storage or -1
RENDERFN_INVOKE Invoke the action callback if there is one
RENDERFN_SET_VALUE * Set the value at index row to the buffer
RENDERFN_GETRANGE * Get the zero based range of values at index row
RENDERFN_GETPART * returns the value of a single part of

* multi edit only

Methods common to all RuntimeMenuItems

You can get the value of any runtime menu item by casting it to a RuntimeMenuItem and calling copyValue

if(isMenuRuntime(item->getType()) {
    asRuntimeItem(item)->copyValue(buffer, bufferSize);

You can get the number of parts, or it’s size (when appropriate):

uint8_t item->getNumberOfParts();
uint8_t item->getNumberOfRows();    

For MultiEditItems

There’s a special case of RuntimeMenuItem called EditableMultiPartMenuItem that supports editing of complex types such as IP Address, Dates, Times, Large Numbers, and character arrays on the device. For these item types, they are edited one part at a time. For example, we edit an IPV4 address one part at a time.

For these types, row 0 is indicating that we are before the editing has started, row 1 indicates we are editing the first part and so on. The way that multi edit works is as follows:

Editing starts (row is set to 0, isEditing = true)
While more parts are left to edit
    Increment the row by 1
    Get the range of values for the current row (RENDERFN_GETRANGE)
    Get the current value of the part (RENDERFN_GETPART)
    Allow editing of the value
    Set the modified value (RENDERFN_SET_VALUE) 
End While

Other pages within this category

comments powered by Disqus

This site uses cookies to analyse traffic, serve ads by Google AdSense (non-personalized in EEA/UK), and to record consent. We also embed Twitter, Youtube and Disqus content on some pages, these companies have their own privacy policies.

Our privacy policy applies to all pages on our site

Should you need further guidance on how to proceed: External link for information about cookie management.