Need some feedback

Post here about your Arduino projects, get help - for Adafruit customers!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
patrikk
 
Posts: 34
Joined: Sun Feb 17, 2013 6:13 pm

Need some feedback

Post by patrikk »

Hi everyone,
I've been working on a menu lib to be able to to traverse through a menu on the LCD.
the structure is similar to the tree structure you have in explorer etc.

My problem is that I cant get it to work perfectly. in the code I've posted here I can step through the menu up and down( submenu) and into menu "item2" but I can't do that with the first item (item1) instead it jumps to item3 and not to the "item1 submenu" what am I missing?

the second thing is that when I enter a submenu( submenu for item 2) I end up at the last submenuitem and not the first one. I can't figure out why it does that I would like it to go to the first subitem ( firstChild).

components:
Arduino Uno
adafruit 16x2 LCD negative with the I2C chip and buttons.

I appreciate all the help

library for the menu:

Code: Select all

/*LcdMenu library*/
#ifndef	LcdMenu_h
#define LcdMenu_h


class MenuItem {
public:
	MenuItem(const char* itemName, char shortKey='\0' ) : name(itemName), shortkey(shortKey) {
		parent = prevSibling = nextSibling = firstChild = 0;
	}

	inline const char* getName() const { return name; }
	inline const char getShortkey() const { return shortkey; }
	inline const bool hasShortkey() const { return (shortkey!='\0'); }
	inline void setBack(MenuItem *b) { parent = b; }

	inline MenuItem* getParent() const { return parent; }
	inline MenuItem* getPrevSibling() const { return prevSibling; }
	inline MenuItem* getNextSibling() const { return nextSibling; }
	inline MenuItem* getFirstChild() const { return firstChild; }
	
	
	MenuItem *moveBack() { return parent; }

	MenuItem *moveUp() { 
		return prevSibling; 
	}

	MenuItem *moveDown() { 
		 return nextSibling;
	}

	MenuItem *moveLeft() { 
		return parent;
	}

	MenuItem *moveRight() { 
		return firstChild;
	}

	//default menu

	MenuItem &setParent(MenuItem &mi) {
		mi.firstChild = this;
		parent = &mi;
		return mi;
	}
	
	MenuItem &setPrevSibling(MenuItem &mi) {
		mi.nextSibling = this;
		prevSibling = &mi;
		return mi;
	}
	
	MenuItem &setNextSibling(MenuItem &mi) {
		mi.prevSibling = this;
		nextSibling = &mi;
		return mi;
	}
	
	MenuItem &setFirstChild(MenuItem &mi) {
		mi.parent = this;
		firstChild = &mi;
		return mi;
	}
	
	
protected:

	const char* name;
	const char shortkey;

	MenuItem *parent;
	MenuItem *prevSibling;
	MenuItem *nextSibling;
	MenuItem *firstChild;
	
};

//no dependant inclusion of string or cstring
bool menuTestStrings(const char *a, const char *b) {
	while (*a) { if (*a != *b) { return false; } b++; a++; }
	return true;
}
bool operator==(const MenuItem &lhs, MenuItem &rhs) {
	return menuTestStrings(lhs.getName(),rhs.getName());
}

struct MenuChangeEvent {
	const MenuItem &from;
	const MenuItem &to;
};

struct MenuUseEvent {
	const MenuItem &item;
};

typedef void (*cb_change)(MenuChangeEvent);
typedef void (*cb_use)(MenuUseEvent);

class	LcdMenu {
public:

	 	LcdMenu(cb_use menuUse, cb_change menuChange = 0) : root("MenuRoot") {
		current = &root;
		cb_menuChange = menuChange;
		cb_menuUse = menuUse;
	}

	MenuItem &getRoot() {
		return root;
	}
	MenuItem &getCurrent() {
		return *current;
	}

	void moveBack() {
		setCurrent(current->getParent());
	}

	void moveUp() {
		setCurrent(current->moveUp());
	}

	void moveDown() {
		setCurrent(current->moveDown());
	}

