Modify section 17.

This commit is contained in:
Toshio Sekiya 2021-06-20 22:16:41 +09:00
parent 4dbd576877
commit dc47dc3077
5 changed files with 129 additions and 121 deletions

View file

@ -36,10 +36,11 @@ Menus can build a complicated structure thanks to the links of menu items.
GMenuModel is an abstract object which represents a menu. GMenuModel is an abstract object which represents a menu.
GMenu is a simple implementation of GMenuModel and a child object of GMenuModel. GMenu is a simple implementation of GMenuModel and a child object of GMenuModel.
GObjct -- GMenuModel -- GMenu GObject -- GMenuModel -- GMenu
Because GMenuModel is an abstract object, it doesn't have any functions to generate it. Because GMenuModel is an abstract object, it isn't instantiatable.
Therefore, if you want to generate a menu, use `g_menu_new` function to generate GMenu object. Therefore, it doesn't have any functions to create it.
If you want to create a menu, use `g_menu_new` to create a GMenu instance.
GMenu inherits all the functions of GMenuModel because of the child object. GMenu inherits all the functions of GMenuModel because of the child object.
GMenuItem is an object directly derived from GObject. GMenuItem is an object directly derived from GObject.
@ -48,10 +49,10 @@ GMenuItem and Gmenu (or GMenuModel) don't have a parent-child relationship.
GObject -- GMenuModel -- GMenu GObject -- GMenuModel -- GMenu
GObject -- GMenuItem GObject -- GMenuItem
Usually, GMenuItem has attributes. GMenuItem has attributes.
One of the attributes is label. One of the attributes is label.
For example, there is a menu item which has "Edit" label in the first diagram in this section. For example, there is a menu item which has "Edit" label in the first diagram in this section.
"Cut", "Copy", "Paste" and "Select All" are also the labels of menu items. "Cut", "Copy", "Paste" and "Select All" are also the labels of the menu items.
Other attributes will be explained later. Other attributes will be explained later.
Some menu items have a link to another GMenu. Some menu items have a link to another GMenu.
@ -101,16 +102,16 @@ The following code is an example.
1. `menu_item_quit` is a menu item. 1. `menu_item_quit` is a menu item.
It has a label "Quit" and is connected to an action "app.quit". It has a label "Quit" and is connected to an action "app.quit".
"app" is a prefix and "quit" is the name of an action. "app" is a prefix and "quit" is the name of an action.
The prefix means that the action belongs to GtkApplication. The prefix means that the action belongs to a GtkApplication instance.
If the menu is clicked, then the corresponding action "quit" which belongs to GtkApplication will be activated. If the menu is clicked, then the corresponding action "quit" which belongs to the GtkApplication will be activated.
2. `act_quit` is an action. 2. `act_quit` is an action.
It has a name "quit". It has a name "quit".
It belongs to GtkApplication, but it is not obvious in the code above. It belongs to the GtkApplication, but it is not obvious in the code above.
The function `g_simple_action_new` generates a stateless action. The function `g_simple_action_new` creates a stateless action.
So, `act_quit` is stateless. So, `act_quit` is stateless.
The meaning of stateless will be explained later. The meaning of stateless will be explained later.
The argument `NULL` means that the action doesn't have an parameter. The argument `NULL` means that the action doesn't have an parameter.
Generally, most of the actions are stateless and have no parameter. Most of the actions are stateless and have no parameter.
When `act_quit` is activated, it will emit "activate" signal. When `act_quit` is activated, it will emit "activate" signal.
3. "activate" signal of the action is connected to the handler `quit_activated`. 3. "activate" signal of the action is connected to the handler `quit_activated`.
So, if the action is activated, the handler will be invoked. So, if the action is activated, the handler will be invoked.
@ -123,94 +124,96 @@ The following is a simple example of menus and actions.
1 #include <gtk/gtk.h> 1 #include <gtk/gtk.h>
2 2
3 static void 3 static void
4 quit_activated(GSimpleAction *action, GVariant *parameter, gpointer app) 4 quit_activated(GSimpleAction *action, GVariant *parameter, gpointer user_data) {
5 { 5 GApplication *app = G_APPLICATION (user_data);
6 g_application_quit (G_APPLICATION(app)); 6
7 } 7 g_application_quit (app);
8 8 }
9 static void 9
10 on_activate (GApplication *app, gpointer user_data) { 10 static void
11 GtkWidget *win = gtk_application_window_new (GTK_APPLICATION (app)); 11 app_activate (GApplication *app, gpointer user_data) {
12 gtk_window_set_title (GTK_WINDOW (win), "menu1"); 12 GtkWidget *win = gtk_application_window_new (GTK_APPLICATION (app));
13 gtk_window_set_default_size (GTK_WINDOW (win), 400, 300); 13 gtk_window_set_title (GTK_WINDOW (win), "menu1");
14 14 gtk_window_set_default_size (GTK_WINDOW (win), 400, 300);
15 GSimpleAction *act_quit = g_simple_action_new ("quit", NULL); 15
16 g_action_map_add_action (G_ACTION_MAP (app), G_ACTION (act_quit)); 16 GSimpleAction *act_quit = g_simple_action_new ("quit", NULL);
17 g_signal_connect (act_quit, "activate", G_CALLBACK (quit_activated), app); 17 g_action_map_add_action (G_ACTION_MAP (app), G_ACTION (act_quit));
18 18 g_signal_connect (act_quit, "activate", G_CALLBACK (quit_activated), app);
19 GMenu *menubar = g_menu_new (); 19
20 GMenuItem *menu_item_menu = g_menu_item_new ("Menu", NULL); 20 GMenu *menubar = g_menu_new ();
21 GMenu *menu = g_menu_new (); 21 GMenuItem *menu_item_menu = g_menu_item_new ("Menu", NULL);
22 GMenuItem *menu_item_quit = g_menu_item_new ("Quit", "app.quit"); 22 GMenu *menu = g_menu_new ();
23 g_menu_append_item (menu, menu_item_quit); 23 GMenuItem *menu_item_quit = g_menu_item_new ("Quit", "app.quit");
24 g_object_unref (menu_item_quit); 24 g_menu_append_item (menu, menu_item_quit);
25 g_menu_item_set_submenu (menu_item_menu, G_MENU_MODEL (menu)); 25 g_object_unref (menu_item_quit);
26 g_menu_append_item (menubar, menu_item_menu); 26 g_menu_item_set_submenu (menu_item_menu, G_MENU_MODEL (menu));
27 g_object_unref (menu_item_menu); 27 g_menu_append_item (menubar, menu_item_menu);
28 28 g_object_unref (menu_item_menu);
29 gtk_application_set_menubar (GTK_APPLICATION (app), G_MENU_MODEL (menubar)); 29
30 gtk_application_window_set_show_menubar (GTK_APPLICATION_WINDOW (win), TRUE); 30 gtk_application_set_menubar (GTK_APPLICATION (app), G_MENU_MODEL (menubar));
31 gtk_window_present (GTK_WINDOW (win)); 31 gtk_application_window_set_show_menubar (GTK_APPLICATION_WINDOW (win), TRUE);
32 /* gtk_widget_show (win); is also OKay instead of gtk_window_present. */ 32 gtk_window_present (GTK_WINDOW (win));
33 } 33 /* gtk_widget_show (win); is also OKay instead of gtk_window_present. */
34 34 }
35 int 35
36 main (int argc, char **argv) { 36 #define APPLICATION_ID "com.github.ToshioCP.menu1"
37 GtkApplication *app; 37
38 int stat; 38 int
39 39 main (int argc, char **argv) {
40 app = gtk_application_new ("com.github.ToshioCP.menu1", G_APPLICATION_FLAGS_NONE); 40 GtkApplication *app;
41 g_signal_connect (app, "activate", G_CALLBACK (on_activate), NULL); 41 int stat;
42 42
43 stat =g_application_run (G_APPLICATION (app), argc, argv); 43 app = gtk_application_new (APPLICATION_ID, G_APPLICATION_FLAGS_NONE);
44 g_object_unref (app); 44 g_signal_connect (app, "activate", G_CALLBACK (app_activate), NULL);
45 return stat; 45
46 } 46 stat =g_application_run (G_APPLICATION (app), argc, argv);
47 47 g_object_unref (app);
48 return stat;
49 }
50
~~~ ~~~
- 3-7: `quit_activated` is a handler of an action `act_quit`. - 3-8: `quit_activated` is a handler of the "activate" signal on the action `act_quit`.
Handlers of actions have three parameters. Handlers of the "activate" signal have three parameters.
1. The action object which has emitted the signal. 1. The action instance on which the signal is emitted.
2. Parameter. 2. Parameter.
In this example it is `NULL` because the second argument of `g_simple_action_new` (line 15) is `NULL`. In this example it is `NULL` because the second argument of `g_simple_action_new` (line 15) is `NULL`.
You don' t need to care about it. You don' t need to care about it.
3. User data. 3. User data.
It is the fourth parameter in the `g_signal_connect` (line 17) that has connected the action and the handler. It is the fourth parameter in the `g_signal_connect` (line 18) that connects the action and the handler.
- 6: A function `g_application_quit` immediately quits the application. - 7: A function `g_application_quit` immediately quits the application.
- 9-33: `on_activate` is a handler of "activate" signal on GtkApplication. - 10-34: `app_activate` is a handler of "activate" signal on the GtkApplication instance.
- 11-13: Generates a GtkApplicationWindow and assigns a pointer to it to `win`. And sets the title and default size. - 12-14: Creates a GtkApplicationWindow `win`. And sets the title and the default size.
- 15: Generates GSimpleAction `act_quit`. - 16: Creates GSimpleAction `act_quit`.
It is stateless. It is stateless.
The first argument of `g_simple_action_new` is a name of the action and the second argument is a parameter. The first argument of `g_simple_action_new` is a name of the action and the second argument is a parameter.
If you don't need the parameter, pass `NULL`. If you don't need the parameter, pass `NULL`.
Therefore, `act_quit` has a name "quit" and no parameter. Therefore, `act_quit` has a name "quit" and no parameter.
- 16: Adds the action to GtkApplication `app`. - 17: Adds the action to GtkApplication `app`.
GtkApplication implements an interface GActionMap and GActionGroup. GtkApplication implements an interface GActionMap and GActionGroup.
And GtkApplication can have a group of actions and actions are added by the function `g_action_map_add_action`. GtkApplication (GActionMap) can have a group of actions and the actions are added with the function `g_action_map_add_action`.
This function is described in GMenuModel section in GIO API reference. This function is described in [GMenuModel section in GIO API reference](https://developer.gnome.org/gio/stable/GActionMap.html#g-action-map-add-action).
- 17: Connects "activate" signal of the action and the handler `quit_activated`. - 18: Connects "activate" signal of the action and the handler `quit_activated`.
- 19-22: Generates GMenu and GMenuItem. - 20-23: Creates GMenu and GMenuItem instances.
`menubar` and `menu` are GMenu. `menubar` and `menu` are GMenu.
`menu_item_menu` and `menu_item_quit` are GMenuItem. `menu_item_menu` and `menu_item_quit` are GMenuItem.
`menu_item_menu` has a label "Menu" and no action. `menu_item_menu` has a label "Menu" and no action.
`menu_item_quit` has a label "Quit". `menu_item_quit` has a label "Quit" and an action "app.quit".
The second argument "app.quit" is a combination of "app" and "quit". The action "app.quit" is a combination of "app" and "quit".
"app" is a prefix and it means that the action belongs to GtkApplication. "quit" is the name of the action. "app" is a prefix and it means that the action belongs to GtkApplication. "quit" is the name of the action.
Therefore, it points the action which belongs to GtkApplication and has the name "quit" -- it is `act_quit`. Therefore, "app.quit" points the action which belongs to the GtkApplication instance and is named "quit".
- 23-24: Appends `act_quit` to `menu`. - 24-25: Appends `menu_item_quit` to `menu`.
As I mentioned before, all the attribute and link values are copied and used to form a new item within `menu`. As I mentioned before, all the attributes and links are copied and used to form a new item in `menu`.
Therefore after the appending, `menu` has a copy of `act_quit` in itself and `act_quit` is no longer needed. Therefore after the appending, `menu_item_quit` is no longer needed.
It is freed by `g_object_unref`. It is freed by `g_object_unref`.
- 25: Sets a submenu link to `menu_item_menu`. - 26: Sets the submenu link in `menu_item_menu` to point `menu`.
And the link points the GMenu `menu`. - 27-28: Appends `menu_item_menu` to `menubar`.
- 26-27: Appends `menu_item_menu` to `menubar`.
Then frees `menu_item_menu`. Then frees `menu_item_menu`.
GMenu and GMenuItem are connected and finally a menu is made up. GMenu and GMenuItem are connected and finally a menu is made up.
The structure of the menu is shown in the diagram below. The structure of the menu is shown in the diagram below.
- 29: The menu is inserted to GtkApplication. - 30: The menu is inserted to GtkApplication.
- 30: Sets GtkApplicationWindow to show the menubar. - 31: Sets GtkApplicationWindow to show the menubar.
- 31: Shows the window. - 32: Shows the window.
![menu and action](../image/menu1.png) ![menu and action](../image/menu1.png)

View file

@ -3,7 +3,8 @@ Up: [Readme.md](../Readme.md), Prev: [Section 17](sec17.md), Next: [Section 19]
# Stateful action # Stateful action
Some actions have states. Some actions have states.
The values of states can be boolean or string. The typical values of states can be boolean or string.
However, other type of states is possible if you want.
Actions which have states are called stateful. Actions which have states are called stateful.
## Stateful action without a parameter ## Stateful action without a parameter

View file

@ -1,13 +1,14 @@
#include <gtk/gtk.h> #include <gtk/gtk.h>
static void static void
quit_activated(GSimpleAction *action, GVariant *parameter, gpointer app) quit_activated(GSimpleAction *action, GVariant *parameter, gpointer user_data) {
{ GApplication *app = G_APPLICATION (user_data);
g_application_quit (G_APPLICATION(app));
g_application_quit (app);
} }
static void static void
on_activate (GApplication *app, gpointer user_data) { app_activate (GApplication *app, gpointer user_data) {
GtkWidget *win = gtk_application_window_new (GTK_APPLICATION (app)); GtkWidget *win = gtk_application_window_new (GTK_APPLICATION (app));
gtk_window_set_title (GTK_WINDOW (win), "menu1"); gtk_window_set_title (GTK_WINDOW (win), "menu1");
gtk_window_set_default_size (GTK_WINDOW (win), 400, 300); gtk_window_set_default_size (GTK_WINDOW (win), 400, 300);
@ -32,13 +33,15 @@ on_activate (GApplication *app, gpointer user_data) {
/* gtk_widget_show (win); is also OKay instead of gtk_window_present. */ /* gtk_widget_show (win); is also OKay instead of gtk_window_present. */
} }
#define APPLICATION_ID "com.github.ToshioCP.menu1"
int int
main (int argc, char **argv) { main (int argc, char **argv) {
GtkApplication *app; GtkApplication *app;
int stat; int stat;
app = gtk_application_new ("com.github.ToshioCP.menu1", G_APPLICATION_FLAGS_NONE); app = gtk_application_new (APPLICATION_ID, G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate", G_CALLBACK (on_activate), NULL); g_signal_connect (app, "activate", G_CALLBACK (app_activate), NULL);
stat =g_application_run (G_APPLICATION (app), argc, argv); stat =g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app); g_object_unref (app);

View file

@ -34,10 +34,11 @@ Menus can build a complicated structure thanks to the links of menu items.
GMenuModel is an abstract object which represents a menu. GMenuModel is an abstract object which represents a menu.
GMenu is a simple implementation of GMenuModel and a child object of GMenuModel. GMenu is a simple implementation of GMenuModel and a child object of GMenuModel.
GObjct -- GMenuModel -- GMenu GObject -- GMenuModel -- GMenu
Because GMenuModel is an abstract object, it doesn't have any functions to generate it. Because GMenuModel is an abstract object, it isn't instantiatable.
Therefore, if you want to generate a menu, use `g_menu_new` function to generate GMenu object. Therefore, it doesn't have any functions to create it.
If you want to create a menu, use `g_menu_new` to create a GMenu instance.
GMenu inherits all the functions of GMenuModel because of the child object. GMenu inherits all the functions of GMenuModel because of the child object.
GMenuItem is an object directly derived from GObject. GMenuItem is an object directly derived from GObject.
@ -46,10 +47,10 @@ GMenuItem and Gmenu (or GMenuModel) don't have a parent-child relationship.
GObject -- GMenuModel -- GMenu GObject -- GMenuModel -- GMenu
GObject -- GMenuItem GObject -- GMenuItem
Usually, GMenuItem has attributes. GMenuItem has attributes.
One of the attributes is label. One of the attributes is label.
For example, there is a menu item which has "Edit" label in the first diagram in this section. For example, there is a menu item which has "Edit" label in the first diagram in this section.
"Cut", "Copy", "Paste" and "Select All" are also the labels of menu items. "Cut", "Copy", "Paste" and "Select All" are also the labels of the menu items.
Other attributes will be explained later. Other attributes will be explained later.
Some menu items have a link to another GMenu. Some menu items have a link to another GMenu.
@ -99,16 +100,16 @@ The following code is an example.
1. `menu_item_quit` is a menu item. 1. `menu_item_quit` is a menu item.
It has a label "Quit" and is connected to an action "app.quit". It has a label "Quit" and is connected to an action "app.quit".
"app" is a prefix and "quit" is the name of an action. "app" is a prefix and "quit" is the name of an action.
The prefix means that the action belongs to GtkApplication. The prefix means that the action belongs to a GtkApplication instance.
If the menu is clicked, then the corresponding action "quit" which belongs to GtkApplication will be activated. If the menu is clicked, then the corresponding action "quit" which belongs to the GtkApplication will be activated.
2. `act_quit` is an action. 2. `act_quit` is an action.
It has a name "quit". It has a name "quit".
It belongs to GtkApplication, but it is not obvious in the code above. It belongs to the GtkApplication, but it is not obvious in the code above.
The function `g_simple_action_new` generates a stateless action. The function `g_simple_action_new` creates a stateless action.
So, `act_quit` is stateless. So, `act_quit` is stateless.
The meaning of stateless will be explained later. The meaning of stateless will be explained later.
The argument `NULL` means that the action doesn't have an parameter. The argument `NULL` means that the action doesn't have an parameter.
Generally, most of the actions are stateless and have no parameter. Most of the actions are stateless and have no parameter.
When `act_quit` is activated, it will emit "activate" signal. When `act_quit` is activated, it will emit "activate" signal.
3. "activate" signal of the action is connected to the handler `quit_activated`. 3. "activate" signal of the action is connected to the handler `quit_activated`.
So, if the action is activated, the handler will be invoked. So, if the action is activated, the handler will be invoked.
@ -121,48 +122,47 @@ The following is a simple example of menus and actions.
menu/menu1.c menu/menu1.c
@@@ @@@
- 3-7: `quit_activated` is a handler of an action `act_quit`. - 3-8: `quit_activated` is a handler of the "activate" signal on the action `act_quit`.
Handlers of actions have three parameters. Handlers of the "activate" signal have three parameters.
1. The action object which has emitted the signal. 1. The action instance on which the signal is emitted.
2. Parameter. 2. Parameter.
In this example it is `NULL` because the second argument of `g_simple_action_new` (line 15) is `NULL`. In this example it is `NULL` because the second argument of `g_simple_action_new` (line 15) is `NULL`.
You don' t need to care about it. You don' t need to care about it.
3. User data. 3. User data.
It is the fourth parameter in the `g_signal_connect` (line 17) that has connected the action and the handler. It is the fourth parameter in the `g_signal_connect` (line 18) that connects the action and the handler.
- 6: A function `g_application_quit` immediately quits the application. - 7: A function `g_application_quit` immediately quits the application.
- 9-33: `on_activate` is a handler of "activate" signal on GtkApplication. - 10-34: `app_activate` is a handler of "activate" signal on the GtkApplication instance.
- 11-13: Generates a GtkApplicationWindow and assigns a pointer to it to `win`. And sets the title and default size. - 12-14: Creates a GtkApplicationWindow `win`. And sets the title and the default size.
- 15: Generates GSimpleAction `act_quit`. - 16: Creates GSimpleAction `act_quit`.
It is stateless. It is stateless.
The first argument of `g_simple_action_new` is a name of the action and the second argument is a parameter. The first argument of `g_simple_action_new` is a name of the action and the second argument is a parameter.
If you don't need the parameter, pass `NULL`. If you don't need the parameter, pass `NULL`.
Therefore, `act_quit` has a name "quit" and no parameter. Therefore, `act_quit` has a name "quit" and no parameter.
- 16: Adds the action to GtkApplication `app`. - 17: Adds the action to GtkApplication `app`.
GtkApplication implements an interface GActionMap and GActionGroup. GtkApplication implements an interface GActionMap and GActionGroup.
And GtkApplication can have a group of actions and actions are added by the function `g_action_map_add_action`. GtkApplication (GActionMap) can have a group of actions and the actions are added with the function `g_action_map_add_action`.
This function is described in GMenuModel section in GIO API reference. This function is described in [GMenuModel section in GIO API reference](https://developer.gnome.org/gio/stable/GActionMap.html#g-action-map-add-action).
- 17: Connects "activate" signal of the action and the handler `quit_activated`. - 18: Connects "activate" signal of the action and the handler `quit_activated`.
- 19-22: Generates GMenu and GMenuItem. - 20-23: Creates GMenu and GMenuItem instances.
`menubar` and `menu` are GMenu. `menubar` and `menu` are GMenu.
`menu_item_menu` and `menu_item_quit` are GMenuItem. `menu_item_menu` and `menu_item_quit` are GMenuItem.
`menu_item_menu` has a label "Menu" and no action. `menu_item_menu` has a label "Menu" and no action.
`menu_item_quit` has a label "Quit". `menu_item_quit` has a label "Quit" and an action "app.quit".
The second argument "app.quit" is a combination of "app" and "quit". The action "app.quit" is a combination of "app" and "quit".
"app" is a prefix and it means that the action belongs to GtkApplication. "quit" is the name of the action. "app" is a prefix and it means that the action belongs to GtkApplication. "quit" is the name of the action.
Therefore, it points the action which belongs to GtkApplication and has the name "quit" -- it is `act_quit`. Therefore, "app.quit" points the action which belongs to the GtkApplication instance and is named "quit".
- 23-24: Appends `act_quit` to `menu`. - 24-25: Appends `menu_item_quit` to `menu`.
As I mentioned before, all the attribute and link values are copied and used to form a new item within `menu`. As I mentioned before, all the attributes and links are copied and used to form a new item in `menu`.
Therefore after the appending, `menu` has a copy of `act_quit` in itself and `act_quit` is no longer needed. Therefore after the appending, `menu_item_quit` is no longer needed.
It is freed by `g_object_unref`. It is freed by `g_object_unref`.
- 25: Sets a submenu link to `menu_item_menu`. - 26: Sets the submenu link in `menu_item_menu` to point `menu`.
And the link points the GMenu `menu`. - 27-28: Appends `menu_item_menu` to `menubar`.
- 26-27: Appends `menu_item_menu` to `menubar`.
Then frees `menu_item_menu`. Then frees `menu_item_menu`.
GMenu and GMenuItem are connected and finally a menu is made up. GMenu and GMenuItem are connected and finally a menu is made up.
The structure of the menu is shown in the diagram below. The structure of the menu is shown in the diagram below.
- 29: The menu is inserted to GtkApplication. - 30: The menu is inserted to GtkApplication.
- 30: Sets GtkApplicationWindow to show the menubar. - 31: Sets GtkApplicationWindow to show the menubar.
- 31: Shows the window. - 32: Shows the window.
![menu and action](../image/menu1.png){width=12.555cm height=3.285cm} ![menu and action](../image/menu1.png){width=12.555cm height=3.285cm}

View file

@ -1,7 +1,8 @@
# Stateful action # Stateful action
Some actions have states. Some actions have states.
The values of states can be boolean or string. The typical values of states can be boolean or string.
However, other type of states is possible if you want.
Actions which have states are called stateful. Actions which have states are called stateful.
## Stateful action without a parameter ## Stateful action without a parameter