I'm going to try share here a little about how to read and try to understand the menus when reading the source code the way I understood it.
It's not finished yet, so I going to keep adding any other information I remember here.
I hope this can at least help other to get a start point to find their own understanding.
I'm going to start by spotting that in order to support multiple languages (translations) we must to use the macro ?__(<index>, <label>) in every place a text needs to be translated. This means menus, dialogs, windows, etc. The index must be unique for functions with the same name, which means we can reuse them in any other function in the same module without any problem.
All module/plugin that implements menus/sub-menus must export a menu/2 function;
The function get two parameters which the first is the parent's Id and the second a list having its options (the menu itself);
So, to append an menu option to the main menu as the Tools we can check for that this way:
In Wings3D, a menu option can have three different responses depending on which mouse button was used to select it. We refer them as LMB, MMB and RMB action (Left, Middle and Right mouse button, respectively).
A simple option, which the action is activated by pressing LMB, is constructed by using a tuple with three elements:
It will look like this (option and description/hint/tooltip):
If the the action will have the option to show the user a input dialog instead of only to run the action directly, then the item must includes a 4th parameter to indicate that which will result in a small gerar icon be shown in the right corner of the option when the menu is shown:
in this case our menu item would look like this:
It will look like this (the [option] parameter will automatically add a second command/hint for RMB):
Multiple options, which the action is activated by others buttons than only pressing LMB, is constructed by using a list of tuples similar to the single option one, but the id will be get from a pick option function which will handle the button clicked and now the 3rd parameter is a tuple that contains the description for each button option. If an mouse option will not be used its respective description must be an empty list ([]). The 4th parameter stays optional and will keep working for LMB option only:
This click_function is a function that will return the real function that handle the mouse buttons pressed (or help atom). The mouse_button value is 1, 2 and 3 for LMB, MMB and RMB respectively:
* that _Ns parameter I don't know exactly what it stands for, but it is used in directions function we can find in wings_util.erl and is used to assembly commands and help information for menus.
in this case our menu item would be defined like this:
and it will look like this:
if we define only options for LMB and RMB, for instance, it can look like this:
"Pure" sub-menus are constructed in a similar way as menu items, but it doesn't need a description (because it's not used) and we use a set <id,function> to create the menu cascade. This function will return a list of menu items. In case on of these items have a sub-menu we repeat this structure all over:
and then it can have this look:
Here is how a "pure" sub-menu item will look like:
and in this one there are three actions for the item which the action for LMB will call a sub-menu (lets call it mixed menu/sub-menus):
Menus can also have check marked options. We create them by providing as 4th parameter with a list with a single tuple this way:
in this case our menu item would look like this:
In this case we are checking for the my_check_pref id stored in the preferences and giving it a default value false.
The result is something like this:
Default preferences values can be defined in a module using the init/0 function.
p.s.: The elements not delimited by '<' and '>' are kept as they are in the code.
It's not finished yet, so I going to keep adding any other information I remember here.
I hope this can at least help other to get a start point to find their own understanding.
I'm going to start by spotting that in order to support multiple languages (translations) we must to use the macro ?__(<index>, <label>) in every place a text needs to be translated. This means menus, dialogs, windows, etc. The index must be unique for functions with the same name, which means we can reuse them in any other function in the same module without any problem.
All module/plugin that implements menus/sub-menus must export a menu/2 function;
Code:
export([menu/2, ...])
The function get two parameters which the first is the parent's Id and the second a list having its options (the menu itself);
Code:
menu({<id>}, <options_list>)
So, to append an menu option to the main menu as the Tools we can check for that this way:
PHP Code:
menu({tolls}, Menu) ->
MyMenu = build_my_menu(),
Menu ++ MyMenu;
menu(_, Menu) ->
Menu.
build_my_menu() ->
[{?__(1, "My Option"), my_option, ?__(2, "My single option for LMB")}].
In Wings3D, a menu option can have three different responses depending on which mouse button was used to select it. We refer them as LMB, MMB and RMB action (Left, Middle and Right mouse button, respectively).
A simple option, which the action is activated by pressing LMB, is constructed by using a tuple with three elements:
Code:
{<label>, <id>, <description/hint>}
It will look like this (option and description/hint/tooltip):
If the the action will have the option to show the user a input dialog instead of only to run the action directly, then the item must includes a 4th parameter to indicate that which will result in a small gerar icon be shown in the right corner of the option when the menu is shown:
Code:
{<label>, <id>, <description/hint>, [option]}
in this case our menu item would look like this:
PHP Code:
build_my_menu() ->
[{?__(1, "My Option"), my_option, ?__(2, "My single option for LMB")}, [option]].
It will look like this (the [option] parameter will automatically add a second command/hint for RMB):
Multiple options, which the action is activated by others buttons than only pressing LMB, is constructed by using a list of tuples similar to the single option one, but the id will be get from a pick option function which will handle the button clicked and now the 3rd parameter is a tuple that contains the description for each button option. If an mouse option will not be used its respective description must be an empty list ([]). The 4th parameter stays optional and will keep working for LMB option only:
Code:
{<label>, <click_function>, {<description/hint LMB>, <description/hint MMB>, <description/hint RMB>}}
This click_function is a function that will return the real function that handle the mouse buttons pressed (or help atom). The mouse_button value is 1, 2 and 3 for LMB, MMB and RMB respectively:
Code:
<click_function>() ->
fun
(<help|mouse_button>, _Ns) -> <command>;
(_, _) -> ignore
end.
in this case our menu item would be defined like this:
PHP Code:
build_my_menu() ->
[{?__(1, "My Option"), my_menu_items(), {?__(2, "My option 1 for LMB"),
?__(3, "My option 2 for MMB"),
?__(4, "My option 3 for RMB")} }].
my_menu_items() ->
fun
(1, _) -> {my_option, opt1};
(2, _) -> {my_option, opt2};
(3, _) -> {my_option, opt3};
(_, _) -> ignore
end.
and it will look like this:
if we define only options for LMB and RMB, for instance, it can look like this:
"Pure" sub-menus are constructed in a similar way as menu items, but it doesn't need a description (because it's not used) and we use a set <id,function> to create the menu cascade. This function will return a list of menu items. In case on of these items have a sub-menu we repeat this structure all over:
Code:
{<label>, <{id, build_submenu_fun}>}
build_submenu_fun() ->
[{<label>, <id>, <description/hint>, [option]},
:
{<label>, <id>, <description/hint>, [option]}]
and then it can have this look:
PHP Code:
build_my_menu() ->
[{?__(1,"My menu"), {my_menu, build_submenu()}}]
build_submenu() ->
[{?__(1, "My option 1 for submenu level 1"), id_option1, ?__(2, "Description of my option 1")},
{?__(3, "My option 2 for submenu level 1"), my_menu_items() , {?__(4, "Description of my option 2 LMB"),
[],
?__(5, "Description of my option 2 RMB")}].
my_menu_items() ->
fun
(1, _) -> {my_option, opt1};
(3, _) -> {my_option, opt2};
(_, _) -> ignore
end.
Here is how a "pure" sub-menu item will look like:
and in this one there are three actions for the item which the action for LMB will call a sub-menu (lets call it mixed menu/sub-menus):
Menus can also have check marked options. We create them by providing as 4th parameter with a list with a single tuple this way:
Code:
{<label>, <id>, <description/hint>, [{crossmark, <boolean_value>}]}
in this case our menu item would look like this:
PHP Code:
build_my_menu() ->
[{?__(1, "My Option"), my_check_option, ?__(2, "My single option for LMB"),
[{crossmark, wings_pref:get_value(my_check_pref, false)}]].
The result is something like this:
Default preferences values can be defined in a module using the init/0 function.
p.s.: The elements not delimited by '<' and '>' are kept as they are in the code.