Hi
Let me introduce and define some keywords. The two words "dialog" and "menu" will be equivalent, i will try to stick to "menu" in the remaining part of this answer.
Definition: A menu is a hierarchy of elements, that defines the complete content of the display.
Let me make an example: A yes/no menu. There are different ways how a yes/no menu could look like. There might be a checkbox with confirm button or there might be two confirm buttons. I choose a the two confirm buttons, so it might look like this:
+-----+ +----+
! yes ! ! no !
+-----+ +----+
Both fields can be selected and activated. So, in principle this menu contains two elements: Two buttons with two different text inside ("yes" and "no"). However in M2tklib such a menu must be a hierarchy. This means, the two elements (yes and no) must be grouped together. For this purpose m2tklib has an additional (invisible) kind of elements. These are the so called container or grouping elements. This container element defines how the child elements are grouped together and how the layout will look like for the child elements:
+---------------+
!+-----+ +----+!
!! yes ! ! no !!
!+-----+ +----+!
+---------------+
Let me move to some code. The yes/no menu will look like this:
M2_BUTTON( el_yes, NULL, "yes", fn_yes );
M2_BUTTON( el_no, NULL, "no", fn_no );
M2_LIST(list_yes_no_menu) = { &el_yes, &el_no };
M2_HLIST(el_hlist, NULL, list_yes_no_menu);
In general the first argument is the element name. For example in the first line of the code "el_yes" is the name of the "yes" box.
So far we discussed three elements: The yes and no buttons and the parent container element. You sould be able to identify this: "el_yes" is the "yes" button, "el_no" is the "no" button and "el_parent" is the parent container which defines the layout for the childs.
But what is "list_yes_no_menu"? It is a C list, which helps us to construct the parent element. In fact almost all container element require M2_LIST. M2_LIST is not an element. It is neither a visible element nor a container, it just belongs to a container. I general M2_LIST and the container element (hier this is M2_HLIST) are written next to each other. In the code example you also see, that the name "list_yes_no_menu" of M2_LIST appears as last argument in M2_HLIST. It is like this: M2_LIST defines the a sequence of child elements, where M2_HLIST defines the actual layout. Especially M2_HLIST defines a horizontal arrangement of the child elements.
If we just replace M2_HLIST with M2_VLIST (a different parent container type)
M2_BUTTON( el_yes, NULL, "yes", fn_yes );
M2_BUTTON( el_no, NULL, "no", fn_no );
M2_LIST(list_yes_no_menu) = { &el_yes, &el_no };
M2_VLIST(el_parent, NULL, list_yes_no_menu);
then the layout will look like this:
+-------+
!+-----+!
!! yes !!
!+-----+!
!+----+ !
!+ no + !
!+----+ !
+-------+
Now, let me introduce the "root element".
Definition: The "root element" is the root element of a menu (see definition above) hierarchy.
Example: The root element for the yes no menu above is "el_parent"
Why do i need the root element? Well, a root element is the key to know all the other elements. From the root element, m2tk knows all the child elements. If you want to draw the menu on the screen, you just need to provide the root element and m2tklib will draw the entire element hierarchy. The function which will do this is "setRoot". "setRoot" actually means: Use the provided root element from now on for drawing the entire menu on the screen.
Now we come to the final property of m2tklib. A user may not only want one single menu. Usually a lot of menues are required in an application. As such, there will be multiple menus and multiple root elements (one root element per menu).
M2tklib can handle and switch between multiple menues. All this is done through the "root element". The "root element" represents the complete menu.
Let me create another example:
M2_BUTTON( el_menu_1, NULL, "click me", fn_1 );
This code just creats one single clickable button on the screen. It will have the label "click me". This menu only contains a single element. It does not contain any container. As such the menu hierarchy is very simple (the tree of the hierarchy has only one element). So the root element is also "el_menu_1".
In order to make this menu visible, i just say "m2.setRoot(&el_menu_1)".
Let me introduce another menu:
M2_BUTTON( el_menu_2, NULL, "click me too", fn_2 );
Now, i want to implement this behavior: If "click me" (menu 1) is selected, menu 2 should appear. How can this be done? This is handled by the last part of M2_BUTTON: fn_1. fn_1 is a user define c function. It has a fixed prototype, but you can define the content:
void fn_1(m2_el_fnarg_p fnarg) {
m2.setRoot(&el_menu_2);
}
fn_1 will be called as soon as you select/click/activate the button "click me" in el_menu_1. "fn_1" is a normal c function. You can do anything here. Start a motor, modify a global variable, get an analog value or (like here) assign a different menu by providing a different root element.
Let me finish the example, by saying that from menu 2 the user should be able to jump back to menu 1. Then the complete example will look like this:
void fn_1(m2_el_fnarg_p fnarg) {
m2.setRoot(&el_menu_2);
}
M2_BUTTON( el_menu_1, NULL, "click me", fn_1 );
void fn_2(m2_el_fnarg_p fnarg) {
m2.setRoot(&el_menu_1);
}
M2_BUTTON( el_menu_2, NULL, "click me too", fn_2 );
However, this code has a problem: In fn_1 i need to know "el_menu_2", but it will be defined later, so this is not (yet) known to the compiler. This problem of a forward declaration will unfortunately appear more often. It is solved with a forward declaration of the menu. The correct code will look like this:
M2_EXTERN_BUTTON(el_menu_2);
void fn_1(m2_el_fnarg_p fnarg) {
m2.setRoot(&el_menu_2);
}
M2_BUTTON( el_menu_1, NULL, "click me", fn_1 );
void fn_2(m2_el_fnarg_p fnarg) {
m2.setRoot(&el_menu_1);
}
M2_BUTTON( el_menu_2, NULL, "click me too", fn_2 );
Does this make sense to you so far?
Here is one more optimization: Very often the user defined function will only change the root element (call setRoot). To simplify this, there is a special element, that includes the user defined function already: M2_ROOT. M2_ROOT is just M2_BUTTON with a user define function, that calls "setRoot". The example can be simplified like this:
M2_EXTERN_BUTTON(el_menu_2);
M2_ROOT( el_menu_1, NULL, "click me", &el_menu_2 );
M2_ROOT( el_menu_2, NULL, "click me too", &el_menu_1 );
Ah, this looks much simpler but is identical to the previous example.
Before i complete this post, here is one more note and one suggestion.
Note:
Each application (usually) needs to start with a startup or main menu. The root element of this main menu is given to the constructor as first argument.
M2tk m2(&el_menu_1, m2_es_arduino, m2_eh_2bs, m2_gh_u8g_fb);
Suggestions:
Have a look at this tutorial: Google Code Archive - Long-term storage for Google Code Project Hosting.
It will repeat some the things, i wrote here.
Let me know if you have further questions. I am sure many things are still unclear, but i hope i have covered the basics.
Oliver
Edit: Fixed yes/no example