Arduino library for creating a menu system

Update

Since this post I've updated the library with non-backwards compatible changes. See this post for more details.

arduino-menusystem is an Arduino library I've written to make it easier to incorporate nested menu's into an Arduino project. It was designed using the composite design pattern, as shown in the following image:

composite

When using this library you will only need to create Menu's, MenuItem's, and a single MenuSystem. The responsibilities of these classes are outlined below:

Menu
Selecting a Menu causes the MenuSystem to enter into it, pointing to the first MenuComponent within. When you create a Menu, use add_menu_item() and add_menu() to build its contents.
MenuItem
Selecting a MenuItem causes the MenuSystem to call the callback function passed to the Menu::add_menu_item() function. The signature for the call back function is: void (*on_select)(MenuItem*).
MenuSystem
The MenuSystem is the interface for interacting with the menu.

Example

First create the various Menu's, MenuItem's, MenuSystem at the top of your project file. You will also need to create a root Menu to hold the top-level menu items:

#include <MenuSystem.h>

MenuSystem ms;
Menu mm("");
MenuItem mi_time("TIME");
MenuItem mi_date("DATE");
MenuItem mi_alarm("ALARM");
Menu mu_disp("DISP");
MenuItem mi_disp_brightness("BRTNS");

In your project's Setup() function,  put the menu system together:

void setup()
{
  // Menus
  mm.add_item(&mi_time, &on_menu_set_time);
  mm.add_item(&mi_date, &on_menu_set_date);
  mm.add_item(&mi_alarm, &on_menu_set_alarm);
  mm.add_menu(&mu_disp);
  mu_disp.add_item(&mi_disp_brightness, &on_menu_set_brightness);
  ms.set_root_menu(&mm);
}

Define your callback functions (only one example is shown here):

void on_menu_set_alarm(MenuItem* pMenuItem)
{
  // Set the alarm
}

And finally, interact with your menu system. This will usually happen when you press buttons ;)

ms.select(); // select/go into the current menuitem/menu
ms.back(); // go back to the menu one level up
ms.next(); // go to the next item in the current menu
ms.prev(); // go to the previous item in the current menu
ms.get_current_menu_name(); // get the current menu name
ms.get_num_menu_items(); // get the number of menu items in the current menu
ms.get_cur_menu_item(); // get the current menu item number in the current menu