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); _______________________________________________ gtk-devel-list mailing list gtk-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-devel-list