diff --git a/gfm/sec10.md b/gfm/sec10.md index 7ea0e69..406bd88 100644 --- a/gfm/sec10.md +++ b/gfm/sec10.md @@ -21,7 +21,7 @@ For example, our source has two things, the definition of TfeTextView and functi It is a good idea to separate them into two files, `tfetextview.c` and `tfe.c`. - `tfetextview.c` includes the definition and functions of TfeTextView. -- `tfe.c` includes functions like `main`, `on_activate`, `on_open` and so on, which relate to GtkApplication and GtkApplicationWindow +- `tfe.c` includes functions like `main`, `app_activate`, `app_open` and so on, which relate to GtkApplication and GtkApplicationWindow Now we have three source files, `tfetextview.c`, `tfe.c` and `tfe3.ui`. The `3` of `tfe3.ui` is like a version number. @@ -29,7 +29,7 @@ Managing version with filenames is one possible idea but it may make bothersome You need to rewrite filename in each version and it affects to contents of source files that refer to filenames. So, we should take `3` away from the filename. -In `tfe.c` the function `tfe_text_view_new` is invoked to generate TfeTextView. +In `tfe.c` the function `tfe_text_view_new` is invoked to create a TfeTextView instance. But it is defined in `tfetextview.c`, not `tfe.c`. The lack of the declaration (not definition) of `tfe_text_view_new` makes error when `tfe.c` is compiled. The declaration is necessary in `tfe.c`. @@ -105,12 +105,12 @@ All the source files are listed below. 2 #include "tfetextview.h" 3 4 static void - 5 on_activate (GApplication *app, gpointer user_data) { + 5 app_activate (GApplication *app, gpointer user_data) { 6 g_print ("You need a filename argument.\n"); 7 } 8 9 static void -10 on_open (GApplication *app, GFile ** files, gint n_files, gchar *hint, gpointer user_data) { +10 app_open (GApplication *app, GFile ** files, gint n_files, gchar *hint, gpointer user_data) { 11 GtkWidget *win; 12 GtkWidget *nb; 13 GtkWidget *lab; @@ -146,11 +146,11 @@ All the source files are listed below. 43 nbp = gtk_notebook_get_page (GTK_NOTEBOOK (nb), scr); 44 g_object_set (nbp, "tab-expand", TRUE, NULL); 45 g_free (filename); -46 } else { -47 filename = g_file_get_path (files[i]); -48 g_print ("No such file: %s.\n", filename); -49 g_free (filename); -50 } +46 } else if ((filename = g_file_get_path (files[i])) != NULL) { +47 g_print ("No such file: %s.\n", filename); +48 g_free (filename); +49 } else +50 g_print ("No valid file is given\n"); 51 } 52 if (gtk_notebook_get_n_pages (GTK_NOTEBOOK (nb)) > 0) { 53 gtk_widget_show (win); @@ -163,9 +163,9 @@ All the source files are listed below. 60 GtkApplication *app; 61 int stat; 62 -63 app = gtk_application_new ("com.github.ToshioCP.tfe3", G_APPLICATION_HANDLES_OPEN); -64 g_signal_connect (app, "activate", G_CALLBACK (on_activate), NULL); -65 g_signal_connect (app, "open", G_CALLBACK (on_open), NULL); +63 app = gtk_application_new ("com.github.ToshioCP.tfe", G_APPLICATION_HANDLES_OPEN); +64 g_signal_connect (app, "activate", G_CALLBACK (app_activate), NULL); +65 g_signal_connect (app, "open", G_CALLBACK (app_open), NULL); 66 stat =g_application_run (G_APPLICATION (app), argc, argv); 67 g_object_unref (app); 68 return stat; @@ -211,7 +211,7 @@ sample.o: sample.c gcc -o sample.o sample.c ~~~ -The sample of Malefile above consists of three elements, `sample.o`, `sample.c` and `gcc -0 sample.o sample.c`. +The sample of Malefile above consists of three elements, `sample.o`, `sample.c` and `gcc -o sample.o sample.c`. - `sample.o` is called target. - `sample.c` is prerequisite. @@ -272,7 +272,7 @@ If you don't use Ruby, you don't need to read this subsection. However, Ruby is really sophisticated and recommendable script language. - Rakefile controls the behavior of `rake`. -- You can write any ruby code in Rakefile. +- You can write any Ruby code in Rakefile. Rake has task and file task, which is similar to target, prerequisite and recipe in make. @@ -304,24 +304,24 @@ Rake has task and file task, which is similar to target, prerequisite and recipe 25 end ~~~ -What `Rakefile` describes is almost same as `Makefile` in the previous subsection. +The contents of the `Rakefile` is almost same as the `Makefile` in the previous subsection. - 3-6: Defines target file, source file and so on. - 1, 8: Loads clean library. And defines CLEAN file list. The files included by CLEAN will be removed when `rake clean` is typed on the command line. -- 10: Default target depends on targetfile. -Default is the final goal of tasks. -- 12-14: Targetfile depends on objfiles. +- 10: The default target depends on `targetfile`. +The task `default` is the final goal of tasks. +- 12-14: `targetfile` depends on `objfiles`. The variable `t` is a task object. - - t.name is a target name - - t.prerequisites is an array of prerequisites. - - t.source is the first element of prerequisites. -- sh is a method to give the following string to shell as an argument and execute the shell. -- 16-21: There's a loop by each element of the array of objfiles. Each object depends on corresponding source file. + - `t.name` is a target name + - `t.prerequisites` is an array of prerequisites. + - `t.source` is the first element of prerequisites. +- `sh` is a method to give the following string to shell as an argument and executes the shell. +- 16-21: There's a loop by each element of the array of `objfiles`. Each object depends on corresponding source file. - 23-25: Resource file depends on xml file and ui file. Rakefile might seem to be difficult for beginners. -But, you can use any ruby syntax in Rakefile, so it is really flexible. +But, you can use any Ruby syntax in Rakefile, so it is really flexible. If you practice Ruby and Rakefile, it will be highly productive tools. ## Meson and ninja @@ -352,16 +352,16 @@ The first parameter is the name of the project and the second is the programming - 2: `dependency` function defines a dependency that is taken by `pkg-config`. We put `gtk4` as an argument. - 5: `import` function imports a module. -In line 5, gnome module is imported and assigned to the variable `gnome`. -gnome module provides helper tools to build GTK programs. -- 6: `.compile_resources` is a method of gnome module and compile files to resources under the instruction of xml file. +In line 5, the gnome module is imported and assigned to the variable `gnome`. +The gnome module provides helper tools to build GTK programs. +- 6: `.compile_resources` is a method of the gnome module and compiles files to resources under the instruction of xml file. In line 6, the resource filename is `resources`, which means `resources.c` and `resources.h`, and xml file is `tfe.gresource.xml`. This method generates C source file by default. - 8: Defines source files. -- 10: Executable function generates a target file by building source files. +- 10: Executable function generates a target file by compiling source files. The first parameter is the filename of the target. The following parameters are source files. -The last parameter has a option `dependencies`. -In line 10 it is `gtkdep` which is defined in line 3. +The last parameter is an option `dependencies`. +`gtkdep` is used in the compilation. Now run meson and ninja. diff --git a/gfm/sec11.md b/gfm/sec11.md index 3cbed5b..d903f91 100644 --- a/gfm/sec11.md +++ b/gfm/sec11.md @@ -2,9 +2,9 @@ Up: [Readme.md](../Readme.md), Prev: [Section 10](sec10.md), Next: [Section 12] # Instance and class -This section and the following four sections are explanations about the next version of the text file editor (tfe). -It is tfe5. -It has many changes from the prior version. +A new version of the text file editor (`tfe`) will be made in this section and the following four sections. +It is `tfe5`. +There are many changes from the prior version. All the sources are listed in [Section 16](sec16.md). They are located in two directories, [src/tfe5](../src/tfe5) and [src/tfetextview](../src/tfetextview). @@ -37,7 +37,8 @@ After that I will explain: GObject and its children are objects, which have both class and instance. First, think about instance of objects. -Instance is structured memories and described as C language structure. +Instance is structured memory. +THe structure is described as C language structure. The following is a structure of TfeTextView. ~~~C @@ -52,12 +53,16 @@ struct _TfeTextView { The members of the structure are: -- `parent` is the instance structure of GtkTextView which is the parent object of TfeTextView. +- The type of `parent` is GtkTextView which is C structure. +It is declared in `gtktextview.h`. +GtkTextView is the parent of TfeTextView. - `file` is a pointer to GFile. It can be NULL if no file corresponds to the TfeTextView object. Notice the program above is the declaration of the structure, not the definition. So, no memories are allocated at this moment. They are to be allocated when `tfe_text_view_new` function is invoked. +The memory allocated with `tfe_text_view_new` is an instance of TfeTextView object. +Therefore, There can be multiple TfeTextView instances if `tfe_text_view_new` is called multiple times. You can find the declaration of the ancestors of TfeTextView in the source files of GTK and GLib. The following is extracts from the source files (not exactly the same). @@ -87,7 +92,7 @@ struct _GtkTextView }; ~~~ -In each structure, its parent instance is declared at the top of members. +In each structure, its parent is declared at the top of the members. So, every ancestors is included in the child instance. This is very important. It guarantees a child widget to inherit all the features from ancestors. @@ -96,9 +101,9 @@ The structure of `TfeTextView` is like the following diagram. ![The structure of the instance TfeTextView](../image/TfeTextView.png) -## Generate TfeTextView instance +## Create TfeTextView instance -The function `tfe_text_view_new` generates a new TfeTextView instance. +The function `tfe_text_view_new` creates a new TfeTextView instance. ~~~C 1 GtkWidget * @@ -117,8 +122,8 @@ When this function is run, the following procedure is gone through. Step one through three is done automatically. Step four is done by the function `tfe_text_view_init`. -> In the same way, `gtk_text_view_init`, `gtk_widget_init` and `g_object_init` is the initialization functions of GtkTextView, GtkWidget and GObject respectively. -> You can find them in the GTK or GLib source files. +In the same way, `gtk_text_view_init`, `gtk_widget_init` and `g_object_init` is the initialization functions of GtkTextView, GtkWidget and GObject respectively. +You can find them in the GTK or GLib source files. ~~~C 1 static void @@ -141,8 +146,8 @@ We need at least two things. One is functions and the other is class. You've already seen many functions. -For example, `tfe_text_view_new` is a function to generate TfeTextView instance. -These functions are similar to object methods in object oriented languages such as Java or Ruby. +For example, `tfe_text_view_new` is a function to create a TfeTextView instance. +These functions are similar to public object methods in object oriented languages such as Java or Ruby. Functions are public, which means that they are expected to be used by other objects. Class comprises mainly pointers to functions. @@ -153,45 +158,46 @@ For example, GObject class is declared in `gobject.h` in GLib source files. 1 typedef struct _GObjectClass GObjectClass; 2 typedef struct _GObjectClass GInitiallyUnownedClass; 3 - 4 struct _GObjectClass { - 5 GTypeClass g_type_class; - 6 /*< private >*/ - 7 GSList *construct_properties; - 8 /*< public >*/ - 9 /* seldom overidden */ -10 GObject* (*constructor) (GType type, -11 guint n_construct_properties, -12 GObjectConstructParam *construct_properties); -13 /* overridable methods */ -14 void (*set_property) (GObject *object, -15 guint property_id, -16 const GValue *value, -17 GParamSpec *pspec); -18 void (*get_property) (GObject *object, -19 guint property_id, -20 GValue *value, -21 GParamSpec *pspec); -22 void (*dispose) (GObject *object); -23 void (*finalize) (GObject *object); -24 /* seldom overidden */ -25 void (*dispatch_properties_changed) (GObject *object, -26 guint n_pspecs, -27 GParamSpec **pspecs); -28 /* signals */ -29 void (*notify) (GObject *object, -30 GParamSpec *pspec); -31 + 4 struct _GObjectClass + 5 { + 6 GTypeClass g_type_class; + 7 /*< private >*/ + 8 GSList *construct_properties; + 9 /*< public >*/ +10 /* seldom overridden */ +11 GObject* (*constructor) (GType type, +12 guint n_construct_properties, +13 GObjectConstructParam *construct_properties); +14 /* overridable methods */ +15 void (*set_property) (GObject *object, +16 guint property_id, +17 const GValue *value, +18 GParamSpec *pspec); +19 void (*get_property) (GObject *object, +20 guint property_id, +21 GValue *value, +22 GParamSpec *pspec); +23 void (*dispose) (GObject *object); +24 void (*finalize) (GObject *object); +25 /* seldom overridden */ +26 void (*dispatch_properties_changed) (GObject *object, +27 guint n_pspecs, +28 GParamSpec **pspecs); +29 /* signals */ +30 void (*notify) (GObject *object, +31 GParamSpec *pspec); 32 /* called when done constructing */ -33 void (*constructed) (GObject *object); +33 void (*constructed) (GObject *object); 34 /*< private >*/ -35 gsize flags; +35 gsize flags; 36 /* padding */ -37 gpointer pdummy[6]; +37 gpointer pdummy[6]; 38 }; +39 ~~~ I'd like to explain some of the members. -There's a pointer to the function `dispose` in line 22. +There's a pointer to the function `dispose` in line 23. ~~~C void (*dispose) (GObject *object); @@ -200,7 +206,7 @@ void (*dispose) (GObject *object); The declaration is a bit complicated. The asterisk before the identifier `dispose` means pointer. So, the pointer `dispose` points to a function which has one parameter, which points a GObject structure, and returns no value. -In the same way, line 23 says `finalize` is a pointer to the function which has one parameter, which points a GObject structure, and returns no value. +In the same way, line 24 says `finalize` is a pointer to the function which has one parameter, which points a GObject structure, and returns no value. ~~~C void (*finalize) (GObject *object); @@ -208,15 +214,19 @@ void (*finalize) (GObject *object); Look at the declaration of `_GObjectClass` so that you would find that most of the members are pointers to functions. -- 10: A function pointed by `constructor` is called when the instance is generated. It completes the initialization of the instance. -- 22: A function pointed by `dispose` is called when the instance destructs itself. +- 11: A function pointed by `constructor` is called when the instance is generated. It completes the initialization of the instance. +- 23: A function pointed by `dispose` is called when the instance destructs itself. Destruction process is divided into two phases. The first one is called disposing. In this phase, the instance releases all the references to other instances. The second phase is finalizing. -- 23: A function pointed by `finalize` finishes the destruction process. +- 24: A function pointed by `finalize` finishes the destruction process. - The other pointers point to functions which are called while the instance lives. +These functions are called class methods. +The methods are open to its descendants. +But not open to the objects which are not the descendants. + ## TfeTextView class TfeTextView class is a structure and it includes all its ancestors' class in it. @@ -227,119 +237,134 @@ Let's look at all the classes from GObject, which is the top level object, to Tf The following is extracts from the source files (not exactly the same). ~~~C - 1 struct _GtkWidgetClass { - 2 GInitiallyUnownedClass parent_class; - 3 /*< public >*/ - 4 guint activate_signal; - 5 /* basics */ - 6 void (* show) (GtkWidget *widget); - 7 void (* hide) (GtkWidget *widget); - 8 void (* map) (GtkWidget *widget); - 9 void (* unmap) (GtkWidget *widget); - 10 void (* realize) (GtkWidget *widget); - 11 void (* unrealize) (GtkWidget *widget); - 12 void (* root) (GtkWidget *widget); - 13 void (* unroot) (GtkWidget *widget); - 14 void (* size_allocate) (GtkWidget *widget, - 15 int width, - 16 int height, - 17 int baseline); - 18 void (* state_flags_changed) (GtkWidget *widget, - 19 GtkStateFlags previous_state_flags); - 20 void (* direction_changed) (GtkWidget *widget, - 21 GtkTextDirection previous_direction); - 22 void (* grab_notify) (GtkWidget *widget, - 23 gboolean was_grabbed); - 24 /* size requests */ - 25 GtkSizeRequestMode (* get_request_mode) (GtkWidget *widget); - 26 void (* measure) (GtkWidget *widget, - 27 GtkOrientation orientation, - 28 int for_size, - 29 int *minimum, - 30 int *natural, - 31 int *minimum_baseline, - 32 int *natural_baseline); - 33 /* Mnemonics */ - 34 gboolean (* mnemonic_activate) (GtkWidget *widget, - 35 gboolean group_cycling); - 36 /* explicit focus */ - 37 gboolean (* grab_focus) (GtkWidget *widget); - 38 gboolean (* focus) (GtkWidget *widget, - 39 GtkDirectionType direction); - 40 void (* set_focus_child) (GtkWidget *widget, - 41 GtkWidget *child); - 42 /* keyboard navigation */ - 43 void (* move_focus) (GtkWidget *widget, - 44 GtkDirectionType direction); - 45 gboolean (* keynav_failed) (GtkWidget *widget, - 46 GtkDirectionType direction); - 47 /* accessibility support - 48 */ - 49 AtkObject * (* get_accessible) (GtkWidget *widget); - 50 gboolean (* query_tooltip) (GtkWidget *widget, - 51 gint x, - 52 gint y, - 53 gboolean keyboard_tooltip, - 54 GtkTooltip *tooltip); - 55 void (* compute_expand) (GtkWidget *widget, - 56 gboolean *hexpand_p, - 57 gboolean *vexpand_p); - 58 void (* css_changed) (GtkWidget *widget, - 59 GtkCssStyleChange *change); - 60 void (* system_setting_changed) (GtkWidget *widget, - 61 GtkSystemSetting settings); - 62 void (* snapshot) (GtkWidget *widget, - 63 GtkSnapshot *snapshot); - 64 gboolean (* contains) (GtkWidget *widget, - 65 gdouble x, - 66 gdouble y); - 67 /*< private >*/ - 68 GtkWidgetClassPrivate *priv; - 69 gpointer padding[8]; - 70 }; - 71 - 72 struct _GtkTextViewClass { - 73 GtkWidgetClass parent_class; - 74 /*< public >*/ - 75 void (* move_cursor) (GtkTextView *text_view, - 76 GtkMovementStep step, - 77 gint count, - 78 gboolean extend_selection); - 79 void (* set_anchor) (GtkTextView *text_view); - 80 void (* insert_at_cursor) (GtkTextView *text_view, - 81 const gchar *str); - 82 void (* delete_from_cursor) (GtkTextView *text_view, - 83 GtkDeleteType type, - 84 gint count); - 85 void (* backspace) (GtkTextView *text_view); - 86 void (* cut_clipboard) (GtkTextView *text_view); - 87 void (* copy_clipboard) (GtkTextView *text_view); - 88 void (* paste_clipboard) (GtkTextView *text_view); - 89 void (* toggle_overwrite) (GtkTextView *text_view); - 90 GtkTextBuffer * (* create_buffer) (GtkTextView *text_view); - 91 void (* snapshot_layer) (GtkTextView *text_view, - 92 GtkTextViewLayer layer, - 93 GtkSnapshot *snapshot); - 94 gboolean (* extend_selection) (GtkTextView *text_view, - 95 GtkTextExtendSelection granularity, - 96 const GtkTextIter *location, - 97 GtkTextIter *start, - 98 GtkTextIter *end); - 99 void (* insert_emoji) (GtkTextView *text_view); -100 /*< private >*/ -101 gpointer padding[8]; -102 }; -103 -104 /* The following definition is generated by the macro G_DECLARE_FINAL_TYPE */ -105 typedef struct { -106 GtkTextView parent_class; -107 } TfeTextViewClass; -108 + 1 struct _GtkWidgetClass + 2 { + 3 GInitiallyUnownedClass parent_class; + 4 + 5 /*< public >*/ + 6 + 7 /* basics */ + 8 void (* show) (GtkWidget *widget); + 9 void (* hide) (GtkWidget *widget); + 10 void (* map) (GtkWidget *widget); + 11 void (* unmap) (GtkWidget *widget); + 12 void (* realize) (GtkWidget *widget); + 13 void (* unrealize) (GtkWidget *widget); + 14 void (* root) (GtkWidget *widget); + 15 void (* unroot) (GtkWidget *widget); + 16 void (* size_allocate) (GtkWidget *widget, + 17 int width, + 18 int height, + 19 int baseline); + 20 void (* state_flags_changed) (GtkWidget *widget, + 21 GtkStateFlags previous_state_flags); + 22 void (* direction_changed) (GtkWidget *widget, + 23 GtkTextDirection previous_direction); + 24 + 25 /* size requests */ + 26 GtkSizeRequestMode (* get_request_mode) (GtkWidget *widget); + 27 void (* measure) (GtkWidget *widget, + 28 GtkOrientation orientation, + 29 int for_size, + 30 int *minimum, + 31 int *natural, + 32 int *minimum_baseline, + 33 int *natural_baseline); + 34 + 35 /* Mnemonics */ + 36 gboolean (* mnemonic_activate) (GtkWidget *widget, + 37 gboolean group_cycling); + 38 + 39 /* explicit focus */ + 40 gboolean (* grab_focus) (GtkWidget *widget); + 41 gboolean (* focus) (GtkWidget *widget, + 42 GtkDirectionType direction); + 43 void (* set_focus_child) (GtkWidget *widget, + 44 GtkWidget *child); + 45 + 46 /* keyboard navigation */ + 47 void (* move_focus) (GtkWidget *widget, + 48 GtkDirectionType direction); + 49 gboolean (* keynav_failed) (GtkWidget *widget, + 50 GtkDirectionType direction); + 51 + 52 gboolean (* query_tooltip) (GtkWidget *widget, + 53 int x, + 54 int y, + 55 gboolean keyboard_tooltip, + 56 GtkTooltip *tooltip); + 57 + 58 void (* compute_expand) (GtkWidget *widget, + 59 gboolean *hexpand_p, + 60 gboolean *vexpand_p); + 61 + 62 void (* css_changed) (GtkWidget *widget, + 63 GtkCssStyleChange *change); + 64 + 65 void (* system_setting_changed) (GtkWidget *widget, + 66 GtkSystemSetting settings); + 67 + 68 void (* snapshot) (GtkWidget *widget, + 69 GtkSnapshot *snapshot); + 70 + 71 gboolean (* contains) (GtkWidget *widget, + 72 double x, + 73 double y); + 74 + 75 /*< private >*/ + 76 + 77 GtkWidgetClassPrivate *priv; + 78 + 79 gpointer padding[8]; + 80 }; + 81 + 82 struct _GtkTextViewClass + 83 { + 84 GtkWidgetClass parent_class; + 85 + 86 /*< public >*/ + 87 + 88 void (* move_cursor) (GtkTextView *text_view, + 89 GtkMovementStep step, + 90 int count, + 91 gboolean extend_selection); + 92 void (* set_anchor) (GtkTextView *text_view); + 93 void (* insert_at_cursor) (GtkTextView *text_view, + 94 const char *str); + 95 void (* delete_from_cursor) (GtkTextView *text_view, + 96 GtkDeleteType type, + 97 int count); + 98 void (* backspace) (GtkTextView *text_view); + 99 void (* cut_clipboard) (GtkTextView *text_view); +100 void (* copy_clipboard) (GtkTextView *text_view); +101 void (* paste_clipboard) (GtkTextView *text_view); +102 void (* toggle_overwrite) (GtkTextView *text_view); +103 GtkTextBuffer * (* create_buffer) (GtkTextView *text_view); +104 void (* snapshot_layer) (GtkTextView *text_view, +105 GtkTextViewLayer layer, +106 GtkSnapshot *snapshot); +107 gboolean (* extend_selection) (GtkTextView *text_view, +108 GtkTextExtendSelection granularity, +109 const GtkTextIter *location, +110 GtkTextIter *start, +111 GtkTextIter *end); +112 void (* insert_emoji) (GtkTextView *text_view); +113 +114 /*< private >*/ +115 +116 gpointer padding[8]; +117 }; +118 +119 /* The following definition is generated by the macro G_DECLARE_FINAL_TYPE */ +120 typedef struct { +121 GtkTextView parent_class; +122 } TfeTextViewClass; +123 ~~~ -- 105-107: This three lines are generated by the macro G\_DECLARE\_FINAL\_TYPE. +- 120-122: This three lines are generated by the macro `G_DECLARE_FINAL_TYPE`. So, they are not written in either `tfe_text_view.h` or `tfe_text_view.c`. -- 2, 73, 106: Each derived class puts its parent class at the first member of its structure. +- 3, 84, 121: Each derived class puts its parent class at the first member of its structure. It is the same as instance structures. - Class members in ancestors are open to the descendant class. So, they can be changed in `tfe_text_view_class_init` function. @@ -413,7 +438,7 @@ tfe_text_view_class_init (TfeTextViewClass *class) { } ~~~ -Each ancestors' class has been generated before TfeTextViewClass is generated. +Each ancestors' class has been created before TfeTextViewClass is created. Therefore, there are four classes and each class has a pointer to each dispose handler. Look at the following diagram. There are four classes -- GObjectClass (GInitiallyUnownedClass), GtkWidgetClass, GtkTextViewClass and TfeTextViewClass. diff --git a/src/class_gobject.c b/src/class_gobject.c index 66288bd..090cd4a 100644 --- a/src/class_gobject.c +++ b/src/class_gobject.c @@ -1,38 +1,39 @@ typedef struct _GObjectClass GObjectClass; typedef struct _GObjectClass GInitiallyUnownedClass; -struct _GObjectClass { +struct _GObjectClass +{ GTypeClass g_type_class; /*< private >*/ GSList *construct_properties; /*< public >*/ - /* seldom overidden */ + /* seldom overridden */ GObject* (*constructor) (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties); /* overridable methods */ - void (*set_property) (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec); - void (*get_property) (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec); - void (*dispose) (GObject *object); - void (*finalize) (GObject *object); - /* seldom overidden */ + void (*set_property) (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); + void (*get_property) (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + void (*dispose) (GObject *object); + void (*finalize) (GObject *object); + /* seldom overridden */ void (*dispatch_properties_changed) (GObject *object, - guint n_pspecs, - GParamSpec **pspecs); + guint n_pspecs, + GParamSpec **pspecs); /* signals */ - void (*notify) (GObject *object, - GParamSpec *pspec); - + void (*notify) (GObject *object, + GParamSpec *pspec); /* called when done constructing */ - void (*constructed) (GObject *object); + void (*constructed) (GObject *object); /*< private >*/ - gsize flags; + gsize flags; /* padding */ - gpointer pdummy[6]; + gpointer pdummy[6]; }; + diff --git a/src/classes.c b/src/classes.c index a7cd635..b9a13f5 100644 --- a/src/classes.c +++ b/src/classes.c @@ -1,7 +1,9 @@ -struct _GtkWidgetClass { +struct _GtkWidgetClass +{ GInitiallyUnownedClass parent_class; + /*< public >*/ - guint activate_signal; + /* basics */ void (* show) (GtkWidget *widget); void (* hide) (GtkWidget *widget); @@ -19,8 +21,7 @@ struct _GtkWidgetClass { GtkStateFlags previous_state_flags); void (* direction_changed) (GtkWidget *widget, GtkTextDirection previous_direction); - void (* grab_notify) (GtkWidget *widget, - gboolean was_grabbed); + /* size requests */ GtkSizeRequestMode (* get_request_mode) (GtkWidget *widget); void (* measure) (GtkWidget *widget, @@ -30,58 +31,70 @@ struct _GtkWidgetClass { int *natural, int *minimum_baseline, int *natural_baseline); + /* Mnemonics */ gboolean (* mnemonic_activate) (GtkWidget *widget, gboolean group_cycling); + /* explicit focus */ gboolean (* grab_focus) (GtkWidget *widget); gboolean (* focus) (GtkWidget *widget, GtkDirectionType direction); void (* set_focus_child) (GtkWidget *widget, GtkWidget *child); + /* keyboard navigation */ void (* move_focus) (GtkWidget *widget, GtkDirectionType direction); gboolean (* keynav_failed) (GtkWidget *widget, GtkDirectionType direction); - /* accessibility support - */ - AtkObject * (* get_accessible) (GtkWidget *widget); + gboolean (* query_tooltip) (GtkWidget *widget, - gint x, - gint y, + int x, + int y, gboolean keyboard_tooltip, GtkTooltip *tooltip); + void (* compute_expand) (GtkWidget *widget, gboolean *hexpand_p, gboolean *vexpand_p); + void (* css_changed) (GtkWidget *widget, GtkCssStyleChange *change); + void (* system_setting_changed) (GtkWidget *widget, GtkSystemSetting settings); + void (* snapshot) (GtkWidget *widget, GtkSnapshot *snapshot); + gboolean (* contains) (GtkWidget *widget, - gdouble x, - gdouble y); + double x, + double y); + /*< private >*/ + GtkWidgetClassPrivate *priv; + gpointer padding[8]; }; -struct _GtkTextViewClass { +struct _GtkTextViewClass +{ GtkWidgetClass parent_class; + /*< public >*/ + void (* move_cursor) (GtkTextView *text_view, GtkMovementStep step, - gint count, + int count, gboolean extend_selection); void (* set_anchor) (GtkTextView *text_view); void (* insert_at_cursor) (GtkTextView *text_view, - const gchar *str); + const char *str); void (* delete_from_cursor) (GtkTextView *text_view, GtkDeleteType type, - gint count); + int count); void (* backspace) (GtkTextView *text_view); void (* cut_clipboard) (GtkTextView *text_view); void (* copy_clipboard) (GtkTextView *text_view); @@ -89,15 +102,17 @@ struct _GtkTextViewClass { void (* toggle_overwrite) (GtkTextView *text_view); GtkTextBuffer * (* create_buffer) (GtkTextView *text_view); void (* snapshot_layer) (GtkTextView *text_view, - GtkTextViewLayer layer, - GtkSnapshot *snapshot); + GtkTextViewLayer layer, + GtkSnapshot *snapshot); gboolean (* extend_selection) (GtkTextView *text_view, GtkTextExtendSelection granularity, const GtkTextIter *location, GtkTextIter *start, GtkTextIter *end); void (* insert_emoji) (GtkTextView *text_view); + /*< private >*/ + gpointer padding[8]; }; diff --git a/src/sec10.src.md b/src/sec10.src.md index 3261dd6..590dfe7 100644 --- a/src/sec10.src.md +++ b/src/sec10.src.md @@ -19,7 +19,7 @@ For example, our source has two things, the definition of TfeTextView and functi It is a good idea to separate them into two files, `tfetextview.c` and `tfe.c`. - `tfetextview.c` includes the definition and functions of TfeTextView. -- `tfe.c` includes functions like `main`, `on_activate`, `on_open` and so on, which relate to GtkApplication and GtkApplicationWindow +- `tfe.c` includes functions like `main`, `app_activate`, `app_open` and so on, which relate to GtkApplication and GtkApplicationWindow Now we have three source files, `tfetextview.c`, `tfe.c` and `tfe3.ui`. The `3` of `tfe3.ui` is like a version number. @@ -27,7 +27,7 @@ Managing version with filenames is one possible idea but it may make bothersome You need to rewrite filename in each version and it affects to contents of source files that refer to filenames. So, we should take `3` away from the filename. -In `tfe.c` the function `tfe_text_view_new` is invoked to generate TfeTextView. +In `tfe.c` the function `tfe_text_view_new` is invoked to create a TfeTextView instance. But it is defined in `tfetextview.c`, not `tfe.c`. The lack of the declaration (not definition) of `tfe_text_view_new` makes error when `tfe.c` is compiled. The declaration is necessary in `tfe.c`. @@ -89,7 +89,7 @@ sample.o: sample.c gcc -o sample.o sample.c ~~~ -The sample of Malefile above consists of three elements, `sample.o`, `sample.c` and `gcc -0 sample.o sample.c`. +The sample of Malefile above consists of three elements, `sample.o`, `sample.c` and `gcc -o sample.o sample.c`. - `sample.o` is called target. - `sample.c` is prerequisite. @@ -132,7 +132,7 @@ If you don't use Ruby, you don't need to read this subsection. However, Ruby is really sophisticated and recommendable script language. - Rakefile controls the behavior of `rake`. -- You can write any ruby code in Rakefile. +- You can write any Ruby code in Rakefile. Rake has task and file task, which is similar to target, prerequisite and recipe in make. @@ -140,24 +140,24 @@ Rake has task and file task, which is similar to target, prerequisite and recipe tfe4/Rakefile @@@ -What `Rakefile` describes is almost same as `Makefile` in the previous subsection. +The contents of the `Rakefile` is almost same as the `Makefile` in the previous subsection. - 3-6: Defines target file, source file and so on. - 1, 8: Loads clean library. And defines CLEAN file list. The files included by CLEAN will be removed when `rake clean` is typed on the command line. -- 10: Default target depends on targetfile. -Default is the final goal of tasks. -- 12-14: Targetfile depends on objfiles. +- 10: The default target depends on `targetfile`. +The task `default` is the final goal of tasks. +- 12-14: `targetfile` depends on `objfiles`. The variable `t` is a task object. - - t.name is a target name - - t.prerequisites is an array of prerequisites. - - t.source is the first element of prerequisites. -- sh is a method to give the following string to shell as an argument and execute the shell. -- 16-21: There's a loop by each element of the array of objfiles. Each object depends on corresponding source file. + - `t.name` is a target name + - `t.prerequisites` is an array of prerequisites. + - `t.source` is the first element of prerequisites. +- `sh` is a method to give the following string to shell as an argument and executes the shell. +- 16-21: There's a loop by each element of the array of `objfiles`. Each object depends on corresponding source file. - 23-25: Resource file depends on xml file and ui file. Rakefile might seem to be difficult for beginners. -But, you can use any ruby syntax in Rakefile, so it is really flexible. +But, you can use any Ruby syntax in Rakefile, so it is really flexible. If you practice Ruby and Rakefile, it will be highly productive tools. ## Meson and ninja @@ -179,16 +179,16 @@ The first parameter is the name of the project and the second is the programming - 2: `dependency` function defines a dependency that is taken by `pkg-config`. We put `gtk4` as an argument. - 5: `import` function imports a module. -In line 5, gnome module is imported and assigned to the variable `gnome`. -gnome module provides helper tools to build GTK programs. -- 6: `.compile_resources` is a method of gnome module and compile files to resources under the instruction of xml file. +In line 5, the gnome module is imported and assigned to the variable `gnome`. +The gnome module provides helper tools to build GTK programs. +- 6: `.compile_resources` is a method of the gnome module and compiles files to resources under the instruction of xml file. In line 6, the resource filename is `resources`, which means `resources.c` and `resources.h`, and xml file is `tfe.gresource.xml`. This method generates C source file by default. - 8: Defines source files. -- 10: Executable function generates a target file by building source files. +- 10: Executable function generates a target file by compiling source files. The first parameter is the filename of the target. The following parameters are source files. -The last parameter has a option `dependencies`. -In line 10 it is `gtkdep` which is defined in line 3. +The last parameter is an option `dependencies`. +`gtkdep` is used in the compilation. Now run meson and ninja. diff --git a/src/sec11.src.md b/src/sec11.src.md index 12b487b..1878ab3 100644 --- a/src/sec11.src.md +++ b/src/sec11.src.md @@ -1,8 +1,8 @@ # Instance and class -This section and the following four sections are explanations about the next version of the text file editor (tfe). -It is tfe5. -It has many changes from the prior version. +A new version of the text file editor (`tfe`) will be made in this section and the following four sections. +It is `tfe5`. +There are many changes from the prior version. All the sources are listed in [Section 16](sec16.src.md). They are located in two directories, [src/tfe5](tfe5) and [src/tfetextview](tfetextview). @@ -35,7 +35,8 @@ After that I will explain: GObject and its children are objects, which have both class and instance. First, think about instance of objects. -Instance is structured memories and described as C language structure. +Instance is structured memory. +THe structure is described as C language structure. The following is a structure of TfeTextView. ~~~C @@ -50,12 +51,16 @@ struct _TfeTextView { The members of the structure are: -- `parent` is the instance structure of GtkTextView which is the parent object of TfeTextView. +- The type of `parent` is GtkTextView which is C structure. +It is declared in `gtktextview.h`. +GtkTextView is the parent of TfeTextView. - `file` is a pointer to GFile. It can be NULL if no file corresponds to the TfeTextView object. Notice the program above is the declaration of the structure, not the definition. So, no memories are allocated at this moment. They are to be allocated when `tfe_text_view_new` function is invoked. +The memory allocated with `tfe_text_view_new` is an instance of TfeTextView object. +Therefore, There can be multiple TfeTextView instances if `tfe_text_view_new` is called multiple times. You can find the declaration of the ancestors of TfeTextView in the source files of GTK and GLib. The following is extracts from the source files (not exactly the same). @@ -85,7 +90,7 @@ struct _GtkTextView }; ~~~ -In each structure, its parent instance is declared at the top of members. +In each structure, its parent is declared at the top of the members. So, every ancestors is included in the child instance. This is very important. It guarantees a child widget to inherit all the features from ancestors. @@ -94,9 +99,9 @@ The structure of `TfeTextView` is like the following diagram. ![The structure of the instance TfeTextView](../image/TfeTextView.png){width=14.39cm height=2.16cm} -## Generate TfeTextView instance +## Create TfeTextView instance -The function `tfe_text_view_new` generates a new TfeTextView instance. +The function `tfe_text_view_new` creates a new TfeTextView instance. @@@include tfetextview/tfetextview.c tfe_text_view_new @@ -112,8 +117,8 @@ When this function is run, the following procedure is gone through. Step one through three is done automatically. Step four is done by the function `tfe_text_view_init`. -> In the same way, `gtk_text_view_init`, `gtk_widget_init` and `g_object_init` is the initialization functions of GtkTextView, GtkWidget and GObject respectively. -> You can find them in the GTK or GLib source files. +In the same way, `gtk_text_view_init`, `gtk_widget_init` and `g_object_init` is the initialization functions of GtkTextView, GtkWidget and GObject respectively. +You can find them in the GTK or GLib source files. @@@include tfetextview/tfetextview.c tfe_text_view_init @@ -133,8 +138,8 @@ We need at least two things. One is functions and the other is class. You've already seen many functions. -For example, `tfe_text_view_new` is a function to generate TfeTextView instance. -These functions are similar to object methods in object oriented languages such as Java or Ruby. +For example, `tfe_text_view_new` is a function to create a TfeTextView instance. +These functions are similar to public object methods in object oriented languages such as Java or Ruby. Functions are public, which means that they are expected to be used by other objects. Class comprises mainly pointers to functions. @@ -146,7 +151,7 @@ class_gobject.c @@@ I'd like to explain some of the members. -There's a pointer to the function `dispose` in line 22. +There's a pointer to the function `dispose` in line 23. ~~~C void (*dispose) (GObject *object); @@ -155,7 +160,7 @@ void (*dispose) (GObject *object); The declaration is a bit complicated. The asterisk before the identifier `dispose` means pointer. So, the pointer `dispose` points to a function which has one parameter, which points a GObject structure, and returns no value. -In the same way, line 23 says `finalize` is a pointer to the function which has one parameter, which points a GObject structure, and returns no value. +In the same way, line 24 says `finalize` is a pointer to the function which has one parameter, which points a GObject structure, and returns no value. ~~~C void (*finalize) (GObject *object); @@ -163,15 +168,19 @@ void (*finalize) (GObject *object); Look at the declaration of `_GObjectClass` so that you would find that most of the members are pointers to functions. -- 10: A function pointed by `constructor` is called when the instance is generated. It completes the initialization of the instance. -- 22: A function pointed by `dispose` is called when the instance destructs itself. +- 11: A function pointed by `constructor` is called when the instance is generated. It completes the initialization of the instance. +- 23: A function pointed by `dispose` is called when the instance destructs itself. Destruction process is divided into two phases. The first one is called disposing. In this phase, the instance releases all the references to other instances. The second phase is finalizing. -- 23: A function pointed by `finalize` finishes the destruction process. +- 24: A function pointed by `finalize` finishes the destruction process. - The other pointers point to functions which are called while the instance lives. +These functions are called class methods. +The methods are open to its descendants. +But not open to the objects which are not the descendants. + ## TfeTextView class TfeTextView class is a structure and it includes all its ancestors' class in it. @@ -185,9 +194,9 @@ The following is extracts from the source files (not exactly the same). classes.c @@@ -- 105-107: This three lines are generated by the macro G\_DECLARE\_FINAL\_TYPE. +- 120-122: This three lines are generated by the macro `G_DECLARE_FINAL_TYPE`. So, they are not written in either `tfe_text_view.h` or `tfe_text_view.c`. -- 2, 73, 106: Each derived class puts its parent class at the first member of its structure. +- 3, 84, 121: Each derived class puts its parent class at the first member of its structure. It is the same as instance structures. - Class members in ancestors are open to the descendant class. So, they can be changed in `tfe_text_view_class_init` function. @@ -253,7 +262,7 @@ tfe_text_view_class_init (TfeTextViewClass *class) { } ~~~ -Each ancestors' class has been generated before TfeTextViewClass is generated. +Each ancestors' class has been created before TfeTextViewClass is created. Therefore, there are four classes and each class has a pointer to each dispose handler. Look at the following diagram. There are four classes -- GObjectClass (GInitiallyUnownedClass), GtkWidgetClass, GtkTextViewClass and TfeTextViewClass. diff --git a/src/tfe4/tfe.c b/src/tfe4/tfe.c index 3fcf76b..4f95b33 100644 --- a/src/tfe4/tfe.c +++ b/src/tfe4/tfe.c @@ -2,12 +2,12 @@ #include "tfetextview.h" static void -on_activate (GApplication *app, gpointer user_data) { +app_activate (GApplication *app, gpointer user_data) { g_print ("You need a filename argument.\n"); } static void -on_open (GApplication *app, GFile ** files, gint n_files, gchar *hint, gpointer user_data) { +app_open (GApplication *app, GFile ** files, gint n_files, gchar *hint, gpointer user_data) { GtkWidget *win; GtkWidget *nb; GtkWidget *lab; @@ -43,11 +43,11 @@ on_open (GApplication *app, GFile ** files, gint n_files, gchar *hint, gpointer nbp = gtk_notebook_get_page (GTK_NOTEBOOK (nb), scr); g_object_set (nbp, "tab-expand", TRUE, NULL); g_free (filename); - } else { - filename = g_file_get_path (files[i]); - g_print ("No such file: %s.\n", filename); - g_free (filename); - } + } else if ((filename = g_file_get_path (files[i])) != NULL) { + g_print ("No such file: %s.\n", filename); + g_free (filename); + } else + g_print ("No valid file is given\n"); } if (gtk_notebook_get_n_pages (GTK_NOTEBOOK (nb)) > 0) { gtk_widget_show (win); @@ -60,9 +60,9 @@ main (int argc, char **argv) { GtkApplication *app; int stat; - app = gtk_application_new ("com.github.ToshioCP.tfe3", G_APPLICATION_HANDLES_OPEN); - g_signal_connect (app, "activate", G_CALLBACK (on_activate), NULL); - g_signal_connect (app, "open", G_CALLBACK (on_open), NULL); + app = gtk_application_new ("com.github.ToshioCP.tfe", G_APPLICATION_HANDLES_OPEN); + g_signal_connect (app, "activate", G_CALLBACK (app_activate), NULL); + g_signal_connect (app, "open", G_CALLBACK (app_open), NULL); stat =g_application_run (G_APPLICATION (app), argc, argv); g_object_unref (app); return stat;