Skip to content
rogerjames99 edited this page Apr 23, 2024 · 24 revisions

Menu definition macros

important for fields (specially SELECT, CHOOSE, TOGGLE), the referred variable must be initialized with a valid value. Otherwise strange behavior can be observed.

Options

This macros define read-only static menu structure (PROGMEM on system that support it).

OP - define a prompt with associated action function

OP(text,action,event mask)

result goFun() {Serial.println("done!");return proceed;}

...
OP("Go!",goFun,enterEvent)

Creates an 'anonymous' option as a parent's menu element. This option is associated with an action function to be called according to element's mask.

Prompts are the menu basic structure; all other elements will share its properties. That is, all can have a title, an action function and an event mask.

The action function will be called on every occurrence of an event in the event mask. The action function can send back some 'result' information to be interpreted by the caller. The meaning of this result depends on the caller and it might ignore it. The option is anonymous because no variable representing this it will be created in your code. Therefore it can only be accessible by indexing the menu that holds it, like menu[0] for indexing into the first option.

altOP define options using a custom user objects class

altOP(classname,title,event handler,event mask)

example

//customizing a prompt look!
//by extending the prompt class
class altPrompt:public prompt {
public:
  altPrompt(constMEM promptShadow& p):prompt(p) {}
  Used printTo(navRoot &root,bool sel,menuOut& out, idx_t idx,idx_t len,idx_t panelNr) override {
    return out.printRaw("special prompt!",len);;
  }
};

MENU(subMenu,"Sub-Menu",showEvent,anyEvent,noStyle
  ,altOP(altPrompt,"",showEvent,anyEvent)
  ,EXIT("<Back")
);

altFIELD - same as FIELD but allows specifying an user object to be constructed and used

this macro is for using custom print and/or custom input menu fields

and example of alternative field is the custom decimal places print decPlaces<3>::menuField

altFIELD(decPlaces<3>::menuField,test,"Test","%",0,100,1,0.001,showEvent,anyEvent,wrapStyle)

it allows adjusting decimal places print for numeric fields

OBJ - Same as option but using user allocated menu item

OBJ(object reference)

Menu

MENU - define a menu

MENU( id, title, action, events mask, styles, Option, Option, [Option,...])

a menu object 'id' is statically created and can be referred in your sketch by its 'id'.

  MENU(myMenu,"Schedule",doNothing,noEvent,wrapStyle
    ,OP("Op A", actionA,enterEvent)
    ,OP("Op B",actionB,enterEvent)
    ,OP("Op C",actionC,enterEvent)
    ,FIELD(test,"Test","%",0,100,10,1,doNothing,noEvent,wrapStyle)
  );

disabling an option.

myMenu[2].disable();//example of disabling a menu option

Fields

Fields are special options that hook up to existing variables (by reference) and will update the variables as result of iteration.

Beware when using string values on AVR devices because the original alternative values are stored in flash memory

FIELD - numeric field for editing and range validate a numeric variable (int, float, double, unsigned int, etc...)

FIELD(var.name, title, units, min., max., step size,fine step size, action, events mask, styles)

int pwm=0;
...
FIELD(pwm,"Power","%",0,100,10,1,doNothing,noEvent,noStyle)

EDIT - Text edit field, edits a zero terminated user buffer (v4.x).

Each character position is validated by a string of allowed characters. The array of validating string can differ in length from the field, on that case only the needed entries are used or recurring entries can be used.

EDIT(label,target buffer,validators,action,events mask,styles)

char* const hexDigit PROGMEM="0123456789ABCDEF";//allowed hexadecimal digits
char* const hexNr[] PROGMEM={"0","x",hexDigit,hexDigit};//validators
char buf1[]="0x11";//the edit target buffer
...
EDIT("Hex",buf1,hexNr,doNothing,noEvent,noStyle)

edit operation:
1 - first * -> enter field navigation use +/- to select character position
2 - second * -> enter character edit use +/- to select character value
3 - third * -> return to field navigation (1)
4 - fourth * without changing position -> exit edit mode

You can also use keyboard to enter characters, enter and escape keys recognized. I use a terminal that sends characters as they are typed (not buffered like the Arduino IDE monitor). It works better for menu iteration.

If using Arduino IDE serial monitor "No line ending" must be selected.

