LCD hierarchal menu class, comments/critiques?

Yeah, I have seen that. I wasn't too fond of the submenu type idea, I sort of wanted everything to just be one type.

Hijacking is totally fine, as long as it's somewhat related. :stuck_out_tongue: Always good to look around at other code.

Brian, thanks for the input. I've changed it to a linked list and it has made it much more flexible, in addition to more than cutting in half an instance of the object!

I can't seem to get the typedef boolean MYCALL(menu&) to work

error: typedef 'MYCALL' is initialized (use __typeof__ instead) In constructor 'menu::menu(char*, int)':
 At global scope:

I'm still having a little trouble though..

I changed my code such that in your main code, you should have a menu pointer, and everything will just return menu pointers that you can put into that. Makes it very flexible I think. I'm having trouble then referencing the menu that is currently pointed to, so I think I may be doing something wrong.

#include <LiquidCrystal.h>

LiquidCrystal lcd(2,-1,3,4,5,6,7);

typedef boolean (*MYCALL)(void);

class menu
{
private:
menu * parent;     //Pointer to parent menu

menu * child;      //Pointer to first child

menu * sibling;    //Pointer to next sibling

MYCALL callback;   //Function associated with menu item
                   
void setparent(menu &p)
{
parent=&p;
}

void addsibling(menu &s,menu &p)
{
if (sibling)
 {
 sibling->addsibling(s,p);
}
else
 {
 sibling=&s;
 sibling->setparent(p);
 }
}

menu * getsibling(int which)
{
if (which==0)
 {
 return this;
 }
else if (sibling)
 {
 return sibling->getsibling(which-1);
 }
else //Asking for a nonexistent sibling
 {
 serror("Sibling does not exist");
 return NULL;
 }
}

public:
char *name;

menu(char *n,MYCALL c)
{
name=n;
callback=c;
}

void addchild(menu &c)
{
if (child)
 {
 child->addsibling(c,*this);
 }
else
 {
 child=&c;
 child->setparent(*this);
 }
}

menu * getchild(int which)
{
if (child)
 {
 return child->getsibling(which);
 }
else //This menu item has no children
 {
 serror("Has no children");
 return NULL;
 }
}

menu * goup()
{
return parent;
}

};


void serror(char *error)
{
Serial.print(error);
/*
lcd.clear();
lcd.print("ERROR");
lcd.setCursor(0,1);
lcd.print(error);
*/
}

boolean none()
{
Serial.println("none");
return 0;
}

boolean some()
{
Serial.println("some");
return 1;
}


menu * Menu;

menu Root("Root",some);

menu Item1("Something",some);
menu Item11("Stuff",none);
menu Item12("More",some);
menu Item121("Deeper",none);
menu Item2("Other",none);
menu Item3("Etc",some);
menu Item31("So On",none);

void menuinit()
{
Root.addchild(Item1);
Root.addchild(Item2);
Root.addchild(Item3);
Item1.addchild(Item11);
Item1.addchild(Item12);
Item12.addchild(Item121);
Item3.addchild(Item31);

Menu=&Root;
}

//UP,DOWN,LEFT,RIGHT,ENTER
int but[5]={8,9,10,11,12};
//Previous States of buttons
boolean pbut[5]={0,0,0,0,0};

int curloc;

boolean dread(int pin)
{
return digitalRead(pin);
}

void buttoncheck()
{
for (int i=0;i<5;i++)
 {
 if (dread(but[i]))
  {
  if (pbut[i]==0)
   {
   button(i);
   pbut[i]=1;
   }
  }
 else
  {
  pbut[i]=0;
  }
 }
}


void button(int which)
{
switch (which)
 {
 case 0://UP
  curloc-=2;
 break;
 case 1://DOWN
  curloc+=2;
 break;
 case 2://LEFT
  curloc--;
 break;
 case 3://RIGHT
  curloc++;
 break;
 case 4://ENTER
 Menu=Menu->getchild(curloc);

 break;
 }
if (curloc<0){curloc+=8;}
curloc%=8;
}





void setup()
{
Serial.begin(9600);
Serial.println(sizeof(menu));
lcd.clear();
menuinit();
lcd.command(0x0F);
}
void loop()
{
lcd.setCursor((curloc%2)*10,curloc/2);
buttoncheck();
}

I would like a function (external to the class) display()
This function would I think be something like this:

void display()
{
void display()
{
menu * tmp;
int i=0;
lcd.clear();
while (tmp=Menu->getchild(i))
 {
 lcd.setCursor(((i%2)*10)+1,i/2);
 lcd.print(tmp->name);
 i++;
 }
}

This works fine for the first Root menu, but once you enter a menu the lcd displays garbage, so I think I'm having pointer trouble...