Jomelo/LCDMenuLib

Add menu items with function?

Closed this issue · 2 comments

Hello, I was curious if it is possible to create menu items programmatically by using a function. One section of my menu I want to be the names of files on an SD card (which will be limited), which I only know at runtime. This is something that would only happen once in the program's lifetime.

Hi,
at the moment it is not possible because some items are saved in flash (PROGMEM), not in ram. I check tomorrow, if i can create a dynamic menu function, thats locks like a tree.

In next beta i add an example for dynamic lists with scrollbars. The current code is not perfektly commented. It can be that there are variables without a function. I have no time to optimaze the code.
I hope the code can help.

DISP function code looks like this.

// this needs some bytes in ram
#define MAX_FILES_IN_LIST 20

uint8_t scroll_row;
uint8_t cursor_real_pos;
uint8_t current_max_list_count;
uint8_t cursor_position_cur;
char file_name_buffer[20];
static char filelist[MAX_FILES_IN_LIST][20];


// *********************************************************************
void LCDML_DISP_setup(LCDML_FUNC_list_files)
// *********************************************************************
{
  // set max file counter
  current_max_list_count = 0;
  // set current cursor position
  cursor_position_cur = 0;
  // 
  scroll_row = 0;
  cursor_real_pos = 0;


  // read sd card files here 
  uint8_t n=0;
  // for example, here with a for loop
  for(uint8_t i = 0; i<10; i++) {
    if(i < MAX_FILES_IN_LIST) { 
      memcpy(filelist[i], "File  .txt", 10);      
      filelist[i][5] = i+48;
      current_max_list_count++; 
    }
  } 
}

void LCDML_DISP_loop(LCDML_FUNC_list_files) 
{
  // loop function, can be run in a loop when LCDML_DISP_triggerMenu(xx) is set
  // the quit button works in every DISP function without any checks; it starts the loop_end function


  uint8_t n_max             = (current_max_list_count >= _LCDML_DISP_rows) ? _LCDML_DISP_rows : (current_max_list_count);;
  uint8_t scrollbar_min     = 0;
  uint8_t scrollbar_max     = current_max_list_count;
  //uint8_t scrollbar_cur_pos = cursor_position_cur;
  uint8_t scroll_pos        = ((1.*n_max * _LCDML_DISP_rows) / (scrollbar_max - 1) * cursor_position_cur);



  // clear display
  // ================
  lcd.clear();

  // display content
  // ==================
  for (uint8_t n = scroll_row; n < (scroll_row+_LCDML_DISP_rows); n++)
  {   
    // set cursor
    lcd.setCursor(1, n-scroll_row);
    // set content
    lcd.print(filelist[n]);
  }

  // set cursor and scrollbar
  // =============================
  for (uint8_t n = scroll_row; n <(scroll_row+_LCDML_DISP_rows); n++)
  {
      lcd.setCursor(0, n-scroll_row);

    // set cursor
    // =====================
    if (n == cursor_position_cur) {
      lcd.write(_LCDML_DISP_cfg_cursor);
      cursor_real_pos = n-scroll_row;
    } else {
      lcd.write(' ');
    }    

    // display scrollbar
    // ==============================
    // delete or reset scrollbar
    if (scrollbar_max > n_max) {
      lcd.setCursor((_LCDML_DISP_cols - 1), n-scroll_row);
      lcd.write((uint8_t)0);
    }
    else {
      lcd.setCursor((_LCDML_DISP_cols - 1), n-scroll_row);
      lcd.print(' ');
    }

    // set scrollbar
    if (scrollbar_max > n_max) {
      //set scroll position
      if (cursor_position_cur == scrollbar_min) {
        // min pos
        lcd.setCursor((_LCDML_DISP_cols - 1), 0);
        lcd.write((uint8_t)1);
      } else if (cursor_position_cur == (scrollbar_max - 1)) {
        // max pos
        lcd.setCursor((_LCDML_DISP_cols - 1), (n_max - 1));
        lcd.write((uint8_t)4);
      } else {
        // between
        lcd.setCursor((_LCDML_DISP_cols - 1), scroll_pos / n_max);
        lcd.write((uint8_t)(scroll_pos % n_max) + 1);
      }
    }


  }



  // control
  // =====================================
  if(LCDML_BUTTON_checkUp()) {
    LCDML_BUTTON_resetAll();
    // scroll up   
    if(cursor_position_cur > 0) {
      cursor_position_cur--;
      if(cursor_real_pos == 0) {
        scroll_row--;    
      }      
    }
    // update content above or remove this line and copy button checks on top of this function
    LCDML_BACK_start(LCDML_BACKEND_menu);    
  }


  if(LCDML_BUTTON_checkDown()) {
    LCDML_BUTTON_resetAll();   
    // scroll down
    if(cursor_position_cur < (current_max_list_count-1)) {
      cursor_position_cur++;
      if(cursor_position_cur > (_LCDML_DISP_rows-1)) {
        scroll_row++; 
      } 
    }
    // update content above or remove this line and copy button checks on top of this function
    LCDML_BACK_start(LCDML_BACKEND_menu);             
  }


  if(LCDML_BUTTON_checkEnter()) {
    LCDML_BUTTON_resetAll();   
    // save selected file (serial.print)
    LCDML_DISP_funcend();
    // output of current line
    Serial.println(filelist[cursor_position_cur]);  
  }  
}

void LCDML_DISP_loop_end(LCDML_FUNC_list_files)
{
  // this functions is ever called when a DISP function is quit
  // you can here reset some global vars or do nothing 

  // Display selected file name

}