[Glade-devel] [glade3, patch] handling internal children
- From: pborelli katamail com (Paolo Borelli)
- Subject: [Glade-devel] [glade3, patch] handling internal children
- Date: Fri, 24 Oct 2003 17:41:24 +0200
--=-lUV/E+zT/MZdxfe5/Q8q
Content-Type: text/plain
Content-Transfer-Encoding: 7bit
Hi!
In the last days (actually nights ;) ) I've worked on handling internal
children in glade3.
Fixing this issue is IMHO pretty important because it affects the
GtkDialog widget and consequently a good part of the .glade files in
Gnome.
As a matter of fact after the below patch I've been able to open a
couple of random glade files from my gnome sources... you still get some
warnings for unimplented things as properties of type FLAGS, but the
project is opened :)
Since those were simpler, I've already committed to cvs the patches
which allow the creation of internal children when a widget is created
from the palette and that write the internal-child attribute when saving
the .glade file; the last step is handling the internal-child attribute
when reading from xml and it is implemented in the attached patch: since
this is the more intrusive patch I thought it was a good idea to pass it
by the list for review before committing.
Note: I only fixed internal children of GtkDialog (i.e. dialog->vbox and
dialog->action_area) but the infrastructure should work also for other
widgets which have internal children. I would really welcome suggestions
(or even better patches) of other widgets that need to handle the
internal-child attribute).
Patch explanation:
[In the patches already in cvs I made sure that when a widget which has
internal children is created also the GladeWidgets associated with
internal children are created; GladeWidegets of internal child have a
->internal member which contains the name of the internal child, e.g.
"vbox"]
In the patch below I move the creation on these GladeWidgets from
fill_empty() to post_create() since this method is executed also when
the widget is created from a .glade file.
When an internal-child is found, we don't have to create the
corresponding GtkWidget, but only the GladeWidget: to do so I factored
out glade_widget_fill_widget_from_node from glade_widget_new_from_node.
To retrieve the actual GtkWidget we must walk up the hierarchy until we
find a parent that can give us the requested internal child via the
class->get_internal_child method.
The method is as usual specified in the catalog xml file.
ciao
paolo
--=-lUV/E+zT/MZdxfe5/Q8q
Content-Disposition: attachment; filename=read_int_child.patch
Content-Type: text/x-patch; name=read_int_child.patch; charset=
Content-Transfer-Encoding: 7bit
? autom4te.cache
? glade-3.desktop
? temp.patch
? src/glade-3
Index: src/glade-gtk.c
===================================================================
RCS file: /cvs/gnome/glade3/src/glade-gtk.c,v
retrieving revision 1.35
diff -u -p -r1.35 glade-gtk.c
--- src/glade-gtk.c 23 Oct 2003 17:40:27 -0000 1.35
+++ src/glade-gtk.c 24 Oct 2003 14:12:27 -0000
@@ -524,7 +524,7 @@ ignore (GObject *object, GValue *value)
/* ------------------------------------ Post Create functions ------------------------------ */
void
-glade_gtk_window_post_create (GObject *object, GValue *not_used)
+glade_gtk_window_post_create (GObject *object)
{
GtkWindow *window = GTK_WINDOW (object);
@@ -534,17 +534,45 @@ glade_gtk_window_post_create (GObject *o
}
void
-glade_gtk_dialog_post_create (GObject *object, GValue *not_used)
+glade_gtk_dialog_post_create (GObject *object)
{
GtkDialog *dialog = GTK_DIALOG (object);
+ GladeWidget *widget;
+ GladeWidget *vbox_widget;
+ GladeWidget *actionarea_widget;
+ GladeWidgetClass *child_class;
g_return_if_fail (GTK_IS_DIALOG (dialog));
+ widget = glade_widget_get_from_gtk_widget (GTK_WIDGET (dialog));
+ if (!widget)
+ return;
+
+ /* create the GladeWidgets for internal childrens */
+ child_class = glade_widget_class_get_by_name ("GtkVBox");
+ if (!child_class)
+ return;
+
+ vbox_widget = glade_widget_new_for_internal_child (child_class, widget,
+ dialog->vbox, "vbox");
+ if (!vbox_widget)
+ return;
+
+ child_class = glade_widget_class_get_by_name ("GtkHButtonBox");
+ if (!child_class)
+ return;
+
+ actionarea_widget = glade_widget_new_for_internal_child (child_class, vbox_widget,
+ dialog->action_area, "action_area");
+ if (!actionarea_widget)
+ return;
+
+ /* set a reasonable default size for a dialog */
gtk_window_set_default_size (GTK_WINDOW (dialog), 320, 260);
}
void
-glade_gtk_message_dialog_post_create (GObject *object, GValue *not_used)
+glade_gtk_message_dialog_post_create (GObject *object)
{
GtkMessageDialog *dialog = GTK_MESSAGE_DIALOG (object);
@@ -554,7 +582,7 @@ glade_gtk_message_dialog_post_create (GO
}
void
-glade_gtk_check_button_post_create (GObject *object, GValue *not_used)
+glade_gtk_check_button_post_create (GObject *object)
{
GtkCheckButton *button = GTK_CHECK_BUTTON (object);
GtkWidget *label;
@@ -569,7 +597,7 @@ glade_gtk_check_button_post_create (GObj
}
void
-glade_gtk_table_post_create (GObject *object, GValue *value)
+glade_gtk_table_post_create (GObject *object)
{
GtkTable *table = GTK_TABLE (object);
GList *list;
@@ -698,42 +726,11 @@ glade_gtk_container_fill_empty (GObject
void
glade_gtk_dialog_fill_empty (GObject *dialog)
{
- GtkWidget *vbox;
- GtkWidget *action_area;
- GladeWidget *widget;
- GladeWidget *vbox_widget;
- GladeWidget *actionarea_widget;
- GladeWidgetClass *child_class;
-
g_return_if_fail (GTK_IS_DIALOG (dialog));
- widget = glade_widget_get_from_gtk_widget (GTK_WIDGET (dialog));
- if (!widget)
- return;
-
- /* create the GladeWidgets for internal childrens */
- vbox = GTK_DIALOG (dialog)->vbox;
- child_class = glade_widget_class_get_by_name ("GtkVBox");
- if (!child_class)
- return;
-
- vbox_widget = glade_widget_new_for_internal_child (child_class, widget,
- vbox, "vbox");
- if (!vbox_widget)
- return;
-
- action_area = GTK_DIALOG (dialog)->action_area;
- child_class = glade_widget_class_get_by_name ("GtkHButtonBox");
- if (!child_class)
- return;
-
- actionarea_widget = glade_widget_new_for_internal_child (child_class, vbox_widget,
- action_area, "action_area");
- if (!actionarea_widget)
- return;
-
/* add a placeholder in the vbox */
- gtk_box_pack_start_defaults (GTK_BOX (vbox), glade_placeholder_new ());
+ gtk_box_pack_start_defaults (GTK_BOX (GTK_DIALOG (dialog)->vbox),
+ glade_placeholder_new ());
}
void
@@ -745,4 +742,23 @@ glade_gtk_paned_fill_empty (GObject *pan
gtk_paned_add2 (GTK_PANED (paned), glade_placeholder_new ());
}
+/* -------------------------------- Get Internal Child functions --------------------------- */
+void
+glade_gtk_dialog_get_internal_child (GtkWidget *dialog,
+ const gchar *name,
+ GtkWidget **child)
+{
+ GtkWidget *child_widget;
+
+ g_return_if_fail (GTK_IS_DIALOG (dialog));
+
+ if (strcmp ("vbox", name) == 0)
+ child_widget = GTK_DIALOG (dialog)->vbox;
+ else if (strcmp ("action_area", name) == 0)
+ child_widget = GTK_DIALOG (dialog)->action_area;
+ else
+ child_widget = NULL;
+
+ *child = child_widget;
+}
Index: src/glade-widget-class.c
===================================================================
RCS file: /cvs/gnome/glade3/src/glade-widget-class.c,v
retrieving revision 1.44
diff -u -p -r1.44 glade-widget-class.c
--- src/glade-widget-class.c 15 Oct 2003 21:48:40 -0000 1.44
+++ src/glade-widget-class.c 24 Oct 2003 14:12:29 -0000
@@ -347,6 +347,7 @@ glade_widget_class_extend_with_file (Gla
char *replace_child_function_name;
char *post_create_function_name;
char *fill_empty_function_name;
+ char *get_internal_child_function_name;
g_return_val_if_fail (filename != NULL, FALSE);
@@ -379,6 +380,13 @@ glade_widget_class_extend_with_file (Gla
g_warning ("Could not find %s\n", fill_empty_function_name);
}
g_free (fill_empty_function_name);
+
+ get_internal_child_function_name = glade_xml_get_value_string (node,
GLADE_TAG_GET_INTERNAL_CHILD_FUNCTION);
+ if (get_internal_child_function_name && widget_class->module) {
+ if (!g_module_symbol (widget_class->module, get_internal_child_function_name, (void **)
&widget_class->get_internal_child))
+ g_warning ("Could not find %s\n", get_internal_child_function_name);
+ }
+ g_free (get_internal_child_function_name);
/* if we found a <properties> tag on the xml file, we add the properties
* that we read from the xml file to the class.
Index: src/glade-widget-class.h
===================================================================
RCS file: /cvs/gnome/glade3/src/glade-widget-class.h,v
retrieving revision 1.26
diff -u -p -r1.26 glade-widget-class.h
--- src/glade-widget-class.h 23 Oct 2003 17:40:27 -0000 1.26
+++ src/glade-widget-class.h 24 Oct 2003 14:12:29 -0000
@@ -83,16 +83,22 @@ struct _GladeWidgetClass
GtkWidget *new,
GtkWidget *container);
- /* Executed after widget creation: e.g. sets the size of a window to a
- * sane default.
+ /* Executed after widget creation: takes care of creating the GladeWidgets
+ * associated with internal children. It also the place to set sane defaults,
+ * e.g. set the size of a window.
*/
void (*post_create_function) (GObject *gobject);
/* If the widget is a container, this method takes care of adding the
- * needed placeholders. If the widget has internal children, this method
- * must create the associated GladeWidgets.
+ * needed placeholders.
*/
void (*fill_empty) (GtkWidget *widget);
+
+ /* Retrieves the the internal child of the given name.
+ */
+ void (*get_internal_child) (GtkWidget *parent,
+ const gchar *name,
+ GtkWidget **child);
};
Index: src/glade-widget.c
===================================================================
RCS file: /cvs/gnome/glade3/src/glade-widget.c,v
retrieving revision 1.81
diff -u -p -r1.81 glade-widget.c
--- src/glade-widget.c 23 Oct 2003 18:45:32 -0000 1.81
+++ src/glade-widget.c 24 Oct 2003 14:12:32 -0000
@@ -604,13 +604,6 @@ glade_widget_create_gtk_widget (GladeWid
* Cuenca
*/
- /* We need to call the post_create_function after the embed of the widget in
- * its parent. Otherwise, calls to gtk_widget_grab_focus et al. will fail
- */
- if (class->post_create_function) {
- class->post_create_function (G_OBJECT (widget));
- }
-
return widget;
}
@@ -687,6 +680,11 @@ glade_widget_new_full (GladeWidgetClass
glade_widget_associate_with_gtk_widget (widget, gtk_widget);
+ /* associate internal children and set sane defaults */
+ if (class->post_create_function) {
+ class->post_create_function (G_OBJECT (gtk_widget));
+ }
+
return widget;
}
@@ -1349,37 +1347,25 @@ glade_widget_new_child_from_node (GladeX
GladeProject *project,
GladeWidget *parent);
-static GladeWidget *
-glade_widget_new_from_node_real (GladeXmlNode *node,
- GladeProject *project,
- GladeWidget *parent)
+static void
+glade_widget_fill_from_node (GladeXmlNode *node, GladeWidget *widget)
{
- GladeWidgetClass *class;
GladeXmlNode *child;
- GladeWidget *widget;
- GladeSignal *signal;
const gchar *class_name;
const gchar *widget_name;
+ g_return_if_fail (GLADE_IS_WIDGET (widget));
+
if (!glade_xml_node_verify (node, GLADE_XML_TAG_WIDGET))
- return NULL;
+ return;
class_name = glade_xml_get_property_string_required (node, GLADE_XML_TAG_CLASS, NULL);
widget_name = glade_xml_get_property_string_required (node, GLADE_XML_TAG_ID, NULL);
if (!class_name || !widget_name)
- return NULL;
-
- class = glade_widget_class_get_by_name (class_name);
- if (!class)
- return NULL;
-
- widget = glade_widget_new_full (class, project);
- if (!widget)
- return NULL;
+ return;
+ g_assert (strcmp (class_name, widget->class->name) == 0);
glade_widget_set_name (widget, widget_name);
- if (parent)
- glade_widget_set_packing_properties (widget, parent->class);
/* Children */
child = glade_xml_node_get_children (node);
@@ -1387,7 +1373,7 @@ glade_widget_new_from_node_real (GladeXm
if (!glade_xml_node_verify_silent (child, GLADE_XML_TAG_CHILD))
continue;
- if (!glade_widget_new_child_from_node (child, project, widget)) {
+ if (!glade_widget_new_child_from_node (child, widget->project, widget)) {
g_warning ("Failed to read child");
continue;
}
@@ -1396,6 +1382,8 @@ glade_widget_new_from_node_real (GladeXm
/* Signals */
child = glade_xml_node_get_children (node);
for (; child; child = glade_xml_node_next (child)) {
+ GladeSignal *signal;
+
if (!glade_xml_node_verify_silent (child, GLADE_XML_TAG_SIGNAL))
continue;
@@ -1418,12 +1406,69 @@ glade_widget_new_from_node_real (GladeXm
continue;
}
}
+}
+
+GladeWidget *
+glade_widget_new_from_node_real (GladeXmlNode *node,
+ GladeProject *project,
+ GladeWidget *parent)
+{
+ GladeWidgetClass *class;
+ GladeWidget *widget;
+ const gchar *class_name;
+
+ if (!glade_xml_node_verify (node, GLADE_XML_TAG_WIDGET))
+ return NULL;
+
+ class_name = glade_xml_get_property_string_required (node, GLADE_XML_TAG_CLASS, NULL);
+ if (!class_name)
+ return NULL;
+
+ class = glade_widget_class_get_by_name (class_name);
+ if (!class)
+ return NULL;
+
+ widget = glade_widget_new_full (class, project);
+ if (!widget)
+ return NULL;
+
+ if (parent)
+ glade_widget_set_packing_properties (widget, parent->class);
+
+ glade_widget_fill_from_node (node, widget);
gtk_widget_show_all (widget->widget);
return widget;
}
+/**
+ * When looking for an internal child we have to walk up the hierarchy...
+ */
+static GladeWidget *
+glade_widget_get_internal_child (GladeWidget *parent,
+ const gchar *internal)
+{
+ GladeWidget *ancestor;
+ GladeWidget *child = NULL;
+
+ ancestor = parent;
+ while (ancestor) {
+ if (ancestor->class->get_internal_child) {
+ GtkWidget *widget;
+ ancestor->class->get_internal_child (ancestor->widget, internal, &widget);
+ if (widget) {
+ child = glade_widget_get_from_gtk_widget (widget);
+ if (child)
+ break;
+ }
+ }
+ ancestor = glade_widget_get_parent (ancestor);
+ }
+
+ return child;
+}
+
static gboolean
glade_widget_new_child_from_node (GladeXmlNode *node,
GladeProject *project,
@@ -1437,14 +1482,6 @@ glade_widget_new_child_from_node (GladeX
if (!glade_xml_node_verify (node, GLADE_XML_TAG_CHILD))
return FALSE;
- /* we don't support internal children yet... */
- internalchild = glade_xml_get_property_string (node, GLADE_XML_TAG_INTERNAL_CHILD);
- if (internalchild) {
- g_warning ("Internal Child not supported yet");
- g_free (internalchild);
- return FALSE;
- }
-
/* is it a placeholder? */
child_node = glade_xml_search_child (node, GLADE_XML_TAG_PLACEHOLDER);
if (child_node) {
@@ -1452,21 +1489,32 @@ glade_widget_new_child_from_node (GladeX
return TRUE;
}
- /* Get and create the widget */
+ /* then it must be a widget */
child_node = glade_xml_search_child_required (node, GLADE_XML_TAG_WIDGET);
if (!child_node)
return FALSE;
- child = glade_widget_new_from_node_real (child_node, project, parent);
- if (!child)
- /*
- * not enough memory... and now, how can I signal it
- * and not make the caller believe that it was a parsing
- * problem?
- */
- return FALSE;
+ /* is it an internal child? */
+ internalchild = glade_xml_get_property_string (node, GLADE_XML_TAG_INTERNAL_CHILD);
+ if (internalchild) {
+ child = glade_widget_get_internal_child (parent, internalchild);
+ if (!child) {
+ g_warning ("Failed to get internal child %s", internalchild);
+ g_free (internalchild);
+ return FALSE;
+ }
+ glade_widget_fill_from_node (child_node, child);
+ } else {
+ child = glade_widget_new_from_node_real (child_node, project, parent);
+ if (!child)
+ /* not enough memory... and now, how can I signal it
+ * and not make the caller believe that it was a parsing
+ * problem?
+ */
+ return FALSE;
- gtk_container_add (GTK_CONTAINER (parent->widget), child->widget);
+ gtk_container_add (GTK_CONTAINER (parent->widget), child->widget);
+ }
/* Get the packing properties */
child_node = glade_xml_search_child (node, GLADE_XML_TAG_PACKING);
@@ -1486,7 +1534,6 @@ glade_widget_new_child_from_node (GladeX
/* the tag should have the form <property name="...id...">...value...</property>*/
id = glade_xml_get_property_string_required (child_properties, GLADE_XML_TAG_NAME,
NULL);
value = glade_xml_get_content (child_properties);
-
if (!value || !id) {
g_warning ("Invalid property %s:%s\n", value, id);
g_free (value);
@@ -1496,8 +1543,7 @@ glade_widget_new_child_from_node (GladeX
glade_util_replace (id, '_', '-');
property = glade_property_get_from_id (child->packing_properties, id);
-
- if (property == NULL) {
+ if (!property) {
g_warning ("Could not apply property from node. Id :%s\n",
id);
continue;
Index: src/glade.h
===================================================================
RCS file: /cvs/gnome/glade3/src/glade.h,v
retrieving revision 1.29
diff -u -p -r1.29 glade.h
--- src/glade.h 20 Oct 2003 18:16:33 -0000 1.29
+++ src/glade.h 24 Oct 2003 14:12:32 -0000
@@ -93,6 +93,7 @@
#define GLADE_TAG_REPLACE_CHILD_FUNCTION "ReplaceChildFunction"
#define GLADE_TAG_POST_CREATE_FUNCTION "PostCreateFunction"
#define GLADE_TAG_FILL_EMPTY_FUNCTION "FillEmptyFunction"
+#define GLADE_TAG_GET_INTERNAL_CHILD_FUNCTION "GetInternalChildFunction"
#define GLADE_TAG_IN_PALETTE "InPalette"
#define GLADE_TAG_CATALOG "GladeCatalog"
Index: widgets/gtkdialog.xml
===================================================================
RCS file: /cvs/gnome/glade3/widgets/gtkdialog.xml,v
retrieving revision 1.5
diff -u -p -r1.5 gtkdialog.xml
--- widgets/gtkdialog.xml 13 Oct 2003 16:15:22 -0000 1.5
+++ widgets/gtkdialog.xml 24 Oct 2003 14:12:32 -0000
@@ -2,6 +2,7 @@
<PostCreateFunction>glade_gtk_dialog_post_create</PostCreateFunction>
<FillEmptyFunction>glade_gtk_dialog_fill_empty</FillEmptyFunction>
+ <GetInternalChildFunction>glade_gtk_dialog_get_internal_child</GetInternalChildFunction>
<Properties>
--=-lUV/E+zT/MZdxfe5/Q8q--
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]