docs: Various wording changes in the GObject how-to

• Consistently make all titles sentence case
 • Fix various typos
 • Remove an unnecessary footnote
 • Remove first person phrasing

https://bugzilla.gnome.org/show_bug.cgi?id=744060
This commit is contained in:
Philip Withnall 2015-02-20 13:04:45 +00:00
parent f1287a9b2f
commit 2e4700d52b

View File

@ -16,11 +16,8 @@
<title>How to define and implement a new GObject</title> <title>How to define and implement a new GObject</title>
<para> <para>
Clearly, this is one of the most common questions people ask: they just This chapter focuses on the implementation of a subtype of GObject, for
want to crank code and implement a subclass of a GObject. Sometimes because example to create a custom class hierarchy, or to subclass a GTK+ widget.
they want to create their own class hierarchy, sometimes because they want
to subclass one of GTK+'s widget. This chapter will focus on the
implementation of a subtype of GObject.
</para> </para>
<sect1 id="howto-gobject-header"> <sect1 id="howto-gobject-header">
@ -261,7 +258,7 @@ G_DEFINE_TYPE_WITH_PRIVATE (MamanBar, maman_bar, G_TYPE_OBJECT)
</sect1> </sect1>
<sect1 id="howto-gobject-construction"> <sect1 id="howto-gobject-construction">
<title>Object Construction</title> <title>Object construction</title>
<para> <para>
People often get confused when trying to construct their GObjects because of the People often get confused when trying to construct their GObjects because of the
@ -296,7 +293,7 @@ G_DEFINE_TYPE_WITH_PRIVATE (MamanBar, maman_bar, G_TYPE_OBJECT)
</para> </para>
<para> <para>
As such, I would recommend writing the following code first: You should write the following code first:
<informalexample><programlisting> <informalexample><programlisting>
G_DEFINE_TYPE_WITH_PRIVATE (MamanBar, maman_bar, G_TYPE_OBJECT) G_DEFINE_TYPE_WITH_PRIVATE (MamanBar, maman_bar, G_TYPE_OBJECT)
@ -365,10 +362,10 @@ bar_class_init (MamanBarClass *klass)
of a type only after the properties passed to the constructors have been of a type only after the properties passed to the constructors have been
set. This is possible through the use of the <function>constructor()</function> set. This is possible through the use of the <function>constructor()</function>
class method as described in <xref linkend="gobject-instantiation"/> or, class method as described in <xref linkend="gobject-instantiation"/> or,
more simply, using the <function>constructed()</function> class method more simply, using the <function>constructed()</function> class method.
available since GLib 2.12. Note that the <function>constructed()</function> Note that the <function>constructed()</function>
virtual function will only be invoked after the properties marked as virtual function will only be invoked after the properties marked as
<function>G_PARAM_CONSTRUCT_ONLY</function>s or <function>G_PARAM_CONSTRUCT_ONLY</function> or
<function>G_PARAM_CONSTRUCT</function> have been consumed, but <function>G_PARAM_CONSTRUCT</function> have been consumed, but
before the regular properties passed to <function>g_object_new()</function> before the regular properties passed to <function>g_object_new()</function>
have been set. have been set.
@ -376,7 +373,7 @@ bar_class_init (MamanBarClass *klass)
</sect1> </sect1>
<sect1 id="howto-gobject-destruction"> <sect1 id="howto-gobject-destruction">
<title>Object Destruction</title> <title>Object destruction</title>
<para> <para>
Again, it is often difficult to figure out which mechanism to use to Again, it is often difficult to figure out which mechanism to use to
@ -387,11 +384,12 @@ bar_class_init (MamanBarClass *klass)
</para> </para>
<para> <para>
The destruction process of your object might be split in two different The destruction process of your object is in two phases: dispose and
phases: dispose and the finalize. This split is necessary to handle finalize. This split is necessary to handle
potential cycles due to the nature of the reference counting mechanism potential cycles due to the nature of the reference counting mechanism
used by GObject, as well as dealing with temporary vivification of used by GObject, as well as dealing with temporary revival of
instances in case of signal emission during the destruction sequence. instances in case of signal emission during the destruction sequence.
See <xref linkend="gobject-memory-cycles"/> for more information.
<informalexample><programlisting> <informalexample><programlisting>
struct _MamanBarPrivate struct _MamanBarPrivate
{ {
@ -463,7 +461,7 @@ maman_bar_init (MamanBar *self);
It is possible that object methods might be invoked after dispose is It is possible that object methods might be invoked after dispose is
run and before finalize runs. GObject does not consider this to be a run and before finalize runs. GObject does not consider this to be a
program error: you must gracefully detect this and neither crash nor program error: you must gracefully detect this and neither crash nor
warn the user, by having a disposed instance revert to an inhert state. warn the user, by having a disposed instance revert to an inert state.
</para> </para>
</sect1> </sect1>
@ -494,8 +492,8 @@ maman_bar_init (MamanBar *self);
<title>Non-virtual public methods</title> <title>Non-virtual public methods</title>
<para> <para>
These are the simplest: you want to provide a simple method which These are the simplest, providing a simple method which
can act on your object. All you need to do is to provide a function acts on the object. Provide a function
prototype in the header and an implementation of that prototype prototype in the header and an implementation of that prototype
in the source file. in the source file.
<informalexample><programlisting> <informalexample><programlisting>
@ -572,7 +570,7 @@ maman_bar_do_action (MamanBar *self, /* parameters */)
</para> </para>
<para> <para>
Please, note that it is possible for you to provide a default It is possible to provide a default
implementation for this class method in the object's implementation for this class method in the object's
<function>class_init</function> function: initialize the <function>class_init</function> function: initialize the
<function>klass-&gt;do_action</function> field to a pointer to the <function>klass-&gt;do_action</function> field to a pointer to the
@ -716,17 +714,19 @@ maman_bar_subtype_class_init (MamanBarSubTypeClass *klass)
<listitem><para>Parent class A defines a public virtual method named <function>foo</function> and <listitem><para>Parent class A defines a public virtual method named <function>foo</function> and
provides a default implementation.</para></listitem> provides a default implementation.</para></listitem>
<listitem><para>Child class B re-implements method <function>foo</function>.</para></listitem> <listitem><para>Child class B re-implements method <function>foo</function>.</para></listitem>
<listitem><para>In the method B::foo, the child class B calls its parent class method A::foo.</para></listitem> <listitem><para>Bs implementation of <function>foo</function> calls (chains up to) its parent class As implementation of <function>foo</function>.</para></listitem>
</itemizedlist> </itemizedlist>
There are various uses to this idiom: There are various uses of this idiom:
<itemizedlist> <itemizedlist>
<listitem><para>You need to extend the behaviour of a class without modifying its code. You create <listitem><para>You need to extend the behaviour of a class without modifying its code. You create
a subclass to inherit its implementation, re-implement a public virtual method to modify the behaviour a subclass to inherit its implementation, re-implement a public virtual method to modify the behaviour
and chain up to ensure that the previous behaviour is not really modified, just extended. and chain up to ensure that the previous behaviour is not really modified, just extended.
</para></listitem> </para></listitem>
<listitem><para>You need to implement the Chain Of Responsibility pattern: each object of the inheritance <listitem><para>You need to implement the
<ulink url="http://en.wikipedia.org/wiki/Chain-of-responsibility_pattern">Chain
Of Responsibility pattern</ulink>: each object of the inheritance
tree chains up to its parent (typically, at the beginning or the end of the method) to ensure that tree chains up to its parent (typically, at the beginning or the end of the method) to ensure that
they each handler is run in turn.</para></listitem> each handler is run in turn.</para></listitem>
</itemizedlist> </itemizedlist>
</para> </para>
@ -737,24 +737,22 @@ maman_bar_subtype_class_init (MamanBarSubTypeClass *klass)
<footnote> <footnote>
<para> <para>
The <emphasis>original</emphasis> adjective used in this sentence is not innocuous. To fully The <emphasis>original</emphasis> adjective used in this sentence is not innocuous. To fully
understand its meaning, you need to recall how class structures are initialized: for each object type, understand its meaning, recall how class structures are initialized: for each object type,
the class structure associated to this object is created by first copying the class structure of its the class structure associated with this object is created by first copying the class structure of its
parent type (a simple <function>memcpy</function>) and then by invoking the class_init callback on parent type (a simple <function>memcpy</function>) and then by invoking the <function>class_init</function> callback on
the resulting class structure. Since the class_init callback is responsible for overwriting the class structure the resulting class structure. Since the <function>class_init</function> callback is responsible for overwriting the class structure
with the user re-implementations of the class methods, we cannot merely use the modified copy of the parent class with the user re-implementations of the class methods, the modified copy of the parent class
structure stored in our derived instance. We want to get a copy of the class structure of an instance of the parent structure stored in the derived instance cannot be used. A copy of the class structure of an instance of the parent
class. class is needed.
</para> </para>
</footnote> </footnote>
</para> </para>
<para>The function <function><link linkend="g-type-class-peek-parent">g_type_class_peek_parent</link></function> <para>
is used to access the original parent class structure. Its input is a Use the <function>parent_class</function> pointer created and initialized
pointer to the class of the derived object and it returns a pointer to by the
the original parent class structure. Instead of using this function <link linkend="G-DEFINE-TYPE:CAPS"><function>G_DEFINE_TYPE</function></link>
directly, though, use the <function>parent_class</function> family of macros, for instance:
pointer created and initialized by the <function>G_DEFINE_TYPE_*</function> family of
macros, for instance:
<informalexample><programlisting> <informalexample><programlisting>
static void static void
b_method_to_call (B *obj, int a) b_method_to_call (B *obj, int a)
@ -785,12 +783,13 @@ b_method_to_call (B *obj, int a)
<title>Defining interfaces</title> <title>Defining interfaces</title>
<para> <para>
The bulk of interface definition has already been shown in <xref linkend="gtype-non-instantiable-classed"/> The theory behind how GObject interfaces work is given in
but I feel it is needed to show exactly how to create an interface. <xref linkend="gtype-non-instantiable-classed"/>; this section covers how to
define and implement an interface.
</para> </para>
<para> <para>
As above, the first step is to get the header right. This interface The first step is to get the header right. This interface
defines two methods: defines two methods:
<informalexample><programlisting> <informalexample><programlisting>
#ifndef __MAMAN_IBAZ_H__ #ifndef __MAMAN_IBAZ_H__
@ -896,56 +895,18 @@ maman_ibaz_do_something (MamanIbaz *self)
</para> </para>
<para> <para>
The first step is to define a normal GObject class, like: The first step is to define a normal final GObject class exactly as in
<informalexample><programlisting> <xref linkend="howto-gobject-header"/>.
#ifndef __MAMAN_BAZ_H__
#define __MAMAN_BAZ_H__
#include &lt;glib-object.h&gt;
#define MAMAN_TYPE_BAZ (maman_baz_get_type ())
#define MAMAN_BAZ(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MAMAN_TYPE_BAZ, Mamanbaz))
#define MAMAN_IS_BAZ(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MAMAN_TYPE_BAZ))
#define MAMAN_BAZ_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MAMAN_TYPE_BAZ, MamanbazClass))
#define MAMAN_IS_BAZ_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MAMAN_TYPE_BAZ))
#define MAMAN_BAZ_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MAMAN_TYPE_BAZ, MamanbazClass))
typedef struct _MamanBaz MamanBaz;
typedef struct _MamanBazClass MamanBazClass;
struct _MamanBaz
{
GObject parent_instance;
gint instance_member;
};
struct _MamanBazClass
{
GObjectClass parent_class;
};
GType maman_baz_get_type (void);
#endif /* __MAMAN_BAZ_H__ */
</programlisting></informalexample>
<!-- Ha ha! "nothing weird or scary". I actually laughed out loud. Oh boy.
The fact that we're so intimate with GObject that all this doesn't look
wierd, that's the scary thing. :) -->
There is clearly nothing specifically weird or scary about this header:
it does not define any weird API or derive from a weird type.
</para> </para>
<para> <para>
The second step is to implement <type>MamanBaz</type> by defining The second step is to implement <type>MamanBaz</type> by defining
its <type>GType</type>. Instead of using it using
<function><link linkend="G-DEFINE-TYPE:CAPS">G_DEFINE_TYPE</link></function>,
use
<function><link linkend="G-DEFINE-TYPE-WITH-CODE:CAPS">G_DEFINE_TYPE_WITH_CODE</link></function> <function><link linkend="G-DEFINE-TYPE-WITH-CODE:CAPS">G_DEFINE_TYPE_WITH_CODE</link></function>
and the and
<function><link linkend="G-IMPLEMENT-INTERFACE:CAPS">G_IMPLEMENT_INTERFACE</link></function> <function><link linkend="G-IMPLEMENT-INTERFACE:CAPS">G_IMPLEMENT_INTERFACE</link></function>
macros. instead of
<function><link linkend="G-DEFINE-TYPE:CAPS">G_DEFINE_TYPE</link></function>:
<informalexample><programlisting> <informalexample><programlisting>
static void maman_ibaz_interface_init (MamanIbazInterface *iface); static void maman_ibaz_interface_init (MamanIbazInterface *iface);
@ -953,8 +914,8 @@ G_DEFINE_TYPE_WITH_CODE (MamanBar, maman_bar, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (MAMAN_TYPE_IBAZ, G_IMPLEMENT_INTERFACE (MAMAN_TYPE_IBAZ,
maman_ibaz_interface_init)) maman_ibaz_interface_init))
</programlisting></informalexample> </programlisting></informalexample>
This definition is very much like all the similar functions we looked This definition is very much like all the similar functions seen
at previously. The only interface-specific code present here is the call to previously. The only interface-specific code present here is the use of
<function><link linkend="G-IMPLEMENT-INTERFACE:CAPS">G_IMPLEMENT_INTERFACE</link></function>. <function><link linkend="G-IMPLEMENT-INTERFACE:CAPS">G_IMPLEMENT_INTERFACE</link></function>.
</para> </para>
@ -1111,14 +1072,9 @@ G_DEFINE_TYPE_WITH_CODE (MamanBar, maman_bar, G_TYPE_OBJECT,
<para> <para>
To include a property named 'name' of type <type>string</type> in the To include a property named 'name' of type <type>string</type> in the
<type>maman_ibaz</type> interface example code above, we only need to <type>MamanIbaz</type> interface example code above, we only need to
add one add one call in <function>maman_ibaz_default_init</function> as shown
<footnote> below:
<para>
That really is one line extended to six for the sake of clarity
</para>
</footnote>
line in the <function>maman_ibaz_default_init</function> as shown below:
<informalexample><programlisting> <informalexample><programlisting>
static void static void
maman_ibaz_default_init (MamanIbazInteface *iface) maman_ibaz_default_init (MamanIbazInteface *iface)
@ -1136,9 +1092,10 @@ maman_ibaz_default_init (MamanIbazInteface *iface)
<para> <para>
One point worth noting is that the declared property wasn't assigned an One point worth noting is that the declared property wasn't assigned an
integer ID. The reason being that integer IDs of properties are used integer ID. The reason being that integer IDs of properties are used
only inside the get and set methods and since interfaces do not only inside the <function>get_property</function> and
implement properties, there is no need to assign integer IDs to <function>set_property</function> virtual methods. Since interfaces
interface properties. declare but do not <emphasis>implement</emphasis> properties, there is no
need to assign integer IDs to them.
</para> </para>
<para> <para>
@ -1226,10 +1183,10 @@ maman_baz_class_init (MamanBazClass *klass)
<title>Overriding interface methods</title> <title>Overriding interface methods</title>
<para> <para>
If a base class already implements an interface, and in a derived If a base class already implements an interface and a derived
class you wish to implement the same interface overriding only certain class needs to implement the same interface but needs to override certain
methods of that interface, you just reimplement the interface and methods, you must reimplement the interface and set only the interface
set only the interface methods you wish to override. methods which need overriding.
</para> </para>
<para> <para>
@ -1283,9 +1240,9 @@ maman_derived_baz_init (MamanDerivedBaz *self)
</para> </para>
<para> <para>
If you wish to call the base class implementation of an interface To call the base class implementation of an interface
method from an derived class where than interface method has been method from an derived class where than interface method has been
overridden then you can stash away the pointer returned from overridden, stash away the pointer returned from
<function><link linkend="g-type-interface-peek-parent">g_type_interface_peek_parent</link></function> <function><link linkend="g-type-interface-peek-parent">g_type_interface_peek_parent</link></function>
in a global variable. in a global variable.
</para> </para>
@ -1339,7 +1296,7 @@ maman_derived_baz_init (MamanDerivedBaz *self)
<title>How to create and use signals</title> <title>How to create and use signals</title>
<para> <para>
The signal system which was built in GType is pretty complex and The signal system in GType is pretty complex and
flexible: it is possible for its users to connect at runtime any flexible: it is possible for its users to connect at runtime any
number of callbacks (implemented in any language for which a binding number of callbacks (implemented in any language for which a binding
exists) exists)
@ -1350,24 +1307,24 @@ maman_derived_baz_init (MamanDerivedBaz *self)
</footnote> </footnote>
to any signal and to stop the emission of any signal at any to any signal and to stop the emission of any signal at any
state of the signal emission process. This flexibility makes it state of the signal emission process. This flexibility makes it
possible to use GSignal for much more than just emit signals which possible to use GSignal for much more than just emitting signals to
can be received by numerous clients. multiple clients.
</para> </para>
<sect1 id="howto-simple-signals"> <sect1 id="howto-simple-signals">
<title>Simple use of signals</title> <title>Simple use of signals</title>
<para> <para>
The most basic use of signals is to implement simple event The most basic use of signals is to implement event
notification: for example, if we have a MamanFile object, and notification. For example, given a <type>MamanFile</type> object with
if this object has a write method, we might wish to be notified a <function>write</function> method, a signal could be emitted whenever
whenever someone has changed something via our MamanFile instance. the file is changed using that method.
The code below shows how the user can connect a callback to the The code below shows how the user can connect a callback to the
"changed" signal. "changed" signal.
<informalexample><programlisting> <informalexample><programlisting>
file = g_object_new (MAMAN_FILE_TYPE, NULL); file = g_object_new (MAMAN_FILE_TYPE, NULL);
g_signal_connect (file, "changed", G_CALLBACK (changed_event), NULL); g_signal_connect (file, "changed", (GCallback) changed_event, NULL);
maman_file_write (file, buffer, strlen (buffer)); maman_file_write (file, buffer, strlen (buffer));
</programlisting></informalexample> </programlisting></informalexample>
@ -1396,32 +1353,26 @@ maman_file_write (MamanFile *self,
const guchar *buffer, const guchar *buffer,
gssize size) gssize size)
{ {
g_return_if_fail (MAMAN_IS_FILE (self));
g_return_if_fail (buffer != NULL || size == 0);
/* First write data. */ /* First write data. */
/* Then, notify user of data written. */ /* Then, notify user of data written. */
g_signal_emit (self, file_signals[CHANGED], 0 /* details */); g_signal_emit (self, file_signals[CHANGED], 0 /* details */);
} }
</programlisting></informalexample> </programlisting></informalexample>
As shown above, you can safely set the details parameter to zero if As shown above, the details parameter can safely be set to zero if no
you do not know what it can be used for. For a discussion of what you detail needs to be conveyed. For a discussion of what it can be used for,
could used it for, see <xref linkend="signal-detail"/> see <xref linkend="signal-detail"/>
</para> </para>
<para> <para>
The signature of the signal handler in the above example is defined as The C signal marshaller should always be
<function>g_cclosure_marshal_VOID__VOID</function>. Its name follows <function>g_cclosure_marshal_generic</function>, which implements generic
a simple convention which encodes the function parameter and return value conversion of arrays of parameters to C callback invocations. GLib used to
types in the function name. Specifically, the value in front of the use type-specific generated marshallers, but that has been deprecated in
double underscore is the type of the return value, while the value(s) favour of the generic marshaller.
after the double underscore denote the parameter types.
</para>
<para>
The header <filename>gobject/gmarshal.h</filename> defines a set of
commonly needed closures that one can use. If you want to have complex
marshallers for your signals you should probably use glib-genmarshal
to autogenerate them from a file containing their return and
parameter types.
</para> </para>
</sect1> </sect1>
</chapter> </chapter>