docs: Replace Maman in the tutorial with a more meaningful example

Change it to a running example of a file viewer application with a file
class and various derived classes and related interfaces. Hopefully the
reader can relate to this a little better than to their maman.

https://bugzilla.gnome.org/show_bug.cgi?id=753935
This commit is contained in:
Philip Withnall 2015-10-18 19:34:44 +01:00
parent 419f57137a
commit bf33f1d98d
3 changed files with 547 additions and 432 deletions

View File

@ -55,68 +55,68 @@
<para>
Objects which inherit from GObject are allowed to override this
constructed class method.
The example below shows how <type>MamanBar</type> overrides the parent's construction process:
The example below shows how <type>ViewerFile</type> overrides the parent's construction process:
<informalexample><programlisting>
#define MAMAN_TYPE_BAR maman_bar_get_type ()
G_DECLARE_FINAL_TYPE (MamanBar, maman_bar, MAMAN, BAR, GObject)
#define VIEWER_TYPE_FILE viewer_file_get_type ()
G_DECLARE_FINAL_TYPE (ViewerFile, viewer_file, VIEWER, FILE, GObject)
struct _MamanBar
struct _ViewerFile
{
GObject parent_instance;
/* instance members */
};
/* will create maman_bar_get_type and set maman_bar_parent_class */
G_DEFINE_TYPE (MamanBar, maman_bar, G_TYPE_OBJECT);
/* will create viewer_file_get_type and set viewer_file_parent_class */
G_DEFINE_TYPE (ViewerFile, viewer_file, G_TYPE_OBJECT)
static void
maman_bar_constructed (GObject *obj)
viewer_file_constructed (GObject *obj)
{
/* update the object state depending on constructor properties */
/* Always chain up to the parent constructed function to complete object
* initialisation. */
G_OBJECT_CLASS (maman_bar_parent_class)-&gt;constructed (obj);
G_OBJECT_CLASS (viewer_file_parent_class)-&gt;constructed (obj);
}
static void
maman_bar_class_init (MamanBarClass *klass)
viewer_file_class_init (ViewerFileClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class-&gt;constructed = maman_bar_constructed;
object_class-&gt;constructed = viewer_file_constructed;
}
static void
maman_bar_init (MamanBar *self)
viewer_file_init (ViewerFile *self)
{
/* initialize the object */
}
</programlisting></informalexample>
If the user instantiates an object <type>MamanBar</type> with:
If the user instantiates an object <type>ViewerFile</type> with:
<informalexample><programlisting>
MamanBar *bar = g_object_new (MAMAN_TYPE_BAR, NULL);
ViewerFile *file = g_object_new (VIEWER_TYPE_FILE, NULL);
</programlisting></informalexample>
If this is the first instantiation of such an object, the
<function>maman_bar_class_init</function> function will be invoked
after any <function>maman_bar_base_class_init</function> function.
<function>viewer_file_class_init</function> function will be invoked
after any <function>viewer_file_base_class_init</function> function.
This will make sure the class structure of this new object is
correctly initialized. Here, <function>maman_bar_class_init</function>
correctly initialized. Here, <function>viewer_file_class_init</function>
is expected to override the object's class methods and setup the
class' own methods. In the example above, the constructor method is
the only overridden method: it is set to
<function>maman_bar_constructor</function>.
<function>viewer_file_constructor</function>.
</para>
<para>
Once <function><link linkend="g-object-new">g_object_new</link></function> has obtained a reference to an initialized
class structure, it invokes its constructor method to create an instance of the new
object, if the constructor has been overridden in <function>maman_bar_class_init</function>.
object, if the constructor has been overridden in <function>viewer_file_class_init</function>.
Overridden constructors must chain up to their parents constructor. In
order to find the parent class and chain up to the parent class
constructor, we can use the <literal>maman_bar_parent_class</literal>
constructor, we can use the <literal>viewer_file_parent_class</literal>
pointer that has been set up for us by the
<link linkend="G-DEFINE-TYPE:CAPS"><literal>G_DEFINE_TYPE</literal></link>
macro.
@ -467,32 +467,32 @@ MamanBar *bar = g_object_new (MAMAN_TYPE_BAR, NULL);
enum
{
PROP_MAMAN_NAME = 1,
PROP_PAPA_NUMBER,
PROP_FILENAME = 1,
PROP_ZOOM_LEVEL,
N_PROPERTIES
};
static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
static void
maman_bar_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
viewer_file_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
MamanBar *self = MAMAN_BAR (object);
ViewerFile *self = VIEWER_FILE (object);
switch (property_id)
{
case PROP_MAMAN_NAME:
g_free (self-&gt;priv-&gt;name);
self-&gt;priv-&gt;name = g_value_dup_string (value);
g_print ("maman: %s\n", self-&gt;priv-&gt;name);
case PROP_FILENAME:
g_free (self-&gt;priv-&gt;filename);
self-&gt;priv-&gt;filename = g_value_dup_string (value);
g_print ("filename: %s\n", self-&gt;priv-&gt;filename);
break;
case PROP_PAPA_NUMBER:
self-&gt;priv-&gt;papa_number = g_value_get_uchar (value);
g_print ("papa: &percnt;u\n", self-&gt;priv-&gt;papa_number);
case PROP_ZOOM_LEVEL:
self-&gt;priv-&gt;zoom_level = g_value_get_uint (value);
g_print ("zoom level: &percnt;u\n", self-&gt;priv-&gt;zoom_level);
break;
default:
@ -503,21 +503,21 @@ maman_bar_set_property (GObject *object,
}
static void
maman_bar_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
viewer_file_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
MamanBar *self = MAMAN_BAR (object);
ViewerFile *self = VIEWER_FILE (object);
switch (property_id)
{
case PROP_MAMAN_NAME:
g_value_set_string (value, self-&gt;priv-&gt;name);
case PROP_FILENAME:
g_value_set_string (value, self-&gt;priv-&gt;filename);
break;
case PROP_PAPA_NUMBER:
g_value_set_uchar (value, self-&gt;priv-&gt;papa_number);
case PROP_ZOOM_LEVEL:
g_value_set_uint (value, self-&gt;priv-&gt;zoom_level);
break;
default:
@ -528,28 +528,28 @@ maman_bar_get_property (GObject *object,
}
static void
maman_bar_class_init (MamanBarClass *klass)
viewer_file_class_init (ViewerFileClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class-&gt;set_property = maman_bar_set_property;
object_class-&gt;get_property = maman_bar_get_property;
object_class-&gt;set_property = viewer_file_set_property;
object_class-&gt;get_property = viewer_file_get_property;
obj_properties[PROP_MAMAN_NAME] =
g_param_spec_string ("maman-name",
"Maman construct prop",
"Set maman's name",
"no-name-set" /* default value */,
obj_properties[PROP_FILENAME] =
g_param_spec_string ("filename",
"Filename",
"Name of the file to load and display from.",
NULL /* default value */,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
obj_properties[PROP_PAPA_NUMBER] =
g_param_spec_uchar ("papa-number",
"Number of current Papa",
"Set/Get papa's number",
0 /* minimum value */,
10 /* maximum value */,
2 /* default value */,
G_PARAM_READWRITE));
obj_properties[PROP_ZOOM_LEVEL] =
g_param_spec_uint ("zoom-level",
"Zoom level",
"Zoom level to view the file at.",
0 /* minimum value */,
10 /* maximum value */,
2 /* default value */,
G_PARAM_READWRITE));
g_object_class_install_properties (object_class,
N_PROPERTIES,
@ -560,15 +560,15 @@ maman_bar_class_init (MamanBarClass *klass)
/* Use */
/************************************************/
GObject *bar;
ViewerFile *file;
GValue val = G_VALUE_INIT;
bar = g_object_new (MAMAN_TYPE_BAR, NULL);
file = g_object_new (VIEWER_TYPE_FILE, NULL);
g_value_init (&amp;val, G_TYPE_CHAR);
g_value_init (&amp;val, G_TYPE_UINT);
g_value_set_char (&amp;val, 11);
g_object_set_property (G_OBJECT (bar), "papa-number", &amp;val);
g_object_set_property (G_OBJECT (file), "zoom-level", &amp;val);
g_value_unset (&amp;val);
</programlisting></informalexample>
@ -577,7 +577,7 @@ g_value_unset (&amp;val);
<para>
<function><link linkend="g-object-set-property">g_object_set_property</link></function> first ensures a property
with this name was registered in bar's <function>class_init</function> handler. If so it walks the class hierarchy,
with this name was registered in <emphasis>file</emphasis>'s <function>class_init</function> handler. If so it walks the class hierarchy,
from bottom-most most-derived type, to top-most fundamental type to find the class
which registered that property. It then tries to convert the user-provided
<link linkend="GValue"><type>GValue</type></link>
@ -615,13 +615,13 @@ g_value_unset (&amp;val);
If the user's GValue had been set to a valid value, <function><link linkend="g-object-set-property">g_object_set_property</link></function>
would have proceeded with calling the object's
<function>set_property</function> class method. Here, since our
implementation of <type>Foo</type> did override this method, execution would jump to
<function>foo_set_property</function> after having retrieved from the
implementation of <type>ViewerFile</type> did override this method, execution would jump to
<function>viewer_file_set_property</function> after having retrieved from the
<link linkend="GParamSpec"><type>GParamSpec</type></link> the <emphasis>param_id</emphasis>
<footnote>
<para>
It should be noted that the param_id used here need only to uniquely identify each
<link linkend="GParamSpec"><type>GParamSpec</type></link> within the <type>FooClass</type> such that the switch
<link linkend="GParamSpec"><type>GParamSpec</type></link> within the <type>ViewerFileClass</type> such that the switch
used in the set and get methods actually works. Of course, this locally-unique
integer is purely an optimization: it would have been possible to use a set of
<emphasis>if (strcmp (a, b) == 0) {} else if (strcmp (a, b) == 0) {}</emphasis> statements.
@ -667,11 +667,11 @@ g_value_unset (&amp;val);
<function><link linkend="g-object-set-valist">g_object_set_valist</link></function> (variadic version) functions can be used to set
multiple properties at once. The client code shown above can then be re-written as:
<informalexample><programlisting>
MamanBar *foo;
foo = /* */;
g_object_set (G_OBJECT (foo),
"papa-number", 2,
"maman-name", "test",
ViewerFile *file;
file = /* */;
g_object_set (G_OBJECT (file),
"zoom-level", 6,
"filename", "~/some-file.txt",
NULL);
</programlisting></informalexample>
This saves us from managing the GValues that we were needing to handle when using

View File

@ -154,9 +154,9 @@ static void test_object (void)
GObject *obj;
GValue obj_vala = G_VALUE_INIT;
GValue obj_valb = G_VALUE_INIT;
obj = g_object_new (MAMAN_TYPE_BAR, NULL);
obj = g_object_new (VIEWER_TYPE_FILE, NULL);
g_value_init (&amp;obj_vala, MAMAN_TYPE_BAR);
g_value_init (&amp;obj_vala, VIEWER_TYPE_FILE);
g_value_set_object (&amp;obj_vala, obj);
g_value_init (&amp;obj_valb, G_TYPE_OBJECT);
@ -164,7 +164,7 @@ static void test_object (void)
/* g_value_copy's semantics for G_TYPE_OBJECT types is to copy the reference.
* This function thus calls g_object_ref.
* It is interesting to note that the assignment works here because
* MAMAN_TYPE_BAR is a G_TYPE_OBJECT.
* VIEWER_TYPE_FILE is a G_TYPE_OBJECT.
*/
g_value_copy (&amp;obj_vala, &amp;obj_valb);
@ -206,27 +206,20 @@ static void test_object (void)
</para></listitem>
<listitem><para>
Use the <function>object_method</function> pattern for function names: to invoke
the method named foo on an instance of object type bar, call
<function>bar_foo</function>.
the method named <function>save</function> on an instance of object type <type>file</type>, call
<function>file_save</function>.
</para></listitem>
<listitem><para>Use prefixing to avoid namespace conflicts with other projects.
If your library (or application) is named <emphasis>Maman</emphasis>,
<footnote>
<para>
<emphasis>Maman</emphasis> is the French word for <emphasis>mum</emphasis>
or <emphasis>mother</emphasis> — nothing more and nothing less.
</para>
</footnote>
prefix all your function names with <emphasis>maman_</emphasis>.
For example: <function>maman_object_method</function>.
If your library (or application) is named <emphasis>Viewer</emphasis>,
prefix all your function names with <emphasis>viewer_</emphasis>.
For example: <function>viewer_object_method</function>.
</para></listitem>
<listitem><para>Create a macro named <function>PREFIX_TYPE_OBJECT</function> which always
returns the GType for the associated object type. For an object of type
<emphasis>Bar</emphasis> in a library prefixed by <emphasis>maman</emphasis>,
use: <function>MAMAN_TYPE_BAR</function>.
<emphasis>File</emphasis> in the <emphasis>Viewer</emphasis> namespace,
use: <function>VIEWER_TYPE_FILE</function>.
This macro is implemented using a function named
<function>prefix_object_get_type</function>.
<function>prefix_object_get_type</function>; for example, <function>viewer_file_get_type</function>.
</para></listitem>
<listitem>
<para>
@ -241,25 +234,28 @@ static void test_object (void)
dynamic type safety by doing runtime checks. It is possible to disable the dynamic
type checks in production builds (see <link linkend="glib-building">building GLib</link>).
For example, we would create
<function>MAMAN_BAR (obj)</function> to keep the previous example.
<function>VIEWER_FILE (obj)</function> to keep the previous example.
</para></listitem>
<listitem><para><function>PREFIX_OBJECT_CLASS (klass)</function>, which
is strictly equivalent to the previous casting macro: it does static casting with
dynamic type checking of class structures. It is expected to return a pointer
to a class structure of type <type>PrefixObjectClass</type>. An example is:
<function>MAMAN_BAR_CLASS</function>.
<function>VIEWER_FILE_CLASS</function>.
</para></listitem>
<listitem><para><function>PREFIX_IS_BAR (obj)</function>, which
<listitem><para><function>PREFIX_IS_OBJECT (obj)</function>, which
returns a <type>gboolean</type> which indicates whether the input
object instance pointer is non-<type>NULL</type> and of type BAR.
object instance pointer is non-<type>NULL</type> and of type <type>OBJECT</type>.
For example, <function>VIEWER_IS_FILE</function>.
</para></listitem>
<listitem><para><function>PREFIX_IS_OBJECT_CLASS (klass)</function>, which returns a boolean
if the input class pointer is a pointer to a class of type OBJECT.
For example, <function>VIEWER_IS_FILE_CLASS</function>.
</para></listitem>
<listitem><para><function>PREFIX_OBJECT_GET_CLASS (obj)</function>,
which returns the class pointer associated to an instance of a given type. This macro
is used for static and dynamic type safety purposes (just like the previous casting
macros).
For example, <function>VIEWER_FILE_GET_CLASS</function>.
</para></listitem>
</itemizedlist>
</listitem>
@ -268,8 +264,8 @@ static void test_object (void)
macros are provided in <filename>gtype.h</filename>. For the example we used above, we would
write the following trivial code to declare the macros:
<informalexample><programlisting>
#define MAMAN_TYPE_BAR maman_bar_get_type ()
G_DECLARE_FINAL_TYPE (MamanBar, maman_bar, MAMAN, BAR, GObject)
#define VIEWER_TYPE_FILE viewer_file_get_type ()
G_DECLARE_FINAL_TYPE (ViewerFile, viewer_file, VIEWER, FILE, GObject)
</programlisting></informalexample>
</para>
@ -278,15 +274,15 @@ G_DECLARE_FINAL_TYPE (MamanBar, maman_bar, MAMAN, BAR, GObject)
<function><link linkend="G-DEFINE-TYPE:CAPS">G_DEFINE_TYPE</link></function>
macro to define a class:
<informalexample><programlisting>
G_DEFINE_TYPE (MamanBar, maman_bar, G_TYPE_OBJECT)
G_DEFINE_TYPE (ViewerFile, viewer_file, G_TYPE_OBJECT)
</programlisting></informalexample>
</para>
<para>
Otherwise, the <function>maman_bar_get_type</function> function must be
Otherwise, the <function>viewer_file_get_type</function> function must be
implemented manually:
<informalexample><programlisting>
GType maman_bar_get_type (void)
GType viewer_file_get_type (void)
{
static GType type = 0;
if (type == 0) {
@ -294,7 +290,7 @@ GType maman_bar_get_type (void)
/* You fill this structure. */
};
type = g_type_register_static (G_TYPE_OBJECT,
"MamanBarType",
"ViewerFile",
&amp;info, 0);
}
return type;
@ -384,45 +380,51 @@ GType maman_bar_get_type (void)
<informalexample><programlisting>
typedef struct {
GObject parent;
/* instance members */
int field_a;
} MamanBar;
gchar *filename;
} ViewerFile;
typedef struct {
GObjectClass parent;
/* class members */
void (*do_action_public_virtual) (MamanBar *self, guint8 i);
/* the first is public, pure and virtual */
void (*open) (ViewerFile *self,
GError **error);
void (*do_action_public_pure_virtual) (MamanBar *self, guint8 i);
} MamanBarClass;
/* the second is public and virtual */
void (*close) (ViewerFile *self,
GError **error);
} ViewerFileClass;
#define MAMAN_TYPE_BAR (maman_bar_get_type ())
#define VIEWER_TYPE_FILE (viewer_file_get_type ())
GType
maman_bar_get_type (void)
viewer_file_get_type (void)
{
static GType type = 0;
if (type == 0) {
const GTypeInfo info = {
sizeof (MamanBarClass),
sizeof (ViewerFileClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) foo_class_init,
(GClassInitFunc) viewer_file_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (MamanBar),
sizeof (ViewerFile),
0, /* n_preallocs */
(GInstanceInitFunc) NULL /* instance_init */
};
type = g_type_register_static (G_TYPE_OBJECT,
"BarType",
"ViewerFile",
&amp;info, 0);
}
return type;
}
</programlisting></informalexample>
Upon the first call to <function>maman_bar_get_type</function>, the type named
<emphasis>BarType</emphasis> will be registered in the type system as inheriting
Upon the first call to <function>viewer_file_get_type</function>, the type named
<emphasis>ViewerFile</emphasis> will be registered in the type system as inheriting
from the type <emphasis>G_TYPE_OBJECT</emphasis>.
</para>
@ -650,28 +652,37 @@ B *b;
classed type which derives from
<link linkend="GTypeInterface"><type>GTypeInterface</type></link>. The following piece of code declares such an interface.
<informalexample><programlisting>
#define MAMAN_TYPE_IBAZ maman_ibaz_get_type ()
G_DECLARE_INTERFACE(MamanIbaz, maman_ibaz, MAMAN, IBAZ, GObject)
#define VIEWER_TYPE_EDITABLE viewer_editable_get_type ()
G_DECLARE_INTERFACE (ViewerEditable, viewer_editable, VIEWER, EDITABLE, GObject)
struct _MamanIbazInterface {
struct _ViewerEditableInterface {
GTypeInterface parent;
void (*do_action) (MamanIbaz *self);
void (*save) (ViewerEditable *self,
GError **error);
};
void maman_ibaz_do_action (MamanIbaz *self);
void viewer_editable_save (ViewerEditable *self,
GError **error);
</programlisting></informalexample>
The interface function, <function>maman_ibaz_do_action</function> is implemented
The interface function, <function>viewer_editable_save</function> is implemented
in a pretty simple way:
<informalexample><programlisting>
void maman_ibaz_do_action (MamanIbaz *self)
void
viewer_editable_save (ViewerEditable *self,
GError **error)
{
g_return_if_fail (MAMAN_IS_IBAZ (self));
ViewerEditableinterface *iface;
MAMAN_IBAZ_GET_INTERFACE (self)->do_action (self);
g_return_if_fail (VIEWER_IS_EDITABLE (self));
g_return_if_fail (error == NULL || *error == NULL);
iface = VIEWER_EDITABLE_GET_INTERFACE (self);
g_return_if_fail (iface->save != NULL);
iface->save (self);
}
</programlisting></informalexample>
<function>maman_ibaz_get_type</function> registers a type named <emphasis>MamanIbaz</emphasis>
<function>viewer_editable_get_type</function> registers a type named <emphasis>ViewerEditable</emphasis>
which inherits from <type>G_TYPE_INTERFACE</type>. All interfaces must
be children of <type>G_TYPE_INTERFACE</type> in the inheritance tree.
</para>
@ -681,7 +692,7 @@ void maman_ibaz_do_action (MamanIbaz *self)
a <link linkend="GTypeInterface"><type>GTypeInterface</type></link> structure. The interface structure is expected to
contain the function pointers of the interface methods. It is good style to
define helper functions for each of the interface methods which simply call
the interface's method directly: <function>maman_ibaz_do_action</function>
the interface's method directly: <function>viewer_editable_save</function>
is one of these.
</para>
@ -691,20 +702,20 @@ void maman_ibaz_do_action (MamanIbaz *self)
to implement an interface:
<informalexample><programlisting>
static void
maman_baz_do_action (MamanIbaz *self)
viewer_file_save (ViewerEditable *self)
{
g_print ("Baz implementation of Ibaz interface Action.\n");
g_print ("File implementation of editable interface save method.\n");
}
static void
maman_ibaz_interface_init (MamanIbazInterface *iface)
viewer_file_editable_interface_init (ViewerEditableInterface *iface)
{
iface->do_action = maman_baz_do_action;
iface->save = viewer_file_save;
}
G_DEFINE_TYPE_WITH_CODE (MamanBaz, maman_baz, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (MAMAN_TYPE_IBAZ,
maman_ibaz_interface_init));
G_DEFINE_TYPE_WITH_CODE (ViewerFile, viewer_file, VIEWER_TYPE_FILE,
G_IMPLEMENT_INTERFACE (VIEWER_TYPE_EDITABLE,
viewer_file_editable_interface_init));
</programlisting></informalexample>
</para>
@ -712,51 +723,52 @@ G_DEFINE_TYPE_WITH_CODE (MamanBaz, maman_baz, G_TYPE_OBJECT,
If your code does have special requirements, you must write a custom
<function>get_type</function> function to register your GType which
inherits from some <link linkend="GObject"><type>GObject</type></link>
and which implements the interface <type>MamanIbaz</type>. For
example, this code registers a new <type>MamanBaz</type> class which
implements <type>MamanIbaz</type>:
and which implements the interface <type>ViewerEditable</type>. For
example, this code registers a new <type>ViewerFile</type> class which
implements <type>ViewerEditable</type>:
<informalexample><programlisting>
static void
maman_baz_do_action (MamanIbaz *self)
viewer_file_save (ViewerEditable *editable)
{
g_print ("Baz implementation of Ibaz interface Action.\n");
g_print ("File implementation of editable interface save method.\n");
}
static void
baz_interface_init (gpointer g_iface,
gpointer iface_data)
viewer_file_editable_interface_init (gpointer g_iface,
gpointer iface_data)
{
MamanIbazInterface *iface = (MamanIbazInterface *)g_iface;
iface->do_action = maman_baz_do_action;
ViewerEditableInterface *iface = g_iface;
iface->save = viewer_file_save;
}
GType
maman_baz_get_type (void)
viewer_file_get_type (void)
{
static GType type = 0;
if (type == 0) {
const GTypeInfo info = {
sizeof (MamanBazClass),
sizeof (ViewerFileClass),
NULL, /* base_init */
NULL, /* base_finalize */
NULL, /* class_init */
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (MamanBaz),
sizeof (ViewerFile),
0, /* n_preallocs */
NULL /* instance_init */
};
const GInterfaceInfo ibaz_info = {
(GInterfaceInitFunc) baz_interface_init, /* interface_init */
NULL, /* interface_finalize */
NULL /* interface_data */
const GInterfaceInfo editable_info = {
(GInterfaceInitFunc) viewer_file_editable_interface_init, /* interface_init */
NULL, /* interface_finalize */
NULL /* interface_data */
};
type = g_type_register_static (G_TYPE_OBJECT,
"MamanBazType",
type = g_type_register_static (VIEWER_TYPE_FILE,
"ViewerFile",
&amp;info, 0);
g_type_add_interface_static (type,
MAMAN_TYPE_IBAZ,
&amp;ibaz_info);
VIEWER_TYPE_EDITABLE,
&amp;editable_info);
}
return type;
}
@ -824,12 +836,12 @@ struct _GInterfaceInfo
<link linkend="G-DEFINE-INTERFACE:CAPS">G_DEFINE_INTERFACE</link>
which can be used to define the interface:
<informalexample><programlisting>
G_DEFINE_INTERFACE (MamanIbaz, maman_ibaz, G_TYPE_OBJECT);
G_DEFINE_INTERFACE (ViewerEditable, viewer_editable, G_TYPE_OBJECT);
static void
maman_ibaz_default_init (MamanIbazInterface *iface)
viewer_editable_default_init (ViewerEditableInterface *iface)
{
/* add properties and signals here, will only called once */
/* add properties and signals here, will only be called once */
}
</programlisting></informalexample>
</para>
@ -838,15 +850,15 @@ maman_ibaz_default_init (MamanIbazInterface *iface)
Or you can do that yourself in a GType function for your interface:
<informalexample><programlisting>
GType
maman_ibaz_get_type (void)
viewer_editable_get_type (void)
{
static volatile gsize type_id = 0;
if (g_once_init_enter (&amp;type_id)) {
const GTypeInfo info = {
sizeof (MamanIbazInterface),
sizeof (ViewerEditableInterface),
NULL, /* base_init */
NULL, /* base_finalize */
maman_ibaz_default_init, /* class_init */
viewer_editable_default_init, /* class_init */
NULL, /* class_finalize */
NULL, /* class_data */
0, /* instance_size */
@ -854,15 +866,15 @@ maman_ibaz_get_type (void)
NULL /* instance_init */
};
GType type = g_type_register_static (G_TYPE_INTERFACE,
"MamanIbaz",
&amp;info, 0);
"ViewerEditable",
&amp;info, 0);
g_once_init_leave (&amp;type_id, type);
}
return type_id;
}
static void
maman_ibaz_default_init (MamanIbazInterface *iface)
viewer_editable_default_init (ViewerEditableInterface *iface)
{
/* add properties and signals here, will only called once */
}

File diff suppressed because it is too large Load Diff