Go Down

Topic: menubackend (Read 2551 times) previous topic - next topic

zioTonino

buon giorno a tutti,
sto provando ad utilizzare la libreria per i menu di Alexander Brevig ma ho un problema nella gestione; il menu è così composto:

Menu
plafo On/Off     imposta orario                                     imposta data
                       - imposta ora  - imposta minuti             - imposta giorno   - imposta mese   - imposta anno
                               
                                                     
Il problema si presenta quando sono all'interno di "imposta ora" o "minuti" o anche all'interno di "imposta mese"; mi spiego meglio: se dall'interno di "imposta giorno" premo il tasto UP il menu torna direttamente ad "imposta data", senza passare per "imposta giorno"! e non ne capisco il motivo! tra l'altro la navigazione tra i menu, senza entrare al loro interno, è invece perfetta ed è possibile muoversi in ogni direzione senza problemi!

Tra le altre cose, non mi è chiaro dove sia stata definita la posizione della voce "menu" che compare all'inizio, al comando menu.toroot! come fa a capire dove metterlo??


Vi allego il codice.

Definizione dei Menu

Code: [Select]
//definizione Menu
MenuBackend menu = MenuBackend(menuUsed,menuChanged);

MenuItem menuPlafoLed = MenuItem("menuPlafoLed");

MenuItem menuSetTime = MenuItem("menuSetTime");
MenuItem menuSetTime_Hour = MenuItem("menuSetTime_Hour");
MenuItem menuSetTime_Minute = MenuItem("menuSetTime_Minute");

MenuItem menuSetData = MenuItem("menuSetData");
MenuItem menuSetData_Day = MenuItem("menuSetData_Day");
MenuItem menuSetData_Month = MenuItem("menuSetData_Month");
MenuItem menuSetData_Year = MenuItem("menuSetData_Year");

//definizione stati del menu
const int statusNull = 0;
const int statusPlafoLed = 1;
const int statusSetTime_Hour = 2;
const int statusSetTime_Minute = 3;
const int statusSetData_Day = 4;
const int statusSetData_Month = 5;
const int statusSetData_Year = 6;

int currentStatusMode = statusNull; //default


Nel setup:

Code: [Select]
 //configure menu  
 menu.getRoot().add(menuPlafoLed).addRight(menuSetTime).addRight(menuSetData);
 menuSetTime.add(menuSetTime_Hour).addRight(menuSetTime_Minute);
 menuSetData.add(menuSetData_Day).addRight(menuSetData_Month).addRight(menuSetData_Year);
 menu.toRoot();


a seguire le funzioni che controllano il menu

Code: [Select]
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("Menu            ");
 }
 else if(newMenuItem.getName()=="menuPlafoLed"){
   lcd.print("plafo ON/OFF    ");
 }
 else if(newMenuItem.getName()=="menuSetTime"){
   lcd.print("imposta orario  ");
 }
 else if(newMenuItem.getName()=="menuSetTime_Hour"){
   lcd.print("imposta ora     ");
 }
 else if(newMenuItem.getName()=="menuSetTime_Minute"){
   lcd.print("imposta minuti  ");
 }
 else if(newMenuItem.getName()=="menuSetData"){
   lcd.print("imposta data    ");
 }
 else if(newMenuItem.getName()=="menuSetData_Day"){
   lcd.print("imposta giorno  ");
 }
 else if(newMenuItem.getName()=="menuSetData_Month"){
   lcd.print("imposta mese    ");
 }
 else if(newMenuItem.getName()=="menuSetData_Year"){
   lcd.print("imposta anno    ");
 }
}