	void moveLeft() {
		setCurrent(current->moveLeft());
	}

	void moveRight() {
		setCurrent(current->moveRight());
	}

	void use() {
		if (cb_menuUse) {
			MenuUseEvent mue = { *current };
			cb_menuUse(mue);
		}
	}

private:
	void setCurrent( MenuItem *next ) {
		if (next) {
			if (cb_menuChange) {
				MenuChangeEvent mce = { *current, *next };
				(*cb_menuChange)(mce);
			}
			current = next;
		}
	}
	MenuItem root;
	MenuItem *current;

	cb_change cb_menuChange;
	cb_use cb_menuUse;
};

#endif
and then the project code:

Code: Select all

#include <LcdMenu.h>    //LcdMenu library
#include <Wire.h>
#include <Adafruit_MCP23017.h>
#include <Adafruit_RGBLCDShield.h>

Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();

// These #defines make it easy to set the backlight color
#define RED 0x1
#define GREEN 0x2
#define YELLOW 0x3
#define BLUE 0x4
#define VIOLET 0x5
#define TEAL 0x6
#define WHITE 0x7


//Menu variables
LcdMenu menu = LcdMenu(menuUsed,menuChanged);
//initialize menuitems
    MenuItem menu1Item1 = MenuItem("Item1");
      MenuItem menuItem1SubItem1 = MenuItem("Item1SubItem1");
      MenuItem menuItem1SubItem2 = MenuItem("Item1SubItem2");
    MenuItem menu1Item2 = MenuItem("Item2");
      MenuItem menuItem2SubItem1 = MenuItem("Item2SubItem1");
      MenuItem menuItem2SubItem2 = MenuItem("Item2SubItem2");
      MenuItem menuItem2SubItem3 = MenuItem("Item2SubItem3");
    MenuItem menu1Item3 = MenuItem("Item3");


void setup()
{
  lcd.begin(16, 2);

  menu.getRoot().setNextSibling(menu1Item1);
  menu1Item1.setPrevSibling(menu1Item3);
  menu1Item1.setNextSibling(menu1Item2);
  menu1Item1.setFirstChild(menuItem1SubItem1);
    menuItem1SubItem1.setParent(menu1Item1);
    menuItem1SubItem1.setNextSibling(menuItem1SubItem2);
    menuItem1SubItem1.setPrevSibling(menuItem1SubItem2);
    
    menuItem1SubItem2.setPrevSibling(menuItem1SubItem1);
    menuItem1SubItem2.setNextSibling(menuItem1SubItem1);
    menuItem1SubItem2.setParent(menu1Item1);
   
 
 
  menu1Item2.setPrevSibling(menu1Item1);
  menu1Item2.setNextSibling(menu1Item3);
  menu1Item2.setFirstChild(menuItem2SubItem1);
    menuItem2SubItem1.setParent(menu1Item2);
    menuItem2SubItem1.setNextSibling(menuItem2SubItem2);
    menuItem2SubItem1.setPrevSibling(menuItem2SubItem3);
    
    menuItem2SubItem2.setPrevSibling(menuItem2SubItem1);
    menuItem2SubItem2.setNextSibling(menuItem2SubItem3);
    menuItem2SubItem2.setParent(menu1Item2);
    
    menuItem2SubItem3.setNextSibling(menuItem2SubItem1);
    menuItem2SubItem3.setParent(menu1Item2);
  
  menu1Item3.setParent(menu1Item1);
  menu1Item3.setPrevSibling(menu1Item2);
  menu1Item3.setNextSibling(menu1Item1);

    //menu1Item1.setPrevSibling(menu1Item3);

  //menu1Item3.setNextSibling(menu.getRoot());
  //menu1Item3.setNextSibling(menu.getRoot());
  //menu.toRoot();
  lcd.setCursor(0,0);  
  lcd.print("Main Menu");

}  // setup()...


void loop()
{

  readButtons();                 
} //loop()... 


