discoverpixy
screen.c
Go to the documentation of this file.
1 /**************************************************************************************************************************************
2 * Project: discoverpixy
3 * Website: https://github.com/t-moe/discoverpixy
4 * Authors: Aaron Schmocker, Timo Lang
5 * Institution: BFH Bern University of Applied Sciences
6 * File: common/gui/screen.c
7 *
8 * Version History:
9 * Date Autor Email SHA Changes
10 * 2015-04-27 timolang@gmail.com cf72baa Introduced a Screen (sub) module and divided app into multiple screens.
11 * 2015-04-27 timolang@gmail.com 77e6d0e Fixed screen implementation.
12 * 2015-05-10 timolang@gmail.com b6ab7c8 Fixed compiler warning in tft and screen module.
13 * 2015-05-17 timolang@gmail.com 2d46336 Improved comments in implementation of button, checkbox, numupdown, tft, touch and screen modules/submodules.
14 * 2015-06-01 timolang@gmail.com eb573bc Finalized calibration. Fixed a bug in screen module.
15 * 2015-06-06 timolang@gmail.com c06661d Fixed some outdated comments in source code. Documented Gui Module in docu.
16 *
17 **************************************************************************************************************************************/
18 
19 #include "screen.h"
20 
21 /* The idea is as follows:
22  * We only call screen callbacks from the gui_screen_update() method, which is called from the applications main loop.
23  * Instructions to switch the screen will be delayed until the gui_screen_update() method is called again.
24  * This makes it safe to change the screen from an touch interrupt (e.g. button callback)
25  */
26 
27 /* Possible Improvements:
28  * Ensure that you can not navigate to a screen which is already in the history (because it will corrupt the list)
29  */
30 
31 static SCREEN_STRUCT* screen_list = NULL; //Head of the linked list which stores the screen history.
32 static SCREEN_STRUCT* screen_current = NULL; //Pointer to the current screen (= tail of the list)
33 static volatile SCREEN_STRUCT* screen_goto = NULL; //Screen we should navigate to once we enter the gui_screen_update() method again
34 
36 {
37  return screen_current;
38 }
39 
40 
42 {
43  if (screen_goto != NULL) { //we received the task to switch the screen
44  SCREEN_STRUCT* go = (SCREEN_STRUCT*) screen_goto; //Backup volatile variable
45  screen_goto = NULL; //reset the "goto instruction", since we're processing it now
46 
47  if (go->next != NULL) { //The screen is not the last in the list, so we're going back
48  if (go->next != screen_current) { //this condition should always be false
49  return; //list corrupted?
50  }
51 
52  screen_current->on_leave(screen_current); //let the current screen free/unregister it's resources
53  go->next = NULL; //remove the current screen from the list
54  } else { //we're going forward (to a new screen)
55  if (screen_current != NULL) { //this is not the first screen
56  screen_current->on_leave(screen_current); //let the current screen free/unregister it's resources
57  screen_current->next = go; //append the new screen to the end of the list
58  } else { //first screen ever seen
59  screen_list = go; //set the new screen as list-head
60  }
61  }
62 
63  go->on_enter(go); //let the new screen allocate/register it's resources
64  screen_current = go; //the new screen is now the current screen. Transition done
65  }
66 
67  if (screen_current != NULL) { //A screen has been set
68  screen_current->on_update(screen_current); //Update current screen
69  }
70 }
71 
72 
73 
75 {
76  if (screen == NULL || screen == screen_current || screen == screen_goto) { //invalid argument passed
77  return false;
78  }
79 
80  screen->next = NULL; //this will become the new tail of the list, so the next pointer must be NULL
81  screen_goto = screen; //"send message" to main loop, to switch the screen
82  return true;
83 }
84 
86 {
87  if (screen_list == NULL) { //the list head is emtpy, nothing to go back to
88  return false;
89  }
90 
91  SCREEN_STRUCT* current = screen_list;
92  SCREEN_STRUCT* last = NULL;
93 
94  //Find second last element in list
95  while (current->next != NULL) {
96  last = current;
97  current = current->next;
98  }
99 
100  if (last == NULL) {
101  return false; //There's only a single screen, there's no going back here
102  }
103 
104  if (current != screen_current) {
105  return false; //The last entry in the list is not the current screen. List corrupted?
106  }
107 
108  screen_goto = last; //"send message" to main loop, to switch the screen
109  return true;
110 }
SCREEN_CALLBACK on_enter
The Callback which is called when the screen is entered. Add/Register all UI-Elements here...
Definition: screen.h:53
struct SCREEN_S * next
Used internally. do not modify, do not initialize.
Definition: screen.h:57
void gui_screen_update()
Definition: screen.c:41
static SCREEN_STRUCT * screen_current
Definition: screen.c:32
static volatile SCREEN_STRUCT * screen_goto
Definition: screen.c:33
static SCREEN_STRUCT * screen_list
Definition: screen.c:31
SCREEN_STRUCT * gui_screen_get_current()
Definition: screen.c:35
SCREEN_CALLBACK on_leave
The Callback which is called when the screen is left. Remove/Unregister all UI-Elements here...
Definition: screen.h:54
bool gui_screen_navigate(SCREEN_STRUCT *screen)
Definition: screen.c:74
static SCREEN_STRUCT screen
bool gui_screen_back()
Definition: screen.c:85
SCREEN_CALLBACK on_update
The Callback which is called repeatedly when the screen should be updated. Update/Redraw all UI-Eleme...
Definition: screen.h:55