Jomelo / LCDMenuLib2

Create a tree menu. Use it with different lcd types / console output / ssh console.
MIT License
249 stars 46 forks source link

Enable disable calculation of the Menu (Open / Close) #93

Closed tusker-tools closed 1 year ago

tusker-tools commented 1 year ago

Hello Jomelo, first of all, thank you for your work!

I am currently using the lib on a STM32 bluepill board with STM32CubeIDE FreeRTOS.

What I like to achieve is to calculate the whole LCDML loop only when a certain condition is met. If not, LCDM shall not be run at all. I am calling LCDML as below (called periodically by the OS):

/* Call this periodically */
if (condition == 1){
    LCDML.loop();   
}
else{
    // do other stuff here
}

With this, entering the menu works just fine. For closing the menu, I created a "close_Function", which is called when clicking on a related menu item. Within that close function, the condition flag is reset to zero. Thus, LCMD.loop() will not be called anymore.

/* Menu close function */
void close_Function(uint8_t param){
   LCDML.goRoot();
   condition = 0;
}

But when trying to call the menu the next time (=set condition 1 again) , the menu is displayed for one recurrence and then directly closed automatically. This happens because the close_Function is called a second time directly after the menu is displayed. This is done here: image

After I set condition=1 the next time, the menu is displayed correctly again.

Could you please give ma a hint how I can prevent that? What do I need to do in the first call of the close function to avoid running the close function a second time?

I'm looking forward to your answer.

Best regards!

tusker-tools commented 1 year ago

Update: When uncommenting FUNC_call() in Line 735, everything is working just fine.

Question: Why is it necessary to "call active function to bring it on a stable state", as stated in the comment? Is this really wanted? There must be somehow a possiblity to call a callback function only once.

I would appreciate it a lot if sb. could give me an answer.

Jomelo commented 1 year ago

Hey, it try to understand your points.

Can you split the loop function to call the lib like in this example ?

boolean first_update = true; 

void close_Function(uint8_t param){
   //LCDML.goRoot(); // only when you want to start the menu on beginning
   condition = 0;
   first_update = false;
}

void loop()
 {
    LCDML.loop_control(); // check buttons and or triggers for the menu structure, call this every time

    if (condition == 1 )
    {  
        // check
        if(first_update == false) 
        {
            LCDML.DISP_update();
            first_update = true;
        }
        LCDML.loop_menu();  // Hier wird der Inhalt erzeugt
   }
}

A menu function is called again on closing to come into the "if(LCDML.FUNC_close()) {..." conditon. After that call the function is closed. The other parts like FUNC_setup and FUNC_loop are not called.

/* ===================================================================== *
 *                                                                       *
 * Menu Callback Function                                                *
 *                                                                       *
 * ===================================================================== *
 *
 * EXAMPLE CODE:
// *********************************************************************
void your_function_name(uint8_t param)
// *********************************************************************
{
  if(LCDML.FUNC_setup())          // ****** SETUP *********
  {
    // remmove compiler warnings when the param variable is not used:
    //LCDML_UNUSED(param);
    // setup
    // is called only if it is started
    // starts a trigger event for the loop function every 100 milliseconds
    LCDML.FUNC_setLoopInterval(100);
    // uncomment this line when the menu should go back to the last called position
    // this could be a cursor position or the an active menu function
    // GBA means => go back advanced
    //LCDML.FUNC_setGBA() 
    //
  }
  if(LCDML.FUNC_loop())           // ****** LOOP *********
  {
    // loop
    // is called when it is triggered
    // - with LCDML_DISP_triggerMenu( milliseconds )
    // - with every button or event status change
    // uncomment this line when the screensaver should not be called when this function is running
    // reset screensaver timer
    //LCDML.SCREEN_resetTimer();
    // check if any button is pressed (enter, up, down, left, right)
    if(LCDML.BT_checkAny()) {
      LCDML.FUNC_goBackToMenu();
    }
  }
  if(LCDML.FUNC_close())      // ****** STABLE END *********
  {
    // loop end
    // you can here reset some global vars or delete it
    // this function is always called when the functions ends.
    // this means when you are calling a jumpTo ore a goRoot function
    // that this part is called before a function is closed
  }
}
 * ===================================================================== *
 */

Have you parts on your menu function which are outside the FUNC_setup / FUNC_loop / FUNC_end conditions ?

tusker-tools commented 1 year ago

Thanks a lot for taking the effort looking into this!

Indeed, within my close_Function I did not check for FUNC_setup / FUNC_loop / FUNC_end conditions (as you can see in my code I initially posted). This was exactly the reason why those parts were called a second time! Now with adding this check as below:

/* Menu close function */
void close_Function(uint8_t param){
   if(LCDML.FUNC_loop()){
      LCDML.goRoot();
      condition = 0;
   }
}

Everything is working as expected finally!

I appreciate your help a lot!