Composite GtkBuilder template
- From: Tristan Van Berkom <tristanvb openismus com>
- To: gtk-devel-list gnome org
- Subject: Composite GtkBuilder template
- Date: Tue, 02 Apr 2013 17:59:16 +0900
I meant to address the list by the end of last week but
some issues cropped proving that the work was not yet finished.
I have been working closely with Benjamin, refining the API
and discussing some of the finer points. This has been a
huge effort that ate up my last two weeks full time work.
The work can be viewed here:
https://git.gnome.org/browse/gtk+/log/?h=composite-templates-new
And while it's a huge list of changes, any thorough peer reviews
would be greatly appreciated of course.
A version of Glade which can be used with this branch can
be built from:
https://git.gnome.org/browse/glade/log/?h=composite-templates-new
Since it's nice and early in the 3.10 cycle, I would like
to finally land this by the end of this week if there are
no objections (I say finally, because I prototyped this years
ago but never got around to really cleaning it up until now).
So here below follows my detailed report.
Cheers,
-Tristan
What is Composite Templates ?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This feature is an association of GtkWidget class data
with GtkBuilder xml.
It allows automation of the creation of composite widgets
without directly accessing the GtkBuilder APIs and comes
with a few features that help to bind a GtkWidget with
it's GtkBuilder xml.
What has been done ?
~~~~~~~~~~~~~~~~~~~~
o The implementation of the API, of course
o A total of 23 composite widgets in GTK+ have been
ported to use GtkBuilder xml to define their content.
The actual xml data is stored in GTK+'s global resources
in a compressed format.
Each widget migration has it's own individual commit
on the branch, which should give any observer a clear
picture of what a migrated composite widget looks like.
o A catalog file for Glade was added to the gtk+/gtk/glade
directory.
This catalog is not meant to be installed, but rather
it gives GTK+ developers access to GTK+'s private
widget classes so that, for instance, a GtkColorSwatch
can be added to a GtkColorEditor, or a GtkPathBar
to a GtkFileChooserDefault interface description.
When running Glade with this custom catalog, a new
section with "GTK+ Private Widgets" appears in
Glade's palette.
o Glade itself has seen improvements in stability
and features, supporting new widgets and the like
up until GTK+ 3.8
I've verified that all of GTK+'s composite widget
xml files can be saved without any data loss or
any meaningless changes (so that commits should be
as relevant as possible).
o A test case has been added which verifies that each of
these classes construct and finalize properly (and
that all of the object which they refer to in the
xml also finalize properly).
o The <template> format is moderately documented in
gtkwidget.h
o gtk_widget_push/pop_composite_child and relevant
APIs (set/get_composite_name()) have been deprecated.
As far as I know, they were never actually useful for
anything, but now we have a real story for composite
widgets so I would like the old APIs gone.
Some critical points
~~~~~~~~~~~~~~~~~~~~
As it currently stands, there are two critical points which
I think need discussion, I'll list four points here for
completeness.
o Intltool
In order to properly extract translations of strings
defined in .ui files, the files need to be listed
with lines like the following in POTFILES.in:
[type: gettext/glade]gtk/gtkfilechooserdefault.ui
This breaks the build without adding IT_PROG_INTLTOOL()
to configure.ac.
Most projects however do use intltool in configure.ac.
Matthias, does this make your life maintaining GTK+
difficult in any specific way ?
Can we merge this and live with it at least until a
newer version of gettext is released that supports
the ".ui" suffix or the [type: ] annotation properly ?
o Private widget types
In order for Glade to load private widget types (which is
needed to edit some of GTK+'s composite widgets), Glade
needs the types to be registered in advance, since they
cannot be loaded with g_module_lookup() in the normal way.
I've added gtk/gtkgladecatalog.c which exports an initialization
function and that registers the private types.
GTK+'s internal catalog (gtk/glade/gtk-private-widgets.xml)
declares this symbol as it's catalog initializer, which
I think is an elegant enough solution.
Benjamin also noted that gtk_test_register_all_types() also
exists but currently does not register the private types.
I could alternatively make that function register private
types and have Glade call it explicitly at initialization
time.
o Ryan's work on overriding default properties.
Ryan is addressing some issues currently in GObject which
will allow us to declare new default values for properties
registered in parent classes.
This will particularly address a problem that exists with
G_PARAM_CONSTRUCT properties.
While this is not directly tied into the composite work,
some additional enhancements should be made after Ryan
land's his new feature.
I can promise to do this additional enhancement work but I
don't think that we should be blocking on it currently.
o Test case requires an environment variable
Currently I have code in gtkwidget.c to assert that
all composite children finalize properly at gtk_widget_destroy()
time.
The problem is that it cannot be done at finalization of
every composite widget, mostly because we cannot assume
that some API accessor to the composite widget caused
a third party to take an additional reference to one
of the composite widget's children. However it can and
should be asserted while testing a composite widget
in a completely stand-alone test case.
This little bit is up for discussion, it's a minor
detail but I don't currently like the fact that I use
an environment variable to enhance testing of composite
widget destruction.
The relevant code can be found here:
https://git.gnome.org/browse/gtk+/tree/gtk/gtkwidget.c?h=composite-templates-new#n10973
And I think my preference would be to add a new API for
GTK+ widget authors _and_ third party widget authors
to properly test finalization of their GTK+ composite widgets.
I would propose something like:
gtk_widget_test_template (GType widget_type);
However, we could leave it as is (at least for now), or
remove the assertions completely. But they did help me
find bugs so I would very much like to keep the assertions.
Presentation and Explanation of the API and features
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The APIs I'm about to discuss are defined here:
https://git.gnome.org/browse/gtk+/tree/gtk/gtkwidget.h?h=composite-templates-new#n946
o Binding a widget class to it's template
This is done by calling gtk_widget_class_set_template()
in your composite widget's class initializer.
The implementation requires that any widget class
that installs a template must also call
gtk_widget_init_template() in the instance initializer.
Previous iterations of the branch did not require this,
however we've found some problems with interface construction
being done at GObjectClass.constructed() time, which is
often too late, so that one function call must be called
at instance initialization time.
o Binding an instance variable to an object defined in the
GtkBuilder xml associated to a template.
Instead of requiring manual management of objects using
gtk_builder_get_object() in the normal way, we provide
an api to associate a widget's private data structure
offset at class initialization time.
Furthermore we automatically memory-manage the object
pointers of your composite widget class, the instance
will own one strong reference to an object referred to
from GtkBuilder XML until GtkWidgetClass.destroy() runs
(you can still access the object one last time in
your own GtkWidgetClass->destroy() implementation) at
which point the strong reference is released and the
private data pointer set to NULL.
void
gtk_widget_class_automate_child (GtkWidgetClass *widget_class,
const gchar *name,
gboolean internal_child,
gssize struct_offset);
An invocation of the above function generally looks like:
gtk_widget_class_automate_child (class, "name_entry", FALSE,
G_STRUCT_OFFSET (FooPrivate, name_entry);
or with the convenience macro:
gtk_widget_class_bind_child (class, FooPrivate, name_entry);
o Automation of the GtkBuildableIface.get_internal_child() method.
In the above API, if 'internal_child' is specified, then an
automated version of GtkBuildableIface.get_internal_child()
will run while building your composite widget inside another
GtkBuilder xml interface description.
o Declaration of signal callbacks
Finally, to allow <signal> definitions to work in an encapsulated
way, within the scope of your own object, another API is provided
to declare them at class initialization time.
void
gtk_widget_class_declare_callback (GtkWidgetClass *widget_class,
const gchar *callback_name,
GCallback callback_symbol);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]