void menuChanged(MenuChangeEvent changed){
  
  MenuItem newMenuItem=changed.to; //get the destination menu
  
  lcd.setCursor(0,1); //set the start position for lcd printing to the second row
  
  if(newMenuItem.getName()==menu.getRoot()){
      lcd.print("Main Menu       ");
  }else if(newMenuItem.getName()=="Item1"){
      lcd.print("Item1           ");
  }else if(newMenuItem.getName()=="Item1SubItem1"){
      lcd.setCursor(0,0);
      lcd.print("--- Item1 ---");
      lcd.setCursor(0,1);
      lcd.print("Item1SubItem1");
  }else if(newMenuItem.getName()=="Item1SubItem2"){
      lcd.print("Item1SubItem2   ");
  }else if(newMenuItem.getName()=="Item2"){
    lcd.setCursor(0,0);
      lcd.print("   Main Menu    ");
      lcd.setCursor(0,1);
      lcd.print("Item2           ");
  }else if(newMenuItem.getName()=="Item2SubItem1"){
      lcd.setCursor(0,0);
      lcd.print("--- Item2 ---");
      lcd.setCursor(0,1);
      lcd.print("Item2SubItem1   ");
  }else if(newMenuItem.getName()=="Item2SubItem2"){
    lcd.setCursor(0,0);
      lcd.print("--- Item2 ---");
      lcd.setCursor(0,1);
      lcd.print("Item2SubItem2   ");
  }else if(newMenuItem.getName()=="Item2SubItem3"){
    lcd.setCursor(0,0);
      lcd.print("--- Item2 ---");
      lcd.setCursor(0,1);
      lcd.print("Item2SubItem3   ");
  }else if(newMenuItem.getName()=="Item3"){
      lcd.print("Item3           ");

  }
}

void menuUsed(MenuUseEvent used){
  lcd.setCursor(0,0);  
  lcd.print("You used        ");
  lcd.setCursor(0,1); 
  lcd.print(used.item.getName());
  delay(1000);  //delay to allow message reading

  //menu.toRoot();  //back to Main
}


void  readButtons(){ 
  int reading;

uint8_t buttons = lcd.readButtons();
  if (buttons) {
    MenuItem currentMenu=menu.getCurrent();
    if (buttons & BUTTON_UP) {
      menu.moveUp();
      delay(500);
      lcd.setBacklight(RED);
    }
    if (buttons & BUTTON_DOWN) {
      menu.moveDown();
      delay(500);
      lcd.setBacklight(YELLOW);
    }
    if (buttons & BUTTON_LEFT) {
        menu.moveLeft();
        delay(500);
      lcd.setBacklight(GREEN);
    }
    if (buttons & BUTTON_RIGHT) {
       menu.moveRight();
       delay(500);
       lcd.setBacklight(TEAL);
    }
    if (buttons & BUTTON_SELECT) {
      if(!(currentMenu.moveRight())){  //if the current menu has a child and has been pressed enter then menu navigate to item below
        menu.use();
        delay(500);
      }else{  //otherwise, if menu has no child and has been pressed enter the current menu is used
        menu.moveRight();
        delay(500);
       } 
      lcd.setBacklight(VIOLET);
    }
  }
}

patrikk
 
Posts: 34
Joined: Sun Feb 17, 2013 6:13 pm

Re: Need some feedback

Post by patrikk »

bump

User avatar
adafruit_support_mike
 
Posts: 67454
Joined: Thu Feb 11, 2010 2:51 pm

Re: Need some feedback

Post by adafruit_support_mike »

The library looks generally okay, but you haven't posted the code that actually creates and navigates the menu. It's possible that you have some confusion between "up/down mean siblings" and "left/right mean parent/child".

User avatar
saltydog
 
Posts: 11
Joined: Mon Aug 22, 2011 10:38 am

Re: Need some feedback

Post by saltydog »

Hi Pat,

was wondering if you had this figured out yet with the menu system for the shield.

Locked
Please be positive and constructive with your questions and comments.

Return to “Arduino”