void menuUsed(MenuUseEvent used){

 if (used.item == menuPlafoLed)

   currentStatusMode = statusPlafoLed;

 else if (used.item == menuSetTime_Hour)

   currentStatusMode = statusSetTime_Hour;

 else if (used.item == menuSetTime_Minute)

   currentStatusMode = statusSetTime_Minute;

 else if (used.item == menuSetData_Day)

   currentStatusMode = statusSetData_Day;

 else if (used.item == menuSetData_Month)

   currentStatusMode = statusSetData_Month;

 else if (used.item == menuSetData_Year)

   currentStatusMode = statusSetData_Year;

else
   
   currentStatusMode = statusNull;
}





void navigateMenus() {
 MenuItem currentMenu = menu.getCurrent();

 switch (buttons){
 case BUTTON_DOWN:
   if(!(currentMenu.moveDown())){  //if the current menu has a child and has been pressed enter then menu navigate to item below
     menu.use();
   }
   else{  //otherwise, if menu has no child and has been pressed enter the current menu is used
     menu.moveDown();
   }
   break;
 case BUTTON_SELECT:
   menu.toRoot();  //back to main
   break;
 case BUTTON_RIGHT:
   menu.moveRight();
   break;      
 case BUTTON_LEFT:
   menu.moveLeft();
   break;  
 case BUTTON_UP:
   menu.moveUp();
   break;
 }

 buttons = 0; //reset the lastButtonPushed variable
}



Nel loop (parziale)

