diff --git a/common/gui/screen.c b/common/gui/screen.c index 23c1498..a8a34ea 100644 --- a/common/gui/screen.c +++ b/common/gui/screen.c @@ -1,17 +1,36 @@ #include "screen.h" -static SCREEN_STRUCT* screen_list = NULL; -static SCREEN_STRUCT* screen_current = NULL; - +static volatile SCREEN_STRUCT* screen_list = NULL; +static volatile SCREEN_STRUCT* screen_current = NULL; +static volatile SCREEN_STRUCT* screen_goto = NULL; SCREEN_STRUCT* gui_screen_get_current() { return screen_current; } void gui_screen_update() { - if(screen_current!=NULL) { - screen_current->on_update(screen_current); + if(screen_goto!=NULL) { //we received the task to switch the screen + SCREEN_STRUCT* go = screen_goto; //Backup volatile variable + screen_goto=NULL; + if(go->next!=NULL) { //we're going back + if(go->next!=screen_current) return; //list corrupted? + screen_current->on_leave(screen_current); + go->next=NULL; + } else { //we're going forward + if(screen_current!=NULL) { //this is not the first screen + screen_current->on_leave(screen_current); + screen_current->next = go; + } else { //first screen ever seen + screen_list=go; + } + } + go->on_enter(go); + screen_current = go; + } + + if(screen_current!=NULL) { //A screen has been set + screen_current->on_update(screen_current); //Update current screen } } @@ -20,14 +39,7 @@ void gui_screen_update() { bool gui_screen_navigate(SCREEN_STRUCT* screen) { if(screen==NULL) return false; screen->next = NULL; - if(screen_current!=NULL) { - screen_current->on_leave(screen_current); - screen_current->next = screen; - } else { - screen_list=screen; - } - screen->on_enter(screen); - screen_current = screen; + screen_goto=screen; //send message to main loop, to switch the screen return true; } @@ -37,17 +49,15 @@ bool gui_screen_back() { if(screen_list==NULL) return false; SCREEN_STRUCT* current = screen_list; SCREEN_STRUCT* last = NULL; + //Find second last element in list while(current->next != NULL) { last = current; current = current->next; } if(last==NULL) return false; //There's only a single screen. if(current!=screen_current) return false; //List corrupted? - current->on_leave(current); - last->next=NULL; - last->on_enter(last); - screen_current=last; - return true; + screen_goto=last; //send message to main loop, to switch the screen + return true; } diff --git a/common/gui/screen.h b/common/gui/screen.h index 3689007..375ccbf 100644 --- a/common/gui/screen.h +++ b/common/gui/screen.h @@ -17,9 +17,17 @@ typedef struct SCREEN_S{ } SCREEN_STRUCT; + +//Navigate to the given string as soon as the app enters the main loop again. Method can be called from an interrupt bool gui_screen_navigate(SCREEN_STRUCT* screen); + +//Navigate one screen back as soon as the app enters the main loop again. Method can be called from an interrupt bool gui_screen_back(); + +//Returns the current active screen SCREEN_STRUCT* gui_screen_get_current(); + +//Updates/switches the screens. Call this from the app main loop, as fast as you can. void gui_screen_update(); #endif /* SCREEN_H */