t06glcd - olikraus/m2tklib GitHub Wiki
Tutorial 6: Low Level Graphics
How can low level graphics be combined with M2tklib?
This tutorial will show:
- How to show both, a menu and additional graphics.
- How to switch to a pure graphics page and how to return to a menu (requires v1.04)
The following picture shows a rectangle combined with a M2tk menu.
This tutorial will be divided into two parts:
- How to combine menus and graphics.
- How to switch between menu and graphics.
Reference: Code for this Tutorial is available in the "Graphics" example (v1.04).
A simple graphics procedure
For further discussion, we will assume that there is a graphics procedure, which directly draws something on the screen. To be consistent with the "Graphics" example, this procedure puts some graphics at the provided x/y position:
void rectangle(uint8_t x, uint8_t y) {
...
}
This procedure shell work completely independent from m2tklib. There is not call to any m2tklib procedures inside "rectangle".
Combine Menues and Graphics
In general it is very easy to combine menus and graphics: Simply draw both, one after the other:
void menu(void) {
m2.checkKey();
if ( m2.handleKey() ) {
m2.draw();
}
}
void loop(void) {
menu();
rectangle(0, 0);
}
This will make all graphics drawn by "rectangle" available in all menus.
In some cases, it could be required not to display something for specific menus or to display something different, depending on the current menu. The "getRoot" procedure can be used to get the current toplevel element. Depending on this toplevel-element, the additional graphics might be enabled or disabled:
void graphics(void) {
// show the graphics depending on the current toplevel element
if ( m2.getRoot() == &el_combine ) {
// combine is active, add graphics
// menu is on the right, put the rectangle to the left
rectangle(0,y);
}
...
}
Now, the graphics and menu can be combined:
void loop(void) {
graphics();
m2.checkKey();
if ( m2.handleKey() ) {
m2.draw();
}
}
In this loop, the following happens:
- Draw low-level graphics on the screen (see procedure above)
- Execute event loop for the menu
Switch to Graphics Page
Goal is to disable the menu for some time and to show some custom graphics. This requires the ability to disable the menu, but keep the key detection alive. This will allow the program to wait for a key event, which enables the menu again.
Disable the Menu
To disable the menu, set&m2_null_element
as root element.
This could be done by the setRoot procedure or by the M2_ROOT element.
As a result, M2_ROOT
could be a button to switch to the graphics screen:
M2_ROOT(el_switch_to_graphics, NULL, "Show Graphics", &m2_null_element); // selecting this, will remove all menues
Show Graphics
As discussed in the first part of this tutorial, there must be a parallel procedure, which checks for the menu state.
The graphics is displayed, if there is no other menu aktive (m2.getRoot() == &m2_null_element
).
void graphics(void) {
// show the graphics depending on the current toplevel element
...
if ( m2.getRoot() == &m2_null_element ) {
// all menus are gone, show the rectangle
rectangle(10,10);
// now check for any keys and assign a suitable menu again
if ( m2.getKey() != M2_KEY_NONE )
m2.setRoot(&el_top);
}
}
Return to the Menu
The example above already shows how to return to a menu:
- Check for any keypress event by calling
getKey
. - Assign a menu as root menu.
There are two important notes here:
getKey
must be called only ifm2_null_element
is the root element. Key events are always removed from the queue bygetKey
. As a result the user could not control any visible menu any more.- It is still required to call
checkKey
andhandleKey
to keep the key event and menu system aktive. This means, the following code is wrong:
// THIS CODE IS WRONG, THIS WILL NOT WORK
m2.checkKey();
if ( m2.getRoot() == &m2_null_element ) {
// do something else on the screen
if ( m2.getKey() != M2_KEY_NONE )
m2.setRoot(&el_top);
}
else {
if ( m2.handleKey() ) {
m2.draw();
}
}
Instead, use the following:
if ( m2.getRoot() == &m2_null_element ) {
// do something else on the screen
if ( m2.getKey() != M2_KEY_NONE )
m2.setRoot(&el_top);
}
m2.checkKey();
if ( m2.handleKey() ) {
m2.draw();
}
Conclusion
- Draw graphics in parallel to the m2tklib "draw()" procedure.
- For the combination of menus and graphics, use a xylist element to have a better control of the menu.
- Use "getRoot" to identify the active menu. This will allow to display graphics according to the active menu.
- Set
m2_null_element
as root element to remove all menus. - Only if there is no menu, you may use
getKey()
. - Always make calls to
handleKey()
.
Links
- Previous Tutorial: Tutorial 5: Simultaneous Operation
- Wiki Start Page