The next release of gnome-utils, 2.13.90, will make libgdict adhere to the API/ABI freeze, even if it’s not part of the Gnome Developer Platform but only of the Desktop.
The freeze had been in effect since the last release (January 18th), and I planned not to change libgdict API; unfortunately, when writing the support for the document_font_name
GConf key, which was introduced in Gnome 2.12 and that should be honoured by any application showing arbitrarily long texts to the user, I noticed that a call to gtk_widget_modify_font
to a GtkContainer
does not propagate to the containers’s children. The widget the Dictionary uses to display the text of the definitions is, in fact, a composite widget (a GtkVBox
) as it needs to hold the text display and the find bar; the inner widgets are held inside a private structure, and are not visible to the outside.
If I wanted to work around this, I would have written something like this function inside the code of the libgdict users:
static void
gtk_container_modify_font_children (GtkContainer *container,
const gchar *font_name)
{
GList *children, *l;
PangoFontDescription *font_desc;
g_return_if_fail (GTK_IS_CONTAINER (container));
font_desc = NULL;
if (font_name)
{
font_desc = pango_font_description_from_string (font_name);
g_return_if_fail (font_desc != NULL);
}
children = gtk_container_get_children (container);
for (l = children; l != NULL; l = l->next)
{
GtkWidget *widget = GTK_WIDGET (l->data);
gtk_widget_modify_font (widget, font_desc);
}
g_list_free (children);
if (font_desc)
pango_font_description_free (font_desc);
}
But it would not have worked; I wanted to change the font of the GtkTextView
widget inside the GdictDefbox
, while the function above would have changed font for all internal widgets – including the find pane.
Assigning a name to the GtkTextView
widget, say “text-display”, by using the gtk_widget_set_name
function, and changing the code of the inner loop to something like this:
...
for (l = children; l != NULL; l = l->next)
{
GtkWidget *widget = GTK_WIDGET (l->data);
const gchar *name = gtk_widget_get_name (widget);
if (strcmp (name, "text-display") == 0)
gtk_widget_modify_font (widget, font_desc);
}
...
I would have avoided the API breakage inside libgdict – but I would also have created a performance bottleneck, since I transformed a constant time operation into a linear time one (from an assignment to a list walk) – plus, I don’t know what happens into gtk_widget_modify_font
; also, I would have created a documentation issue, since I now would have to document the widget’s name and hope that nobody would ever have the urge to change the GdictDefbox
font – at least, not after having had lunch.
Giving a name to the inner children of a composite widget is always a good practice – it makes handling these kind of situations easier; but between an hackish approach and a breakage of an API freeze, I would rather choose the latter. Hacks tend to get sticky, and you get a design by accretion if you let them stick around enough.
So, I opten for adding a new property to the GdictDefbox
widget, called font-name
, and its two accessor functions:
G_CONST_RETURN gchar *gdict_defbox_get_font_name (GdictDefbox *defbox);
void gdict_defbox_set_font_name (GdictDefbox *defbox,
const gchar *font_name);
Which are just proxies for the gtk_widget_modify_font
function. Since nobody uses libgdict (it’s been out there only for the folks using Ubuntu or jhbuild), the breakage is really minimal; nevertheless, I feel a bit guilty for not having tested this stuff before, in time for the freeze.