Code: [Select]
void loop(){
 //inizializzazione RTC
 DateTime now = RTC.now();

 //leggo eventuali pressioni dei pulsanti
 buttons = lcd.readButtons();
 delay(50);

 //se il pulsante è SELECT imposto lo stato su 0
 if (buttons == BUTTON_SELECT){
   currentStatusMode = statusNull;
 }

 switch(currentStatusMode){

   //se non sono in nessun menu child allora alla pressione di un pulsante navigo nei menu  
 case statusNull:
   navigateMenus();
   break;

   //accensione/spegnimento manuale plafo led
   case(statusPlafoLed):

   if (buttons == BUTTON_UP){
     menu.moveUp();

      //altro codice

   break;

     //altro codice




zioTonino


la libreria:
Code: [Select]
/*
||
|| @file MenuBackend.h
|| @version 1.0
|| @author Alexander Brevig
|| @contact alexanderbrevig@gmail.com
||
|| @description
|| | Provide an easy way of making menus
|| #
||
|| @license
|| | This library is free software; you can redistribute it and/or
|| | modify it under the terms of the GNU Lesser General Public
|| | License as published by the Free Software Foundation; version
|| | 2.1 of the License.
|| |
|| | This library is distributed in the hope that it will be useful,
|| | but WITHOUT ANY WARRANTY; without even the implied warranty of
|| | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
|| | Lesser General Public License for more details.
|| |
|| | You should have received a copy of the GNU Lesser General Public
|| | License along with this library; if not, write to the Free Software
|| | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
|| #
||
*/

#ifndef MenuBackend_h
#define MenuBackend_h

class MenuBackend;
class MenuItem
{
friend class MenuBackend; //provide acces to private
public:

MenuItem(const char* itemName, const char itemShortkey = 0) : name(itemName), shortkey(itemShortkey)
{
before = 0;
right = 0;
after = 0;
left = 0;
back = 0;
}

//void use(){} //update some internal data / statistics

const char* getName() const { return name; }
bool hasShortkey() const { return (shortkey!=0); }
const char getShortkey() const { return shortkey; }

MenuItem *moveBack() { return back; }

MenuItem *moveUp() {
if (before)
{
before->back = this;
}
return before;
}

MenuItem *moveDown() {
if (after)
{
after->back = this;
}
return after;
}

MenuItem *moveLeft() {
if (left)
{
left->back = this;
}
return left;
}

MenuItem *moveRight() {
if (right)
{
right->back = this;
}
return right;
}
//default vertical menu
MenuItem &add(MenuItem &mi) { return addAfter(mi); }

MenuItem &addBefore(MenuItem &mi)
{
mi.set(this,AFTER);
set(&mi,BEFORE);
return mi;
}
MenuItem &addRight(MenuItem &mi)
{
mi.set(this,LEFT);
set(&mi,RIGHT);
return mi;
}
MenuItem &addAfter(MenuItem &mi)
{
mi.set(this,BEFORE);
set(&mi,AFTER);
return mi;
}
MenuItem &addLeft(MenuItem &mi)
{
mi.set(this,RIGHT);
set(&mi,LEFT);
return mi;
}
protected:
typedef const unsigned char insert_t;
static insert_t BEFORE = 0;
static insert_t RIGHT = 1;
static insert_t AFTER = 2;
static insert_t LEFT = 3;
void set(MenuItem *mi, insert_t at)
{
switch (at)
{
case BEFORE: before = mi; break;
case RIGHT: right = mi; break;
case AFTER: after = mi; break;
case LEFT: left = mi; break;
}
}

const char* name;
const char shortkey;

MenuItem *before;
MenuItem *right;
MenuItem *after;
MenuItem *left;
MenuItem *back;
};


//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==(MenuItem &lhs, char* test)
{
return menuTestStrings(lhs.getName(),test);
}
bool operator==(const MenuItem &lhs, char* test)
{
return menuTestStrings(lhs.getName(),test);
}
bool operator==(MenuItem &lhs, MenuItem &rhs)
{
return menuTestStrings(lhs.getName(),rhs.getName());
}
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 MenuBackend
{
public:
MenuBackend(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->moveBack());
}

void toRoot() {
        setCurrent( &getRoot() );
    }

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

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

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

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

void use(char shortkey)
{
recursiveSearch(shortkey,&root);
use();
}

void use()
{
//current->use();
if (cb_menuUse)
{
MenuUseEvent mue = { *current };
(*cb_menuUse)(mue);
}
}
private:
void setCurrent( MenuItem *next )
{
if (next)
{
MenuChangeEvent mce = { *current, *next };
current = next;
if (cb_menuChange)
{
(*cb_menuChange)(mce);
}
}
}
void foundShortkeyItem(MenuItem *mi)
{
mi->back = current;
current = mi;
}
bool canSearch(const char shortkey, MenuItem *m)
{
if (m==0) { return false; }
else
{
if (m->getShortkey()==shortkey)
{
foundShortkeyItem(m);
}
return true;
}
}
void recursiveSearchAfter(const char shortkey, MenuItem *m)
{
if (canSearch(shortkey,m))
{
recursiveSearchAfter(shortkey, m->after);
recursiveSearchRight(shortkey, m->right);
recursiveSearchLeft(shortkey, m->left);
}
}
void recursiveSearchRight(const char shortkey, MenuItem *m)
{
if (canSearch(shortkey,m))
{
recursiveSearchAfter(shortkey, m->after);
recursiveSearchRight(shortkey, m->right);
recursiveSearchBefore(shortkey, m->before);
}
}
void recursiveSearchLeft(const char shortkey, MenuItem *m)
{
if (canSearch(shortkey,m))
{
recursiveSearchAfter(shortkey, m->after);
recursiveSearchLeft(shortkey, m->left);
recursiveSearchBefore(shortkey, m->before);
}
}
void recursiveSearchBefore(const char shortkey, MenuItem *m)
{
if (canSearch(shortkey,m))
{
recursiveSearchRight(shortkey, m->right);
recursiveSearchLeft(shortkey, m->left);
recursiveSearchBefore(shortkey, m->before);
}
}
void recursiveSearch(const char shortkey, MenuItem *m)
{
if (canSearch(shortkey,m))
{
recursiveSearchAfter(shortkey, m->after);
recursiveSearchRight(shortkey, m->right);
recursiveSearchLeft(shortkey, m->left);
recursiveSearchBefore(shortkey, m->before);
}
}
MenuItem root;
MenuItem *current;
cb_change cb_menuChange;
cb_use cb_menuUse;
};

#endif



GRAZIE

Go Up