VALUEOBJ allows mixing user allocated value objects with regular VALUE ones (v4.x).

This is to be used within SELECT, TOGGLE or CHOICE fields.

SELECT - define variable value by selecting from an enumerated list of possible values. Click to start, select, click to end.

SELECT(var.name, id, title, action, events mask, styles, value, value [, value ...])

This creates a static menu like structure associated with a variable, enumerating all possible variable values. Changing the selection will change the variable value and also reflects variable changes done elsewhere.

int mode=0;
SELECT(mode,selMenu,"Select",doNothing,noEvent,noStyle
  ,VALUE("Eco",0,doNothing,noEvent)
  ,VALUE("Normal",1,doNothing,noEvent)
  ,VALUE("Full",2,doNothing,noEvent)
);

MENU(myMenu,"Schedule",doNothing,noEvent,wrapStyle
  ,SUBMENU(selMenu)
  ,...
)

TOGGLE - set a variable value by toggling from an enumerated list of possible values. Change value every click.

TOGGLE(var.name, id, title, action, event mask, styles, value, value [,value ...])

int dir=LOW;
TOGGLE(dir,dirPinMenu,"Dir: ",doNothing,noEvent,wrapStyle
  ,VALUE("Up",HIGH,doNothing,noEvent)
  ,VALUE("Down",LOW,doNothing,noEvent)
);

//hooking the toggle to a menu
MENU(myMenu,"Schedule",doNothing,noEvent,wrapStyle
  ,SUBMENU(dirPinMenu)
  ,...
);

Creates a menu-like structure enumerating all possible values of the associated var.

CHOOSE - define variable value by choosing from an enumerated list of possible values. Enumerated list of values shown as a sub-menu.

CHOOSE(var.name, id, title, action, event mask, styles, value, value [,value ...])

int chooseTest=1;//some variable used by your code (not necessarily an int)
CHOOSE(chooseTest,chooseMenu,"Choose",doNothing,noEvent,noStyle
  ,VALUE("First",1,doNothing,noEvent)
  ,VALUE("Second",2,doNothing,noEvent)
  ,VALUE("Third",3,doNothing,noEvent)
  ,VALUE("Last",-1,doNothing,noEvent)
);

MENU(mainMenu,"Main menu",doNothing,noEvent,wrapStyle
  ,SUBMENU(chooseMenu)
  ,...
);

Creates a static menu-like structure enumerating all possible values of the associated variable.

SUBMENU - include a menu as sub-menu or a SELECT|TOGGLE|CHOOSE field.

MENU(myMenu,"Schedule",doNothing,noEvent,wrapStyle
  ,OP("Op A", actionA,enterEvent)
  ,OP("Op B",actionB,enterEvent)
  ,OP("Op C",actionC,enterEvent)
  ,FIELD(test,"Test","%",0,100,10,1,doNothing,noEvent,wrapStyle)
);

MENU(mainMenu,"Main menu",doNothing,noEvent,wrapStyle
  ,SUBMENU(myMenu)
  ,...
);

include a menu or menu like structure as element of the current menu.

EXIT - quick define special option to leave current menu.

EXIT("<Back")

Create an option that exits the current menu as default action.

styles

Elements can have this static styles.

noStyle accepts system defaults to this elements

wrapStyle element values list have a circular arrangement.

events

this is used to for the filter mask and also send as a parameter to the event handler function.

noEvent no event (use if you do not want an handler function)

activateEvent the item is about to be active (system event) (do not use)

enterEvent entering navigation level (this menuNode is now active)

exitEvent leaving navigation level

returnEvent entering previous level (return) (not implemented yet)

focusEvent element just gained focus

blurEvent element about to lose focus

selFocusEvent child just gained focus

selBlurEvent child about to lose focus

updateEvent field values has been updated, this is only used if options->useUpdateEvent=true otherwise enterEvent will be used. (from 3.1.0)

anyEvent all events

events can be combined like:

enterEvent | exitEvent | updateEvent

when forming a mask of allowed events, as when defining menu elements.

They should not be combined when sending navigation commands.

User commands

These commands are for semi-automated mode. User code can call the navigation root with them.

example:

nav.doNav(upCmd);

see navigation commands for a list of available commands.